Move the player outline repeating timer into a new OnLevelStart() callback for the player. Fixes a bug where the player outline will no longer update after the initial stage. Added more player timer helper functions for better control. Release Build 11031.
This commit is contained in:
parent
f717abfa54
commit
45e6027c9e
@ -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.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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>&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<std::weak_ptr<Monster>,StackCount,Mar
|
||||
lockOnTargets.emplace_back(markData);
|
||||
}
|
||||
|
||||
void AiL::AddToSpecialMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCount,MarkTime>markData){
|
||||
lockOnSpecialTargets.emplace_back(markData);
|
||||
}
|
||||
|
||||
void AiL::_SetCurrentLevel(const MapName map){
|
||||
currentLevel=map;
|
||||
}
|
||||
|
@ -228,7 +228,9 @@ private:
|
||||
float targetZoom{1.f};
|
||||
float zoomAdjustSpeed{0.1f};
|
||||
std::vector<std::tuple<std::weak_ptr<Monster>,StackCount,MarkTime>>lockOnTargets;
|
||||
std::vector<std::tuple<std::weak_ptr<Monster>,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<std::string,TilesetData>&GetTilesets()const;
|
||||
void AddToMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCount,MarkTime>markData);
|
||||
void AddToSpecialMarkedTargetList(std::tuple<std::weak_ptr<Monster>,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.
|
||||
|
||||
|
@ -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}});
|
||||
|
@ -41,11 +41,11 @@ All rights reserved.
|
||||
#include "Monster.h"
|
||||
|
||||
Buff::Buff(std::variant<Player*,std::weak_ptr<Monster>>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<Player*,std::weak_ptr<Monster>>attachedTarget,BuffType type,float duration,float intensity,std::set<ItemAttribute> 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<Player*,std::weak_ptr<Monster>>attachedTarget,BuffType type,float duration,float intensity,std::set<std::string> 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<Player*,std::weak_ptr<Monster>>attachedTarget,BuffType t
|
||||
}
|
||||
|
||||
Buff::Buff(std::variant<Player*,std::weak_ptr<Monster>>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;
|
||||
|
@ -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<Player*,std::weak_ptr<Monster>>attachedTarget; //Who has this buff.
|
||||
PlayerBuffExpireCallbackFunction playerBuffCallbackFunc=[](Player*p,Buff&b){};
|
||||
MonsterBuffExpireCallbackFunction monsterBuffCallbackFunc=[](std::weak_ptr<Monster>m,Buff&b){};
|
||||
float originalDuration{};
|
||||
|
||||
Buff(std::variant<Player*,std::weak_ptr<Monster>>attachedTarget,BuffType type,float duration,float intensity);
|
||||
Buff(std::variant<Player*,std::weak_ptr<Monster>>attachedTarget,BuffType type,float duration,float intensity,std::set<ItemAttribute> attr);
|
||||
|
@ -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<Buff>&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<float>(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<Buff>&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<std::weak_ptr<Monster>>Monster::GetNearestMonster(const vf2d point,const float maxDistance,const bool onUpperLevel,const float z){
|
||||
std::optional<std::weak_ptr<Monster>>closestMonster;
|
||||
std::optional<std::weak_ptr<Monster>>closestGenericMonster;
|
||||
|
@ -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<geom2d::rect<float>>&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<std::weak_ptr<Monster>>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<Monster>&sharedMonsterPtr);
|
||||
std::weak_ptr<Monster>weakPtr;
|
||||
void LongLastingMarkEffect(float&out_markDuration); //Modifies a given duration.
|
||||
private:
|
||||
struct STRATEGY{
|
||||
static std::string ERR;
|
||||
|
@ -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<std::weak_ptr<Monster>>onScreenMonsters;
|
||||
std::copy_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),std::back_inserter(onScreenMonsters),[](const std::shared_ptr<Monster>&monster){
|
||||
geom2d::rect<float>gameView{game->camera.GetViewPosition(),game->camera.GetViewSize()};
|
||||
return geom2d::overlaps(gameView,geom2d::circle<float>(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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -41,4 +41,5 @@ enum class PlayerTimerType{
|
||||
DEADLY_MIRAGE_SECOND_CAST,
|
||||
ADRENALINE_STIM,
|
||||
PLAYER_OUTLINE_TIMER,
|
||||
OPPORTUNITY_SHOT_RANDOM_SPECIAL_MARK,
|
||||
};
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Binary file not shown.
BIN
Adventures in Lestoria/assets/sounds/lockon_special.ogg
Normal file
BIN
Adventures in Lestoria/assets/sounds/lockon_special.ogg
Normal file
Binary file not shown.
BIN
Adventures in Lestoria/assets/special_target.png
Normal file
BIN
Adventures in Lestoria/assets/special_target.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user