diff --git a/SeasonsOfLoneliness.cpp b/SeasonsOfLoneliness.cpp index 21fd4b4..392883c 100644 --- a/SeasonsOfLoneliness.cpp +++ b/SeasonsOfLoneliness.cpp @@ -228,6 +228,8 @@ public: Animation POWER_METEOR_SHOWER_ANIMATION; Animation POWER_METEOR_STORM_ANIMATION; Animation POWER_SNOWSTORM_ANIMATION; + Animation CONSUME_SNACK_ANIMATION; + Animation CONSUME_MEAL_ANIMATION; 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); 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); 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); @@ -236,16 +238,20 @@ public: 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); 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); 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); + 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); + 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); bool IN_BATTLE_ENCOUNTER = false; int BATTLE_ENTRY_TIMER = 0; int EFFECT_TIMER = 0; - #define WEATHER_POWER_COUNT 5 //Number of powers that are in the game. Update storage array accordingly. + #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,}; + SNOWSTORM, + CONSUME_SNACK, + CONSUME_MEAL}; battle::BATTLESTATE BATTLE_STATE=battle::NONE; std::vector availablePowers; WEATHER_POWER*BATTLE_CARD_SELECTION=HAILSTORM; @@ -258,6 +264,7 @@ public: int RAND_CALLS=0; std::vector BATTLE_DISPLAY_NUMBERS; bool PLAYER_TURN_COMPLETE=false; + int FOOD_REGEN_TURNS=0; std::vectorMOVESET_SPIDEY; @@ -265,7 +272,8 @@ public: 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; + *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; @@ -290,6 +298,8 @@ public: POWER_METEOR_SHOWER_DECAL=new Decal(new Sprite("assets/meteor_shower_icon.png")); POWER_METEOR_STORM_DECAL=new Decal(new Sprite("assets/meteor_storm.png")); POWER_SNOWSTORM_DECAL=new Decal(new Sprite("assets/snowstorm_icon.png")); + CONSUME_SNACK_DECAL=new Decal(new Sprite("assets/snack.png")); + CONSUME_MEAL_DECAL=new Decal(new Sprite("assets/meal.png")); SPIDEY_DECAL=new Decal(new Sprite("assets/spidey.png")); TARGETING_CIRCLE=new Decal(new Sprite("assets/targetCircle.png")); TARGETING_RANGE_CIRCLE=new Decal(new Sprite("assets/targetRange.png")); @@ -360,6 +370,16 @@ public: POWER_SNOWSTORM_ANIMATION.frames.push_back({32,0}); POWER_SNOWSTORM_ANIMATION.frames.push_back({64,0}); POWER_SNOWSTORM_ANIMATION.skip_frames=nodeAnimationSkipFrames; + CONSUME_SNACK_ANIMATION.spr=CONSUME_SNACK_DECAL; + CONSUME_SNACK_ANIMATION.frames.push_back({0,0}); + CONSUME_SNACK_ANIMATION.frames.push_back({32,0}); + CONSUME_SNACK_ANIMATION.frames.push_back({64,0}); + CONSUME_SNACK_ANIMATION.skip_frames=nodeAnimationSkipFrames; + CONSUME_MEAL_ANIMATION.spr=CONSUME_MEAL_DECAL; + CONSUME_MEAL_ANIMATION.frames.push_back({0,0}); + CONSUME_MEAL_ANIMATION.frames.push_back({32,0}); + CONSUME_MEAL_ANIMATION.frames.push_back({64,0}); + CONSUME_MEAL_ANIMATION.skip_frames=nodeAnimationSkipFrames; HAILSTORM->playerOwnCount=3; HURRICANE->playerOwnCount=1; @@ -425,67 +445,24 @@ public: } switch (BATTLE_STATE) { case battle::PLAYER_SELECTION:{ - BATTLE_STATE=battle::PLAYER_TARGET_SELECTION; - 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; + if (WEATHER_POWERS[BATTLE_CARD_SELECTION_IND]->playerOwnCount>0) { + BATTLE_STATE=battle::PLAYER_TARGET_SELECTION; + if (WEATHER_POWERS[BATTLE_CARD_SELECTION_IND]->name.compare("MEAL")==0||WEATHER_POWERS[BATTLE_CARD_SELECTION_IND]->name.compare("SNACK")==0) { + setupBattleTurns(); + } else + 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; + } } } } }break; case battle::PLAYER_TARGET_SELECTION:{ - //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; - } - } - PLAYER_TURN_COMPLETE=false; - BATTLE_STATE=battle::MOVE_RESOLUTION; - //Seed Storm has prio. - if (!PLAYER_TURN_COMPLETE&&BATTLE_CARD_SELECTION->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; - } - } - //Otherwise, every enemy has a chance to go before the player unless they are slowed, then they always go after. - for (int i=0;ihp>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.top(); - turnOrder.pop(); - BATTLE_STATE=battle::WAIT_TURN_ANIMATION; - EFFECT_TIMER=0; + setupBattleTurns(); }break; } } @@ -742,6 +719,11 @@ public: for (int i=0;iname.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; @@ -828,7 +810,17 @@ public: } else if (EFFECT_TIMER==ref->effectTime-10){ if (BATTLE_CURRENT_TURN_ENTITY==-1) { - effectRadius({CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y+CURRENT_ENCOUNTER.y},ref,true); + 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); } @@ -1351,12 +1343,14 @@ public: } void DrawCard(WEATHER_POWER*data,vf2d offset={0,0},vf2d scale={1,1},float darknessFactor=1.0) { - 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,data->bgcol*darknessFactor,Pixel(72, 160, 212,0),data->bgcol*darknessFactor); - 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,Pixel(72, 160, 212,0),data->bgcol*darknessFactor,data->bgcol*darknessFactor); - 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,data->bgcol*darknessFactor,data->bgcol*darknessFactor,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,data->bgcol*darknessFactor,data->bgcol*darknessFactor); + float dimColor=data->playerOwnCount==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); + 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) { @@ -1364,9 +1358,9 @@ public: } } } - DrawStringPropDecal({(WIDTH/6+4)*scale.x+offset.x,(HEIGHT/2+8)*scale.y+offset.y},data->name,data->textcol*darknessFactor,{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,{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) { @@ -1374,7 +1368,7 @@ public: } } } - 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.",olc::WHITE*darknessFactor,{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.",olc::WHITE*darknessFactor*dimColor,{1.5*scale.x,1.5*scale.y}); } @@ -1384,6 +1378,18 @@ public: if (finalDamage<0) { //This is a healing effect. if (playerForce) { + if (power->damage==-1002) { + //Instead heal for their max health. + PLAYER_MAXHP+=5; + int finalDamage=-PLAYER_MAXHP; + foodCount--; + } else + if (power->damage==-1001) { + //Instead heal for their max health. + FOOD_REGEN_TURNS=4; + int 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); @@ -1433,6 +1439,58 @@ public: srand(time(NULL)+RAND_CALLS++); return std::rand(); } + + 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; + } + } + PLAYER_TURN_COMPLETE=false; + BATTLE_STATE=battle::MOVE_RESOLUTION; + //Seed Storm has prio. + if (!PLAYER_TURN_COMPLETE&&BATTLE_CARD_SELECTION->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; + } + } + //Otherwise, every enemy has a chance to go before the player unless they are slowed, then they always go after. + for (int i=0;ihp>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.top(); + turnOrder.pop(); + BATTLE_STATE=battle::WAIT_TURN_ANIMATION; + EFFECT_TIMER=0; + } }; diff --git a/Seasons_of_Loneliness b/Seasons_of_Loneliness index f7f8523..27da788 100755 Binary files a/Seasons_of_Loneliness and b/Seasons_of_Loneliness differ diff --git a/assets/meal.png b/assets/meal.png new file mode 100644 index 0000000..d64888e Binary files /dev/null and b/assets/meal.png differ diff --git a/assets/snack.png b/assets/snack.png new file mode 100644 index 0000000..c7fa0c3 Binary files /dev/null and b/assets/snack.png differ