diff --git a/Adventures in Lestoria Tests/BuffTests.cpp b/Adventures in Lestoria Tests/BuffTests.cpp index 0cc0b653..abd4e938 100644 --- a/Adventures in Lestoria Tests/BuffTests.cpp +++ b/Adventures in Lestoria Tests/BuffTests.cpp @@ -125,5 +125,41 @@ namespace BuffTests Game::Update(3.f); Assert::AreEqual(95,game->GetPlayer()->GetHealth(),L"Player should have taken 5 health from the expired callback provided."); } + TEST_METHOD(MonsterHasBuffFunctionTest){ + Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))}; + Game::Update(0.f); + Assert::AreEqual(false,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should not have a speedboost buff before being given one."); + m.AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f); + Assert::AreEqual(false,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should not have a speedboost buff when given an unrelated buff."); + m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f); + Assert::AreEqual(true,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should now have a speedboost buff."); + m.AddBuff(BuffType::SPEEDBOOST,2.f,1.f); + Assert::AreEqual(true,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should still report having a speedboost buff."); + Game::Update(0.f); + Game::Update(1.f); + Assert::AreEqual(true,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should still have one speedboost buff."); + Game::Update(1.f); + Assert::AreEqual(false,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should no longer have a speedboost buff."); + m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f); + m.RemoveBuff(BuffType::SPEEDBOOST); + Assert::AreEqual(false,m.HasBuff(BuffType::SPEEDBOOST),L"Monster should no longer have a speedboost buff."); + } + TEST_METHOD(PlayerHasBuffFunctionTest){ + Assert::AreEqual(false,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should not have a speedboost buff before being given one."); + game->GetPlayer()->AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f); + Assert::AreEqual(false,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should not have a speedboost buff when given an unrelated buff."); + game->GetPlayer()->AddBuff(BuffType::SPEEDBOOST,1.f,1.f); + Assert::AreEqual(true,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should now have a speedboost buff."); + game->GetPlayer()->AddBuff(BuffType::SPEEDBOOST,2.f,1.f); + Assert::AreEqual(true,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should still report having a speedboost buff."); + Game::Update(0.f); + Game::Update(1.f); + Assert::AreEqual(true,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should still have one speedboost buff."); + Game::Update(1.f); + Assert::AreEqual(false,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should no longer have a speedboost buff."); + game->GetPlayer()->AddBuff(BuffType::SPEEDBOOST,1.f,1.f); + game->GetPlayer()->RemoveBuff(BuffType::SPEEDBOOST); + Assert::AreEqual(false,game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST),L"Player should no longer have a speedboost buff."); + } }; } \ No newline at end of file diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index 8003831b..77388535 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -835,6 +835,10 @@ + + + + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 41a7adab..582a01c1 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -1250,6 +1250,9 @@ Source Files\Monster Strategies + + Source Files\Monster Strategies + diff --git a/Adventures in Lestoria/GiantCrab.cpp b/Adventures in Lestoria/GiantCrab.cpp new file mode 100644 index 00000000..9251fe1b --- /dev/null +++ b/Adventures in Lestoria/GiantCrab.cpp @@ -0,0 +1,84 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions or derivations of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions or derivative works in binary form must reproduce the above +copyright notice. This list of conditions and the following disclaimer must be +reproduced in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +Portions of this software are copyright © 2024 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion + +#include "MonsterStrategyHelpers.h" +#include "util.h" +#include "AdventuresInLestoria.h" +#include "SoundEffect.h" +#include "BulletTypes.h" + +using A=Attribute; + +INCLUDE_game + +void Monster::STRATEGY::GIANT_CRAB(Monster&m,float fElapsedTime,std::string strategy){ + enum PhaseName{ + PREPARE_CHARGE, + CHARGE, + }; + switch(PHASE()){ + case PREPARE_CHARGE:{ + m.F(A::CASTING_TIMER)-=fElapsedTime; + if(m.F(A::CASTING_TIMER)<=0.f){ + m.AddBuff(BuffType::SPEEDBOOST,ConfigFloat("Charge Time"),0.f); + m.F(A::SPEED_RAMPUP_TIMER)=0.1f; + SETPHASE(CHARGE); + } + }break; + case CHARGE:{ + m.F(A::CHASE_TIMER)+=fElapsedTime; + m.F(A::SPEED_RAMPUP_TIMER)-=fElapsedTime; + if(m.F(A::CHASE_TIMER)>=ConfigFloat("Charge Time")||m.ReachedTargetPos()){ + m.F(A::CHASE_TIMER)=0.f; + m.target=geom2d::line(m.GetPos(),game->GetPlayer()->GetPos()).rpoint(util::distance(m.GetPos(),game->GetPlayer()->GetPos())+ConfigPixels("Charge Extend Distance")); + m.RemoveBuff(BuffType::SPEEDBOOST); + m.F(A::CASTING_TIMER)=ConfigFloat("Charge Wait Time"); + SETPHASE(PREPARE_CHARGE); + } + if(m.F(A::SPEED_RAMPUP_TIMER)<=0.f){ + m.F(A::SPEED_RAMPUP_TIMER)=0.1f; + if(m.HasBuff(BuffType::SPEEDBOOST)){ + const float buffIntensity{m.GetBuffs(BuffType::SPEEDBOOST)[0].intensity}; + m.EditBuff(BuffType::SPEEDBOOST,0).intensity=std::min(buffIntensity+ConfigFloat("Movespeed Rampup Final Amount")/100.f/(ConfigFloat("Movespeed Rampup Time")/0.1f),ConfigFloat("Movespeed Rampup Final Amount")/100.f); + } + } + + RUN_TOWARDS(m,fElapsedTime,"Run Towards"); + }break; + } +} \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 36cbc5b6..bc885dc9 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -92,23 +92,23 @@ const int Monster::GetHealth()const{ const int Monster::GetMaxHealth()const{ return int(GetModdedStatBonuses("Health")); } -int Monster::GetAttack(){ +int Monster::GetAttack()const{ return int(GetModdedStatBonuses("Attack")); } -float Monster::GetMoveSpdMult(){ - float moveSpdPct=stats.A("Move Spd %")/100.f; +float Monster::GetMoveSpdMult()const{ + float moveSpdPct=stats.A_Read("Move Spd %")/100.f; float mod_moveSpd=moveSpdPct; - for(Buff&b:GetBuffs(SLOWDOWN)){ + for(const Buff&b:GetBuffs(SLOWDOWN)){ mod_moveSpd-=moveSpdPct*b.intensity; } - for(Buff&b:GetBuffs(SELF_INFLICTED_SLOWDOWN)){ + for(const Buff&b:GetBuffs(SELF_INFLICTED_SLOWDOWN)){ mod_moveSpd-=moveSpdPct*b.intensity; } - for(Buff&b:GetBuffs(LOCKON_SPEEDBOOST)){ + for(const Buff&b:GetBuffs(LOCKON_SPEEDBOOST)){ mod_moveSpd+=moveSpdPct*b.intensity; } - for(Buff&b:GetBuffs(SPEEDBOOST)){ + for(const Buff&b:GetBuffs(SPEEDBOOST)){ mod_moveSpd+=moveSpdPct*b.intensity; } return mod_moveSpd; @@ -460,7 +460,7 @@ void Monster::Draw()const{ if(markedForDeletion)return; Pixel blendCol{WHITE}; - std::optional>glowPurpleBuff; + std::optionalglowPurpleBuff; if(GetBuffs(BuffType::GLOW_PURPLE).size()>0)glowPurpleBuff=GetBuffs(BuffType::GLOW_PURPLE)[0]; @@ -473,7 +473,7 @@ void Monster::Draw()const{ else if(HasBuff(BuffType::CURSE_OF_DEATH))blendCol=GetBuffBlendCol(BuffType::CURSE_OF_DEATH,1.4f,{255,0,0}); else if(HasBuff(BuffType::COLOR_MOD))blendCol=GetBuffBlendCol(BuffType::COLOR_MOD,1.4f,PixelRaw(GetBuffs(BuffType::COLOR_MOD)[0].intensity),1.f); else if(HasBuff(BuffType::SLOWDOWN))blendCol=GetBuffBlendCol(BuffType::SLOWDOWN,1.4f,{255,255,128},0.5f); - else if(glowPurpleBuff.has_value())blendCol=Pixel{uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().get().duration))),uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().get().duration))),uint8_t(128+127*abs(sin(1.4*glowPurpleBuff.value().get().duration)))}; + else if(glowPurpleBuff.has_value())blendCol=Pixel{uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().duration))),uint8_t(255*abs(sin(1.4*glowPurpleBuff.value().duration))),uint8_t(128+127*abs(sin(1.4*glowPurpleBuff.value().duration)))}; const vf2d hitTimerOffset=vf2d{sin(20*PI*lastHitTimer+randomFrameOffset),0.f}*2.f*GetSizeMult(); const vf2d zOffset=-vf2d{0,GetZ()}; @@ -961,13 +961,13 @@ std::vector>Monster::EditBuffs(BuffType buff){ return filteredBuffs; } -std::vectorMonster::GetBuffs(BuffType buff)const{ +const std::vectorMonster::GetBuffs(BuffType buff)const{ std::vectorfilteredBuffs; std::copy_if(buffList.begin(),buffList.end(),std::back_inserter(filteredBuffs),[&buff](const Buff&b){return b.type==buff;}); return filteredBuffs; } -std::vectorMonster::GetBuffs(std::vectorbuffs)const{ +const std::vectorMonster::GetBuffs(std::vectorbuffs)const{ std::vectorfilteredBuffs; std::copy_if(buffList.begin(),buffList.end(),std::back_inserter(filteredBuffs),[&buffs](const Buff&b){return std::find(buffs.begin(),buffs.end(),b.type)!=buffs.end();}); return filteredBuffs; @@ -1252,7 +1252,7 @@ const float Monster::GetDamageReductionFromBuffs()const{ const float Monster::GetCollisionDamage()const{ float collisionDmg=0.f; - for(Buff&b:GetBuffs(FIXED_COLLISION_DMG)){ + for(const Buff&b:GetBuffs(FIXED_COLLISION_DMG)){ collisionDmg+=b.intensity; } if(collisionDmg>0)return collisionDmg; @@ -1661,4 +1661,7 @@ void Monster::SetPhase(const std::string&strategyName,int phase){ const int Monster::GetPhase(const std::string&strategyName){ if(!phase.contains(strategyName))phase[strategyName]=0; return this->phase[strategyName]; +} +const bool Monster::HasBuff(BuffType buff)const{ + return std::find_if(buffList.begin(),buffList.end(),[type=buff](const Buff&buff){return buff.type==type;})!=buffList.end(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 01cefcb3..18f28d28 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -86,9 +86,9 @@ public: const vf2d&GetPos()const; const int GetHealth()const; const int GetMaxHealth()const; - int GetAttack(); + int GetAttack()const; //This function returns the multiplier for the movespd from the base spd. So 100 movespd is 1.0. - float GetMoveSpdMult(); + float GetMoveSpdMult()const; //Obtains the size multiplier (from 0.f-1.f). float GetSizeMult()const; Animate2D::Frame GetFrame()const; @@ -149,8 +149,9 @@ public: void AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks,Buff::MonsterBuffExpireCallbackFunction expireCallback); void AddBuff(BuffType type,BuffRestorationType restorationType,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks); void AddBuff(BuffType type,BuffRestorationType restorationType,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks,Buff::MonsterBuffExpireCallbackFunction expireCallback); - std::vectorGetBuffs(BuffType buff)const; - std::vectorGetBuffs(std::vectorbuffs)const; + const bool HasBuff(BuffType buff)const; + const std::vectorGetBuffs(BuffType buff)const; + const std::vectorGetBuffs(std::vectorbuffs)const; //Removes all buffs of a given type. void RemoveBuff(BuffType type); State::State GetState(); @@ -370,6 +371,7 @@ private: static void PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::string strategy); static void PARROT(Monster&m,float fElapsedTime,std::string strategy); static void CRAB(Monster&m,float fElapsedTime,std::string strategy); + static void GIANT_CRAB(Monster&m,float fElapsedTime,std::string strategy); }; bool bumpedIntoTerrain=false; //Gets set to true before a strategy executes if the monster runs into some terrain on this frame. bool attackedByPlayer=false; //Gets set to true before a strategy executes if the monster has been attacked by the player. diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h index b5ef6e1b..94df958a 100644 --- a/Adventures in Lestoria/MonsterAttribute.h +++ b/Adventures in Lestoria/MonsterAttribute.h @@ -149,4 +149,5 @@ enum class Attribute{ PARROT_FLY_TIMER, MID_PHASE, RUM_DRINK_COUNT, + SPEED_RAMPUP_TIMER, }; \ No newline at end of file diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index 3006249c..e345ae1c 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -2290,7 +2290,15 @@ void Player::SetTestScreenAimingLocation(vf2d forcedAimingLoc){ testAimingLoc=forcedAimingLoc; } void Player::SetAbility4(const Ability&ability){ - + switch(GetClass()){ + case WARRIOR:{Warrior::ability4=ability;}break; + case RANGER:{Ranger::ability4=ability;}break; + case WIZARD:{Wizard::ability4=ability;}break; + case THIEF:{Thief::ability4=ability;}break; + case TRAPPER:{Trapper::ability4=ability;}break; + case WITCH:{Witch::ability4=ability;}break; + default:{ERR(std::format("WARNING! Class {} is invalid! THIS SHOULD NOT BE HAPPENING!",int(GetClass())));} + } } void Player::RemoveMoney(const uint32_t moneyCost){ @@ -2300,4 +2308,7 @@ void Player::RemoveMoney(const uint32_t moneyCost){ void Player::AddMoney(const uint32_t moneyCost){ SetMoney(GetMoney()+moneyCost); +} +const bool Player::HasBuff(BuffType buff)const{ + return std::find_if(buffList.begin(),buffList.end(),[type=buff](const Buff&buff){return buff.type==type;})!=buffList.end(); } \ No newline at end of file diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index aa81d892..0d93e6af 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -184,7 +184,7 @@ public: void AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks,Buff::PlayerBuffExpireCallbackFunction expireCallbackFunc); void AddBuff(BuffType type,BuffRestorationType restorationType,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks); void AddBuff(BuffType type,BuffRestorationType restorationType,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks,Buff::PlayerBuffExpireCallbackFunction expireCallbackFunc); - + const bool HasBuff(BuffType buff)const; const std::vectorGetBuffs(BuffType buff)const; const std::vectorGetStatBuffs(const std::vector&attr)const; diff --git a/Adventures in Lestoria/RUN_STRATEGY.cpp b/Adventures in Lestoria/RUN_STRATEGY.cpp index 0deaab39..c0ca4f12 100644 --- a/Adventures in Lestoria/RUN_STRATEGY.cpp +++ b/Adventures in Lestoria/RUN_STRATEGY.cpp @@ -74,6 +74,7 @@ void Monster::InitializeStrategies(){ STRATEGY_DATA.insert("Seagull",Monster::STRATEGY::SEAGULL); STRATEGY_DATA.insert("Sandworm",Monster::STRATEGY::SANDWORM); STRATEGY_DATA.insert("Parrot",Monster::STRATEGY::PARROT); + STRATEGY_DATA.insert("Giant Crab",Monster::STRATEGY::GIANT_CRAB); STRATEGY_DATA.SetInitialized(); } diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 35b423f2..c77bc116 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 11683 +#define VERSION_BUILD 11710 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/Campaigns/3_1.tmx b/Adventures in Lestoria/assets/Campaigns/3_1.tmx index 08825543..50b77c1b 100644 --- a/Adventures in Lestoria/assets/Campaigns/3_1.tmx +++ b/Adventures in Lestoria/assets/Campaigns/3_1.tmx @@ -1,5 +1,5 @@ - + @@ -1243,17 +1243,7 @@ - - - - - - - - - - - + diff --git a/Adventures in Lestoria/assets/config/MonsterStrategies.txt b/Adventures in Lestoria/assets/config/MonsterStrategies.txt index b5601763..5ecb55ed 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -1173,4 +1173,15 @@ MonsterStrategy Charge Wait Time = 0.3s Charge Max Time = 3s } + Giant Crab + { + Charge Time = 5s + Charge Wait Time = 1s + + Charge Extend Distance = 600 + + Movespeed Rampup Time = 2s + # Amount of movespeed gain by end of rampup time. + Movespeed Rampup Final Amount = 100% + } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/config/Monsters.txt b/Adventures in Lestoria/assets/config/Monsters.txt index c8a2637a..bf773486 100644 --- a/Adventures in Lestoria/assets/config/Monsters.txt +++ b/Adventures in Lestoria/assets/config/Monsters.txt @@ -1561,7 +1561,7 @@ Monsters Collision Radius = 10 - Strategy = Crab + Strategy = Giant Crab #Size of each animation frame SheetFrameSize = 48,48 diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 65e6186b..4fb0f924 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ