diff --git a/Adventures in Lestoria/Buff.h b/Adventures in Lestoria/Buff.h index 30f1d090..2e68ad2c 100644 --- a/Adventures in Lestoria/Buff.h +++ b/Adventures in Lestoria/Buff.h @@ -49,6 +49,8 @@ enum BuffType{ LOCKON_SPEEDBOOST, //Specifically used for wolves. SPEEDBOOST, BARRIER_DAMAGE_REDUCTION, //Creates a visual barrier around the target + FIXED_COLLISION_DMG, //Does a fixed amount of collision damage based on intensity of this buff. + COLLISION_KNOCKBACK_STRENGTH, //Causes an amount of knockback based on intensity when hit via collision with this buff }; class AiL; diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 862092b1..ba2b89bf 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -372,14 +372,36 @@ void Monster::DrawReflection(float drawRatioX,float multiplierX){ game->SetDecalMode(DecalMode::NORMAL); } void Monster::Collision(Player*p){ - if(MONSTER_DATA[name].GetCollisionDmg()>0&&lastHitPlayer==0.0f){ - if(p->Hurt(MONSTER_DATA[name].GetCollisionDmg(),OnUpperLevel(),GetZ())){ + if(GetCollisionDamage()>0&&lastHitPlayer==0.0f){ + if(p->Hurt(GetCollisionDamage(),OnUpperLevel(),GetZ())){ lastHitPlayer=1.0f; } } + + #pragma region Knockback due to buffs + vf2d knockbackVecNorm=geom2d::line(GetPos(),p->GetPos()).vector().norm(); + float knockbackStrength=0.f; + std::vector knockbackBuffs=GetBuffs(COLLISION_KNOCKBACK_STRENGTH); + for(Buff&b:knockbackBuffs){ + knockbackStrength+=b.intensity; + } + p->Knockback(knockbackVecNorm*knockbackStrength); + #pragma endregion + Collision(); } void Monster::Collision(Monster&m){ + + #pragma region Knockback due to buffs + vf2d knockbackVecNorm=geom2d::line(GetPos(),m.GetPos()).vector().norm(); + float knockbackStrength=0.f; + std::vector knockbackBuffs=GetBuffs(COLLISION_KNOCKBACK_STRENGTH); + for(Buff&b:knockbackBuffs){ + knockbackStrength+=b.intensity; + } + m.Knockback(knockbackVecNorm*knockbackStrength); + #pragma endregion + Collision(); } void Monster::Collision(){ @@ -720,4 +742,13 @@ const float Monster::GetDamageReductionFromBuffs()const{ dmgReduction+=b.intensity; } return std::min(1.0f,dmgReduction); +} + +const float Monster::GetCollisionDamage()const{ + float collisionDmg=0.f; + for(Buff&b:GetBuffs(FIXED_COLLISION_DMG)){ + collisionDmg+=b.intensity; + } + if(collisionDmg>0)return collisionDmg; + else return MONSTER_DATA[name].GetCollisionDmg(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index fac02544..60fc978c 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -185,6 +185,7 @@ public: //Rotates this enemy's sprite towards a given location. Also flips it to face the correct direction. void RotateTowardsPos(const vf2d&targetPos); const float GetDamageReductionFromBuffs()const; + const float GetCollisionDamage()const; private: std::string name; vf2d pos; diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h index decbaa8d..66383db8 100644 --- a/Adventures in Lestoria/MonsterAttribute.h +++ b/Adventures in Lestoria/MonsterAttribute.h @@ -88,4 +88,5 @@ enum class Attribute{ WISP_PATTERN_LIST, ENVIRONMENT_TIMER, ENVIRONMENT_PHASE, + CHARGE_COOLDOWN, }; \ No newline at end of file diff --git a/Adventures in Lestoria/Ursule.cpp b/Adventures in Lestoria/Ursule.cpp index a3b8acca..1877fefd 100644 --- a/Adventures in Lestoria/Ursule.cpp +++ b/Adventures in Lestoria/Ursule.cpp @@ -114,6 +114,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy m.PerformOtherAnimation(2); m.F(A::SHOOT_TIMER)=std::max(0.f,m.F(A::SHOOT_TIMER)-fElapsedTime); + #pragma region Environment Color Change Handling m.F(A::ENVIRONMENT_TIMER)=std::max(0.f,m.F(A::ENVIRONMENT_TIMER)-fElapsedTime); switch(m.I(A::ENVIRONMENT_PHASE)){ case 0:{ //Fade out. @@ -138,6 +139,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy } }break; } + #pragma endregion if(m.I(A::PHASE_REPEAT_COUNT)>0){ if(m.F(A::SHOOT_TIMER)==0.f){ @@ -174,19 +176,94 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy m.I(A::PHASE_REPEAT_COUNT)--; } }else{ + + auto TransitionToPhase3=[&](){ + m.phase=3; + game->SetWorldColor(ConfigPixel("Phase 3.Environment Fade-In Color")); + m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Phase 3.Environment Fade-in Time"); + m.I(A::ENVIRONMENT_PHASE)=0; + m.RemoveBuff(BARRIER_DAMAGE_REDUCTION); + }; + if(m.F(A::RECOVERY_TIME)==0.f){ - if(ConfigFloat("Phase 2.Wisp Count Phase Change Wait")==0.f)m.phase=3; + if(ConfigFloat("Phase 2.Wisp Count Phase Change Wait")==0.f){ + TransitionToPhase3(); + } m.F(A::RECOVERY_TIME)=ConfigFloat("Phase 2.Wisp Count Phase Change Wait"); }else{ m.F(A::RECOVERY_TIME)-=fElapsedTime; if(m.F(A::RECOVERY_TIME)<=0.f){ - m.phase=3; + TransitionToPhase3(); } } } }break; case 3:{ + #pragma region Environment Color Change Handling + m.F(A::ENVIRONMENT_TIMER)=std::max(0.f,m.F(A::ENVIRONMENT_TIMER)-fElapsedTime); + switch(m.I(A::ENVIRONMENT_PHASE)){ + case 0:{ //Fade out. Use the phase 2 environment fade-in color as the previous color to lerp out from. + game->SetWorldColor(ConfigPixel("Phase 2.Environment Fade-In Color")*util::lerp(0.f,1.0f,m.F(A::ENVIRONMENT_TIMER)/ConfigFloat("Phase 3.Environment Fade-out Time"))); + if(m.F(A::ENVIRONMENT_TIMER)==0.f){ + game->SetWorldColor({0,0,0,255}); + m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Phase 3.Environment Fade-in Time"); + m.I(A::ENVIRONMENT_PHASE)++; + game->SetWorldColorFunc([&](vi2d pos){return game->GetWorldColor();}); + } + }break; + case 1:{ //Fade in. + Pixel fadeInCol=ConfigPixel("Phase 3.Environment Fade-In Color"); + + game->SetWorldColor(fadeInCol*util::lerp(1.f,0.f,m.F(A::ENVIRONMENT_TIMER)/ConfigFloat("Phase 3.Environment Fade-in Time"))); + if(m.F(A::ENVIRONMENT_TIMER)==0.f){ + game->SetWorldColor(fadeInCol); + } + }break; + } + #pragma endregion + float distToPlayer=geom2d::line(game->GetPlayer()->GetPos(),m.GetPos()).length(); + m.F(A::CHARGE_COOLDOWN)=std::max(0.f,m.F(A::CHARGE_COOLDOWN)-fElapsedTime); + + if(m.I(A::PHASE)!=0)goto bear2; //Prevent doing anything else if a part of bear AI is still running. + + if(distToPlayer>=ConfigFloat("Phase 3.Charge Range")/100.f*24.f&&m.F(A::CHARGE_COOLDOWN)==0.f){ + if(ConfigFloat("Phase 3.Charge Cast Time")!=0.f){ + if(m.F(A::CASTING_TIMER)==0.f)m.F(A::CASTING_TIMER)=ConfigFloat("Phase 3.Charge Cast Time"); + } + if(m.F(A::CASTING_TIMER)>0.f){ + m.F(A::CASTING_TIMER)=std::max(0.f,m.F(A::CASTING_TIMER)-fElapsedTime); + if(m.F(A::CASTING_TIMER)==0.f){ + m.phase=4; + m.AddBuff(SPEEDBOOST,10.f,ConfigFloat("Phase 3.Charge Speed Boost")/100.f); + m.AddBuff(FIXED_COLLISION_DMG,10.f,ConfigFloat("Phase 3.Charge Attack Damage")); + m.AddBuff(COLLISION_KNOCKBACK_STRENGTH,10.f,ConfigFloat("Phase 3.Charge Attack Knockback Strength")); + m.target=geom2d::line(m.GetPos(),game->GetPlayer()->GetPos()).upoint(2.0f); + m.F(A::CHARGE_COOLDOWN)=ConfigFloat("Phase 3.Charge Attack Cooldown"); + m.PerformOtherAnimation(3); + break; + } + } + } + + bear2: + BEAR(m,fElapsedTime,"Bear"); + }break; + case 4:{ //A charging phase. + if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){ + vf2d newPos=m.pos+geom2d::line(m.pos,m.target).vector().norm()*100*fElapsedTime*m.GetMoveSpdMult(); + m.SetPos(newPos); + } + + float distToTarget=geom2d::line(m.target,m.GetPos()).length(); + + if(distToTarget<=4.f){ + m.phase=3; + m.RemoveBuff(SPEEDBOOST); + m.RemoveBuff(FIXED_COLLISION_DMG); + m.RemoveBuff(COLLISION_KNOCKBACK_STRENGTH); + m.PerformIdleAnimation(); + } }break; default:{ ERR(std::format("WARNING! Unknown phase {} for {} reached!",m.phase,m.GetName())); diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 07ce7c99..91430954 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 6322 +#define VERSION_BUILD 6336 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/MonsterStrategies.txt b/Adventures in Lestoria/assets/config/MonsterStrategies.txt index b912eaa3..71505565 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -382,14 +382,23 @@ MonsterStrategy } Phase 3 { + # Amount of time the environment fades out to pitch black. + Environment Fade-out Time = 0.4s + + # Amount of time for the environment to fade in with the new color. + Environment Fade-in Time = 2.0s + + # New fade-in environment color. + Environment Fade-In Color = 255, 255, 255, 255 + # Minimum range the bear will decide to charge the player. - Charge Range = 700 + Charge Range = 450 # Amount of time the bear spends preparing to charge. - Charge Cast Time = 0.6s + Charge Cast Time = 0.1s # Amount of speed to gain during the charge attack. - Charge Speed Boost = 60% + Charge Speed Boost = 200% # Cooldown time of the charge attack. Charge Attack Cooldown = 15.0s @@ -398,7 +407,7 @@ MonsterStrategy Charge Attack Damage = 30 # Amount of knockback to cause to the player when hit by the charging attack. - Charge Attack Knockback Strength = 2.5 + Charge Attack Knockback Strength = 3.5 } Phase 4 { diff --git a/Adventures in Lestoria/assets/config/Monsters.txt b/Adventures in Lestoria/assets/config/Monsters.txt index a70143b7..38cfa03f 100644 --- a/Adventures in Lestoria/assets/config/Monsters.txt +++ b/Adventures in Lestoria/assets/config/Monsters.txt @@ -364,7 +364,7 @@ Monsters #Size of each animation frame - SheetFrameSize = 24,24 + SheetFrameSize = 26,26 # Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse) IdleAnimation = 4, 0.3, Repeat @@ -386,5 +386,6 @@ Monsters ANIMATION[0] = 4, 0.1, OneShot ANIMATION[1] = 6, 0.15, OneShot ANIMATION[2] = 2, 0.2, Reverse + ANIMATION[3] = 5, 0.2, Repeat } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/monsters/Ursule Mother of Bears2.png b/Adventures in Lestoria/assets/monsters/Ursule Mother of Bears2.png index 13689567..0e8d67cb 100644 Binary files a/Adventures in Lestoria/assets/monsters/Ursule Mother of Bears2.png and b/Adventures in Lestoria/assets/monsters/Ursule Mother of Bears2.png differ diff --git a/Adventures in Lestoria/assets/monsters/Ursule, Mother of Bears.png b/Adventures in Lestoria/assets/monsters/Ursule, Mother of Bears.png index 05819bf0..833bbe4b 100644 Binary files a/Adventures in Lestoria/assets/monsters/Ursule, Mother of Bears.png and b/Adventures in Lestoria/assets/monsters/Ursule, Mother of Bears.png differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index b7cb28ea..976ee4fe 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ