Finished converting Battle Cry to Entity compatibility. Add unit test to ensure block works for monsters.
This commit is contained in:
parent
81774b55f0
commit
00704856b0
@ -1094,30 +1094,39 @@
|
||||
<ClCompile Include="Spider.cpp" />
|
||||
<ClCompile Include="tests\BuffTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EffectTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EnchantTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EngineTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\FileTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\GeometryTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\ItemTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\MonsterTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\PlayerTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ThunderOrb.cpp" />
|
||||
<ClCompile Include="TileGroup.cpp" />
|
||||
|
||||
@ -69,10 +69,11 @@ namespace classutils{//Classes have bit-wise operator capabilities.
|
||||
}
|
||||
};
|
||||
|
||||
#define CONFIG_F(var)e.IsFriendly() ? var##_F : Monster::STRATEGY::_GetFloat(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName())
|
||||
#define CONFIG_I(var)e.IsFriendly() ? var##_I : Monster::STRATEGY::_GetInt(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName())
|
||||
#define CONFIG_S(var)e.IsFriendly() ? var##_S : Monster::STRATEGY::_GetString(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName())
|
||||
#define CONFIG_F(var)(e.IsFriendly() ? var##_F : Monster::STRATEGY::_GetFloat(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName()))
|
||||
#define CONFIG_f(var,index)(e.IsFriendly() ? var##_f[index] : Monster::STRATEGY::_GetFloat(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName(),index))
|
||||
#define CONFIG_I(var)(e.IsFriendly() ? var##_I : Monster::STRATEGY::_GetInt(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName()))
|
||||
#define CONFIG_S(var)(e.IsFriendly() ? var##_S : Monster::STRATEGY::_GetString(*e.ToMonster(),var,(*e.ToMonster()).GetStrategyName()))
|
||||
|
||||
#define IFPLAYER e.ForPlayer([](Player&p){
|
||||
#define IFMONSTER e.ForMonster([](Monster&m){
|
||||
#define IFPLAYER e.ForPlayer([&](Player&p){
|
||||
#define IFMONSTER e.ForMonster([&](Monster&m){
|
||||
#define ENDIF });
|
||||
@ -144,9 +144,17 @@ Buff&Entity::AddBuff(BuffType type,float duration,float intensity){
|
||||
CallClassFunc(AddBuff(type,duration,intensity));
|
||||
}
|
||||
|
||||
Buff&Entity::AddBuff(BuffType type,float duration,float intensity,std::set<std::string>attr){
|
||||
CallClassFunc(AddBuff(type,duration,intensity,attr));
|
||||
}
|
||||
|
||||
void Entity::ForPlayer(std::function<void(Player&p)>func){
|
||||
if(is(Player*))func(*get(Player*));
|
||||
}
|
||||
void Entity::ForMonster(std::function<void(Monster&p)>func){
|
||||
if(is(Monster*))func(*get(Monster*));
|
||||
}
|
||||
|
||||
const float Entity::GetZ()const{
|
||||
CallClassFunc(GetZ());
|
||||
}
|
||||
@ -75,12 +75,14 @@ public:
|
||||
const float GetMoveSpdMult()const;
|
||||
const float GetSizeMult()const;
|
||||
const int GetAttack()const;
|
||||
const float GetZ()const;
|
||||
const FriendlyType IsFriendly()const;
|
||||
const State::State GetState()const;
|
||||
const bool CanMove()const;
|
||||
const bool HasEnchant(const std::string&enchant)const;
|
||||
float&GetBlockTimer()const;
|
||||
Buff&AddBuff(BuffType type,float duration,float intensity);
|
||||
Buff&AddBuff(BuffType type,float duration,float intensity,std::set<std::string>attr);
|
||||
private:
|
||||
mutableconst std::variant<Monster*,Player*>entity;
|
||||
inline bool operator==(const Entity&rhs){return entity==rhs.entity;}
|
||||
|
||||
@ -573,10 +573,10 @@ void Monster::Draw()const{
|
||||
|
||||
const auto DrawBaseMonster=[&](vf2d scale={1.f,1.f},Pixel col=WHITE){
|
||||
game->view.DrawPartialRotatedDecal(drawPos,GetFrame().GetSourceImage()->Decal(),finalSpriteRot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,col);
|
||||
if(blockTimer>0.f)game->view.DrawPartialRotatedDecal(drawPos,GFX["block.png"].Decal(),finalSpriteRot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,col);
|
||||
};
|
||||
const auto DrawOverlayMonster=[&](vf2d scale={1.f,1.f},Pixel col=WHITE){
|
||||
game->view.DrawPartialRotatedDecal(drawPos,GFX[overlaySprite].Decal(),finalSpriteRot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,col);
|
||||
if(blockTimer>0.f)game->view.DrawPartialRotatedDecal(drawPos,GFX["block.png"].Decal(),finalSpriteRot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,col);
|
||||
};
|
||||
const auto DrawMountedMonster=[&](vf2d scale={1.f,1.f},Pixel col=WHITE){
|
||||
game->view.DrawPartialRotatedDecal(drawPos+mountedSprOffset,GetMountedFrame().value().GetSourceImage()->Decal(),finalSpriteRot,GetMountedFrame().value().GetSourceRect().size/2,GetMountedFrame().value().GetSourceRect().pos,GetMountedFrame().value().GetSourceRect().size,scale,col);
|
||||
@ -822,6 +822,7 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da
|
||||
#pragma endregion
|
||||
|
||||
mod_dmg-=mod_dmg*GetDamageReductionFromBuffs();
|
||||
if(blockTimer)mod_dmg=0;
|
||||
}
|
||||
|
||||
if(HitByPlayerAbility){
|
||||
@ -897,9 +898,7 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da
|
||||
SoundEffect::PlaySFX(GetHurtSound(),GetPos());
|
||||
}
|
||||
}
|
||||
if(game->InBossEncounter()&&isBoss){
|
||||
game->BossDamageDealt(int(mod_dmg));
|
||||
}
|
||||
if(game->InBossEncounter()&&isBoss)game->BossDamageDealt(int(mod_dmg));
|
||||
|
||||
using A=Attribute;
|
||||
GetInt(A::HITS_UNTIL_DEATH)=std::max(0,GetInt(A::HITS_UNTIL_DEATH)-1);
|
||||
|
||||
@ -485,13 +485,6 @@ private:
|
||||
vf2d addedVel{};
|
||||
std::weak_ptr<Monster>attachedTarget; //A monster attached to another monster can then use this to alter behaviors based on the state of that other monster.
|
||||
float unconsciousTimer{};
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
const bool IsUnconscious()const;
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
const float UnconsciousTime()const;
|
||||
bool manualIgnoreTerrain{false}; //A manual flag that can be toggled on to dynamically make this monster ignore terrain collision.
|
||||
float collisionRadius{}; //The collision radius can be modified, it's just set initially to the monster database entry.
|
||||
@ -511,7 +504,14 @@ private:
|
||||
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.
|
||||
uint8_t transparency{255U};
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
const bool IsUnconscious()const;
|
||||
float blockTimer{};
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
|
||||
struct MonsterSpawner{
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 13532
|
||||
#define VERSION_BUILD 13551
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -57,7 +57,7 @@ DEFINE_STRATEGY(WARRIORTHIEF)
|
||||
const float distToPlayer{util::distance(m.GetPos(),game->GetPlayer()->GetPos())};
|
||||
if(distToPlayer<100.f&&m.F(A::DEFENSIVE_COOLDOWN)<=0.f){
|
||||
m.F(A::DEFENSIVE_COOLDOWN)=ConfigFloat("Warrior.Right Click Ability.Cooldown");
|
||||
Warrior::rightClickAbility.action(&m,m.GetPos());
|
||||
Warrior::ability1.action(&m,m.GetPos());
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "config.h"
|
||||
#include "SoundEffect.h"
|
||||
#include<ranges>
|
||||
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_BULLET_LIST
|
||||
@ -125,17 +126,17 @@ void Warrior::InitializeClassAbilities(){
|
||||
#pragma endregion
|
||||
#pragma region Warrior Ability 1 (Battlecry)
|
||||
Warrior::ability1.action=
|
||||
[](Entity e,vf2d pos={}){Player*p=e.ToPlayer(); //TODO
|
||||
game->AddEffect(Effect{p->GetPos(),CONFIG_F("Warrior.Ability 1.EffectLifetime"),"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F});
|
||||
p->AddBuff(BuffType::STAT_UP,"Warrior.Ability 1.AttackUpDuration"_F,"Warrior.Ability 1.AttackIncrease"_F,{"Attack %"});
|
||||
p->AddBuff(BuffType::DAMAGE_REDUCTION,"Warrior.Ability 1.DamageReductionDuration"_F,"Warrior.Ability 1.DamageReduction"_F);
|
||||
for(std::shared_ptr<Monster>&m:MONSTER_LIST){
|
||||
if(m->GetSizeMult()>="Warrior.Ability 1.AffectedSizeRange"_f[0]&&m->GetSizeMult()<="Warrior.Ability 1.AffectedSizeRange"_f[1]&&geom2d::overlaps(geom2d::circle<float>(p->GetPos(),12*"Warrior.Ability 1.Range"_I/100.f),geom2d::circle<float>(m->GetPos(),m->GetSizeMult()*12))){
|
||||
m->AddBuff(BuffType::SLOWDOWN,"Warrior.Ability 1.SlowdownDuration"_F,"Warrior.Ability 1.SlowdownAmt"_F);
|
||||
if(p->HasEnchant("Battle Shout"))m->Hurt(p->GetDefense()*"Battle Shout"_ENC["DEFENSE DAMAGE"]/100.f,p->OnUpperLevel(),p->GetZ());
|
||||
}
|
||||
[](Entity e,vf2d pos={}){
|
||||
game->AddEffect(Effect{e.GetPos(),CONFIG_F("Warrior.Ability 1.EffectLifetime"),"battlecry_effect.png",e.OnUpperLevel(),CONFIG_F("Warrior.Ability 1.Range")/350,CONFIG_F("Warrior.Ability 1.EffectFadetime")});
|
||||
e.AddBuff(BuffType::STAT_UP,CONFIG_F("Warrior.Ability 1.AttackUpDuration"),CONFIG_F("Warrior.Ability 1.AttackIncrease"),{"Attack %"});
|
||||
e.AddBuff(BuffType::DAMAGE_REDUCTION,CONFIG_F("Warrior.Ability 1.DamageReductionDuration"),CONFIG_F("Warrior.Ability 1.DamageReduction"));
|
||||
|
||||
for(Entity&affectedEntity:game->GetTargetsInRange(e.GetPos(),12*CONFIG_I("Warrior.Ability 1.Range")/100.f,e.OnUpperLevel(),e.GetZ(),e.IsFriendly()?HurtType::MONSTER:HurtType::PLAYER)|std::views::filter([&e](Entity&filteredEnt){
|
||||
return filteredEnt.GetSizeMult()>=CONFIG_f("Warrior.Ability 1.AffectedSizeRange",0)&&filteredEnt.GetSizeMult()<=CONFIG_f("Warrior.Ability 1.AffectedSizeRange",1);})){
|
||||
affectedEntity.AddBuff(BuffType::SLOWDOWN,CONFIG_F("Warrior.Ability 1.SlowdownDuration"),CONFIG_F("Warrior.Ability 1.SlowdownAmt"));
|
||||
IFPLAYER{if(p.HasEnchant("Battle Shout"))affectedEntity.Hurt(p.GetDefense()*"Battle Shout"_ENC["DEFENSE DAMAGE"]/100.f,p.OnUpperLevel(),p.GetZ());}ENDIF
|
||||
}
|
||||
SoundEffect::PlaySFX("Warrior Battlecry",SoundEffect::CENTERED);
|
||||
SoundEffect::PlaySFX("Warrior Battlecry",e.GetPos());
|
||||
return true;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
@ -1481,5 +1481,34 @@ MonsterStrategy
|
||||
Warrior.Right Click Ability.Duration = 3s
|
||||
Warrior.Right Click Ability.SlowAmt = 0.3
|
||||
Warrior.Right Click Ability.Cooldown = 15s
|
||||
|
||||
# Amount of time in seconds the attack damage increase lasts.
|
||||
Warrior.Ability 1.AttackUpDuration = 10
|
||||
|
||||
# Percentage of attack damage to increase by.
|
||||
Warrior.Ability 1.AttackIncrease = 0.1
|
||||
|
||||
# Amount of time in seconds the damage reduction increase lasts.
|
||||
Warrior.Ability 1.DamageReductionDuration = 10
|
||||
|
||||
# Percentage of damage reduction to increase by.
|
||||
Warrior.Ability 1.DamageReduction = 0.1
|
||||
|
||||
# The smallest and largest size of enemies this ability affects (inclusive).
|
||||
Warrior.Ability 1.AffectedSizeRange = 0,1
|
||||
|
||||
# How long the applied slow debuff lasts in seconds.
|
||||
Warrior.Ability 1.SlowdownDuration = 6
|
||||
|
||||
# Percentage of speed down applied to affected enemies.
|
||||
Warrior.Ability 1.SlowdownAmt = 0.4
|
||||
|
||||
# Amount of time the effect lives for on-screen before fading begins.
|
||||
Warrior.Ability 1.EffectLifetime = 0.1
|
||||
# Amount of time the effect fades out.
|
||||
Warrior.Ability 1.EffectFadetime = 0.3
|
||||
Warrior.Ability 1.Cooldown = 12
|
||||
Warrior.Ability 1.Range = 500
|
||||
|
||||
}
|
||||
}
|
||||
@ -3,15 +3,15 @@ HUB = 2026-02-27 21:53:33.6533357
|
||||
TEST_MAP = 2026-01-26 20:40:12.7201277
|
||||
BOSS_1 = 2026-02-27 21:53:33.6513354
|
||||
WORLD_MAP = 2026-02-27 21:53:33.6568368
|
||||
CAMPAIGN_1_1 = 2026-01-21 20:30:58.3723266
|
||||
CAMPAIGN_1_1 = 2026-05-04 03:43:46.2305986
|
||||
BOSS_1_B = 2024-09-13 21:28:58.8886132
|
||||
BOSS_2 = 2026-01-21 20:30:58.4312572
|
||||
BOSS_3 = 2026-04-23 20:04:39.8919861
|
||||
BOSS_3_B = 2026-04-23 20:04:39.8919861
|
||||
BOSS_3_B = 2026-05-04 20:46:34.9920916
|
||||
CAMPAIGN_7_1 = 2024-09-13 21:28:58.8570782
|
||||
CAMPAIGN_1_4 = 2026-04-28 20:00:03.4806604
|
||||
CAMPAIGN_1_4 = 2026-05-04 20:46:34.9852665
|
||||
BOSS_2_B = 2026-01-21 20:30:58.4322614
|
||||
CAMPAIGN_1_2 = 2026-04-28 19:44:26.2017819
|
||||
CAMPAIGN_1_2 = 2026-05-04 20:46:34.9832592
|
||||
CAMPAIGN_1_3 = 2024-09-13 21:28:58.8532684
|
||||
CAMPAIGN_1_5 = 2024-09-13 21:28:58.8557772
|
||||
CAMPAIGN_4_8 = 2026-02-26 21:44:13.5419545
|
||||
@ -21,10 +21,10 @@ CAMPAIGN_1_B1 = 2024-09-13 21:28:58.8605592
|
||||
CAMPAIGN_1_8 = 2024-09-13 21:28:58.8595553
|
||||
CAMPAIGN_4_5 = 2026-02-26 21:44:13.5315825
|
||||
CAMPAIGN_2_1 = 2026-01-21 20:30:58.3756334
|
||||
CAMPAIGN_2_2 = 2026-04-28 19:44:26.2126272
|
||||
CAMPAIGN_2_3 = 2026-04-23 20:04:39.8896736
|
||||
CAMPAIGN_2_2 = 2026-05-04 20:46:34.9887816
|
||||
CAMPAIGN_2_3 = 2026-04-29 02:06:13.0636912
|
||||
CAMPAIGN_2_4 = 2026-01-21 20:30:58.3804324
|
||||
CAMPAIGN_2_5 = 2026-04-23 20:04:39.8906724
|
||||
CAMPAIGN_2_5 = 2026-05-04 20:46:34.9911006
|
||||
CAMPAIGN_2_6 = 2026-01-21 20:30:58.3836104
|
||||
CAMPAIGN_2_7 = 2026-01-21 20:30:58.3846135
|
||||
CAMPAIGN_2_8 = 2026-01-21 20:30:58.3866133
|
||||
@ -38,7 +38,7 @@ CAMPAIGN_3_5 = 2026-01-21 20:30:58.3977329
|
||||
CAMPAIGN_3_6 = 2026-01-21 20:30:58.4008008
|
||||
CAMPAIGN_3_7 = 2026-01-21 20:30:58.4023071
|
||||
CAMPAIGN_3_8 = 2026-01-21 20:30:58.4049027
|
||||
CAMPAIGN_3_B1 = 2026-04-23 20:04:39.8919861
|
||||
CAMPAIGN_3_B1 = 2026-05-04 20:46:34.9920916
|
||||
CAMPAIGN_4_1 = 2026-04-13 18:08:48.5353335
|
||||
CAMPAIGN_4_2 = 2026-02-26 21:44:13.5210572
|
||||
CAMPAIGN_4_4 = 2026-02-26 21:44:13.5270745
|
||||
|
||||
@ -636,3 +636,9 @@ TEST(MonsterTests,"MonsterManaRecoveryTest"){
|
||||
REQUIRE(testMonster.mp==1);
|
||||
REQUIRE(testMonster.mpRemainder==0.f);
|
||||
}
|
||||
TEST(MonsterTests,"MonsterBlockingTest"){
|
||||
Monster&fireMage{game->SpawnMonster({24,24},MONSTER_DATA.at("Skeleton Fire Mage"))};
|
||||
fireMage.blockTimer=5.f;
|
||||
fireMage.Hurt(100,fireMage.OnUpperLevel(),fireMage.GetZ());
|
||||
REQUIRE(fireMage.GetMaxHealth()==fireMage.GetHealth());
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user