diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index f0f47662..482aff6f 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -1403,15 +1403,19 @@ void AiL::RenderWorld(float fElapsedTime){ } #pragma endregion #pragma region Remaining Rendering - for(Monster*m:monstersBeforeLower){ + while(monstersBeforeLowerIt!=monstersBeforeLower.end()){ + Monster*const m=*monstersBeforeLowerIt; m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy()); m->Draw(); + ++monstersBeforeLowerIt; } for(const Effect*const e:backgroundEffectsLower){ e->Draw(); } - for(const int dropInd:dropsBeforeLower){ + while(dropsBeforeLowerIt!=dropsBeforeLower.end()){ + const int dropInd=*dropsBeforeLowerIt; ItemDrop::drops[dropInd].Draw(); + ++dropsBeforeLowerIt; } if(!player->rendered&&!player->upperLevel){ player->rendered=true; @@ -1421,11 +1425,14 @@ void AiL::RenderWorld(float fElapsedTime){ } RenderPlayer(player->GetPos(),{1,1}); } - for(Monster* m:monstersAfterLower){ + while(monstersAfterLowerIt!=monstersAfterLower.end()){ + Monster*const m=*monstersAfterLowerIt; m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy()); m->Draw(); + ++monstersAfterLowerIt; } - for(const int dropInd:dropsAfterLower){ + while(dropsAfterLowerIt!=dropsAfterLower.end()){ + const int dropInd=*dropsAfterLowerIt; ItemDrop::drops[dropInd].Draw(); } for(const Bullet*const b:bulletsLower){ @@ -1697,14 +1704,17 @@ void AiL::RenderWorld(float fElapsedTime){ } #pragma endregion #pragma region Remaining Upper Rendering - for(Monster*m:monstersBeforeUpper){ + while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){ + Monster*const m=*monstersBeforeUpperIt; m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy()); m->Draw(); + ++monstersBeforeUpperIt; } for(const Effect*const e:backgroundEffectsUpper){ e->Draw(); } - for(const int dropInd:dropsBeforeUpper){ + while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){ + const int dropInd=*dropsBeforeUpperIt; ItemDrop::drops[dropInd].Draw(); } if(!player->rendered&&player->upperLevel){ @@ -1715,12 +1725,16 @@ void AiL::RenderWorld(float fElapsedTime){ } RenderPlayer(player->GetPos(),{1,1}); } - for(Monster*m:monstersAfterUpper){ + while(monstersAfterUpperIt!=monstersAfterUpper.end()){ + Monster*const m=*monstersAfterUpperIt; m->strategyDraw(this,*m,MONSTER_DATA[m->GetName()].GetAIStrategy()); m->Draw(); + ++monstersAfterUpperIt; } - for(const int dropInd:dropsAfterUpper){ + while(dropsAfterUpperIt!=dropsAfterUpper.end()){ + const int dropInd=*dropsAfterUpperIt; ItemDrop::drops[dropInd].Draw(); + ++dropsAfterUpperIt; } for(const Bullet*const b:bulletsUpper){ b->Draw(); @@ -2285,6 +2299,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){ totalDamageDealt=0; encounterStarted=false; totalBossEncounterMobs=0; + SetWindSpeed({}); Inventory::Clear("Monster Loot"); Inventory::Clear("Stage Loot"); Inventory::ResetLoadoutItemsUsed(); @@ -4273,4 +4288,11 @@ Overlay&AiL::GetOverlay(){ void AiL::SetOverlay(std::string animationName,Pixel overlayCol){ hudOverlay=Overlay{animationName,overlayCol}; +} + +void AiL::SetWindSpeed(vf2d newWindSpd){ + windSpd=newWindSpd; +} +const vf2d&AiL::GetWindSpeed()const{ + return windSpd; } \ No newline at end of file diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h index fcbafcca..e48d36cf 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.h +++ b/Adventures in Lestoria/AdventuresInLestoria.h @@ -196,6 +196,7 @@ private: float vignetteDisplayTime=0.f; bool savingFile=false; bool prevStageCompleted=false; + vf2d windSpd{}; void ValidateGameStatus(); void _PrepareLevel(MapName map,MusicChange changeMusic); @@ -351,6 +352,8 @@ public: void SetBossIndicatorPos(const vf2d pos); void SetOverlay(std::string animationName,Pixel overlayCol); Overlay&GetOverlay(); + void SetWindSpeed(vf2d newWindSpd); + const vf2d&GetWindSpeed()const; struct TileGroupData{ vi2d tilePos; diff --git a/Adventures in Lestoria/Bullet.cpp b/Adventures in Lestoria/Bullet.cpp index dd032577..4639ddf9 100644 --- a/Adventures in Lestoria/Bullet.cpp +++ b/Adventures in Lestoria/Bullet.cpp @@ -139,6 +139,7 @@ void Bullet::_Update(const float fElapsedTime){ }else{ pos+=vel*fElapsedTime; } + if(IsPlayerAutoAttackProjectile()){pos+=game->GetWindSpeed()*game->GetElapsedTime();} if(/*World size in PIXELS!*/vi2d worldSize=game->GetCurrentMapData().MapSize*game->GetCurrentMapData().TileSize;pos.x+radius<-WINDOW_SIZE.x||pos.x-radius>worldSize.x+WINDOW_SIZE.x||pos.y+radius<-WINDOW_SIZE.y||pos.y-radius>worldSize.y+WINDOW_SIZE.y){ dead=true; return; @@ -225,5 +226,5 @@ const bool Bullet::IsPlayerAutoAttackProjectile()const{ } void Bullet::AddVelocity(vf2d vel){ - this->vel+=vel; + this->vel+=vel*game->GetElapsedTime(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 5a5fa170..547d332c 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -440,7 +440,7 @@ void Monster::Draw()const{ if(GetZ()>0){ vf2d shadowScale=vf2d{8*GetSizeMult()/3.f,1}/std::max(1.f,GetZ()/24); - game->view.DrawDecal(drawPos-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); + game->view.DrawDecal(GetPos()+hitTimerOffset-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK); } const bool NotOnTitleScreen=GameState::STATE!=GameState::states[States::MAIN_MENU]; diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index 3ce9c79f..c87364a3 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -143,7 +143,7 @@ void Player::ForceSetPos(vf2d pos){ Moved(); } -bool Player::_SetX(float x,const bool playerInvoked){ +bool Player::_SetX(float x,MoveFlag::MoveFlag flags,const bool playerInvoked){ vf2d newPos={x,pos.y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -152,7 +152,7 @@ bool Player::_SetX(float x,const bool playerInvoked){ #pragma endregion if(NoTileCollisionExistsHere()){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); - Moved(); + Moved(flags); return true; } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; @@ -162,21 +162,21 @@ bool Player::_SetX(float x,const bool playerInvoked){ collision.pos+=tilePos; if(NoPlayerCollisionWithTile()){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); - Moved(); + Moved(flags); return true; }else if(playerInvoked){ //If player invoked, we'll try the smart move system. vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); newPos={newPos.x,pos.y+pushDir.y*12}; if(NoPlayerCollisionWithTile()){ - return _SetY(pos.y+pushDir.y*game->GetElapsedTime()*12,false); + return _SetY(pos.y+pushDir.y*game->GetElapsedTime()*12,flags,false); } } } return false; }; -bool Player::_SetY(float y,const bool playerInvoked){ +bool Player::_SetY(float y,MoveFlag::MoveFlag flags,const bool playerInvoked){ vf2d newPos={pos.x,y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); @@ -185,7 +185,7 @@ bool Player::_SetY(float y,const bool playerInvoked){ #pragma endregion if(NoTileCollisionExistsHere()){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); - Moved(); + Moved(flags); return true; } else { geom2d::rectcollision={collisionRect.pos,collisionRect.size}; @@ -195,37 +195,37 @@ bool Player::_SetY(float y,const bool playerInvoked){ collision.pos+=tilePos; if(NoPlayerCollisionWithTile()){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); - Moved(); + Moved(flags); return true; }else if(playerInvoked){ //If player invoked, we'll try the smart move system.{ vf2d pushDir=geom2d::line(collision.middle(),pos).vector().norm(); newPos={pos.x+pushDir.x*12,newPos.y}; if(NoPlayerCollisionWithTile()){ - return _SetX(pos.x+pushDir.x*game->GetElapsedTime()*12,false); + return _SetX(pos.x+pushDir.x*game->GetElapsedTime()*12,flags,false); } } } return false; } -bool Player::SetX(float x){ - return _SetX(x); +bool Player::SetX(float x,MoveFlag::MoveFlag flags){ + return _SetX(x,flags); } -bool Player::SetY(float y){ - return _SetY(y); +bool Player::SetY(float y,MoveFlag::MoveFlag flags){ + return _SetY(y,flags); } void Player::SetZ(float z){ this->z=z; } -bool Player::SetPos(vf2d pos){ - bool resultX=SetX(pos.x); - bool resultY=SetY(pos.y); +bool Player::SetPos(vf2d pos,MoveFlag::MoveFlag flags){ + bool resultX=SetX(pos.x,flags); + bool resultY=SetY(pos.y,flags); if(resultY&&!resultX){ - resultX=SetX(pos.x); + resultX=SetX(pos.x,flags); } return resultX||resultY; } @@ -548,6 +548,12 @@ void Player::Update(float fElapsedTime){ ERR(std::format("WARNING! The velocity vector for the player is NOT normal! Current vel:{} . Attempting manual resetting of velocity.",vel.str())); vel={}; } + + vf2d finalWindSpd=game->GetWindSpeed(); + if(GetState()==State::BLOCK)finalWindSpd*=1-("Warrior.Right Click Ability.Knockback Reduction"_F/100.f); + + game->GetPlayer()->SetPos(game->GetPlayer()->GetPos()+finalWindSpd*game->GetElapsedTime(),MoveFlag::PREVENT_CAST_CANCELLING); + if(vel!=vf2d{0,0}){ float newX=pos.x+vel.x*fElapsedTime; float newY=pos.y+vel.y*fElapsedTime; @@ -875,8 +881,8 @@ void Player::CancelCast(){ } } -void Player::Moved(){ - if(state==State::CASTING){ +void Player::Moved(MoveFlag::MoveFlag flags){ + if(!(flags&MoveFlag::PREVENT_CAST_CANCELLING)&&state==State::CASTING){ state=State::NORMAL; castPrepAbility->waitForRelease=true; CancelCast(); @@ -1078,7 +1084,7 @@ void Player::_SetIframes(float duration){ } bool Player::Heal(int damage,bool suppressDamageNumber){ - hp=std::clamp(hp+damage,0,int(GetStat("Health"))); + hp=std::clamp(hp+damage,0,int(GetMaxHealth())); if(!suppressDamageNumber&&damage>0){ DAMAGENUMBER_LIST.push_back(std::make_shared(GetPos(),damage,true,HEALTH_GAIN)); } @@ -1577,5 +1583,5 @@ void Player::ProximityKnockback(const vf2d centerPoint,const float knockbackFact } void Player::AddVelocity(vf2d vel){ - this->vel+=vel; + this->vel+=vel*game->GetElapsedTime(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index cf1275b0..98153b76 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -62,6 +62,13 @@ struct CastInfo{ vf2d castPos{}; }; +namespace MoveFlag{ + enum MoveFlag{ + NONE = 0b0, + PREVENT_CAST_CANCELLING = 0b1, + }; +}; + class EntityStats{ friend class Inventory; ItemAttributable equipStats; //The stats after gear calculations are applied. @@ -148,12 +155,12 @@ public: void RestoreMana(int amt,bool suppressDamageNumber=false); void ConsumeMana(int amt); //Returns true if the move was valid and successful. - bool SetX(float x); + bool SetX(float x,MoveFlag::MoveFlag flags=MoveFlag::NONE); //Returns true if the move was valid and successful. - bool SetY(float y); + bool SetY(float y,MoveFlag::MoveFlag flags=MoveFlag::NONE); void SetZ(float z); //Returns true if the move was valid and successful. - bool SetPos(vf2d pos); + bool SetPos(vf2d pos,MoveFlag::MoveFlag flags=MoveFlag::NONE); //Ignores collision checking and sets the player at the given position. void ForceSetPos(vf2d pos); void SetState(State::State newState); @@ -189,7 +196,7 @@ public: bool IsOutOfCombat(); float GetEndZoneStandTime(); //Triggers when the player has moved. - void Moved(); + void Moved(MoveFlag::MoveFlag flags=MoveFlag::NONE); virtual ~Player()=default; virtual Class GetClass()=0; virtual bool AutoAttack()=0; @@ -311,12 +318,12 @@ private: //If playerInvoked is true, this means the player was the one that instantiated this input, and it's not an extra movement done via collision. //Set playerInvoked to false when you don't want a movement loop due to collisions. //Typical usage is playerInvoked is true on first call, and playerInvoked is false on all subsequent chained calls. - bool _SetX(float x,const bool playerInvoked=true); + bool _SetX(float x,MoveFlag::MoveFlag flags=MoveFlag::NONE,const bool playerInvoked=true); //Returns true if the move was valid and successful. //If playerInvoked is true, this means the player was the one that instantiated this input, and it's not an extra movement done via collision. //Set playerInvoked to false when you don't want a movement loop due to collisions. //Typical usage is playerInvoked is true on first call, and playerInvoked is false on all subsequent chained calls. - bool _SetY(float y,const bool playerInvoked=true); + bool _SetY(float y,MoveFlag::MoveFlag flags=MoveFlag::NONE,const bool playerInvoked=true); const bool UsingAutoAim()const; void InitializeMinimapImage(); bool lowHealthSoundPlayed=false; diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index d49fa3b3..a057fb0e 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -23,4 +23,5 @@ New Monster Sound Effects DEMO ==== +Health % max health healing bug Go back and apply new rendering code. \ No newline at end of file diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index a5fcaa45..21f5efbd 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 2 #define VERSION_PATCH 3 -#define VERSION_BUILD 9497 +#define VERSION_BUILD 9507 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Zephy.cpp b/Adventures in Lestoria/Zephy.cpp index e0590338..1c7ac236 100644 --- a/Adventures in Lestoria/Zephy.cpp +++ b/Adventures in Lestoria/Zephy.cpp @@ -256,10 +256,8 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy) vf2d windSpd={m.F(A::WIND_STRENGTH)*"Player.MoveSpd"_F,0.f}; //Assume we landed left and causing a wind attack to the right. if(!LeftLandingSite)windSpd*=-1; - game->GetPlayer()->AddVelocity(windSpd); + game->SetWindSpeed(windSpd); m.F(A::CASTING_TIMER)=ConfigFloat("Wind Attack.Wind Duration"); - - std::for_each(BULLET_LIST.begin(),BULLET_LIST.end(),[&](const std::unique_ptr&bullet){if(bullet->IsPlayerAutoAttackProjectile()){bullet->AddVelocity(windSpd);}}); #pragma endregion if(m.F(A::CASTING_TIMER)<=0.f){ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 3f0fd583..1e5bbc34 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ