#define OLC_PGE_APPLICATION #include "pixelGameEngine.h" #include "data.h" #define OLC_PGEX_SPLASHSCREEN #include "splash.h" #include using namespace olc; enum GAMESTATE{ CUTSCENE_1, CUTSCENE_2, CUTSCENE_3, GAMEWORLD, WAITING_FOR_CUTSCENE_3, GAME_OVER, }; namespace cutscene{ enum CUTSCENE{ NONE, PAN_DOME, PAUSE_TO_CUTSCENE_3, CUTSCENE_4, TRANSITION_CUTSCENE, //Exit the dome. TRANSITION_CUTSCENE_2, //Enter the dome. NODE_COLLECT_CUTSCENE }; } namespace battle{ enum BATTLESTATE{ NONE, WAITING_FOR_CAMERA, PLAYER_SELECTION, PLAYER_TARGET_SELECTION, ENEMY_SELECTION, MOVE_RESOLUTION, PERFORM_TURN, WAIT_TURN_ANIMATION, DAMAGE_RESOLUTION, }; } #define WIDTH 256 #define HEIGHT 224 #define ALPHA_SCREEN1 128 #define ALPHA_SCREEN2 20 #define FADE_SPD 6 #define MOVE_SPD 0.1 #define MESSAGE_SCROLL_WAIT_SPD 2 //Number of frames to wait. #define BATTLE_CAMERA_SCROLL_SPD 0.05 //How fast to scroll over to the battle. class DisplayNumber{ public: int number; //Negative means healing. int frame; //Frame it was created. float x,y; int alpha=255; DisplayNumber(int numb,int x,int y,int frameCount) { this->number=numb; this->x=x; this->y=y; this->frame=frameCount; } }; class Animation{ public: Decal*spr; std::vector frames; int frame=0; bool flipped=false; int skip_frames=1; //Essentially the animation speed. Number of frames to wait for next frame. int width=32; int height=32; vi2d getCurrentFrame() { return frames[frame]; } }; std::vector updateAnimationsList; //Used to store animations in the game that we need to keep track of and update. Probably don't touch this. class ObjectLoadInfo{ public: Decal*spr; bool hasanim=false; Animation*anim; ObjectLoadInfo(Decal*spr) { this->spr=spr; } ObjectLoadInfo(Decal*spr,Animation*anim) { this->spr=spr; this->anim=anim; this->hasanim=true; updateAnimationsList.push_back(anim); } }; class Object{ public: float x,y; Decal*spr; std::string name; bool hasAnim=false; Animation*anim; }; class ParticleEffect{ public: vf2d effectPos; vf2d effectSize; vf2d pos_low; vf2d pos_high; vf2d size_low; vf2d size_high; vf2d spd_low; vf2d spd_high; olc::Pixel col_low; olc::Pixel col_high; int amt; olc::Pixel foregroundColor; ParticleEffect(vf2d effectPos,vf2d effectSize,vf2d pos_low,vf2d pos_high,vf2d size_low,vf2d size_high,vf2d spd_low,vf2d spd_high,olc::Pixel col_low,olc::Pixel col_high,int amt,olc::Pixel foregroundColor) { this->effectPos=effectPos; this->effectSize=effectSize; this->pos_low=pos_low; this->pos_high=pos_high; this->size_low=size_high; this->spd_low=spd_low; this->spd_high=spd_high; this->col_low=col_low; this->col_high=col_high; this->amt=amt; this->foregroundColor=foregroundColor; } }; class WEATHER_POWER{ public: std::string description; std::string name; Animation*anim; Animation*effectAnim; int damage; int damageRoll; int range; int playerOwnCount; Pixel bgcol; Pixel textcol; int effectTime; ParticleEffect*effect; WEATHER_POWER(std::string name,std::string desc,Animation*icon,Animation*effect,int dmg,int dmgRoll,int range,Pixel bgcol,Pixel textcol,int effectTime,ParticleEffect*parteff) { this->description=desc; this->name=name; this->anim=icon; this->effectAnim=effect; this->damage=dmg; this->damageRoll=dmgRoll; this->range=range; this->bgcol=bgcol; this->textcol=textcol; this->effectTime=effectTime; this->effect=parteff; } }; class Entity{ public: bool ally; int hp; int maxhp; Decal*spr; int x; int y; std::string name; WEATHER_POWER*selectedMove; std::vector moveSet; bool turnComplete=false; bool slowed=false; int damageFrame=0; Entity(Decal*spr,std::string name,int x,int y,int hp,int maxhp,std::vectormoveset) { this->spr=spr; this->name=name; this->x=x; this->y=y; this->maxhp=hp; this->hp=hp; this->maxhp=maxhp; this->moveSet=moveset; } }; class Encounter{ public: int x,y; std::vector entities; std::vector turnOrder; }; namespace effect { class Pixel{ public: vf2d pos, size, spd; int r,g,b,a; int o_r,o_g,o_b,o_a; Pixel() { pos={0,0}; size={0,0}; spd={0,0}; }; Pixel(vf2d pos,vf2d size,vf2d spd,olc::Pixel col) { this->pos=pos; this->size=size; this->spd=spd; this->r=this->o_r=col.r; this->g=this->o_g=col.g; this->b=this->o_b=col.b; this->a=this->o_a=col.a; } }; }; class SeasonsOfLoneliness : public PixelGameEngine { public: SeasonsOfLoneliness() { sAppName = "Seasons of Loneliness"; } #define STARTING_MAP "assets/maps/map2" public: GAMESTATE GAME_STATE=GAMEWORLD; int textInd=0; int cursorX=0; int transitionTime=0; bool fade=false; int transparency=0; int frameCount=0; float elapsedTime=0; const float TARGET_RATE = 1/60.0; std::string MAP_NAME = ""; std::string CUTSCENE_CONSOLE_TEXT = ""; int**MAP=NULL; int MAP_WIDTH=-1; int MAP_HEIGHT=-1; Decal*TILES; float PLAYER_COORDS[2] = {14,4}; std::vector OBJECTS; bool CUTSCENE_ACTIVE=false; cutscene::CUTSCENE CURRENT_CUTSCENE=cutscene::NONE; int CUTSCENE_TIMER=0; bool CUTSCENE_FLAGS[8]; bool messageBoxVisible=false; int messageBoxCursor; std::string messageBoxSpeaker; std::string messageBoxText; std::string messageBoxRefText; bool firstNewline=false; bool secondNewline=false; bool foodMeterVisible=false; int foodCount=3; bool oxygenMeterVisible=false; int oxygenQualityLevel=34; int plantState=0b10010110101000101010100110101010; SplashScreen splash; Animation current_playerAnim; Animation playerAnim; Animation playerAnimRight; Animation playerAnimLeft; Animation playerAnimDown; Animation playerAnimWalkUp; Animation playerAnimWalkDown; Animation playerAnimWalkRight; Animation playerAnimWalkLeft; Animation playerAnimPlantUp; Animation playerAnimPlantDown; Animation playerAnimPlantRight; Animation playerAnimPlantLeft; Animation POWER_HAILSTORM_ANIMATION; Animation POWER_HURRICANE_ANIMATION; Animation POWER_METEOR_SHOWER_ANIMATION; Animation POWER_METEOR_STORM_ANIMATION; Animation POWER_SNOWSTORM_ANIMATION; Animation CONSUME_SNACK_ANIMATION; Animation CONSUME_MEAL_ANIMATION; ParticleEffect*HAILSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{4,4},{-2,0.5},{-0.5,2},Pixel(143, 242, 255,255),Pixel(255,255,255,255),300,Pixel(220, 226, 227,0)); ParticleEffect*HURRICANE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-4,1},{-1,4},Pixel(225, 248, 252,64),Pixel(255,255,255,128),300,Pixel(220, 226, 227,0)); ParticleEffect*METEOR_RAIN_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{3,3},{6,6},{-1,0.2},{-0.2,1},Pixel(46, 31, 31,255),Pixel(43, 31, 46,255),50,Pixel(30, 10, 36,0)); ParticleEffect*METEOR_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{3,3},{10,10},{-2,0.1},{-0.1,2},Pixel(46, 31, 31,255),Pixel(181, 72, 46,255),75,Pixel(30, 10, 36,48)); ParticleEffect*SNOWSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-1,0.5},{1,2},Pixel(193, 198, 201,200),Pixel(255,255,255,255),400,Pixel(220, 226, 227,0)); ParticleEffect*SANDSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-20,1},{20,3},Pixel(133, 98, 66,130),Pixel(158, 93, 33,210),300,Pixel(87, 78, 69,0)); ParticleEffect*SEED_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-0.5,-1},{0.5,-0.2},Pixel(65, 98, 66,130),Pixel(65, 117, 60,210),100,Pixel(70, 158, 62,0)); ParticleEffect*AVALANCHE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{8,8},{-4,2},{4,4},Pixel(143, 242, 255,255),Pixel(255,255,255,255),300,Pixel(220, 226, 227,0)); ParticleEffect*CONSUME_SNACK_EFF = new ParticleEffect({0,0},{64,64},{64,64},{64,64},{1,1},{2,2},{-0.1,-0.5},{0.1,-0.05},Pixel(255,255,255,130),Pixel(255,255,255,210),30,Pixel(147, 161, 90,0)); //Used for CONSUME_MEAL too. WEATHER_POWER*HAILSTORM = new WEATHER_POWER("Hailstorm","Causes a flurry of hard cold rocks to be unleashed in target area. 60+30d",&POWER_HAILSTORM_ANIMATION,&POWER_HAILSTORM_ANIMATION,60,30,160,Pixel(72, 160, 212,255),Pixel(93, 161, 163,255),120,HAILSTORM_EFF); WEATHER_POWER*HURRICANE = new WEATHER_POWER("Hurricane","Causes heavy winds, scattering seeds, heavy rain. 20+10d",&POWER_HURRICANE_ANIMATION,&POWER_HURRICANE_ANIMATION,20,10,200,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,HURRICANE_EFF); WEATHER_POWER*METEOR_RAIN = new WEATHER_POWER("Meteor Rain","Causes space rocks to fall on target area. 50+50d",&POWER_METEOR_SHOWER_ANIMATION,&POWER_METEOR_SHOWER_ANIMATION,50,50,96,Pixel(96, 86, 153,255),Pixel(170, 103, 201,255),120,METEOR_STORM_EFF); WEATHER_POWER*METEOR_STORM = new WEATHER_POWER("Meteor Storm","Larger space rocks. 120+60d",&POWER_METEOR_STORM_ANIMATION,&POWER_METEOR_STORM_ANIMATION,120,60,140,Pixel(89, 4, 33,255),Pixel(130, 56, 1,255),120,METEOR_RAIN_EFF); WEATHER_POWER*SNOWSTORM = new WEATHER_POWER("Snowstorm","Slows down targets and causes rapid temperature drops. 15+10d",&POWER_SNOWSTORM_ANIMATION,&POWER_SNOWSTORM_ANIMATION,15,10,140,Pixel(183, 196, 194,255),Pixel(222, 255, 254,255),120,SNOWSTORM_EFF); WEATHER_POWER*SANDSTORM = new WEATHER_POWER("Sandstorm","",&POWER_HAILSTORM_ANIMATION,&POWER_HAILSTORM_ANIMATION,5,10,64,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,SANDSTORM_EFF); WEATHER_POWER*SEED_STORM = new WEATHER_POWER("Seed Storm","",&POWER_HAILSTORM_ANIMATION,&POWER_HAILSTORM_ANIMATION,-10,15,30,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,SEED_STORM_EFF); WEATHER_POWER*AVALANCHE = new WEATHER_POWER("Avalanche","",&POWER_HAILSTORM_ANIMATION,&POWER_HAILSTORM_ANIMATION,15,10,200,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,AVALANCHE_EFF); WEATHER_POWER*CONSUME_SNACK = new WEATHER_POWER("Snack","Restores 33% health for 5 turns. If battle ends before effect ends, food is not consumed.",&CONSUME_SNACK_ANIMATION,&CONSUME_SNACK_ANIMATION,-1001,1,200,Pixel(147, 173, 66,255),Pixel(255, 188, 3,255),120,CONSUME_SNACK_EFF); WEATHER_POWER*CONSUME_MEAL = new WEATHER_POWER("Meal","Restores all health. Increases Maximum Health by 5.",&CONSUME_MEAL_ANIMATION,&CONSUME_MEAL_ANIMATION,-1002,1,200,Pixel(147, 173, 66,255),Pixel(255, 188, 3,255),120,CONSUME_SNACK_EFF); bool IN_BATTLE_ENCOUNTER = false; int BATTLE_ENTRY_TIMER = 0; int EFFECT_TIMER = 0; #define WEATHER_POWER_COUNT 7 //Number of powers that are in the game. Update storage array accordingly. WEATHER_POWER*WEATHER_POWERS[WEATHER_POWER_COUNT] = { HAILSTORM, HURRICANE, METEOR_RAIN, METEOR_STORM, SNOWSTORM, CONSUME_SNACK, CONSUME_MEAL}; battle::BATTLESTATE BATTLE_STATE=battle::NONE; std::vector availablePowers; WEATHER_POWER*BATTLE_CARD_SELECTION=HAILSTORM; int BATTLE_CARD_SELECTION_IND=0; int PLAYER_SELECTED_TARGET=-1; int PLAYER_MAXHP=60; int PLAYER_HP=PLAYER_MAXHP; int BATTLE_CURRENT_TURN_ENTITY=-1; int CURRENT_ENCOUNTER_IND=-1; int RAND_CALLS=0; std::vector BATTLE_DISPLAY_NUMBERS; bool PLAYER_TURN_COMPLETE=false; int FOOD_REGEN_TURNS=0; WEATHER_POWER* CUTSCENE_DISPLAYED_CARD; Pixel FOREGROUND_EFFECT_COLOR; Pixel ORIGINAL_FOREGROUND_EFFECT_COLOR; int PIXEL_LIMIT=0; vf2d PIXEL_POS; vf2d PIXEL_SIZE; std::vectorMOVESET_SPIDEY; float PIXEL_EFFECT_TRANSPARENCY=0.5; Decal*DOME_DECAL,*FOOD_METER_DECAL,*OXYGEN_METER_DECAL,*PLANT_DECAL, *PLAYER_DECAL, *WEATHERNODE_EFFECT_DECAL,*POWER_HAILSTORM_DECAL,*POWER_HURRICANE_DECAL,*POWER_METEOR_SHOWER_DECAL,*POWER_METEOR_STORM_DECAL,*POWER_SNOWSTORM_DECAL, *SPIDEY_DECAL,*TARGETING_CIRCLE,*TARGETING_RANGE_CIRCLE,*HEALTHBAR_DECAL, *CONSUME_SNACK_DECAL,*CONSUME_MEAL_DECAL; std::map BASE_OBJECTS; std::vector ENCOUNTERS; Encounter ENCOUNTER_SPIDEY_1; Encounter CURRENT_ENCOUNTER; std::queue turnOrder; #define MAX_PIXELS 500 effect::Pixel*pixels[MAX_PIXELS]; bool OnUserCreate() override { SetPixelMode(Pixel::ALPHA); ConsoleCaptureStdOut(true); #define LAYERS 2 //How many layers exist. for (int i=1;iplayerOwnCount=3; HURRICANE->playerOwnCount=1; METEOR_RAIN->playerOwnCount=5; MOVESET_SPIDEY.push_back(SANDSTORM); MOVESET_SPIDEY.push_back(SEED_STORM); MOVESET_SPIDEY.push_back(AVALANCHE); ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",2,3,80,80,MOVESET_SPIDEY)); ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",4,4,80,80,MOVESET_SPIDEY)); ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",6,2,80,80,MOVESET_SPIDEY)); ENCOUNTER_SPIDEY_1.x=79; ENCOUNTER_SPIDEY_1.y=47; ENCOUNTERS.push_back(ENCOUNTER_SPIDEY_1); BASE_OBJECTS["DOME"]=new ObjectLoadInfo(DOME_DECAL); BASE_OBJECTS["PLANT"]=new ObjectLoadInfo(PLANT_DECAL); BASE_OBJECTS["EXIT"]=new ObjectLoadInfo(NULL); BASE_OBJECTS["HAILSTORM_NODE"]=new ObjectLoadInfo(POWER_HAILSTORM_DECAL,&POWER_HAILSTORM_ANIMATION); BASE_OBJECTS["HURRICANE_NODE"]=new ObjectLoadInfo(POWER_HURRICANE_DECAL,&POWER_HURRICANE_ANIMATION); BASE_OBJECTS["METEORSHOWER_NODE"]=new ObjectLoadInfo(POWER_METEOR_SHOWER_DECAL,&POWER_METEOR_SHOWER_ANIMATION); BASE_OBJECTS["METEORSTORM_NODE"]=new ObjectLoadInfo(POWER_METEOR_STORM_DECAL,&POWER_METEOR_STORM_ANIMATION); BASE_OBJECTS["SNOWSTORM_NODE"]=new ObjectLoadInfo(POWER_SNOWSTORM_DECAL,&POWER_SNOWSTORM_ANIMATION); for (int i=0;i=STORY_TEXT1.length()) { fadeOut(); } }break; } } void ActionButtonPress() { switch (GAME_STATE) { case GAMEWORLD:{ if (PLAYER_COORDS[0]>=8&&PLAYER_COORDS[0]<12&& PLAYER_COORDS[1]>=2&&PLAYER_COORDS[1]<6) { //cout<<"You are standing over plant "<playerOwnCount>0) { BATTLE_STATE=battle::PLAYER_TARGET_SELECTION; if (!(BATTLE_CARD_SELECTION->name.compare("Meal")==0||BATTLE_CARD_SELECTION->name.compare("Snack")==0)) { if (PLAYER_SELECTED_TARGET==-1||CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp<=0) { for (int i=0;ially&&ent->hp>0) { PLAYER_SELECTED_TARGET=i; break; } } } } else { PLAYER_SELECTED_TARGET=-2; setupBattleTurns(); } } }break; case battle::PLAYER_TARGET_SELECTION:{ setupBattleTurns(); }break; } switch (CURRENT_CUTSCENE) { case cutscene::NODE_COLLECT_CUTSCENE:{ EndCutscene(); }break; } } bool OnUserUpdate(float fElapsedTime) override { elapsedTime+=fElapsedTime; while (elapsedTime>TARGET_RATE) { elapsedTime-=TARGET_RATE; updateGame(); } if (GetKey(F1).bPressed) { ConsoleShow(F1,false); } if (playerCanMove()) { if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) { changeAnimation(playerAnimWalkRight); } if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) { changeAnimation(playerAnimWalkLeft); } if (GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) { changeAnimation(playerAnimWalkUp); } if (GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed) { changeAnimation(playerAnimWalkDown); } if (!GetKey(D).bHeld&&!GetKey(RIGHT).bHeld&&!GetKey(NP6).bHeld&& !GetKey(A).bHeld&&!GetKey(LEFT).bHeld&&!GetKey(NP4).bHeld&& !GetKey(S).bHeld&&!GetKey(UP).bHeld&&!GetKey(NP8).bHeld&& !GetKey(W).bHeld&&!GetKey(DOWN).bHeld&&!GetKey(NP5).bHeld&&!GetKey(NP2).bHeld) { if (GetKey(D).bReleased||GetKey(RIGHT).bReleased||GetKey(NP6).bReleased) { changeAnimation(playerAnimRight); } if (GetKey(A).bReleased||GetKey(LEFT).bReleased||GetKey(NP4).bReleased) { changeAnimation(playerAnimLeft); } if (GetKey(W).bReleased||GetKey(UP).bReleased||GetKey(NP8).bReleased) { changeAnimation(playerAnim); } if (GetKey(S).bReleased||GetKey(DOWN).bReleased||GetKey(NP5).bReleased||GetKey(NP2).bReleased) { changeAnimation(playerAnimDown); } } } else if (IN_BATTLE_ENCOUNTER) { switch (BATTLE_STATE) { case battle::PLAYER_SELECTION:{ if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) { BATTLE_CARD_SELECTION_IND=(BATTLE_CARD_SELECTION_IND+1)%availablePowers.size(); BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND]; } if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) { if (--BATTLE_CARD_SELECTION_IND<0) { BATTLE_CARD_SELECTION_IND=availablePowers.size()-1; } BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND]; } }break; case battle::PLAYER_TARGET_SELECTION:{ if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) { while (true) { PLAYER_SELECTED_TARGET=(PLAYER_SELECTED_TARGET+1)%CURRENT_ENCOUNTER.entities.size(); if (CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0) { break; } } } if (GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) { PLAYER_SELECTED_TARGET=-1; BATTLE_STATE=battle::PLAYER_SELECTION; } if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) { while (true) { if (--PLAYER_SELECTED_TARGET<0) { PLAYER_SELECTED_TARGET=CURRENT_ENCOUNTER.entities.size()-1; } if (CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0) { break; } } } }break; } } SetDrawTarget(nullptr); Clear(BLANK); SetDrawTarget(1); drawGame(); // called once per frame return true; } void fadeOutCompleted() { switch (GAME_STATE) { case CUTSCENE_1:{ GAME_STATE=CUTSCENE_2; PlayCutscene(cutscene::PAN_DOME); fadeIn(); }break; case CUTSCENE_2:{ fadeIn(); PlayCutscene(cutscene::CUTSCENE_4); GAME_STATE=GAMEWORLD; }break; } switch (CURRENT_CUTSCENE) { case cutscene::TRANSITION_CUTSCENE:{ LoadMap("assets/maps/map1"); PLAYER_COORDS[0]=40.5; PLAYER_COORDS[1]=37.5; fadeIn(); EndCutscene(); }break; case cutscene::TRANSITION_CUTSCENE_2:{ LoadMap("assets/maps/map2"); TeleportToMapFileCoords(8,17); fadeIn(); EndCutscene(); }break; } } void fadeInCompleted() { } void PlayCutscene(cutscene::CUTSCENE scene) { CURRENT_CUTSCENE=scene; switch (scene) { case cutscene::PAN_DOME:{ PLAYER_COORDS[0]=14; PLAYER_COORDS[1]=35+(64/2/32); }break; case cutscene::PAUSE_TO_CUTSCENE_3:{ CUTSCENE_CONSOLE_TEXT.clear(); textInd=0; }break; case cutscene::CUTSCENE_4:{ LoadMap("assets/maps/map2"); PLAYER_COORDS[0]=16; PLAYER_COORDS[1]=6; }break; } for (int i=0;i<8;i++) { CUTSCENE_FLAGS[i]=false; } CUTSCENE_TIMER=0; } void updateGame(){ frameCount++; if (CURRENT_CUTSCENE!=cutscene::NONE) { CUTSCENE_TIMER++; } if (fade&&transparency<255) { transparency=std::clamp(transparency+FADE_SPD,0,255); if (transparency==255) { fadeOutCompleted(); } } else if (!fade&&transparency>0) { transparency=std::clamp(transparency-FADE_SPD,0,255); if (transparency==0) { fadeInCompleted(); } } if (messageBoxVisible) { if (frameCount%MESSAGE_SCROLL_WAIT_SPD==0) { if (messageBoxCursorskip_frames==0) { anim->frame=(anim->frame+1)%anim->frames.size(); } } if (playerCanMove()) { bool changed=false; if (GetKey(D).bHeld||GetKey(RIGHT).bHeld||GetKey(NP6).bHeld) { PLAYER_COORDS[0]=std::clamp(PLAYER_COORDS[0]+MOVE_SPD,0.1,(double)MAP_WIDTH); //ConsoleClear(); //cout<<"("<playerOwnCount+=amountGained; std::cout<<"Increased HAILSTORM power inventory count by "<playerOwnCount+=amountGained; std::cout<<"Increased HURRICANE power inventory count by "<playerOwnCount+=amountGained; std::cout<<"Increased METEORSHOWER power inventory count by "<playerOwnCount+=amountGained; std::cout<<"Increased METEORSTORM power inventory count by "<playerOwnCount+=amountGained; std::cout<<"Increased SNOWSTORM power inventory count by "<name.compare("Snack")==0||WEATHER_POWERS[i]->name.compare("Meal")==0) { WEATHER_POWERS[i]->playerOwnCount=foodCount; } } availablePowers.erase(availablePowers.begin(),availablePowers.end()); IN_BATTLE_ENCOUNTER=true; CURRENT_ENCOUNTER=enc; CURRENT_ENCOUNTER_IND=i; BATTLE_ENTRY_TIMER=0; BATTLE_STATE=battle::WAITING_FOR_CAMERA; for (int i=0;iplayerOwnCount>0) { availablePowers.push_back(WEATHER_POWERS[i]); } } BATTLE_CARD_SELECTION_IND=0; BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND]; PLAYER_SELECTED_TARGET=-1; } } } for (int i=0;iframe>60) { BATTLE_DISPLAY_NUMBERS.erase(BATTLE_DISPLAY_NUMBERS.begin()+i--); delete numb; } else { numb->y-=0.01; numb->alpha-=4; } } if (IN_BATTLE_ENCOUNTER) { BATTLE_ENTRY_TIMER++; switch (BATTLE_STATE) { case battle::WAITING_FOR_CAMERA: { if (BATTLE_ENTRY_TIMER>45) { int TARGET_COORDS_X=CURRENT_ENCOUNTER.x+WIDTH/32/2; int TARGET_COORDS_Y=CURRENT_ENCOUNTER.y+HEIGHT/32/2; if (PLAYER_COORDS[0]==TARGET_COORDS_X&&PLAYER_COORDS[1]==TARGET_COORDS_Y) { BATTLE_STATE = battle::PLAYER_SELECTION; EFFECT_TIMER = 0; } else if (PLAYER_COORDS[0]!=TARGET_COORDS_X) { if (PLAYER_COORDS[0]TARGET_COORDS_X) { PLAYER_COORDS[0]=TARGET_COORDS_X; } } else { PLAYER_COORDS[0]-=BATTLE_CAMERA_SCROLL_SPD; if (PLAYER_COORDS[0]TARGET_COORDS_Y) { PLAYER_COORDS[1]=TARGET_COORDS_Y; } } else { PLAYER_COORDS[1]-=BATTLE_CAMERA_SCROLL_SPD; if (PLAYER_COORDS[1]x,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y); } } else { if (CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove->damage<0) { applyPixelEffect(CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove,CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->x,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->y); } else { applyPixelEffect(CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove,PLAYER_COORDS[0],PLAYER_COORDS[1]); } } } EFFECT_TIMER++; WEATHER_POWER*ref; if (BATTLE_CURRENT_TURN_ENTITY==-1) { ref=BATTLE_CARD_SELECTION; } else { ref=CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove; } PIXEL_EFFECT_TRANSPARENCY=(0.5*cos(((M_PI/(30.0*(ref->effectTime/120.0)))/2)*EFFECT_TIMER-M_PI)+0.5); if (EFFECT_TIMER==30&&ref->name.compare("Seed Storm")==0) { if (BATTLE_CURRENT_TURN_ENTITY==-1) { effectRadius({PLAYER_COORDS[0],PLAYER_COORDS[1]},ref,true); } else { effectRadius({CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->y+CURRENT_ENCOUNTER.y},ref,false); } } else if (EFFECT_TIMER==ref->effectTime-10){ if (BATTLE_CURRENT_TURN_ENTITY==-1) { if (FOOD_REGEN_TURNS>0) { FOOD_REGEN_TURNS--; PLAYER_HP=std::clamp(PLAYER_HP+(int)(PLAYER_MAXHP*0.33),0,PLAYER_MAXHP); DisplayNumber*numb = new DisplayNumber((int)(-PLAYER_MAXHP*0.33),PLAYER_COORDS[0],PLAYER_COORDS[1],frameCount); BATTLE_DISPLAY_NUMBERS.push_back(numb); } if (PLAYER_SELECTED_TARGET==-2) { effectRadius({PLAYER_COORDS[0],PLAYER_COORDS[1]},ref,true); } else { effectRadius({CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y+CURRENT_ENCOUNTER.y},ref,true); } } else { effectRadius({PLAYER_COORDS[0],PLAYER_COORDS[1]},ref,false); } } for (int i=0;ipos+=pixels[i]->spd; if (pixels[i]->pos.xpos.x=PIXEL_POS.x+PIXEL_SIZE.x; } if (pixels[i]->pos.x>PIXEL_POS.x+PIXEL_SIZE.x) { pixels[i]->pos.x=PIXEL_POS.x; } if (pixels[i]->pos.ypos.y=PIXEL_POS.y+PIXEL_SIZE.y; } if (pixels[i]->pos.y>PIXEL_POS.y+PIXEL_SIZE.y) { pixels[i]->pos.y=PIXEL_POS.y; } pixels[i]->a=pixels[i]->o_a*PIXEL_EFFECT_TRANSPARENCY; } if (EFFECT_TIMER>ref->effectTime) { BATTLE_STATE=battle::DAMAGE_RESOLUTION; EFFECT_TIMER=0; } }break; case battle::DAMAGE_RESOLUTION:{ EFFECT_TIMER++; if (EFFECT_TIMER>60) { std::cout<<"In here: "<hp>0) { allDead=false; break; } } if (allDead) { IN_BATTLE_ENCOUNTER=false; ENCOUNTERS.erase(ENCOUNTERS.begin()+CURRENT_ENCOUNTER_IND); BATTLE_CARD_SELECTION_IND=0; PLAYER_SELECTED_TARGET=-1; BATTLE_STATE=battle::NONE; performCropUpdate(8); if (FOOD_REGEN_TURNS>0) { FOOD_REGEN_TURNS=0; foodCount++; } } else { BATTLE_STATE=battle::PLAYER_SELECTION; PLAYER_SELECTED_TARGET=-1; } } else { BATTLE_CURRENT_TURN_ENTITY=turnOrder.front(); turnOrder.pop(); if (BATTLE_CURRENT_TURN_ENTITY==-1) { if (PLAYER_HP<=0) { GAME_STATE=GAME_OVER; break; } } else { if (CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->hp<=0) { break; } } BATTLE_STATE=battle::WAIT_TURN_ANIMATION; PIXEL_EFFECT_TRANSPARENCY=0; EFFECT_TIMER=0; } } }break; } } switch (CURRENT_CUTSCENE) { case cutscene::CUTSCENE_4:{ if (!messageBoxVisible) { if (!CUTSCENE_FLAGS[0]) { CUTSCENE_FLAGS[0]=true; DisplayMessageBox(0); } else if (!CUTSCENE_FLAGS[1]) { CUTSCENE_FLAGS[1]=true; DisplayMessageBox(1); } else if (!CUTSCENE_FLAGS[2]) { CUTSCENE_FLAGS[2]=true; DisplayMessageBox(2); foodMeterVisible=true; } else if (!CUTSCENE_FLAGS[3]) { CUTSCENE_FLAGS[3]=true; DisplayMessageBox(3); oxygenMeterVisible=true; } } }break; } switch (GAME_STATE) { case CUTSCENE_1: case CUTSCENE_3:{ std::string refText; switch (GAME_STATE) { case CUTSCENE_1:{ refText=STORY_TEXT1; }break; case CUTSCENE_3:{ refText=STORY_TEXT2; }break; } if (GAME_STATE==CUTSCENE_3&&frameCount%4!=0) {break;} if (textIndWIDTH-32) { int tempIndex=textInd; while (CUTSCENE_CONSOLE_TEXT[--tempIndex]!=' ') { CUTSCENE_CONSOLE_TEXT.erase(tempIndex); cursorX--; } CUTSCENE_CONSOLE_TEXT.erase(tempIndex++); CUTSCENE_CONSOLE_TEXT+='\n'; cursorX=0; while (tempIndex120) { fadeOut(); } } if (PLAYER_COORDS[0]>38+(128/2/32)) { PLAYER_COORDS[0]=38+(128/2/32); CUTSCENE_FLAGS[0]=true; CUTSCENE_TIMER=0; } }break; case WAITING_FOR_CUTSCENE_3:{ if (transparency>200) { GAME_STATE=CUTSCENE_3; } }break; } } void advanceMessageBox() { char c = messageBoxRefText[messageBoxCursor++]; printf("%c",c); if (c=='\n') { if (!firstNewline) { firstNewline=true; return; } else if (!secondNewline) { secondNewline=true; return; } } if (firstNewline&&!secondNewline) { messageBoxSpeaker+=c; return; } messageBoxText+=c; if (GetTextSizeProp(messageBoxText).x>WIDTH-16) { int tempIndex=messageBoxCursor; while (messageBoxText[--tempIndex]!=' ') { messageBoxText.erase(tempIndex); } messageBoxText.erase(tempIndex++); messageBoxText+='\n'; while (tempIndex=0) { DrawWrappedText({5,5},"Target "+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->name+" "+(char)('A'+PLAYER_SELECTED_TARGET)+" with "+BATTLE_CARD_SELECTION->name,WIDTH-8,BLACK,{2,2}); DrawWrappedText({4,4},"Target "+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->name+" "+(char)('A'+PLAYER_SELECTED_TARGET)+" with "+BATTLE_CARD_SELECTION->name,WIDTH-8,WHITE,{2,2}); DrawStringDecal({WIDTH-GetTextSize(" Back").x-1,HEIGHT-GetTextSize(" Back").y-1}," Back",BLACK,{1,1}); DrawStringDecal({WIDTH-GetTextSize(" Back").x-2,HEIGHT-GetTextSize(" Back").y-2}," Back",GREEN,{1,1}); } }break; case battle::WAIT_TURN_ANIMATION:{ if (BATTLE_CURRENT_TURN_ENTITY==-1) { DrawWrappedText({4,4},"Player uses "+BATTLE_CARD_SELECTION->name,WIDTH-8,WHITE,{2,2}); } else { DrawWrappedText({4,4},CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->name+" "+(char)('A'+BATTLE_CURRENT_TURN_ENTITY)+" with "+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove->name,WIDTH-8,WHITE,{2,2}); } SetDrawTarget(nullptr); for (int i=0;isize.x==1&&pixels[i]->size.y==1) { Draw(pixels[i]->pos,{pixels[i]->r,pixels[i]->g,pixels[i]->b,pixels[i]->a}); } else { FillRectDecal(pixels[i]->pos,pixels[i]->size,{pixels[i]->r,pixels[i]->g,pixels[i]->b,pixels[i]->a}); } } SetDrawTarget(1); FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(ORIGINAL_FOREGROUND_EFFECT_COLOR.r,ORIGINAL_FOREGROUND_EFFECT_COLOR.g,ORIGINAL_FOREGROUND_EFFECT_COLOR.b,ORIGINAL_FOREGROUND_EFFECT_COLOR.a*PIXEL_EFFECT_TRANSPARENCY)); }break; } if (IN_BATTLE_ENCOUNTER||(!CUTSCENE_ACTIVE&&PLAYER_HP!=PLAYER_MAXHP)) { DrawStringDecal({4+1,HEIGHT-10-GetTextSize("HP:").y+1},"HP: "+std::to_string(PLAYER_HP),BLACK); DrawStringDecal({4,HEIGHT-10-GetTextSize("HP:").y},"HP: "+std::to_string(PLAYER_HP)); DrawHealthbar({2,HEIGHT-10},WIDTH/2,(float)PLAYER_HP/PLAYER_MAXHP,BLACK); for (auto&numb:BATTLE_DISPLAY_NUMBERS) { std::string display=((numb->number>0)?"-"+std::to_string(numb->number):"+"+std::to_string(numb->number*-1)); for (int x=-1;x<=1;x++) { for (int y=-1;y<=1;y++) { if (x!=0&&y!=0) { DrawStringDecal({((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x/2+x-8,((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-12-GetTextSize(display).y/2+y},display,(numb->number>0)?Pixel(255,0,0,numb->alpha):Pixel(0,255,0,numb->alpha),{2,2}); } } } DrawStringDecal({((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x/2-8,((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-12-GetTextSize(display).y/2},display,Pixel(255,255,255,numb->alpha),{2,2}); //std::cout<x<<"/"<y<<" "<<(((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x/2)<<","<<(((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-8-GetTextSize(display).y/2)<<": ("<alpha<<")"<=0&&(int)(xOffset+x)=0&&(int)(yOffset+y)spr,{obj.anim->getCurrentFrame().x,obj.anim->getCurrentFrame().y},{obj.anim->width,obj.anim->height},{(float)sin(frameCount*2/60.0),1},Pixel((float)sin(frameCount*4/60.0)*55+200,(float)sin(frameCount*4/60.0)*55+200,(float)sin(frameCount*4/60.0+M_PI)+65*125,255)); } else if (obj.hasAnim) { DrawPartialDecal({(obj.x-PLAYER_COORDS[0])*32+WIDTH/2+(obj.anim->flipped?32:0),(obj.y-PLAYER_COORDS[1])*32+HEIGHT/2},obj.anim->spr,{obj.anim->getCurrentFrame().x,obj.anim->getCurrentFrame().y},{obj.anim->width,obj.anim->height},{obj.anim->flipped?-1:1,1}); } else { DrawDecal({(obj.x-PLAYER_COORDS[0])*32+WIDTH/2,(obj.y-PLAYER_COORDS[1])*32+HEIGHT/2},obj.spr); } } } else if (obj.name.compare("EXIT")==0) { GradientFillRectDecal({(obj.x-PLAYER_COORDS[0])*32+WIDTH/2,(obj.y-PLAYER_COORDS[1])*32+HEIGHT/2},{32,32},Pixel(0,0,0,0),WHITE,WHITE,Pixel(0,0,0,0)); } } for (auto&enc:ENCOUNTERS) { int targetX=-1,targetY=-1; for (auto&ent:enc.entities) { if (BATTLE_STATE==battle::PLAYER_TARGET_SELECTION&&PLAYER_SELECTED_TARGET>=0&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x==ent->x&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y==ent->y) { DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},TARGETING_CIRCLE,{ent->spr->sprite->width/32,ent->spr->sprite->height/32},{255,210,0,255}); DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},ent->spr,{1,1},{(0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175,(0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175,(0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175,255}); targetX=ent->x;targetY=ent->y; } else { if (ent->hp>0) { DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},ent->spr); } } if (ent->hp>0) { DrawHealthbar({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2+ent->spr->sprite->height+2},ent->spr->sprite->width,(float)ent->hp/ent->maxhp,BLACK); } } if (targetX!=-1&&targetY!=-1) { DrawDecal({(enc.x+targetX-PLAYER_COORDS[0])*32+WIDTH/2-BATTLE_CARD_SELECTION->range+16,(enc.y+targetY-PLAYER_COORDS[1])*32+HEIGHT/2-BATTLE_CARD_SELECTION->range+16},TARGETING_RANGE_CIRCLE,{BATTLE_CARD_SELECTION->range*2/32.0,BATTLE_CARD_SELECTION->range*2/32.0},{255,60,0,(0.5*(float)sin(frameCount*4/60.0)+0.5)*100}); } } } void DrawHealthbar(vf2d pos,float width,float pct,Pixel col) { GradientFillRectDecal(pos,{width*pct,8},RED,RED,Pixel((1/pct)*255,255*pct,0,255),Pixel((1/pct)*255,255*pct,0,255)); DrawDecal(pos,HEALTHBAR_DECAL,{width/32,1},col); } int getPlantId(int x, int y) { return ((int)x-8)%4+((int)y-2)*4; } int getPlantStatus(int x,int y) { return plantState>>getPlantId(x,y)*2&0b11; } void setPlantStatus(int x,int y,char state) { int numb=0b11111111111111111111111111111111; int numb2=0; numb-=3<>data; if (MAP_WIDTH==-1) { std::stringstream stream(data); stream>>MAP_WIDTH; } else if (MAP_HEIGHT==-1) { std::stringstream stream(data); stream>>MAP_HEIGHT; } else if (y>obj.x; std::stringstream split2(data.substr(data.find(';')+1,data.find(';',data.find(";")+1)-(data.find(';')+1))); split2>>obj.y; std::string split3 = data.substr(data.find(';',data.find(";")+1)+1,data.length()-(data.find(';',data.find(";")+1)+1)); if (split3.compare("NULL")!=0) { obj.spr=BASE_OBJECTS[split3]->spr; if (BASE_OBJECTS[split3]->hasanim) { obj.hasAnim=true; obj.anim=BASE_OBJECTS[split3]->anim; } } else { obj.spr=NULL; } obj.name=split3; printf("Loaded object %s: (%f,%f)\n",split3.c_str(),obj.x,obj.y); OBJECTS.push_back(obj); } } } printf("Loaded %dx%d map:\n",MAP_WIDTH,MAP_HEIGHT); for (int y=0;y=obj.x&&PLAYER_COORDS[0]<=obj.x+obj.anim->width/32.0&& PLAYER_COORDS[1]>=obj.y&&PLAYER_COORDS[1]<=obj.y+obj.anim->height/32.0; } else { if (obj.spr==NULL) { return PLAYER_COORDS[0]>=obj.x&&PLAYER_COORDS[0]<=obj.x+1&& PLAYER_COORDS[1]>=obj.y&&PLAYER_COORDS[1]<=obj.y+1; } else { return PLAYER_COORDS[0]>=obj.x&&PLAYER_COORDS[0]<=obj.x+obj.spr->sprite->width/32.0&& PLAYER_COORDS[1]>=obj.y&&PLAYER_COORDS[1]<=obj.y+obj.spr->sprite->height/32.0; } } } bool collidesWithPlayer(Encounter obj) { return PLAYER_COORDS[0]>=obj.x&&PLAYER_COORDS[0]<=obj.x+WIDTH/32&& PLAYER_COORDS[1]>=obj.y&&PLAYER_COORDS[1]<=obj.y+HEIGHT/32; } void DrawWrappedText(vf2d pos,std::string text,int targetWidth,Pixel col,vf2d scale) { std::string wrappedText; int marker=0; while (markertargetWidth) { int tempMarker=marker; while (wrappedText[tempMarker]!=' ') { wrappedText.erase(tempMarker--); } wrappedText.erase(tempMarker++); wrappedText+='\n'; while (tempMarkertargetWidth) { int tempMarker=marker; while (wrappedText[tempMarker]!=' ') { wrappedText.erase(tempMarker--); } wrappedText.erase(tempMarker++); wrappedText+='\n'; while (tempMarkerplayerOwnCount==0?0.4:1; GradientFillRectDecal({(WIDTH/6)*scale.x+offset.x,(HEIGHT/6)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor); GradientFillRectDecal({(WIDTH/6*3+1)*scale.x+offset.x,(HEIGHT/6)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor); GradientFillRectDecal({(WIDTH/6)*scale.x+offset.x,(HEIGHT/6*3)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0)); GradientFillRectDecal({(WIDTH/6*3+1)*scale.x+offset.x,(HEIGHT/6*3)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor); DrawPartialDecal({(WIDTH/2-data->anim->width/2*3)*scale.x+offset.x,(HEIGHT/6+16-data->anim->height/2)*scale.y+offset.y},data->anim->spr,data->anim->getCurrentFrame(),{data->anim->width,data->anim->height},{3*scale.x,3*scale.y},WHITE*darknessFactor*dimColor); for (int x=-1;x<=1;x++) { for (int y=-1;y<=1;y++) { if (x!=0&&y!=0) { DrawStringPropDecal({(WIDTH/6+4+x)*scale.x+offset.x,(HEIGHT/2+8+y)*scale.y+offset.y},data->name,BLACK,{2*scale.x,2*scale.y}); } } } DrawStringPropDecal({(WIDTH/6+4)*scale.x+offset.x,(HEIGHT/2+8)*scale.y+offset.y},data->name,data->textcol*darknessFactor*dimColor,{2*scale.x,2*scale.y}); DrawWrappedPropText({(WIDTH/6+4+1)*scale.x+offset.x,(HEIGHT/2+24+1)*scale.y+offset.y},data->description,(WIDTH/3*2-8)*scale.x,BLACK,{scale.x,scale.y}); DrawWrappedPropText({(WIDTH/6+4)*scale.x+offset.x,(HEIGHT/2+24)*scale.y+offset.y},data->description,(WIDTH/3*2-8)*scale.x,Pixel(227, 245, 255,255)*darknessFactor*dimColor,{scale.x,scale.y}); for (int x=-1;x<=1;x++) { for (int y=-1;y<=1;y++) { if (x!=0&&y!=0) { DrawStringPropDecal({(WIDTH/6+4+WIDTH/3*2-8-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").x*1.5+x)*scale.x+offset.x,(HEIGHT/6*3+HEIGHT/6*2-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").y*1.5-4+y)*scale.y+offset.y},std::to_string(data->playerOwnCount)+" uses remaining.",olc::BLACK,{1.5*scale.x,1.5*scale.y}); } } } DrawStringPropDecal({(WIDTH/6+4+WIDTH/3*2-8-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").x*1.5)*scale.x+offset.x,(HEIGHT/6*3+HEIGHT/6*2-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").y*1.5-4)*scale.y+offset.y},std::to_string(data->playerOwnCount)+" uses remaining.",(data->playerOwnCount==0)?olc::RED:olc::WHITE*darknessFactor,{1.5*scale.x,1.5*scale.y}); } void effectRadius(vi2d coords,WEATHER_POWER*power,bool playerForce) { int finalDamage=power->damage+rand()%power->damageRoll*sign(power->damage); std::cout<<"Emitting effect radius for "<name<<" for PlayerForce:"<damage==-1002) { //Instead heal for their max health. PLAYER_MAXHP+=5; finalDamage=-PLAYER_MAXHP; foodCount--; } else if (power->damage==-1001) { //Instead heal for their max health. FOOD_REGEN_TURNS=4; finalDamage=-PLAYER_MAXHP*0.33; foodCount--; } PLAYER_HP=std::clamp(PLAYER_HP-finalDamage,0,PLAYER_MAXHP); DisplayNumber*numb = new DisplayNumber(finalDamage,PLAYER_COORDS[0],PLAYER_COORDS[1],frameCount); BATTLE_DISPLAY_NUMBERS.push_back(numb); } else { for (int i=0;idamage+rand()%power->damageRoll*sign(power->damage); Entity*ent=CURRENT_ENCOUNTER.entities[i]; if (ent->hp>0&&distancetoCoords({(ent->x+CURRENT_ENCOUNTER.x)*32,(ent->y+CURRENT_ENCOUNTER.y)*32},coords*32)<=power->range) { ent->hp=std::clamp(ent->hp-finalDamage,0,ent->maxhp); DisplayNumber*numb = new DisplayNumber(finalDamage,ent->x+CURRENT_ENCOUNTER.x,ent->y+CURRENT_ENCOUNTER.y,frameCount); BATTLE_DISPLAY_NUMBERS.push_back(numb); ent->damageFrame=frameCount; } } } } else { //Damaging effect. if (playerForce) { for (int i=0;idamage+rand()%power->damageRoll*sign(power->damage); Entity*ent=CURRENT_ENCOUNTER.entities[i]; std::cout<<"Distance was "<x+CURRENT_ENCOUNTER.x)*32,(ent->y+CURRENT_ENCOUNTER.y)*32},coords*32)<<"\n"; if (ent->hp>0&&distancetoCoords({(ent->x+CURRENT_ENCOUNTER.x)*32,(ent->y+CURRENT_ENCOUNTER.y)*32},coords*32)<=power->range) { ent->hp=std::clamp(ent->hp-finalDamage,0,ent->maxhp); DisplayNumber*numb = new DisplayNumber(finalDamage,ent->x+CURRENT_ENCOUNTER.x,ent->y+CURRENT_ENCOUNTER.y,frameCount); BATTLE_DISPLAY_NUMBERS.push_back(numb); ent->damageFrame=frameCount; } } } else { PLAYER_HP=std::clamp(PLAYER_HP-finalDamage,0,PLAYER_MAXHP); DisplayNumber*numb = new DisplayNumber(finalDamage,PLAYER_COORDS[0],PLAYER_COORDS[1],frameCount); BATTLE_DISPLAY_NUMBERS.push_back(numb); } } } double distancetoCoords(vf2d c1,vf2d c2) { return sqrt(pow(c1.x-c2.x,2)+pow(c2.y-c1.y,2)); } int sign(int x) { return (x > 0) - (x < 0); } int rand() { srand(time(NULL)+RAND_CALLS++); return std::rand(); } void performCropUpdate(int chanceToRegrow) { for (int x=0;x<4;x++) { for (int y=0;y<4;y++) { if (rand()%chanceToRegrow==0) { setPlantStatus(x,y,std::clamp(getPlantStatus(x,y)+1,0,2)); } } } } void setupBattleTurns() { //Remove the card from inventory. BATTLE_CARD_SELECTION->playerOwnCount--; BATTLE_STATE=battle::ENEMY_SELECTION; for (int i=0;ihp>0) { CURRENT_ENCOUNTER.entities[i]->selectedMove=CURRENT_ENCOUNTER.entities[i]->moveSet[rand()%CURRENT_ENCOUNTER.entities[i]->moveSet.size()]; CURRENT_ENCOUNTER.entities[i]->turnComplete=false; if (CURRENT_ENCOUNTER.entities[i]->selectedMove->name.compare("Seed Storm")==0) { std::cout<<" Entity "<name.compare("Seed Storm")==0) { turnOrder.push(-1); PLAYER_TURN_COMPLETE=true; } for (int i=0;ihp>0&&!CURRENT_ENCOUNTER.entities[i]->turnComplete&& CURRENT_ENCOUNTER.entities[i]->selectedMove->name.compare("Seed Storm")==0) { turnOrder.push(i); CURRENT_ENCOUNTER.entities[i]->turnComplete=true; std::cout<<" Entity "<name.compare("Meal")==0||BATTLE_CARD_SELECTION->name.compare("Snack")==0)) { turnOrder.push(-1); PLAYER_TURN_COMPLETE=true; } //Otherwise, every enemy has a chance to go before the player unless they are slowed, then they always go after. for (int i=0;iname.compare("Meal")==0||BATTLE_CARD_SELECTION->name.compare("Snack")==0)) { turnOrder.push(-1); PLAYER_TURN_COMPLETE=true; } if (ent->hp>0&&!ent->turnComplete&& !ent->slowed&&rand()%2==0) { turnOrder.push(i); ent->turnComplete=true; } } if (!PLAYER_TURN_COMPLETE) { turnOrder.push(-1); PLAYER_TURN_COMPLETE=true; } //Finally, any enemies that haven't gone will now go. for (int i=0;ihp>0&&!ent->turnComplete) { turnOrder.push(i); ent->turnComplete=true; } } BATTLE_STATE=battle::PERFORM_TURN; BATTLE_CURRENT_TURN_ENTITY=turnOrder.front(); turnOrder.pop(); BATTLE_STATE=battle::WAIT_TURN_ANIMATION; EFFECT_TIMER=0; } void displayPowerInfo(WEATHER_POWER*POWER){ PlayCutscene(cutscene::NODE_COLLECT_CUTSCENE); CUTSCENE_DISPLAYED_CARD=POWER; } void applyPixelEffect(WEATHER_POWER*power,int x,int y) { SetDrawTarget(nullptr); Clear(BLANK); SetDrawTarget(1); applyPixelEffect( {(x-PLAYER_COORDS[0])*32+WIDTH/2-16-power->effect->effectSize.x/2,(y-PLAYER_COORDS[1])*32+HEIGHT/2-16-power->effect->effectSize.y/2}, power->effect->effectSize, power->effect->pos_low, power->effect->pos_high, power->effect->size_low, power->effect->size_high, power->effect->spd_low, power->effect->spd_high, power->effect->col_low, power->effect->col_high, power->effect->amt, power->effect->foregroundColor ); } void applyPixelEffect(vf2d effectPos,vf2d effectSize,vf2d pos_low,vf2d pos_high,vf2d size_low,vf2d size_high,vf2d spd_low,vf2d spd_high,olc::Pixel col_low,olc::Pixel col_high,int amt,olc::Pixel foregroundColor) { for (int i=0;ipos={range(pos_low.x,pos_high.x),range(pos_low.y,pos_high.y)}; pixels[i]->size={range(size_low.x,size_high.x),range(size_low.y,size_high.y)}; std::cout<size.x)<<","<size.y)<<"\n"; pixels[i]->spd={range(spd_low.x,spd_high.x),range(spd_low.y,spd_high.y)}; pixels[i]->r=range(col_low.r,col_high.r); pixels[i]->g=range(col_low.g,col_high.g); pixels[i]->b=range(col_low.b,col_high.b); pixels[i]->a=range(col_low.a,col_high.a); pixels[i]->o_a=range(col_low.a,col_high.a); } ORIGINAL_FOREGROUND_EFFECT_COLOR=FOREGROUND_EFFECT_COLOR=foregroundColor; PIXEL_POS=effectPos; PIXEL_SIZE=effectSize; PIXEL_LIMIT=amt; } void clearPixelEffect() { PIXEL_LIMIT=0; } //Returns a number between 0.0 and X. float random(float X) { return (float)rand()/RAND_MAX * X; } float range(float val1,float val2) { return random(val2-val1)+val1; } //Basically, click on a spot in the text editor and this function translates it into the proper teleport coords so you don't have to. void TeleportToMapFileCoords(int ln,int col) { PLAYER_COORDS[0]=col-1+0.5; PLAYER_COORDS[1]=ln-3+0.5; } }; int main() { SeasonsOfLoneliness demo; if (demo.Construct(256, 224, 4, 4)) demo.Start(); return 0; }