diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index f65a3474..c758b010 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -950,99 +950,17 @@ void AiL::ProximityKnockback(const vf2d pos,const float radius,const float knock } void AiL::PopulateRenderLists(){ - monstersBeforeLower.clear(); - monstersAfterLower.clear(); - monstersBeforeUpper.clear(); - monstersAfterUpper.clear(); - bulletsLower.clear(); - bulletsUpper.clear(); - backgroundEffectsLower.clear(); - backgroundEffectsUpper.clear(); - foregroundEffectsLower.clear(); - foregroundEffectsUpper.clear(); - endZones.clear(); - upperEndZones.clear(); - dropsBeforeLower.clear(); - dropsAfterLower.clear(); - dropsBeforeUpper.clear(); - dropsAfterUpper.clear(); - tilesWithCollision.clear(); tilesWithoutCollision.clear(); Player*pl=GetPlayer(); pl->rendered=false; - std::sort(MONSTER_LIST.begin(),MONSTER_LIST.end(),[](std::shared_ptr&m1,std::shared_ptr&m2){return m1->GetPos().yGetPos().y;}); - std::sort(ItemDrop::drops.begin(),ItemDrop::drops.end(),[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y&b1,std::unique_ptr&b2){return b1->pos.ypos.y;}); - std::sort(foregroundEffects.begin(),foregroundEffects.end(),[](std::unique_ptr&e1,std::unique_ptr&e2){return e1->pos.ypos.y;}); - std::sort(backgroundEffects.begin(),backgroundEffects.end(),[](std::unique_ptr&e1,std::unique_ptr&e2){return e1->pos.ypos.y;}); - - for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){ - Monster&m=**it; - if(m.GetPos().yGetPos().y){//This monster renders before the player does (behind the player) - if(m.OnUpperLevel()){ - monstersBeforeUpper.push_back(&m); - }else{ - monstersBeforeLower.push_back(&m); - } - } else {//This monster renders after the player does (in front of the player) - if(m.OnUpperLevel()){ - monstersAfterUpper.push_back(&m); - }else{ - monstersAfterLower.push_back(&m); - } - } - } - for(int i=0;iGetPos().y){//This item drop renders before the player does (behind the player) - if(drop.OnUpperLevel()){ - dropsBeforeUpper.push_back(i); - }else{ - dropsBeforeLower.push_back(i); - } - } else {//This item drop renders after the player does (in front of the player) - if(drop.OnUpperLevel()){ - dropsAfterUpper.push_back(i); - }else{ - dropsAfterLower.push_back(i); - } - } - } - for(auto it=BULLET_LIST.begin();it!=BULLET_LIST.end();++it){ - IBullet*b=(*it).get(); - if(b->OnUpperLevel()){ - bulletsUpper.push_back(b); - }else{ - bulletsLower.push_back(b); - } - } - for(auto it=foregroundEffects.begin();it!=foregroundEffects.end();++it){ - Effect*e=(*it).get(); - if(e->OnUpperLevel()){ - foregroundEffectsUpper.push_back(e); - }else{ - foregroundEffectsLower.push_back(e); - } - } - for(auto it=backgroundEffects.begin();it!=backgroundEffects.end();++it){ - Effect*e=(*it).get(); - if(e->OnUpperLevel()){ - backgroundEffectsUpper.push_back(e); - }else{ - backgroundEffectsLower.push_back(e); - } - } - - for(const ZoneData&zone:GetZones().at("EndZone")){ - if(zone.isUpper){ - upperEndZones.push_back(zone); - }else{ - endZones.push_back(zone); - } - } + std::ranges::sort(MONSTER_LIST,[](std::shared_ptr&m1,std::shared_ptr&m2){return m1->GetPos().yGetPos().y;}); + std::ranges::sort(ItemDrop::drops,[](ItemDrop&id1,ItemDrop&id2){return id1.GetPos().y&b1,std::unique_ptr&b2){return b1->pos.ypos.y;}); + std::ranges::sort(foregroundEffects,[](std::unique_ptr&e1,std::unique_ptr&e2){return e1->pos.ypos.y;}); + std::ranges::sort(backgroundEffects,[](std::unique_ptr&e1,std::unique_ptr&e2){return e1->pos.ypos.y;}); } void AiL::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){ @@ -1107,6 +1025,25 @@ void AiL::RenderWorld(float fElapsedTime){ PopulateRenderLists(); + #pragma region Populate Render Lists + auto monstersBeforeUpper{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr&m){return m->GetPos().yGetPos().y&&m->OnUpperLevel();})}; + auto monstersBeforeLower{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr&m){return m->GetPos().yGetPos().y&&!m->OnUpperLevel();})}; + auto monstersAfterUpper{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr&m){return m->GetPos().y>=pl->GetPos().y&&m->OnUpperLevel();})}; + auto monstersAfterLower{MONSTER_LIST|std::views::filter([&pl](const std::shared_ptr&m){return m->GetPos().y>=pl->GetPos().y&&!m->OnUpperLevel();})}; + auto dropsBeforeUpper{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().yGetPos().y&&drop.OnUpperLevel();})}; + auto dropsBeforeLower{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().yGetPos().y&&!drop.OnUpperLevel();})}; + auto dropsAfterUpper{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y>=pl->GetPos().y&&drop.OnUpperLevel();})}; + auto dropsAfterLower{ItemDrop::drops|std::views::filter([&pl](const ItemDrop&drop){return drop.GetPos().y>=pl->GetPos().y&&!drop.OnUpperLevel();})}; + auto bulletsUpper{BULLET_LIST|std::views::filter([](const std::unique_ptr&bullet){return bullet->OnUpperLevel();})}; + auto bulletsLower{BULLET_LIST|std::views::filter([](const std::unique_ptr&bullet){return !bullet->OnUpperLevel();})}; + auto foregroundEffectsUpper{foregroundEffects|std::views::filter([](const std::unique_ptr&effect){return effect->OnUpperLevel();})}; + auto foregroundEffectsLower{foregroundEffects|std::views::filter([](const std::unique_ptr&effect){return !effect->OnUpperLevel();})}; + auto backgroundEffectsUpper{backgroundEffects|std::views::filter([](const std::unique_ptr&effect){return effect->OnUpperLevel();})}; + auto backgroundEffectsLower{backgroundEffects|std::views::filter([](const std::unique_ptr&effect){return !effect->OnUpperLevel();})}; + auto upperEndZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return zone.isUpper;})}; + auto endZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return !zone.isUpper;})}; + #pragma endregion + auto RenderPlayer=[&](vf2d pos,vf2d scale){ if(player->IsInvisible())return; vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult()); @@ -1458,7 +1395,7 @@ void AiL::RenderWorld(float fElapsedTime){ break; } while(dropsBeforeLowerIt!=dropsBeforeLower.end()){ - const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt]; + const ItemDrop&drop{*dropsBeforeLowerIt}; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); ++dropsAfterLowerIt; @@ -1570,16 +1507,16 @@ void AiL::RenderWorld(float fElapsedTime){ #pragma endregion #pragma region Remaining Rendering while(monstersBeforeLowerIt!=monstersBeforeLower.end()){ - Monster*const m=*monstersBeforeLowerIt; - m->Draw(); + const Monster&m=**monstersBeforeLowerIt; + m.Draw(); ++monstersBeforeLowerIt; } - for(const Effect*const e:backgroundEffectsLower){ + for(std::unique_ptr&e:backgroundEffectsLower){ e->_Draw(); } while(dropsBeforeLowerIt!=dropsBeforeLower.end()){ - const int dropInd=*dropsBeforeLowerIt; - ItemDrop::drops[dropInd].Draw(); + const ItemDrop&drop{*dropsBeforeLowerIt}; + drop.Draw(); ++dropsBeforeLowerIt; } if(!player->rendered&&!player->upperLevel){ @@ -1588,22 +1525,24 @@ void AiL::RenderWorld(float fElapsedTime){ vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } + if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE); + else SetDecalMode(DecalMode::NORMAL); RenderPlayer(player->GetPos(),{1,1}); } while(monstersAfterLowerIt!=monstersAfterLower.end()){ - Monster*const m=*monstersAfterLowerIt; - m->Draw(); + const Monster&m=**monstersAfterLowerIt; + m.Draw(); ++monstersAfterLowerIt; } while(dropsAfterLowerIt!=dropsAfterLower.end()){ - const int dropInd=*dropsAfterLowerIt; - ItemDrop::drops[dropInd].Draw(); + const ItemDrop&drop{*dropsAfterLowerIt}; + drop.Draw(); ++dropsAfterLowerIt; } - for(const IBullet*const b:bulletsLower){ + for(std::unique_ptr&b:bulletsLower){ b->_Draw(); } - for(const Effect*const e:foregroundEffectsLower){ + for(std::unique_ptr&e:foregroundEffectsLower){ e->_Draw(); } #pragma endregion @@ -1751,7 +1690,7 @@ void AiL::RenderWorld(float fElapsedTime){ break; } while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){ - const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt]; + const ItemDrop&drop{*dropsBeforeUpperIt}; if(drop.pos.yGetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } + if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE); + else SetDecalMode(DecalMode::NORMAL); RenderPlayer(player->GetPos(),{1,1}); } while(monstersAfterUpperIt!=monstersAfterUpper.end()){ @@ -1788,7 +1729,7 @@ void AiL::RenderWorld(float fElapsedTime){ break; } while(dropsAfterUpperIt!=dropsAfterUpper.end()){ - const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt]; + const ItemDrop&drop{*dropsAfterUpperIt}; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); ++dropsBeforeUpperIt; @@ -1828,7 +1769,7 @@ void AiL::RenderWorld(float fElapsedTime){ ++monstersBeforeUpperIt; } while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){ - const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt]; + const ItemDrop&drop{*dropsBeforeUpperIt}; drop.Draw(); ++dropsBeforeUpperIt; } @@ -1837,6 +1778,8 @@ void AiL::RenderWorld(float fElapsedTime){ vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24); view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } + if(player->IsUsingAdditiveBlending())SetDecalMode(DecalMode::ADDITIVE); + else SetDecalMode(DecalMode::NORMAL); RenderPlayer(player->GetPos(),{1,1}); } while(monstersAfterUpperIt!=monstersAfterUpper.end()){ @@ -1849,7 +1792,7 @@ void AiL::RenderWorld(float fElapsedTime){ break; } while(dropsAfterUpperIt!=dropsAfterUpper.end()){ - const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt]; + const ItemDrop&drop{*dropsAfterUpperIt}; if(drop.pos.ygroup->GetCollisionRange().middle().y){ drop.Draw(); ++dropsAfterUpperIt; @@ -1871,16 +1814,16 @@ void AiL::RenderWorld(float fElapsedTime){ #pragma endregion #pragma region Remaining Upper Rendering while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){ - Monster*const m=*monstersBeforeUpperIt; - m->Draw(); + const Monster&m=**monstersBeforeUpperIt; + m.Draw(); ++monstersBeforeUpperIt; } - for(const Effect*const e:backgroundEffectsUpper){ + for(std::unique_ptr&e:backgroundEffectsUpper){ e->_Draw(); } while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){ - const int dropInd=*dropsBeforeUpperIt; - ItemDrop::drops[dropInd].Draw(); + const ItemDrop&drop{*dropsBeforeUpperIt}; + drop.Draw(); ++dropsBeforeUpperIt; } if(!player->rendered&&player->upperLevel){ @@ -1892,19 +1835,19 @@ void AiL::RenderWorld(float fElapsedTime){ RenderPlayer(player->GetPos(),{1,1}); } while(monstersAfterUpperIt!=monstersAfterUpper.end()){ - Monster*const m=*monstersAfterUpperIt; - m->Draw(); + const Monster&m=**monstersAfterUpperIt; + m.Draw(); ++monstersAfterUpperIt; } while(dropsAfterUpperIt!=dropsAfterUpper.end()){ - const int dropInd=*dropsAfterUpperIt; - ItemDrop::drops[dropInd].Draw(); + const ItemDrop&drop{*dropsAfterUpperIt}; + drop.Draw(); ++dropsAfterUpperIt; } - for(const IBullet*const b:bulletsUpper){ + for(std::unique_ptr&b:bulletsUpper){ b->_Draw(); } - for(const Effect*const e:foregroundEffectsUpper){ + for(std::unique_ptr&e:foregroundEffectsUpper){ e->_Draw(); } #pragma endregion diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h index bb77b070..04cf0bcc 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.h +++ b/Adventures in Lestoria/AdventuresInLestoria.h @@ -173,8 +173,6 @@ public: private: std::vector>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted; std::vectortilesWithCollision,tilesWithoutCollision; - std::vectordropsBeforeLower,dropsAfterLower,dropsBeforeUpper,dropsAfterUpper; - std::vectorendZones,upperEndZones; std::vectorcircleCooldownPoints; std::vectorsquareCircleCooldownPoints; std::mapMAP_TILESETS; @@ -190,9 +188,6 @@ private: int bridgeLayerIndex=-1; float bridgeFadeFactor=0.f; int DEBUG_PATHFINDING=0; - std::vectormonstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper; - std::vectorbulletsLower,bulletsUpper; - std::vectorbackgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper; float reflectionUpdateTimer=0; float reflectionStepTime=0; std::setvisibleTiles; diff --git a/Adventures in Lestoria/GhostOfPirateCaptain.cpp b/Adventures in Lestoria/GhostOfPirateCaptain.cpp index 9c84a3e8..7fef7daf 100644 --- a/Adventures in Lestoria/GhostOfPirateCaptain.cpp +++ b/Adventures in Lestoria/GhostOfPirateCaptain.cpp @@ -62,11 +62,16 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std }; static const uint8_t PHASE_COUNT{uint8_t(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetValueCount())}; + static uint8_t TOTAL_CANNON_SHOTS{0}; const auto AdvanceCannonPhase{[&m,&strategy](){ m.GetFloat(A::CANNON_TIMER)=0.f; //if(m.GetInt(A::CANNON_PHASE)+1>=PHASE_COUNT)m.GetInt(A::CANNON_SHOT_TYPE)=util::random()%5; - m.GetInt(A::CANNON_PHASE)=(m.GetInt(A::CANNON_PHASE)+1)%PHASE_COUNT; + const int prevCannonPhase{m.I(A::CANNON_PHASE)}; + m.I(A::CANNON_PHASE)=(m.I(A::CANNON_PHASE)+1)%PHASE_COUNT; + if(prevCannonPhase>m.I(A::CANNON_PHASE)){//Phase has wrapped around, reset cannon shot count. + m.I(A::CANNON_SHOT_COUNT)=0; + } }}; if(m.F(A::SHRAPNEL_SHOT_FALL_TIMER)>0.f){ @@ -82,22 +87,24 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std } switch(PHASE()){ + enum CannonPhaseType{ + CANNON_SHOT, + SILENCE, + SHRAPNEL_SHOT, + }; case INIT:{ for(int i:std::ranges::iota_view(0U,PHASE_COUNT)){ - m.VEC(A::CANNON_PHASES).emplace_back(DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetInt(i)); + const int cannonCycle{DATA.GetProperty("MonsterStrategy.Ghost of Pirate Captain.Cannon Cycle").GetInt(i)}; + m.VEC(A::CANNON_PHASES).emplace_back(cannonCycle); + if(cannonCycle==CANNON_SHOT)TOTAL_CANNON_SHOTS++; } - m.I(A::CANNON_SHOT_TYPE)=BOMBARDMENT; + m.I(A::CANNON_SHOT_TYPE)=PREDICTION; SETPHASE(NORMAL); }break; case NORMAL:{ m.F(A::CANNON_TIMER)+=fElapsedTime; const int phase{std::any_cast(m.VEC(A::CANNON_PHASES)[m.I(A::CANNON_PHASE)])}; switch(phase){ - enum CannonPhaseType{ - CANNON_SHOT, - SILENCE, - SHRAPNEL_SHOT, - }; case CANNON_SHOT:{//Normal Cannon Shot. Takes on one of five varieties. if(m.F(A::CANNON_TIMER)>=ConfigFloat("Cannon Shot Delay")){ switch(m.I(A::CANNON_SHOT_TYPE)){ @@ -108,19 +115,30 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet; }break; case PRECISE_BOMBARDMENT:{ - + const float randomAng{util::random_range(0,2*PI)}; + const float range{util::random_range(0,ConfigPixels("Precise Bombardment Max Distance"))}; + const vf2d targetPos{game->GetPlayer()->GetPos()+vf2d{range,randomAng}.cart()}; + CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet; }break; case LINE:{ - + //Draw a line from one side of the screen to the other, drawing through the middle. + if(m.I(A::CANNON_SHOT_COUNT)==0)m.F(A::LINE_SHOT_ANG)=util::random_range(0,2*PI); + const vf2d targetPos{geom2d::line{game->GetPlayer()->GetPos()+vf2d{float(game->ScreenHeight()),m.F(A::LINE_SHOT_ANG)}.cart(),game->GetPlayer()->GetPos()+vf2d{float(game->ScreenHeight()),m.F(A::LINE_SHOT_ANG)+PI}.cart()}.upoint(float(m.I(A::CANNON_SHOT_COUNT))/TOTAL_CANNON_SHOTS)}; + CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet; }break; case SHARPSHOOTER:{ - + if(m.I(A::CANNON_SHOT_COUNT)%2==0)CreateBullet(FallingBullet)("cannonball.png",game->GetPlayer()->GetPos(),ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet; }break; case PREDICTION:{ - + LOG(std::format("Previous Pos: {} Current: {}",game->GetPlayer()->GetPreviousPos().str(),game->GetPlayer()->GetPos().str())); + const float angle{util::angleTo(game->GetPlayer()->GetPreviousPos(),game->GetPlayer()->GetPos())}; + const float range{util::random_range(0,100.f*game->GetPlayer()->GetMoveSpdMult())*ConfigFloat("Cannon Shot Impact Time")}; + const vf2d targetPos{game->GetPlayer()->GetPos()+vf2d{range,angle}.cart()}; + CreateBullet(FallingBullet)("cannonball.png",targetPos,ConfigVec("Cannon Vel"),ConfigFloatArr("Cannon Vel",2),ConfigFloat("Indicator Time"),ConfigPixels("Cannon Radius"),ConfigInt("Cannon Damage"),m.OnUpperLevel(),false,ConfigFloat("Cannon Knockback Amt"),ConfigFloat("Cannon Shot Impact Time"),false,ConfigPixel("Cannon Spell Circle Color"),vf2d{ConfigFloat("Cannon Radius")/100.f*1.75f,ConfigFloat("Cannon Radius")/100.f*1.75f},util::random(2*PI),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Circle Rotation Spd")),ConfigPixel("Cannon Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Cannon Spell Insignia Rotation Spd")))EndBullet; }break; } AdvanceCannonPhase(); + m.I(A::CANNON_SHOT_COUNT)++; } }break; case SILENCE:{ diff --git a/Adventures in Lestoria/ItemDrop.cpp b/Adventures in Lestoria/ItemDrop.cpp index 281109dd..a280d7a9 100644 --- a/Adventures in Lestoria/ItemDrop.cpp +++ b/Adventures in Lestoria/ItemDrop.cpp @@ -69,7 +69,7 @@ vf2d ItemDrop::GetPos()const{ return pos; } -bool ItemDrop::OnUpperLevel(){ +bool ItemDrop::OnUpperLevel()const{ return upperLevel; } diff --git a/Adventures in Lestoria/ItemDrop.h b/Adventures in Lestoria/ItemDrop.h index 5ef21068..d7797f37 100644 --- a/Adventures in Lestoria/ItemDrop.h +++ b/Adventures in Lestoria/ItemDrop.h @@ -59,7 +59,7 @@ class ItemDrop{ public: static void Initialize(); vf2d GetPos()const; - bool OnUpperLevel(); + bool OnUpperLevel()const; void Draw()const; static void UpdateDrops(float fElapsedTime); static const std::vector&GetDrops(); diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h index 6d7c8975..ad6ed16d 100644 --- a/Adventures in Lestoria/MonsterAttribute.h +++ b/Adventures in Lestoria/MonsterAttribute.h @@ -169,5 +169,7 @@ enum class Attribute{ CANNON_PHASES, SHRAPNEL_SHOT_COUNT, SHRAPNEL_SHOT_FALL_TIMER, - + CANNON_SHOT_COUNT, + LINE_SHOT_ANG, + LAST_PLAYER_POS, }; \ No newline at end of file diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index df2dcf5a..5035174e 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -399,6 +399,7 @@ void Player::Update(float fElapsedTime){ hpRecoveryTimer=std::max(0.f,hpRecoveryTimer-fElapsedTime); hp6RecoveryTimer=std::max(0.f,hp6RecoveryTimer-fElapsedTime); hp4RecoveryTimer=std::max(0.f,hp4RecoveryTimer-fElapsedTime); + const vf2d previousPosTemp{GetPos()}; //The logic here is that the previous position must be a different value from the actual position and should only change when the position of the player actually changes, this means we must wait for the entire frame to resolve to see if any movement has occurred to update to the "new previous position". This variable is resolved at the bottom of this Update function. RunTimers(); PerformHPRecovery(); @@ -855,6 +856,10 @@ void Player::Update(float fElapsedTime){ } } #pragma endregion + + if(previousPosTemp!=GetPos()){ + previousPos=previousPosTemp; //The logic here is that the previous position must be a different value from the actual position and should only change when the position of the player actually changes, this means we must wait for the entire frame to resolve to see if any movement has occurred to update to the "new previous position". The previous position temp variable is set at the top of this Update function. + } } float Player::GetSwordSwingTimer(){ @@ -2323,4 +2328,7 @@ const bool Player::HasBuff(BuffType buff)const{ } const bool Player::CoveredInInk()const{ return HasBuff(BuffType::INK_SLOWDOWN); +} +const vf2d&Player::GetPreviousPos()const{ + return previousPos; } \ No newline at end of file diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index d7f77713..e09c77b0 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -339,6 +339,7 @@ public: void PrepareCast(Ability&ability); //NOTE: This usually is not called unless we are running tests! PrepareCast is meant to be used before we use CastSpell in unit tests. void SetTestScreenAimingLocation(vf2d forcedAimingLoc); const bool CoveredInInk()const; + const vf2d&GetPreviousPos()const; //The position the player was at on the last frame, can be used for comparison purposes to predict where the player may be next. private: static std::vector>ABILITY_LIST; const int SHIELD_CAPACITY{32}; @@ -433,6 +434,7 @@ private: bool catForm{false}; std::optionaltestAimingLoc{}; vf2d addedVel{}; + vf2d previousPos{pos}; protected: const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F; const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 5a35a03d..70274499 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 11980 +#define VERSION_BUILD 11997 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index ac5dfa1a..e796bc14 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ