diff --git a/Adventures in Lestoria Tests/MonsterTests.cpp b/Adventures in Lestoria Tests/MonsterTests.cpp index 183b6476..5334e42d 100644 --- a/Adventures in Lestoria Tests/MonsterTests.cpp +++ b/Adventures in Lestoria Tests/MonsterTests.cpp @@ -403,7 +403,7 @@ namespace MonsterTests Assert::AreEqual(0,testMonster.GetMarkStacks(),L"Monster has 0 marks initially."); - testMonster.AddBuff(BuffType::TRAPPER_MARK,7.f,5); //Apply 5 marks of Trapper Mark. + testMonster.ApplyMark(7.f,5U); Assert::AreEqual(5,testMonster.GetMarkStacks(),L"Monster has 5 marks after receiving a buff."); @@ -438,6 +438,11 @@ namespace MonsterTests Assert::AreEqual(1,testMonster.GetMarkStacks(),L"Monster should have 1 mark remaining after using TriggerMark function"); Assert::AreEqual(24,testMonster.GetHealth(),L"Monster should not take damage from the TriggerMark function (Mark deals 6 damage though)."); + + game->SetElapsedTime(10.f); + testMonster.Update(10.f); + + Assert::AreEqual(0,testMonster.GetMarkStacks(),L"The marks should have expired after 10 seconds."); } }; } \ No newline at end of file diff --git a/Adventures in Lestoria/Animation.cpp b/Adventures in Lestoria/Animation.cpp index bd602a57..acb1d2a2 100644 --- a/Adventures in Lestoria/Animation.cpp +++ b/Adventures in Lestoria/Animation.cpp @@ -331,6 +331,15 @@ void sig::Animation::InitializeAnimations(){ } ANIMATION_DATA[std::format("GOBLIN_BOW_ATTACK_{}",animationIndex)]=mountShootAnimation; } + + #pragma region Trapper Target Mark Debuff + AnimationData targetAnimData{.frameDuration{0.1f},.style{Animate2D::Style::Repeat}}; + Animate2D::FrameSequence targetAnim(targetAnimData.frameDuration,targetAnimData.style); + targetAnim.AddFrame({&GFX["target.png"],{{int(0*24),0},{24,24}}}); + targetAnim.AddFrame({&GFX["target.png"],{{int(0*24),0},{24,24}}}); + targetAnim.AddFrame({&GFX["target.png"],{{int(1*24),0},{24,24}}}); + ANIMATION_DATA["target.png"]=targetAnim; + #pragma endregion for(auto&dat:GFX){ std::string imgFile=dat.first; diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 7c307931..9bb96176 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -265,8 +265,10 @@ bool Monster::Update(float fElapsedTime){ monsterHurtSoundCooldown=std::max(0.f,monsterHurtSoundCooldown-fElapsedTime); lastHitPlayer=std::max(0.f,lastHitPlayer-fElapsedTime); lastPathfindingCooldown=std::max(0.f,lastPathfindingCooldown-fElapsedTime); + markApplicationTimer=std::max(0.f,markApplicationTimer-fElapsedTime); lastFacingDirectionChange+=fElapsedTime; timeSpentAlive+=fElapsedTime; + if(IsSolid()){ if(GetPos().y>=game->GetPlayer()->GetPos().y)solidFadeTimer=std::min(TileGroup::FADE_TIME,solidFadeTimer+game->GetElapsedTime()); else solidFadeTimer=std::max(0.f,solidFadeTimer-game->GetElapsedTime()); @@ -467,8 +469,28 @@ void Monster::Draw()const{ std::vectorshieldBuffs=GetBuffs(BARRIER_DAMAGE_REDUCTION); if(shieldBuffs.size()>0){ - game->view.DrawRotatedDecal(drawPos,GFX["block.png"].Decal(),0.f,GFX["block.png"].Sprite()->Size()/2,{GetSizeMult(),GetSizeMult()}); + game->view.DrawRotatedDecal(drawPos,GFX["block.png"].Decal(),0.f,GFX["block.png"].Sprite()->Size()/2,{GetSizeMult(),GetSizeMult()},blendCol); + } + + #pragma region Render Trapper Marked Targets + const uint8_t markStackCount{GetMarkStacks()}; + if(markStackCount>0){ + float markRotation{-util::lerp(0.f,10.f,markApplicationTimer/0.5f)*sin(PI*markApplicationTimer)}; + vf2d markScale{vf2d{}.lerp(vf2d{GetSizeMult(),GetSizeMult()},(0.5f-markApplicationTimer)/0.5f)}; + const Animate2D::Frame&markImg{ANIMATION_DATA["target.png"].GetFrame(game->GetRunTime())}; + Pixel markCol{markStackCount>1?WHITE:RED}; + const std::vector&buffList{GetBuffs(BuffType::TRAPPER_MARK)}; + float remainingStackDuration{}; + for(const Buff&b:buffList){ + if(b.type==BuffType::TRAPPER_MARK){ + remainingStackDuration=b.duration; + break; + } + } + if(remainingStackDuration<1.f)markCol.a*=remainingStackDuration; + game->view.DrawPartialRotatedDecal(drawPos,markImg.GetSourceImage()->Decal(),markRotation,markImg.GetSourceRect().size/2.f,markImg.GetSourceRect().pos,markImg.GetSourceRect().size,markScale,markCol); } + #pragma endregion if(GameSettings::TerrainCollisionBoxesEnabled()&&IsSolid()&&solidFadeTimer>0.f){ float distToPlayer=geom2d::line(game->GetPlayer()->GetPos(),GetPos()).length(); @@ -1201,7 +1223,7 @@ const std::optional>&Monster::GetRectangleCollision()const{ return MONSTER_DATA.at(GetName()).GetRectangleCollision(); } -const int Monster::GetMarkStacks()const{ +const uint8_t Monster::GetMarkStacks()const{ const std::vector&markBuffs{GetBuffs(BuffType::TRAPPER_MARK)}; int stackCount{}; for(const Buff&b:markBuffs){ @@ -1212,14 +1234,30 @@ const int Monster::GetMarkStacks()const{ void Monster::RemoveMarkStack(){ if(GetMarkStacks()<=0)ERR("WARNING! Tried to remove a mark stack, but no stacks exist. THIS SHOULD NOT BE HAPPENING!"); + bool removeMarkDebuff{false}; for(Buff&b:buffList){ if(b.type==BuffType::TRAPPER_MARK&&b.intensity>0){ b.intensity--; + if(b.intensity==0)removeMarkDebuff=true; break; } } + if(removeMarkDebuff)RemoveBuff(BuffType::TRAPPER_MARK); } void Monster::TriggerMark(){ Hurt(0,OnUpperLevel(),GetZ(),HurtFlag::PLAYER_ABILITY); +} + +void Monster::ApplyMark(float time,uint8_t stackCount){ + if(GetMarkStacks()>0){ + for(Buff&b:buffList){ + if(b.type==BuffType::TRAPPER_MARK){ + b.intensity+=stackCount; + b.duration=std::max(b.duration,time); + break; + } + } + }else AddBuff(BuffType::TRAPPER_MARK,time,stackCount); + markApplicationTimer=0.5f; } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 55b44fe1..ac8e77e3 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -199,8 +199,9 @@ public: const float GetModdedStatBonuses(std::string_view stat)const; //The collision rectangle is only used currently for determining the safe spots for the stone golem boss fight. const std::optional>&GetRectangleCollision()const; - const int GetMarkStacks()const; //Number of Trapper marks on this target. + const uint8_t GetMarkStacks()const; //Number of Trapper marks on this target. void TriggerMark(); //Deals no damage, but causes a mark proc to occur. + void ApplyMark(float time,uint8_t stackCount); //Adds stackCount mark stacks to the target, refreshing the buff to time time. private: //NOTE: Marking a monster for deletion does not trigger any death events. It just simply removes the monster from the field!! // The way this works is that monsters marked for deletion will cause the monster update loop to detect there's at least one or more monsters that must be deleted and will call erase_if on the list at the end of the iteration loop. @@ -283,6 +284,7 @@ private: float solidFadeTimer{0.f}; bool _Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag damageRule,HurtFlag::HurtFlag hurtFlags); void RemoveMarkStack(); + float markApplicationTimer{}; //Used for animations involving the mark being applied to the target. private: struct STRATEGY{ static std::string ERR; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index e85f6a84..b6894668 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 10262 +#define VERSION_BUILD 10264 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index e4c11d7a..8f0e1851 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -109,6 +109,7 @@ Images GFX_LargeRock = large_rock.png GFX_Dagger = dagger.png GFX_Shine = shine.png + GFX_TargetMark = target.png GFX_Thief_Sheet = nico-thief.png GFX_Trapper_Sheet = nico-trapper.png diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 756bc17f..244b30d1 100644 Binary files a/Adventures in Lestoria/assets/gamepack.pak and b/Adventures in Lestoria/assets/gamepack.pak differ diff --git a/Adventures in Lestoria/assets/target.png b/Adventures in Lestoria/assets/target.png new file mode 100644 index 00000000..5dfb5a23 Binary files /dev/null and b/Adventures in Lestoria/assets/target.png differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 7a1a38cc..91908612 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ