diff --git a/Adventures in Lestoria Tests/EnchantTests.cpp b/Adventures in Lestoria Tests/EnchantTests.cpp index f8286482..5c058249 100644 --- a/Adventures in Lestoria Tests/EnchantTests.cpp +++ b/Adventures in Lestoria Tests/EnchantTests.cpp @@ -949,5 +949,25 @@ namespace EnchantTests trap.MonsterHit(newMonster,1); //Simulate 1 mark stack on the monster to trigger the bleed. Assert::AreEqual("Trapper.Ability 2.Marked Target Bleed"_f[1]+"Lingering Scent"_ENC["BLEED EXTRA DURATION"],newMonster.GetBuffs(BuffType::OVER_TIME)[0].duration,L"Bleed duration should be 10 seconds by default."); } + TEST_METHOD(SpecialMarkNoEnchantCheck){ + game->ChangePlayerClass(TRAPPER); + player=game->GetPlayer(); + Monster&newMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])}; + for(int i:std::ranges::iota_view(0,10)){ + game->SetElapsedTime(1.f); + game->OnUserUpdate(1.f); + } + Assert::AreEqual(size_t(0),newMonster.GetBuffs(BuffType::SPECIAL_MARK).size(),L"A special mark should not be spawned without the enchant."); + } + TEST_METHOD(SpecialMarkEnchantCheck){ + game->ChangePlayerClass(TRAPPER); + player=game->GetPlayer(); + Monster&newMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])}; + for(int i:std::ranges::iota_view(0,10)){ + game->SetElapsedTime(1.f); + game->OnUserUpdate(1.f); + } + Assert::AreEqual(size_t(1),newMonster.GetBuffs(BuffType::SPECIAL_MARK).size(),L"A special mark should spawned with the enchant."); + } }; } diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 9a4bf7b6..a1b3d701 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -2403,6 +2403,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){ backgroundEffects.clear(); foregroundEffects.clear(); lockOnTargets.clear(); + lockOnSpecialTargets.clear(); ItemDrop::drops.clear(); GameEvent::events.clear(); Audio::SetBGMPitch(1.f); @@ -2795,6 +2796,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){ SteamUserStats()->StoreStats(); ) ClearGarbage(); + + GetPlayer()->OnLevelStart(); return true; }); } @@ -4414,6 +4417,13 @@ void AiL::GlobalGameUpdates(){ } #pragma endregion + auto EnfeebledTargetEffect = [](const MarkTime&time,const std::weak_ptr&monster){ + if(game->GetPlayer()->HasEnchant("Enfeebled Target")){ + monster.lock()->AddBuff(BuffType::SLOWDOWN,time,"Enfeebled Target"_ENC["SLOW PCT"]/100.f); + monster.lock()->AddBuff(BuffType::STAT_UP,time,-"Enfeebled Target"_ENC["DAMAGE REDUCTION PCT"]/100.f,{"Attack %"}); + } + }; + #pragma region Marked Targets Update if(lockOnTargets.size()>0){ lastLockOnTargetTime=std::max(0.f,lastLockOnTargetTime-GetElapsedTime()); @@ -4421,10 +4431,7 @@ void AiL::GlobalGameUpdates(){ const auto&[monster,stackCount,time]=lockOnTargets.front(); if(!monster.expired()){ monster.lock()->AddBuff(BuffType::TRAPPER_MARK,time,stackCount); - if(game->GetPlayer()->HasEnchant("Enfeebled Target")){ - monster.lock()->AddBuff(BuffType::SLOWDOWN,time,"Enfeebled Target"_ENC["SLOW PCT"]/100.f); - monster.lock()->AddBuff(BuffType::STAT_UP,time,-"Enfeebled Target"_ENC["DAMAGE REDUCTION PCT"]/100.f,{"Attack %"}); - } + EnfeebledTargetEffect(time,monster); SoundEffect::PlaySFX("Lock On",monster.lock()->GetPos()); lastLockOnTargetTime=0.2f; } @@ -4432,6 +4439,21 @@ void AiL::GlobalGameUpdates(){ } } #pragma endregion + #pragma region Special Marked Targets Update + if(lockOnSpecialTargets.size()>0){ + lastLockOnSpecialTargetTime=std::max(0.f,lastLockOnSpecialTargetTime-GetElapsedTime()); + if(lastLockOnSpecialTargetTime<=0.f){ + const auto&[monster,stackCount,time]=lockOnSpecialTargets.front(); + if(!monster.expired()){ + monster.lock()->AddBuff(BuffType::SPECIAL_MARK,time,stackCount); + EnfeebledTargetEffect(time,monster); + SoundEffect::PlaySFX("Lock On Special",monster.lock()->GetPos()); + lastLockOnSpecialTargetTime=0.2f; + } + lockOnSpecialTargets.erase(lockOnSpecialTargets.begin()); + } + } + #pragma endregion if(GetMousePos()!=lastMousePos){ lastMouseMovement=0.f; @@ -4565,6 +4587,10 @@ void AiL::AddToMarkedTargetList(std::tuple,StackCount,Mar lockOnTargets.emplace_back(markData); } +void AiL::AddToSpecialMarkedTargetList(std::tuple,StackCount,MarkTime>markData){ + lockOnSpecialTargets.emplace_back(markData); +} + void AiL::_SetCurrentLevel(const MapName map){ currentLevel=map; } diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h index 8615ee90..5b419e13 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.h +++ b/Adventures in Lestoria/AdventuresInLestoria.h @@ -228,7 +228,9 @@ private: float targetZoom{1.f}; float zoomAdjustSpeed{0.1f}; std::vector,StackCount,MarkTime>>lockOnTargets; + std::vector,StackCount,MarkTime>>lockOnSpecialTargets; float lastLockOnTargetTime{}; + float lastLockOnSpecialTargetTime{}; void AdminConsole(); virtual bool OnConsoleCommand(const std::string& sCommand)override final; Pixel vignetteOverlayCol{"Interface.Vignette Color"_Pixel}; @@ -387,6 +389,7 @@ public: void PlayFootstepSound(); const std::map&GetTilesets()const; void AddToMarkedTargetList(std::tuple,StackCount,MarkTime>markData); + void AddToSpecialMarkedTargetList(std::tuple,StackCount,MarkTime>markData); void InitializeClasses(); void _SetCurrentLevel(const MapName map); //NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level. diff --git a/Adventures in Lestoria/Animation.cpp b/Adventures in Lestoria/Animation.cpp index 7d48bf93..74230916 100644 --- a/Adventures in Lestoria/Animation.cpp +++ b/Adventures in Lestoria/Animation.cpp @@ -419,6 +419,12 @@ void sig::Animation::InitializeAnimations(){ 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; + AnimationData specialTargetAnimData{.frameDuration{0.1f},.style{Animate2D::Style::Repeat}}; + Animate2D::FrameSequence specialTargetAnim(specialTargetAnimData.frameDuration,specialTargetAnimData.style); + specialTargetAnim.AddFrame({&GFX["special_target.png"],{{int(0*24),0},{24,24}}}); + specialTargetAnim.AddFrame({&GFX["special_target.png"],{{int(0*24),0},{24,24}}}); + specialTargetAnim.AddFrame({&GFX["special_target.png"],{{int(1*24),0},{24,24}}}); + ANIMATION_DATA["special_target.png"]=specialTargetAnim; #pragma endregion CreateHorizontalAnimationSequence("bear_trap.png",3,{24,24},AnimationData{.frameDuration{0.1f},.style{Animate2D::Style::PingPong}}); diff --git a/Adventures in Lestoria/Buff.cpp b/Adventures in Lestoria/Buff.cpp index e9aad0bd..4b7395e2 100644 --- a/Adventures in Lestoria/Buff.cpp +++ b/Adventures in Lestoria/Buff.cpp @@ -41,11 +41,11 @@ All rights reserved. #include "Monster.h" Buff::Buff(std::variant>attachedTarget,BuffType type,float duration,float intensity) - :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity){} + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity),originalDuration(this->duration){} Buff::Buff(std::variant>attachedTarget,BuffType type,float duration,float intensity,std::set attr) - :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity),attr(attr){} + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity),attr(attr),originalDuration(this->duration){} Buff::Buff(std::variant>attachedTarget,BuffType type,float duration,float intensity,std::set attr) - :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity){ + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity),originalDuration(this->duration){ for(const std::string&s:attr){ this->attr.insert(ItemAttribute::attributes.at(s)); } @@ -109,7 +109,7 @@ Buff::Buff(std::variant>attachedTarget,BuffType t } Buff::Buff(std::variant>attachedTarget,BuffType type,BuffRestorationType restorationType,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks) - :attachedTarget(attachedTarget),type(type),restorationType(restorationType),duration(duration),intensity(intensity),nextTick(timeBetweenTicks),timeBetweenTicks(timeBetweenTicks),overTimeType(overTimeType){} + :attachedTarget(attachedTarget),type(type),restorationType(restorationType),duration(duration),intensity(intensity),nextTick(timeBetweenTicks),timeBetweenTicks(timeBetweenTicks),overTimeType(overTimeType),originalDuration(this->duration){} void Buff::Update(AiL*game,float fElapsedTime){ duration-=fElapsedTime; diff --git a/Adventures in Lestoria/Buff.h b/Adventures in Lestoria/Buff.h index a855c9c3..2083ba5b 100644 --- a/Adventures in Lestoria/Buff.h +++ b/Adventures in Lestoria/Buff.h @@ -52,6 +52,7 @@ enum BuffType{ SELF_INFLICTED_SLOWDOWN, //Used for monsters and can't be applied by any player abilities. ADRENALINE_RUSH, //Intensity indicates the stack count (used by the Bloodlust enchant) this buff gives which in turn increases attack. TRAPPER_MARK, + SPECIAL_MARK, //The mark applied by the Opportunity Shot. OVER_TIME, ONE_OFF, //This is used as a hack fix for the RestoreDuringCast Item script since they require us to restore 1 tick immediately. Over time buffs do not apply a tick immediately. OVER_TIME_DURING_CAST, @@ -94,6 +95,7 @@ struct Buff{ std::variant>attachedTarget; //Who has this buff. PlayerBuffExpireCallbackFunction playerBuffCallbackFunc=[](Player*p,Buff&b){}; MonsterBuffExpireCallbackFunction monsterBuffCallbackFunc=[](std::weak_ptrm,Buff&b){}; + float originalDuration{}; Buff(std::variant>attachedTarget,BuffType type,float duration,float intensity); Buff(std::variant>attachedTarget,BuffType type,float duration,float intensity,std::set attr); diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index fb876c7c..4dbcf726 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -525,6 +525,32 @@ void Monster::Draw()const{ game->view.DrawPartialRotatedDecal(drawPos,markImg.GetSourceImage()->Decal(),markRotation,markImg.GetSourceRect().size/2.f,markImg.GetSourceRect().pos,markImg.GetSourceRect().size,markScale,markCol); } #pragma endregion + #pragma region Render Trapper Special Marked Targets + const uint8_t specialMarkStackCount{GetSpecialMarkStacks()}; + float specialMarkOriginalDuration{}; + if(specialMarkStackCount>0){ + const std::vector&buffList{GetBuffs(BuffType::SPECIAL_MARK)}; + float remainingStackDuration{}; + for(const Buff&b:buffList){ + if(b.type==BuffType::SPECIAL_MARK){ + remainingStackDuration=b.duration; + specialMarkOriginalDuration=b.originalDuration; + break; + } + } + const bool OpportunityShotActive{game->GetPlayer()->HasEnchant("Opportunity Shot")&&specialMarkOriginalDuration-remainingStackDuration<="Opportunity Shot"_ENC["MARK TRIGGER TIME"]}; + + float markRotation{-util::lerp(0.f,10.f,specialMarkApplicationTimer/0.5f)*sin(PI*specialMarkApplicationTimer)}; + vf2d markScale{vf2d{}.lerp(vf2d{GetSizeMult(),GetSizeMult()},(0.5f-specialMarkApplicationTimer)/0.5f)}; + + Animate2D::Frame markImg={ANIMATION_DATA["target.png"].GetFrame(game->GetRunTime())}; + if(OpportunityShotActive)markImg={ANIMATION_DATA["special_target.png"].GetFrame(game->GetRunTime())}; + + Pixel markCol{WHITE}; + 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(); @@ -694,8 +720,18 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da } if(HitByPlayerAbility){ - if(GetMarkStacks()>0){ + auto ApplyMarkEffects=[&](){ Hurt(game->GetPlayer()->GetAttack()*"Trapper.Ability 1.Damage Increase Bonus"_F/100.f,OnUpperLevel(),GetZ(),HurtFlag::DOT); + }; + + if(GetSpecialMarkStacks()>0){ + ApplyMarkEffects(); + const Buff specialMarkBuff{GetBuffs(BuffType::SPECIAL_MARK)[0]}; + if(game->GetPlayer()->HasEnchant("Opportunity Shot")&&specialMarkBuff.originalDuration-specialMarkBuff.duration<="Opportunity Shot"_ENC["MARK TRIGGER TIME"])Trapper::ability1.cooldown-="Opportunity Shot"_ENC["MARK COOLDOWN REDUCE"]; + RemoveSpecialMarkStack(); + }else + if(GetMarkStacks()>0){ + ApplyMarkEffects(); RemoveMarkStack(); } if(game->GetPlayer()->HasEnchant("Lethal Tempo")){ @@ -1310,6 +1346,15 @@ const uint8_t Monster::GetMarkStacks()const{ return stackCount; } +const uint8_t Monster::GetSpecialMarkStacks()const{ + const std::vector&markBuffs{GetBuffs(BuffType::SPECIAL_MARK)}; + int stackCount{}; + for(const Buff&b:markBuffs){ + stackCount+=b.intensity; + } + return stackCount; +} + void Monster::RemoveMarkStack(){ if(!IsAlive())return; if(GetMarkStacks()<=0)ERR("WARNING! Tried to remove a mark stack, but no stacks exist. THIS SHOULD NOT BE HAPPENING!"); @@ -1324,13 +1369,31 @@ void Monster::RemoveMarkStack(){ if(removeMarkDebuff)RemoveBuff(BuffType::TRAPPER_MARK); } +void Monster::RemoveSpecialMarkStack(){ + if(!IsAlive())return; + if(GetSpecialMarkStacks()<=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::SPECIAL_MARK&&b.intensity>0){ + b.intensity--; + if(b.intensity==0)removeMarkDebuff=true; + break; + } + } + if(removeMarkDebuff)RemoveBuff(BuffType::SPECIAL_MARK); +} + void Monster::TriggerMark(){ Hurt(0,OnUpperLevel(),GetZ(),HurtFlag::PLAYER_ABILITY); } +void Monster::LongLastingMarkEffect(float&out_markDuration){ + if(game->GetPlayer()->HasEnchant("Long-Lasting Mark"))out_markDuration="Long-Lasting Mark"_ENC["DURATION"]; +} + void Monster::ApplyMark(float time,uint8_t stackCount){ float markDuration{time}; - if(game->GetPlayer()->HasEnchant("Long-Lasting Mark"))markDuration="Long-Lasting Mark"_ENC["DURATION"]; + LongLastingMarkEffect(markDuration); if(GetMarkStacks()>0){ for(Buff&b:buffList){ @@ -1347,6 +1410,25 @@ void Monster::ApplyMark(float time,uint8_t stackCount){ markApplicationTimer=0.5f; } +void Monster::ApplySpecialMark(float time,uint8_t stackCount){ + float markDuration{time}; + LongLastingMarkEffect(markDuration); + + if(GetSpecialMarkStacks()>0){ + for(Buff&b:buffList){ + if(b.type==BuffType::SPECIAL_MARK){ + b.intensity+=stackCount; + + b.duration=std::max(b.duration,markDuration); + break; + } + } + }else{ + game->AddToSpecialMarkedTargetList({GetWeakPointer(),stackCount,markDuration}); + } + markApplicationTimer=0.5f; +} + std::optional>Monster::GetNearestMonster(const vf2d point,const float maxDistance,const bool onUpperLevel,const float z){ std::optional>closestMonster; std::optional>closestGenericMonster; diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 1445067d..e1e73a34 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -204,8 +204,10 @@ public: //The collision rectangle is only used currently for determining the safe spots for the stone golem boss fight. const std::optional>&GetRectangleCollision()const; const uint8_t GetMarkStacks()const; //Number of Trapper marks on this target. + const uint8_t GetSpecialMarkStacks()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. + void ApplySpecialMark(float time,uint8_t stackCount); //Adds stackCount special mark stacks to the target, refreshing the buff to time time. //Gets the nearest target that can be immediately targeted static std::optional>GetNearestMonster(const vf2d point,const float maxDistance,const bool onUpperLevel,const float z); const bool InUndamageableState(const bool onUpperLevel,const float z)const; @@ -298,9 +300,12 @@ private: float solidFadeTimer{0.f}; bool _Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag damageRule,HurtFlag::HurtFlag hurtFlags); void RemoveMarkStack(); + void RemoveSpecialMarkStack(); float markApplicationTimer{}; //Used for animations involving the mark being applied to the target. + float specialMarkApplicationTimer{}; //Used for animations involving the mark being applied to the target. void SetWeakPointer(std::shared_ptr&sharedMonsterPtr); std::weak_ptrweakPtr; + void LongLastingMarkEffect(float&out_markDuration); //Modifies a given duration. private: struct STRATEGY{ static std::string ERR; diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index 6e1a7c22..4321aaa0 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -121,8 +121,24 @@ void Player::Initialize(){ } afterImage.Decal()->Update(); playerOutline.Create(24,24); - +} + +void Player::OnLevelStart(){ AddTimer(PlayerTimerType::PLAYER_OUTLINE_TIMER,Timer{"Player Outline Update Timer",0.05f,[&](){UpdatePlayerOutline();},Timer::REPEAT}); + AddTimer(PlayerTimerType::OPPORTUNITY_SHOT_RANDOM_SPECIAL_MARK,Timer{"Opportunity Shot","Opportunity Shot"_ENC["MARK TIME"],[&](){ + if(HasEnchant("Opportunity Shot")){ + std::vector>onScreenMonsters; + std::copy_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),std::back_inserter(onScreenMonsters),[](const std::shared_ptr&monster){ + geom2d::rectgameView{game->camera.GetViewPosition(),game->camera.GetViewSize()}; + return geom2d::overlaps(gameView,geom2d::circle(monster->GetPos(),monster->GetCollisionRadius())); + }); + if(onScreenMonsters.size()>0){ + uint8_t randomChoice{uint8_t(util::random()%onScreenMonsters.size())}; + onScreenMonsters[randomChoice].lock()->ApplySpecialMark("Trapper.Ability 1.Duration"_F,1U); + } + + } + },Timer::TimerType::REPEAT}); } void Player::InitializeMinimapImage(){ @@ -803,7 +819,6 @@ void Player::Update(float fElapsedTime){ } #pragma endregion - #pragma region Handle knockup timers if(knockUpTimer>0.f){ knockUpTimer=std::max(0.f,knockUpTimer-fElapsedTime); @@ -2077,6 +2092,10 @@ Timer&Player::AddTimer(const PlayerTimerType type,const Timer&timer){ return newTimer; } +const bool Player::HasTimer(const PlayerTimerType type)const{ + return timers.count(type); +} + Timer&Player::GetTimer(const PlayerTimerType type){ return timers.at(type); } diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index 25cb0619..ed74445d 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -315,6 +315,7 @@ public: const bool HasEnchantWithAbilityAffected(const std::string_view abilityName)const; //Returns whether or not the player has an enchant that affects the provided name. Timer&AddTimer(const PlayerTimerType type,const Timer&timer); Timer&GetTimer(const PlayerTimerType type); + const bool HasTimer(const PlayerTimerType type)const; void CancelTimer(const PlayerTimerType type); void ResetTimers(); void _ForceCastSpell(Ability&ability); @@ -406,6 +407,7 @@ private: Renderable playerOutline; void UpdatePlayerOutline(); void OnBuffAdd(Buff&newBuff); + void OnLevelStart(); protected: const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F; const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F; diff --git a/Adventures in Lestoria/PlayerTimerType.h b/Adventures in Lestoria/PlayerTimerType.h index 34718fd2..97bd1d7d 100644 --- a/Adventures in Lestoria/PlayerTimerType.h +++ b/Adventures in Lestoria/PlayerTimerType.h @@ -41,4 +41,5 @@ enum class PlayerTimerType{ DEADLY_MIRAGE_SECOND_CAST, ADRENALINE_STIM, PLAYER_OUTLINE_TIMER, + OPPORTUNITY_SHOT_RANDOM_SPECIAL_MARK, }; \ No newline at end of file diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 9a547e6e..bc0b38f0 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 11022 +#define VERSION_BUILD 11031 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/assets/config/audio/events.txt b/Adventures in Lestoria/assets/config/audio/events.txt index 4c28863b..df3508d8 100644 --- a/Adventures in Lestoria/assets/config/audio/events.txt +++ b/Adventures in Lestoria/assets/config/audio/events.txt @@ -221,6 +221,12 @@ Events # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) File[0] = lockon.ogg, 100%, 140%, 140% } + Lock On Special + { + CombatSound = True + # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) + File[0] = lockon_special.ogg, 100% + } Menu Navigate { # Muted for now. diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index d273b76e..b57d1f18 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -122,6 +122,7 @@ Images GFX_MonsterSoul = monstersoul.png GFX_MonsterSoulGlow = monstersoulglow.png GFX_Glow = glow.png + GFX_SpecialTargetMark = special_target.png GFX_Thief_Sheet = nico-thief.png GFX_Trapper_Sheet = nico-trapper.png diff --git a/Adventures in Lestoria/assets/config/items/ItemEnchants.txt b/Adventures in Lestoria/assets/config/items/ItemEnchants.txt index 1c82438d..b4edbff9 100644 --- a/Adventures in Lestoria/assets/config/items/ItemEnchants.txt +++ b/Adventures in Lestoria/assets/config/items/ItemEnchants.txt @@ -286,7 +286,7 @@ Item Enchants } Opportunity Shot { - Description = "Every {MARK TIME} seconds a random enemy on screen gets {MARK AMOUNT} Mark. If a mark on that Target is triggered within {MARK TRIGGER TIME} seconds, your Mark Target's cooldown is reduced by {MARK COOLDOWN REDUCE} seconds." + Description = "Every {MARK TIME} seconds an enemy gets marked. If triggered within {MARK TRIGGER TIME} seconds, Mark Target's cooldown is reduced by {MARK COOLDOWN REDUCE} seconds." Affects = Auto Attack MARK TIME = 8s diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 5fdf8ffe..51eb3b69 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/sounds/lockon_special.ogg b/Adventures in Lestoria/assets/sounds/lockon_special.ogg new file mode 100644 index 00000000..522a84fa Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/lockon_special.ogg differ diff --git a/Adventures in Lestoria/assets/special_target.png b/Adventures in Lestoria/assets/special_target.png new file mode 100644 index 00000000..c74d1292 Binary files /dev/null and b/Adventures in Lestoria/assets/special_target.png differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 79d49de4..629311d4 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ