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 @@
-