diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index 902ded40..24a1c65c 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -732,6 +732,10 @@ + + + + @@ -748,6 +752,10 @@ + + + + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 12302572..6cd88614 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -1139,6 +1139,12 @@ Source Files\Bullet Types + + Source Files\Bullet Types + + + Source Files + diff --git a/Adventures in Lestoria/Animation.cpp b/Adventures in Lestoria/Animation.cpp index acb1d2a2..f3f2c36b 100644 --- a/Adventures in Lestoria/Animation.cpp +++ b/Adventures in Lestoria/Animation.cpp @@ -341,6 +341,8 @@ void sig::Animation::InitializeAnimations(){ ANIMATION_DATA["target.png"]=targetAnim; #pragma endregion + CreateHorizontalAnimationSequence("bear_trap.png",3,{24,24},AnimationData{.frameDuration{0.1f},.style{Animate2D::Style::PingPong}}); + for(auto&dat:GFX){ std::string imgFile=dat.first; if(!ANIMATION_DATA.count(imgFile)){ diff --git a/Adventures in Lestoria/Arrow.cpp b/Adventures in Lestoria/Arrow.cpp index 592c3491..fb36c430 100644 --- a/Adventures in Lestoria/Arrow.cpp +++ b/Adventures in Lestoria/Arrow.cpp @@ -97,13 +97,13 @@ BulletDestroyState Arrow::PlayerHit(Player*player) return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState Arrow::MonsterHit(Monster& monster) +BulletDestroyState Arrow::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { fadeOutTime=0.2f; game->AddEffect(std::make_unique(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25)); return BulletDestroyState::KEEP_ALIVE; } -void Arrow::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void Arrow::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/BearTrap.cpp b/Adventures in Lestoria/BearTrap.cpp new file mode 100644 index 00000000..e3a3fe84 --- /dev/null +++ b/Adventures in Lestoria/BearTrap.cpp @@ -0,0 +1,76 @@ +#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 "BulletTypes.h" +#include "AdventuresInLestoria.h" + +INCLUDE_ANIMATION_DATA +INCLUDE_game + +BearTrap::BearTrap(vf2d pos,float radius,int damage,float fadeinTime,float fadeoutTime,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale) + :Bullet(pos,{},radius,damage,"Ability Icons/bear_trap.png",upperLevel,hitsMultiple,lifetime,false,friendly,col,scale,0.f,"Trap Hit"){ + fadeInTime=fadeinTime; + animation.AddState("bear_trap.png",ANIMATION_DATA["bear_trap.png"]); + if(!friendly)ERR("WARNING! Trying to use unimplemented enemy version of the Bear Trap Bullet!"); +} +void BearTrap::ModifyOutgoingDamageData(HurtDamageInfo&data){ + data.hurtFlags|=HurtFlag::PLAYER_ABILITY; +} + +BulletDestroyState BearTrap::PlayerHit(Player*player){ + fadeOutTime=0.5f; + animation.ChangeState(internal_animState,"bear_trap.png"); + return BulletDestroyState::KEEP_ALIVE; +} + +BulletDestroyState BearTrap::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ + fadeOutTime=0.5f; + animation.ChangeState(internal_animState,"bear_trap.png"); + + const float bleedDamage{"Trapper.Ability 2.Marked Target Bleed"_f[0]/100.f*game->GetPlayer()->GetAttack()}; + const float bleedDuration{"Trapper.Ability 2.Marked Target Bleed"_f[1]}; + const float timeBetweenTicks{"Trapper.Ability 2.Marked Target Bleed"_f[2]}; + + if(markStacksBeforeHit>0){ + const uint8_t resetStackCount{uint8_t("Trapper.Ability 2.Marked Target Stack Count Reset"_I)+1U}; //Add an additional stack because we know the target hit is about to lose one stack. + const uint8_t numberOfStacksToReplenish{uint8_t(resetStackCount-monster.GetMarkStacks())}; + monster.ApplyMark("Trapper.Ability 2.Marked Target Reset Time"_F,numberOfStacksToReplenish); + monster.AddBuff(BuffRestorationType::OVER_TIME,BuffOverTimeType::HP_DAMAGE_OVER_TIME,bleedDuration,bleedDamage,timeBetweenTicks); + } + return BulletDestroyState::KEEP_ALIVE; +} \ No newline at end of file diff --git a/Adventures in Lestoria/Bomb.cpp b/Adventures in Lestoria/Bomb.cpp index 651b9782..9d18a65e 100644 --- a/Adventures in Lestoria/Bomb.cpp +++ b/Adventures in Lestoria/Bomb.cpp @@ -97,7 +97,7 @@ void Bomb::Update(float fElapsedTime){ BulletDestroyState Bomb::PlayerHit(Player*player){ return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState Bomb::MonsterHit(Monster&monster){ +BulletDestroyState Bomb::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ return BulletDestroyState::KEEP_ALIVE; } @@ -106,4 +106,4 @@ void Bomb::Draw(const Pixel blendCol)const{ game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()},bomb_animation.GetFrame(animation).GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,bomb_animation.GetFrame(animation).GetSourceRect().size/2,bomb_animation.GetFrame(animation).GetSourceRect().pos,bomb_animation.GetFrame(animation).GetSourceRect().size,scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,uint8_t(util::lerp(col.a,0,1-((fadeOutTime-GetFadeoutTimer())/fadeOutTime)))}); } -void Bomb::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Bomb::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/Buff.cpp b/Adventures in Lestoria/Buff.cpp new file mode 100644 index 00000000..3d0f9980 --- /dev/null +++ b/Adventures in Lestoria/Buff.cpp @@ -0,0 +1,101 @@ +#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 "Buff.h" +#include "Player.h" +#include "Monster.h" + + +Buff::Buff(std::variantattachedTarget,BuffType type,float duration,float intensity) + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity){} +Buff::Buff(std::variantattachedTarget,BuffType type,float duration,float intensity,std::set attr) + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity),attr(attr){} +Buff::Buff(std::variantattachedTarget,BuffType type,float duration,float intensity,std::set attr) + :attachedTarget(attachedTarget),type(type),duration(duration),intensity(intensity){ + for(const std::string&s:attr){ + this->attr.insert(ItemAttribute::attributes.at(s)); + } +} +Buff::Buff(std::variantattachedTarget,BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks) + :attachedTarget(attachedTarget),type(type==BuffRestorationType::OVER_TIME||type==BuffRestorationType::ONE_OFF?OVER_TIME:OVER_TIME_DURING_CAST),duration(duration),intensity(intensity),nextTick(duration-timeBetweenTicks),timeBetweenTicks(timeBetweenTicks),overTimeType(overTimeType){} + +void Buff::Update(AiL*game,float fElapsedTime){ + duration-=fElapsedTime; + if(enabled&&overTimeType.has_value()&&nextTick>0&&durationHeal(intensity); + else IfEntity(Monster)GetEntity(Monster)->Heal(intensity); + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + case MP_RESTORATION:{ + IfEntity(Player)GetEntity(Player)->RestoreMana(intensity); + else IfEntity(Monster)ERR("WARNING! Monsters don't have mana, this functionality is not supported!") + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + case HP_PCT_RESTORATION:{ + IfEntity(Player)GetEntity(Player)->Heal(GetEntity(Player)->GetMaxHealth()*intensity/100.f); + else IfEntity(Monster)GetEntity(Monster)->Heal(GetEntity(Monster)->GetMaxHealth()*intensity/100.f); + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + case MP_PCT_RESTORATION:{ + IfEntity(Player)GetEntity(Player)->RestoreMana(GetEntity(Player)->GetMaxMana()*intensity/100.f); + else IfEntity(Monster)ERR("WARNING! Monsters don't have mana, this functionality is not supported!") + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + case HP_DAMAGE_OVER_TIME:{ + IfEntity(Player)GetEntity(Player)->Hurt(intensity,GetEntity(Player)->OnUpperLevel(),GetEntity(Player)->GetZ(),HurtFlag::DOT); + else IfEntity(Monster)GetEntity(Monster)->Hurt(intensity,GetEntity(Monster)->OnUpperLevel(),GetEntity(Monster)->GetZ(),HurtFlag::DOT); + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + case HP_PCT_DAMAGE_OVER_TIME:{ + IfEntity(Player)GetEntity(Player)->Hurt(GetEntity(Player)->GetMaxHealth()*intensity/100.f,GetEntity(Player)->OnUpperLevel(),GetEntity(Player)->GetZ(),HurtFlag::DOT); + else IfEntity(Monster)GetEntity(Monster)->Hurt(GetEntity(Monster)->GetMaxHealth()*intensity/100.f,GetEntity(Monster)->OnUpperLevel(),GetEntity(Monster)->GetZ(),HurtFlag::DOT); + else ERR("WARNING! Buff Over Time attached Target is somehow not a Player nor a Monster Pointer! THIS SHOULD NOT BE HAPPENING!") + }break; + } +} \ No newline at end of file diff --git a/Adventures in Lestoria/Buff.h b/Adventures in Lestoria/Buff.h index 8ab1e7aa..ef36fdf3 100644 --- a/Adventures in Lestoria/Buff.h +++ b/Adventures in Lestoria/Buff.h @@ -44,8 +44,6 @@ enum BuffType{ DAMAGE_REDUCTION, SLOWDOWN, BLOCK_SLOWDOWN, - RESTORATION, - RESTORATION_DURING_CAST, LOCKON_SPEEDBOOST, //Specifically used for wolves. SPEEDBOOST, BARRIER_DAMAGE_REDUCTION, //Creates a visual barrier around the target @@ -54,7 +52,29 @@ enum BuffType{ SELF_INFLICTED_SLOWDOWN, //Used for monsters and can't be applied by any player abilities. ADRENALINE_RUSH, TRAPPER_MARK, + DAMAGE_OVER_TIME, + OVER_TIME, + ONE_OFF, + OVER_TIME_DURING_CAST, }; +enum class BuffRestorationType{ + ONE_OFF, + OVER_TIME, + OVER_TIME_DURING_CAST, +}; +namespace BuffOverTimeType{ + enum BuffOverTimeType{ + HP_RESTORATION, + HP_PCT_RESTORATION, + MP_RESTORATION, + MP_PCT_RESTORATION, + HP_DAMAGE_OVER_TIME, + HP_PCT_DAMAGE_OVER_TIME, + }; +}; + +#define IfEntity(type) if(std::holds_alternative(attachedTarget)) +#define GetEntity(type) std::get(attachedTarget) class AiL; @@ -65,17 +85,16 @@ struct Buff{ float intensity=1; float nextTick=0; std::set attr; - std::functionrepeatAction; - inline Buff(BuffType type,float duration,float intensity) - :type(type),duration(duration),intensity(intensity){} - inline Buff(BuffType type,float duration,float intensity,std::set attr) - :type(type),duration(duration),intensity(intensity),attr(attr){} - inline Buff(BuffType type,float duration,float intensity,std::set attr) - :type(type),duration(duration),intensity(intensity){ - for(const std::string&s:attr){ - this->attr.insert(ItemAttribute::attributes.at(s)); - } - } - inline Buff(BuffType type,float duration,float intensity,float timeBetweenTicks,std::functionrepeatAction) - :type(type),duration(duration),intensity(intensity),nextTick(duration-timeBetweenTicks),timeBetweenTicks(timeBetweenTicks),repeatAction(repeatAction){} + std::variantattachedTarget; //Who has this buff. + + Buff(std::variantattachedTarget,BuffType type,float duration,float intensity); + Buff(std::variantattachedTarget,BuffType type,float duration,float intensity,std::set attr); + Buff(std::variantattachedTarget,BuffType type,float duration,float intensity,std::set attr); + Buff(std::variantattachedTarget,BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks); + + void Update(AiL*game,float fElapsedTime); +private: + bool enabled{true}; + std::optionaloverTimeType; + void BuffTick(AiL*game,float fElapsedTime); }; \ No newline at end of file diff --git a/Adventures in Lestoria/Bullet.cpp b/Adventures in Lestoria/Bullet.cpp index a6ff3f1b..89c035bd 100644 --- a/Adventures in Lestoria/Bullet.cpp +++ b/Adventures in Lestoria/Bullet.cpp @@ -43,4 +43,4 @@ Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool fr //Initializes a bullet with an animation. Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple,float lifetime,bool rotatesWithAngle,bool friendly,Pixel col,vf2d scale,float image_angle,std::string_view hitSound) :IBullet(pos,vel,radius,damage,animation,upperLevel,hitsMultiple,lifetime,rotatesWithAngle,friendly,col,scale,image_angle,hitSound){} -void Bullet::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Bullet::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/Bullet.h b/Adventures in Lestoria/Bullet.h index c62a8744..5a0440ae 100644 --- a/Adventures in Lestoria/Bullet.h +++ b/Adventures in Lestoria/Bullet.h @@ -45,5 +45,5 @@ public: //Initializes a bullet with an animation. Bullet(vf2d pos,vf2d vel,float radius,int damage,std::string animation,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool rotatesWithAngle=false,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f,std::string_view hitSound=""); protected: - virtual void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + virtual void ModifyOutgoingDamageData(HurtDamageInfo&data); }; \ No newline at end of file diff --git a/Adventures in Lestoria/BulletTypes.h b/Adventures in Lestoria/BulletTypes.h index 1862d529..40b6f3ed 100644 --- a/Adventures in Lestoria/BulletTypes.h +++ b/Adventures in Lestoria/BulletTypes.h @@ -45,8 +45,8 @@ struct EnergyBolt:public Bullet{ EnergyBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct FireBolt:public Bullet{ @@ -54,8 +54,8 @@ struct FireBolt:public Bullet{ FireBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct LightningBolt:public Bullet{ @@ -63,8 +63,8 @@ struct LightningBolt:public Bullet{ LightningBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Arrow:public Bullet{ @@ -79,8 +79,8 @@ struct Arrow:public Bullet{ // The perception level can be a value from 0-90 indicating the sweep angle to check beyond the initial aiming angle. const vf2d PointToBestTargetPath(const uint8_t perceptionLevel); BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct ChargedArrow:public Bullet{ @@ -88,8 +88,8 @@ struct ChargedArrow:public Bullet{ ChargedArrow(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct FrogTongue:public Bullet{ @@ -101,17 +101,17 @@ struct FrogTongue:public Bullet{ FrogTongue(Monster&sourceMonster,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength=1.0f,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! void Draw(const Pixel blendCol)const override; - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Wisp:public Bullet{ Wisp(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; enum class HorizontalFlip{ @@ -139,8 +139,8 @@ struct DaggerStab:public Bullet{ DaggerStab(Monster&sourceMonster,float radius,int damage,const float knockbackAmt,bool upperLevel,const Direction facingDir,const float daggerFrameDuration,const float daggerStabDistance,const DirectionOffsets offsets,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct DaggerSlash:public Bullet{ @@ -152,8 +152,8 @@ struct DaggerSlash:public Bullet{ DaggerSlash(Monster&sourceMonster,float radius,int damage,const float knockbackAmt,bool upperLevel,const Direction facingDir,const float daggerFrameDuration,const float daggerSlashDistance,bool friendly=false,Pixel col=WHITE); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Bomb:public Bullet{ @@ -169,8 +169,8 @@ struct Bomb:public Bullet{ Bomb(const vf2d pos,const float z,const float gravity,const float detonationTime,const float bombFadeoutTime,float bombKnockbackFactor,const vf2d targetPos,const float explosionRadius,const int damage,const bool upperLevel,const bool friendly=false,const Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); void Draw(const Pixel blendCol)const override; }; @@ -192,11 +192,11 @@ struct LevitatingRock:public Bullet{ LevitatingRock(const Monster&attachedTarget,const vf2d&attackingTarget,const float fadeInTime,const float facingRotOffset,const float distance,const float lockOnTime,const float waitTime,const float targetSpd,const float radius,const int damage,const bool upperLevel,const bool friendly=false,const Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! void Draw(const Pixel blendCol)const override; void AssignMaster(LevitatingRock*masterRock); const bool IsMaster()const; - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Tornado:public Bullet{ @@ -210,8 +210,8 @@ struct Tornado:public Bullet{ Tornado(vf2d centerPoint,float distance,float initialRot,float rotSpd,int damage,const float knockupAmt,const float knockbackAmt,const float lifetime,bool upperLevel,bool friendly=false,Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Debris:public Bullet{ @@ -221,8 +221,8 @@ struct Debris:public Bullet{ Debris(const vf2d pos,const vf2d vel,const int damage,const float radius,const float knockbackAmt,const float rotSpd,const float lifetime,bool upperLevel,bool friendly=false,Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); void Draw(const Pixel blendCol)const override; }; @@ -234,13 +234,13 @@ struct LargeTornado:public Bullet{ LargeTornado(vf2d pos,const float suctionAmt,const float knockupAmt,const float knockbackAmt,const int damage,const float radius,const float lifetime,bool upperLevel,bool friendly=false,Pixel col=WHITE,const vf2d scale={1,1}); void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct Feather:public Bullet{ Feather(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; struct LargeStone:public Bullet{ @@ -249,8 +249,8 @@ public: protected: void Update(float fElapsedTime)override; BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! - BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); private: const float gravity; const float fixedTimeStep{1/30.f}; @@ -270,7 +270,7 @@ struct FallingStone:public Bullet{ protected: void Update(float fElapsedTime)override; void Draw(const Pixel blendCol)const override; - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + void ModifyOutgoingDamageData(HurtDamageInfo&data); private: const vf2d targetPos; const float zVel{}; @@ -285,7 +285,7 @@ struct DeadlyDash:public Bullet{ DeadlyDash(vf2d startPos,vf2d endPos,float radius,float afterImagesLingeringTime,int damage,float knockbackAmt,bool upperLevel,bool friendly,float afterImagesSpreadDist,const std::string&animation,Pixel col); protected: void Draw(const Pixel blendCol)const override; - void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags); + void ModifyOutgoingDamageData(HurtDamageInfo&data); private: const vf2d startPos; const vf2d endPos; @@ -294,4 +294,11 @@ private: const float afterImagesLingeringTime; const float knockbackAmt; std::string animation; +}; + +struct BearTrap:public Bullet{ + BearTrap(vf2d pos,float radius,int damage,float fadeinTime,float fadeoutTime,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1}); + BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! + BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! + void ModifyOutgoingDamageData(HurtDamageInfo&data); }; \ No newline at end of file diff --git a/Adventures in Lestoria/ChargedArrow.cpp b/Adventures in Lestoria/ChargedArrow.cpp index 27be7fe8..d4eadf11 100644 --- a/Adventures in Lestoria/ChargedArrow.cpp +++ b/Adventures in Lestoria/ChargedArrow.cpp @@ -64,11 +64,11 @@ BulletDestroyState ChargedArrow::PlayerHit(Player*player) return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState ChargedArrow::MonsterHit(Monster& monster) +BulletDestroyState ChargedArrow::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { return BulletDestroyState::KEEP_ALIVE; } -void ChargedArrow::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void ChargedArrow::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/DaggerSlash.cpp b/Adventures in Lestoria/DaggerSlash.cpp index f63744a4..4a67e185 100644 --- a/Adventures in Lestoria/DaggerSlash.cpp +++ b/Adventures in Lestoria/DaggerSlash.cpp @@ -92,11 +92,11 @@ BulletDestroyState DaggerSlash::PlayerHit(Player*player){ Deactivate(); return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState DaggerSlash::MonsterHit(Monster&monster){ +BulletDestroyState DaggerSlash::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ game->AddEffect(std::make_unique(pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{})); monster.Knockback(util::pointTo(sourceMonster.GetPos(),monster.GetPos())*knockbackAmt); Deactivate(); return BulletDestroyState::KEEP_ALIVE; } -void DaggerSlash::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void DaggerSlash::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/DaggerStab.cpp b/Adventures in Lestoria/DaggerStab.cpp index 0863f9fc..2a5b7150 100644 --- a/Adventures in Lestoria/DaggerStab.cpp +++ b/Adventures in Lestoria/DaggerStab.cpp @@ -98,11 +98,11 @@ BulletDestroyState DaggerStab::PlayerHit(Player*player){ Deactivate(); return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState DaggerStab::MonsterHit(Monster&monster){ +BulletDestroyState DaggerStab::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ game->AddEffect(std::make_unique(pos,0,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult()*0.25f,0.25,vf2d{})); monster.Knockback(util::pointTo(sourceMonster.GetPos(),monster.GetPos())*knockbackAmt); Deactivate(); return BulletDestroyState::KEEP_ALIVE; } -void DaggerStab::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void DaggerStab::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/DamageNumber.cpp b/Adventures in Lestoria/DamageNumber.cpp index 9491af4b..0eb25b61 100644 --- a/Adventures in Lestoria/DamageNumber.cpp +++ b/Adventures in Lestoria/DamageNumber.cpp @@ -51,13 +51,11 @@ DamageNumber::DamageNumber() DamageNumber::DamageNumber(vf2d pos,int damage,bool friendly,DamageNumberType::DamageNumberType type): pos(pos),damage(damage),friendly(friendly),type(type),invertedDirection(type==INTERRUPT),riseSpd(20.f){ if(type==INTERRUPT||type==MANA_GAIN)riseSpd=40.f; - originalRiseSpd=riseSpd; RecalculateSize(); } void DamageNumber::RecalculateSize(){ float damageMultRatio=damage/game->GetPlayer()->GetEquipStat("Attack")/2.f; - riseSpd=originalRiseSpd; if(!friendly){ float newSize=std::clamp(roundf(damageMultRatio),1.0f,4.0f); diff --git a/Adventures in Lestoria/DamageNumber.h b/Adventures in Lestoria/DamageNumber.h index 46a7cb32..8ddda37d 100644 --- a/Adventures in Lestoria/DamageNumber.h +++ b/Adventures in Lestoria/DamageNumber.h @@ -60,7 +60,6 @@ struct DamageNumber{ bool invertedDirection=false; DamageNumberType::DamageNumberType type=DamageNumberType::HEALTH_LOSS; const static float MOVE_UP_TIME; - float originalRiseSpd=0.f; DamageNumber(); //The friendly flag indicates if the number was for a friendly/player target or if it's for a monster target (set to false) DamageNumber(vf2d pos,int damage,bool friendly=false,DamageNumberType::DamageNumberType type=DamageNumberType::HEALTH_LOSS); diff --git a/Adventures in Lestoria/DeadlyDash.cpp b/Adventures in Lestoria/DeadlyDash.cpp index 2216281c..9a489800 100644 --- a/Adventures in Lestoria/DeadlyDash.cpp +++ b/Adventures in Lestoria/DeadlyDash.cpp @@ -92,7 +92,7 @@ void DeadlyDash::Draw(const Pixel blendCol)const{ } } -void DeadlyDash::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ +void DeadlyDash::ModifyOutgoingDamageData(HurtDamageInfo&data){ //NOTE: Despite it looking like we modify the damage here, the radius passed to Bullet is 0, so this shouldn't matter anyways, the damage happens in the check in Update() - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/Debris.cpp b/Adventures in Lestoria/Debris.cpp index 627bc3a8..14f66a80 100644 --- a/Adventures in Lestoria/Debris.cpp +++ b/Adventures in Lestoria/Debris.cpp @@ -53,7 +53,7 @@ BulletDestroyState Debris::PlayerHit(Player*player){ fadeOutTime=0.5f; return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState Debris::MonsterHit(Monster&monster){ +BulletDestroyState Debris::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ monster.Knockback(vel.norm()*knockbackAmt); fadeOutTime=0.5f; return BulletDestroyState::KEEP_ALIVE; @@ -62,4 +62,4 @@ void Debris::Draw(const Pixel blendCol)const{ game->view.DrawPartialRotatedDecal(pos-vf2d{0,GetZ()}+drawOffsetY,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2+image_angle:image_angle,{12,12},vf2d{randomFrame*24.f,0.f},{24,24},scale,blendCol); } -void Debris::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Debris::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/EnergyBolt.cpp b/Adventures in Lestoria/EnergyBolt.cpp index 7c90dd66..83620f34 100644 --- a/Adventures in Lestoria/EnergyBolt.cpp +++ b/Adventures in Lestoria/EnergyBolt.cpp @@ -65,13 +65,13 @@ BulletDestroyState EnergyBolt::PlayerHit(Player*player) return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState EnergyBolt::MonsterHit(Monster& monster) +BulletDestroyState EnergyBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F; game->AddEffect(std::make_unique(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F)); return BulletDestroyState::KEEP_ALIVE; } -void EnergyBolt::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void EnergyBolt::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/FallingStone.cpp b/Adventures in Lestoria/FallingStone.cpp index 1d8a0512..7910e86d 100644 --- a/Adventures in Lestoria/FallingStone.cpp +++ b/Adventures in Lestoria/FallingStone.cpp @@ -89,4 +89,4 @@ void FallingStone::Draw(const Pixel blendCol)const{ Bullet::Draw(blendCol); } -void FallingStone::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void FallingStone::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/Feather.cpp b/Adventures in Lestoria/Feather.cpp index b8060ba4..bb24cdf2 100644 --- a/Adventures in Lestoria/Feather.cpp +++ b/Adventures in Lestoria/Feather.cpp @@ -44,4 +44,4 @@ Feather::Feather(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool SetBulletType(BulletType::FEATHER); } -void Feather::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Feather::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/FireBolt.cpp b/Adventures in Lestoria/FireBolt.cpp index fa9955da..3118b059 100644 --- a/Adventures in Lestoria/FireBolt.cpp +++ b/Adventures in Lestoria/FireBolt.cpp @@ -87,7 +87,7 @@ BulletDestroyState FireBolt::PlayerHit(Player*player) return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState FireBolt::MonsterHit(Monster& monster) +BulletDestroyState FireBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F; for(int i=0;i<"Wizard.Ability 1.BulletHitExplosionParticleCount"_I;i++){ @@ -101,6 +101,6 @@ BulletDestroyState FireBolt::MonsterHit(Monster& monster) return BulletDestroyState::KEEP_ALIVE; } -void FireBolt::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void FireBolt::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/FrogTongue.cpp b/Adventures in Lestoria/FrogTongue.cpp index b86dec88..e08b15a1 100644 --- a/Adventures in Lestoria/FrogTongue.cpp +++ b/Adventures in Lestoria/FrogTongue.cpp @@ -67,7 +67,7 @@ void FrogTongue::Update(float fElapsedTime){ if(friendly){ for(std::unique_ptr&m:MONSTER_LIST){ if(hitList.find(&*m)==hitList.end()&&geom2d::overlaps(m->BulletCollisionHitbox(),tongueLine)){ - _MonsterHit(*m); + _MonsterHit(*m,m->GetMarkStacks()); hitList.insert(&*m); } } @@ -83,7 +83,7 @@ BulletDestroyState FrogTongue::PlayerHit(Player*player){ } return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState FrogTongue::MonsterHit(Monster&monster){ +BulletDestroyState FrogTongue::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ monster.Hurt(damage,OnUpperLevel(),0); geom2d::linelineToTarget(pos,targetPos); vf2d drawVec=lineToTarget.vector().norm()*3; @@ -100,6 +100,6 @@ void FrogTongue::Draw(const Pixel blendCol)const{ game->view.DrawRotatedDecal(tongueEndPos,GFX["tongue_end.png"].Decal(),drawVec.polar().y,{2.f,2.f},{1.f,1.f},col); } -void FrogTongue::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void FrogTongue::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/HurtDamageInfo.h b/Adventures in Lestoria/HurtDamageInfo.h index fa6b36aa..d2f444fb 100644 --- a/Adventures in Lestoria/HurtDamageInfo.h +++ b/Adventures in Lestoria/HurtDamageInfo.h @@ -51,6 +51,7 @@ enum class TrueDamageFlag{ }; struct HurtDamageInfo{ + std::varianttargetPtr; int damage{}; bool onUpperLevel{false}; float z{}; diff --git a/Adventures in Lestoria/IBullet.cpp b/Adventures in Lestoria/IBullet.cpp index 858324dc..2c4ffe74 100644 --- a/Adventures in Lestoria/IBullet.cpp +++ b/Adventures in Lestoria/IBullet.cpp @@ -102,15 +102,16 @@ void IBullet::_Update(const float fElapsedTime){ for(std::unique_ptr&m:MONSTER_LIST){ if(geom2d::overlaps(m->BulletCollisionHitbox(),geom2d::circle(pos,radius))){ if(hitList.find(&*m)==hitList.end()){ - HurtDamageInfo damageData{damage,OnUpperLevel(),z,HurtFlag::NONE}; - ModifyOutgoingDamageData(damageData.damage,damageData.onUpperLevel,damageData.z,damageData.hurtFlags); + HurtDamageInfo damageData{&*m,damage,OnUpperLevel(),z,HurtFlag::NONE}; + ModifyOutgoingDamageData(damageData); + uint8_t markStacksBeforeHit{m->GetMarkStacks()}; if(m->Hurt(damageData)){ if(!hitsMultiple){ - if(_MonsterHit(*m)==BulletDestroyState::DESTROY){ + if(_MonsterHit(*m,markStacksBeforeHit)==BulletDestroyState::DESTROY){ dead=true; } return false; - }else _MonsterHit(*m); + }else _MonsterHit(*m,markStacksBeforeHit); hitList.insert(&*m); } } @@ -119,9 +120,9 @@ void IBullet::_Update(const float fElapsedTime){ } else { if(geom2d::overlaps(game->GetPlayer()->Hitbox(),geom2d::circle(pos,radius))){ if(hitList.find(game->GetPlayer())==hitList.end()){ - HurtDamageInfo damageData{damage,OnUpperLevel(),z,HurtFlag::NONE}; + HurtDamageInfo damageData{game->GetPlayer(),damage,OnUpperLevel(),z,HurtFlag::NONE}; //NOTE: OnHurt() will potentially change the Damage Data, passing it along to bullet children that might need to modify the flags! - ModifyOutgoingDamageData(damageData.damage,damageData.onUpperLevel,damageData.z,damageData.hurtFlags); + ModifyOutgoingDamageData(damageData); if(game->GetPlayer()->Hurt(damageData)){ if(!hitsMultiple){ if(_PlayerHit(&*game->GetPlayer())==BulletDestroyState::DESTROY){ @@ -202,8 +203,8 @@ BulletDestroyState IBullet::_PlayerHit(Player*player){ if(hitSound)SoundEffect::PlaySFX(hitSound.value(),pos); return destroyBullet; } -BulletDestroyState IBullet::_MonsterHit(Monster&monster){ - const BulletDestroyState destroyBullet=MonsterHit(monster); +BulletDestroyState IBullet::_MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ + const BulletDestroyState destroyBullet=MonsterHit(monster,markStacksBeforeHit); if(iframeTimerOnHit>0.f)monster.ApplyIframes(iframeTimerOnHit); if(hitSound)SoundEffect::PlaySFX(hitSound.value(),pos); return destroyBullet; @@ -212,7 +213,7 @@ BulletDestroyState IBullet::PlayerHit(Player*player){ if(!hitsMultiple)fadeOutTime=0.15f; return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState IBullet::MonsterHit(Monster&monster){ +BulletDestroyState IBullet::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ if(!hitsMultiple)fadeOutTime=0.15f; return BulletDestroyState::KEEP_ALIVE; } diff --git a/Adventures in Lestoria/IBullet.h b/Adventures in Lestoria/IBullet.h index 2b409f7e..3b245046 100644 --- a/Adventures in Lestoria/IBullet.h +++ b/Adventures in Lestoria/IBullet.h @@ -93,7 +93,7 @@ private: protected: float drawOffsetY{}; BulletDestroyState _PlayerHit(Player*player); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. - BulletDestroyState _MonsterHit(Monster&monster); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. + BulletDestroyState _MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. const float&GetFadeoutTimer()const; void SetBulletType(const BulletType type); const double GetTimeAlive()const; @@ -114,7 +114,7 @@ public: virtual BulletDestroyState PlayerHit(Player*player); //Used by special bullets to control custom despawning behavior! Return true when the bullet should be destroyed. Return false to handle it otherwise (like deactivating it instead). You become responsible for getting rid of the bullet. //DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! - virtual BulletDestroyState MonsterHit(Monster&monster); + virtual BulletDestroyState MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit); Animate2D::Frame GetFrame()const; virtual void Draw(const Pixel blendCol)const; bool OnUpperLevel(); @@ -129,5 +129,5 @@ public: const bool IsActivated()const; const bool IsDeactivated()const; const double GetAliveTime()const; - virtual void ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags)=0; + virtual void ModifyOutgoingDamageData(HurtDamageInfo&data)=0; }; \ No newline at end of file diff --git a/Adventures in Lestoria/Item.cpp b/Adventures in Lestoria/Item.cpp index 5ecac966..a362f5ea 100644 --- a/Adventures in Lestoria/Item.cpp +++ b/Adventures in Lestoria/Item.cpp @@ -385,28 +385,24 @@ const uint32_t ItemProps::PropCount(const std::string&prop)const{ else return uint32_t((*scriptProps)[prop].GetValueCount()); } +const std::unordered_mapItemInfo::NameToBuffType{ + {"HP Restore",BuffOverTimeType::HP_RESTORATION}, + {"HP % Restore",BuffOverTimeType::HP_PCT_RESTORATION}, + {"MP Restore",BuffOverTimeType::MP_RESTORATION}, + {"MP % Restore",BuffOverTimeType::MP_PCT_RESTORATION}, +}; + void ItemInfo::InitializeScripts(){ ITEM_SCRIPTS["Restore"]=[](AiL*game,ItemProps props){ - auto ParseItemScriptData=[&](const std::string&propName,std::functionaction){ + for(const auto&[propName,buffType]:NameToBuffType){ int restoreAmt=props.GetIntProp(propName); - action(game,restoreAmt); + + game->GetPlayer()->AddBuff(BuffRestorationType::ONE_OFF,NameToBuffType.at(propName),0.01f,float(restoreAmt),0.0f); if(restoreAmt>0&&props.PropCount(propName)==3){ - game->GetPlayer()->AddBuff(RESTORATION,props.GetFloatProp(propName,2),float(restoreAmt),props.GetFloatProp(propName,1),action); + game->GetPlayer()->AddBuff(BuffRestorationType::OVER_TIME,NameToBuffType.at(propName),props.GetFloatProp(propName,2),float(restoreAmt),props.GetFloatProp(propName,1)); } - }; - ParseItemScriptData("HP Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->Heal(restoreAmt); - }); - ParseItemScriptData("HP % Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->Heal(int(game->GetPlayer()->GetMaxHealth()*restoreAmt/100.0f)); - }); - ParseItemScriptData("MP Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->RestoreMana(restoreAmt); - }); - ParseItemScriptData("MP % Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->RestoreMana(int(game->GetPlayer()->GetMaxMana()*props.GetIntProp("MP % Restore")/100.f)); - }); + } return true; }; @@ -425,26 +421,15 @@ void ItemInfo::InitializeScripts(){ } return true; }; - ITEM_SCRIPTS["RestoreDuringCast"]=[&](AiL*game,ItemProps props){ - auto ParseItemScriptData=[&](const std::string&propName,std::functionaction){ + ITEM_SCRIPTS["RestoreDuringCast"]=[](AiL*game,ItemProps props){ + for(const auto&[propName,buffType]:NameToBuffType){ int restoreAmt=props.GetIntProp(propName); - action(game,restoreAmt); + + game->GetPlayer()->AddBuff(BuffRestorationType::ONE_OFF,NameToBuffType.at(propName),0.01f,float(restoreAmt),0.0f); if(restoreAmt>0&&props.PropCount(propName)==3){ - game->GetPlayer()->AddBuff(RESTORATION_DURING_CAST,props.GetFloatProp(propName,2),float(restoreAmt),props.GetFloatProp(propName,1),action); + game->GetPlayer()->AddBuff(BuffRestorationType::OVER_TIME_DURING_CAST,NameToBuffType.at(propName),props.GetFloatProp(propName,2),float(restoreAmt),props.GetFloatProp(propName,1)); } - }; - ParseItemScriptData("HP Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->Heal(restoreAmt); - }); - ParseItemScriptData("HP % Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->Heal(int(game->GetPlayer()->GetMaxHealth()*restoreAmt/100.0f)); - }); - ParseItemScriptData("MP Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->RestoreMana(restoreAmt); - }); - ParseItemScriptData("MP % Restore",[&](AiL*game,int restoreAmt){ - game->GetPlayer()->RestoreMana(int(game->GetPlayer()->GetMaxMana()*props.GetIntProp("MP % Restore")/100.f)); - }); + } return true; }; diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index 4f2570df..e6940ce8 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -48,6 +48,7 @@ All rights reserved. #include "FunctionPriming.h" #include "IT.h" #include +#include "Buff.h" class AiL; class ItemInfo; @@ -339,6 +340,7 @@ private: static void InitializeSets(); static std::mapnameToEquipSlot; static std::vector>craftableConsumables; + const static std::unordered_mapNameToBuffType; public: static void InitializeItems(); ItemInfo(); diff --git a/Adventures in Lestoria/LargeStone.cpp b/Adventures in Lestoria/LargeStone.cpp index e70d4b3e..b0c27fcd 100644 --- a/Adventures in Lestoria/LargeStone.cpp +++ b/Adventures in Lestoria/LargeStone.cpp @@ -95,8 +95,8 @@ BulletDestroyState LargeStone::PlayerHit(Player*player){ return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState LargeStone::MonsterHit(Monster&monster){ +BulletDestroyState LargeStone::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ return BulletDestroyState::KEEP_ALIVE; } -void LargeStone::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void LargeStone::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/LargeTornado.cpp b/Adventures in Lestoria/LargeTornado.cpp index 0c7d0079..00d84755 100644 --- a/Adventures in Lestoria/LargeTornado.cpp +++ b/Adventures in Lestoria/LargeTornado.cpp @@ -64,7 +64,7 @@ BulletDestroyState LargeTornado::PlayerHit(Player*player){ return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState LargeTornado::MonsterHit(Monster&monster){ +BulletDestroyState LargeTornado::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ if(monster.IgnoresTerrainCollision())return BulletDestroyState::KEEP_ALIVE; //All airborne enemy types won't care about this. monster.Knockback(util::pointTo(pos,monster.GetPos())*knockbackAmt); @@ -75,4 +75,4 @@ BulletDestroyState LargeTornado::MonsterHit(Monster&monster){ return BulletDestroyState::KEEP_ALIVE; } -void LargeTornado::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void LargeTornado::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/LevitatingRock.cpp b/Adventures in Lestoria/LevitatingRock.cpp index a5bca037..fca3dcf0 100644 --- a/Adventures in Lestoria/LevitatingRock.cpp +++ b/Adventures in Lestoria/LevitatingRock.cpp @@ -93,7 +93,7 @@ BulletDestroyState LevitatingRock::PlayerHit(Player*player){ player->Knockback(vel/3.f); return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState LevitatingRock::MonsterHit(Monster&monster){ +BulletDestroyState LevitatingRock::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ if(initialWaitTime>0.f)return BulletDestroyState::KEEP_ALIVE; fadeOutTime=0.5f; @@ -114,4 +114,4 @@ const bool LevitatingRock::IsMaster()const{ return slaveRocks.size()>0; } -void LevitatingRock::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void LevitatingRock::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/LightningBolt.cpp b/Adventures in Lestoria/LightningBolt.cpp index e6608324..2c876282 100644 --- a/Adventures in Lestoria/LightningBolt.cpp +++ b/Adventures in Lestoria/LightningBolt.cpp @@ -86,7 +86,7 @@ BulletDestroyState LightningBolt::PlayerHit(Player*player) return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState LightningBolt::MonsterHit(Monster& monster) +BulletDestroyState LightningBolt::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit) { fadeOutTime="Wizard.Ability 2.BulletFadeoutTime"_F; game->AddEffect(std::make_unique(monster.GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange)); @@ -109,6 +109,6 @@ BulletDestroyState LightningBolt::MonsterHit(Monster& monster) return BulletDestroyState::KEEP_ALIVE; } -void LightningBolt::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){ - if(friendly)hurtFlags|=HurtFlag::PLAYER_ABILITY; +void LightningBolt::ModifyOutgoingDamageData(HurtDamageInfo&data){ + if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index e6834892..7292b0ae 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -328,14 +328,8 @@ bool Monster::Update(float fElapsedTime){ } if(IsAlive()){ - for(std::vector::iterator it=buffList.begin();it!=buffList.end();++it){ - Buff&b=*it; - b.duration-=fElapsedTime; - if(b.duration<=0){ - it=buffList.erase(it); - if(it==buffList.end())break; - } - } + std::for_each(buffList.begin(),buffList.end(),[&](Buff&b){b.Update(game,fElapsedTime);}); + std::erase_if(buffList,[](Buff&b){return b.duration<=0;}); if(!HasIframes()){ for(std::unique_ptr&m:MONSTER_LIST){ const float monsterRadius{GetCollisionRadius()}; @@ -674,7 +668,7 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da dotNumberPtr.get()->RecalculateSize(); }else{ dotNumberPtr=std::make_shared(pos-vf2d{0,GetCollisionRadius()/2.f},int(mod_dmg),false,DamageNumberType::DOT); - dotNumberPtr->riseSpd=dotNumberPtr->originalRiseSpd=-10.f; + dotNumberPtr->riseSpd=-10.f; DAMAGENUMBER_LIST.push_back(dotNumberPtr); } lastDotTimer=0.05f; @@ -759,17 +753,17 @@ const bool Monster::OnUpperLevel()const{ } void Monster::AddBuff(BuffType type,float duration,float intensity){ - buffList.push_back(Buff{type,duration,intensity}); + buffList.push_back(Buff{this,type,duration,intensity}); } void Monster::AddBuff(BuffType type,float duration,float intensity,std::setattr){ if(type==STAT_UP)std::for_each(attr.begin(),attr.end(),[](const ItemAttribute&attr){if(attr.ActualName()!="Health"&&attr.ActualName()!="Health %"&&attr.ActualName()!="Attack"&&attr.ActualName()!="Attack %")ERR(std::format("WARNING! Stat Up Attribute type {} is NOT IMPLEMENTED!",attr.ActualName()));}); - buffList.emplace_back(type,duration,intensity,attr); + buffList.emplace_back(this,type,duration,intensity,attr); } void Monster::AddBuff(BuffType type,float duration,float intensity,std::setattr){ if(type==STAT_UP)std::for_each(attr.begin(),attr.end(),[](const std::string&attr){if(attr!="Health"&&attr!="Health %"&&attr!="Attack"&&attr!="Attack %")ERR(std::format("WARNING! Stat Up Attribute type {} is NOT IMPLEMENTED!",attr));}); - buffList.emplace_back(type,duration,intensity,attr); + buffList.emplace_back(this,type,duration,intensity,attr); } void Monster::RemoveBuff(BuffType type){ @@ -956,6 +950,8 @@ void Monster::OnDeath(){ SpawnDrops(); game->GetPlayer()->AddAccumulatedXP(MONSTER_DATA.at(name).GetXP()); + + RemoveBuff(BuffType::TRAPPER_MARK); } const ItemAttributable&Monster::GetStats()const{ @@ -1234,6 +1230,7 @@ const uint8_t Monster::GetMarkStacks()const{ } 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!"); bool removeMarkDebuff{false}; for(Buff&b:buffList){ @@ -1295,4 +1292,8 @@ std::optionalMonster::GetNearestMonster(const vf2d point,const float m const bool Monster::InUndamageableState(const bool onUpperLevel,const float z)const{ return Invulnerable()||!IsAlive()||onUpperLevel!=OnUpperLevel()||AttackAvoided(z); +} + +void Monster::AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks){ + buffList.push_back(Buff{this,type,overTimeType,duration,intensity,timeBetweenTicks}); } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index bd51e310..af1f0f10 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -140,6 +140,7 @@ public: void AddBuff(BuffType type,float duration,float intensity,std::setattr); //NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!! void AddBuff(BuffType type,float duration,float intensity,std::setattr); + void AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks); std::vectorGetBuffs(BuffType buff)const; //Removes all buffs of a given type. void RemoveBuff(BuffType type); diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index d87d21e1..b0777801 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -384,13 +384,7 @@ void Player::Update(float fElapsedTime){ manaTickTimer+=0.2f; RestoreMana(1,true); } - for(Buff&b:buffList){ - b.duration-=fElapsedTime; - if(b.nextTick>0&&b.durationRecalculateSize(); }else{ dotNumberPtr=std::make_shared(pos-vf2d{0,8.f},int(mod_dmg),false,DamageNumberType::DOT); + dotNumberPtr->riseSpd=-10.f; DAMAGENUMBER_LIST.push_back(dotNumberPtr); } lastDotTimer=0.05f; @@ -935,7 +930,7 @@ Key Player::GetFacingDirection(){ void Player::CancelCast(){ bool wasCasting=castInfo.castTimer>0; castInfo={"",0}; - std::erase_if(buffList,[](Buff&b){return b.type==RESTORATION_DURING_CAST;}); //Remove all buffs that would be applied during a cast, as we got interrupted. + std::erase_if(buffList,[](Buff&b){return b.type==OVER_TIME_DURING_CAST;}); //Remove all buffs that would be applied during a cast, as we got interrupted. if(wasCasting){ DAMAGENUMBER_LIST.push_back(std::make_shared(GetPos(),0,true,DamageNumberType::INTERRUPT)); } @@ -1028,18 +1023,18 @@ void Player::UpdateIdleAnimation(Key direction){ } void Player::AddBuff(BuffType type,float duration,float intensity){ - buffList.push_back(Buff{type,duration,intensity}); + buffList.push_back(Buff{this,type,duration,intensity}); } void Player::AddBuff(BuffType type,float duration,float intensity,std::setattr){ if(type==STAT_UP)std::for_each(attr.begin(),attr.end(),[](const ItemAttribute&attr){if(attr.ActualName()!="Health"&&attr.ActualName()!="Health %"&&attr.ActualName()!="Attack"&&attr.ActualName()!="Attack %"&&attr.ActualName()!="Defense"&&attr.ActualName()!="Defense %"&&attr.ActualName()!="CDR"&&attr.ActualName()!="Move Spd %")ERR(std::format("WARNING! Stat Up Attribute type {} is NOT IMPLEMENTED!",attr.ActualName()));}); - buffList.push_back(Buff{type,duration,intensity,attr}); + buffList.push_back(Buff{this,type,duration,intensity,attr}); } void Player::AddBuff(BuffType type,float duration,float intensity,std::setattr){ if(type==STAT_UP)std::for_each(attr.begin(),attr.end(),[](const std::string&attr){if(attr!="Health"&&attr!="Health %"&&attr!="Attack"&&attr!="Attack %"&&attr!="Defense"&&attr!="Defense %"&&attr!="CDR"&&attr!="Move Spd %")ERR(std::format("WARNING! Stat Up Attribute type {} is NOT IMPLEMENTED!",attr));}); - buffList.push_back(Buff{type,duration,intensity,attr}); + buffList.push_back(Buff{this,type,duration,intensity,attr}); } -void Player::AddBuff(BuffType type,float duration,float intensity,float timeBetweenTicks,std::functionrepeatAction){ - buffList.push_back(Buff{type,duration,intensity,timeBetweenTicks,repeatAction}); +void Player::AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks){ + buffList.push_back(Buff{this,type,overTimeType,duration,intensity,timeBetweenTicks}); } bool Player::OnUpperLevel(){ diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index 24fb0ccc..b2464b75 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -103,6 +103,7 @@ class Player{ friend struct Witch; friend class State_GameRun; friend class Inventory; + friend class ItemInfo; friend void ItemOverlay::Draw(); friend class PlayerTests::PlayerTest; friend class ItemTests::ItemTest; @@ -179,7 +180,7 @@ public: void AddBuff(BuffType type,float duration,float intensity,std::setattr); //NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!! void AddBuff(BuffType type,float duration,float intensity,std::setattr); - void AddBuff(BuffType type,float duration,float intensity,float timeBetweenTicks,std::functionrepeatAction); + void AddBuff(BuffRestorationType type,BuffOverTimeType::BuffOverTimeType overTimeType,float duration,float intensity,float timeBetweenTicks); const std::vectorGetBuffs(BuffType buff)const; const std::vectorGetStatBuffs(const std::vector&attr)const; diff --git a/Adventures in Lestoria/Tornado.cpp b/Adventures in Lestoria/Tornado.cpp index b91b5c65..583465b5 100644 --- a/Adventures in Lestoria/Tornado.cpp +++ b/Adventures in Lestoria/Tornado.cpp @@ -66,7 +66,7 @@ BulletDestroyState Tornado::PlayerHit(Player*player){ return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState Tornado::MonsterHit(Monster&monster){ +BulletDestroyState Tornado::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ if(monster.IgnoresTerrainCollision())return BulletDestroyState::KEEP_ALIVE; //All airborne enemy types won't care about this. monster.Knockback(util::pointTo(centerPoint,monster.GetPos())*knockbackAmt); @@ -77,4 +77,4 @@ BulletDestroyState Tornado::MonsterHit(Monster&monster){ return BulletDestroyState::KEEP_ALIVE; } -void Tornado::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Tornado::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/Trapper.cpp b/Adventures in Lestoria/Trapper.cpp index c0e70db4..9e83e4dd 100644 --- a/Adventures in Lestoria/Trapper.cpp +++ b/Adventures in Lestoria/Trapper.cpp @@ -112,10 +112,13 @@ void Trapper::InitializeClassAbilities(){ return true; }; #pragma endregion - #pragma region Trapper Ability 2 (???) + #pragma region Trapper Ability 2 (Bear Trap) Trapper::ability2.action= [](Player*p,vf2d pos={}){ - return false; + CreateBullet(BearTrap)(p->GetPos(),"Trapper.Ability 2.Trap Radius"_I,"Trapper.Ability 2.DamageMult"_F*p->GetAttack(),0.2f,0.5f,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet; + SoundEffect::PlaySFX("Place Down Trap",p->GetPos()); + p->SetAnimationBasedOnTargetingDirection("SETTRAP",p->GetFacingDirection()); + return true; }; #pragma endregion #pragma region Trapper Ability 3 (???) diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index ecded043..c3bbf217 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 10275 +#define VERSION_BUILD 10300 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Wisp.cpp b/Adventures in Lestoria/Wisp.cpp index 0b8d47be..a9a77d5f 100644 --- a/Adventures in Lestoria/Wisp.cpp +++ b/Adventures in Lestoria/Wisp.cpp @@ -54,11 +54,11 @@ BulletDestroyState Wisp::PlayerHit(Player*player){ fadeOutTime="MonsterStrategy.Ursule.Phase 2.Wisp Fadeout Time"_F; return BulletDestroyState::KEEP_ALIVE; } -BulletDestroyState Wisp::MonsterHit(Monster&monster){ +BulletDestroyState Wisp::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){ SoundEffect::PlaySFX("Wisp Hit",monster.GetPos()); game->AddEffect(std::make_unique(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25,vf2d{},"MonsterStrategy.Ursule.Phase 2.Wisp Color"_Pixel)); fadeOutTime="MonsterStrategy.Ursule.Phase 2.Wisp Fadeout Time"_F; return BulletDestroyState::KEEP_ALIVE; } -void Wisp::ModifyOutgoingDamageData(int&damage,bool&onUpperLevel,float&z,HurtFlag::HurtFlag&hurtFlags){} \ No newline at end of file +void Wisp::ModifyOutgoingDamageData(HurtDamageInfo&data){} \ No newline at end of file diff --git a/Adventures in Lestoria/assets/bear_trap.png b/Adventures in Lestoria/assets/bear_trap.png new file mode 100644 index 00000000..d9ac77aa Binary files /dev/null and b/Adventures in Lestoria/assets/bear_trap.png differ diff --git a/Adventures in Lestoria/assets/config/audio/events.txt b/Adventures in Lestoria/assets/config/audio/events.txt index f6fdc049..025e1bb0 100644 --- a/Adventures in Lestoria/assets/config/audio/events.txt +++ b/Adventures in Lestoria/assets/config/audio/events.txt @@ -186,6 +186,12 @@ Events # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) File[0] = button_click2.ogg, 30%, 30%, 60% } + Place Down Trap + { + CombatSound = True + # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) + File[0] = place_down.ogg, 90% + } Player Hit { CombatSound = True @@ -310,6 +316,12 @@ Events # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) File[0] = toggle_off.ogg, 100% } + Trap Hit + { + CombatSound = True + # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) + File[0] = trap_hit.ogg, 70% + } Unequip Armor { # Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%) diff --git a/Adventures in Lestoria/assets/config/classes/Trapper.txt b/Adventures in Lestoria/assets/config/classes/Trapper.txt index e9f314bc..691cb0fb 100644 --- a/Adventures in Lestoria/assets/config/classes/Trapper.txt +++ b/Adventures in Lestoria/assets/config/classes/Trapper.txt @@ -66,7 +66,7 @@ Trapper Cooldown Bar Color 1 = 64, 0, 0, 192 Cooldown Bar Color 2 = 128, 0, 0, 192 - Precast Time = 0 + Precast Time = 0.1s Casting Range = 1200 Casting Size = 100 } @@ -81,9 +81,13 @@ Trapper # Whether or not this ability cancels casts. CancelCast = 0 + DamageMult = 2.5x Marked Target Reset Time = 7s - Marked Target Hit Count Reset = 5 - Marked Target Bleed = 10%, 10s + # What to reset the stack count to if a marked target runs into the trap. + Marked Target Stack Count Reset = 5 + # % of Attack, Duration, Time per tick + Marked Target Bleed = 10%, 10s, 1s + Trap Radius = 11px #RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown. Cooldown Bar Color 1 = 64, 0, 0, 192 @@ -104,7 +108,7 @@ Trapper # Whether or not this ability cancels casts. CancelCast = 0 - Damage = 5.5x + DamageMult = 5.5x Explosion Radius = 200 Trap Activation Time = 1.5s Trap Auto Detonate Time = 5s diff --git a/Adventures in Lestoria/assets/config/gfx/gfx.txt b/Adventures in Lestoria/assets/config/gfx/gfx.txt index 8926224f..87ca19cf 100644 --- a/Adventures in Lestoria/assets/config/gfx/gfx.txt +++ b/Adventures in Lestoria/assets/config/gfx/gfx.txt @@ -111,6 +111,7 @@ Images GFX_Shine = shine.png GFX_TargetMark = target.png GFX_MarkTrail = mark_trail.png + GFX_BearTrap = bear_trap.png GFX_Thief_Sheet = nico-thief.png GFX_Trapper_Sheet = nico-trapper.png diff --git a/Adventures in Lestoria/assets/config/items/ItemScript.txt b/Adventures in Lestoria/assets/config/items/ItemScript.txt index 7508503e..7fb02610 100644 --- a/Adventures in Lestoria/assets/config/items/ItemScript.txt +++ b/Adventures in Lestoria/assets/config/items/ItemScript.txt @@ -2,6 +2,8 @@ ItemScript { # Used with the Item Database. # Any of these properties can be overwritten by specifying them in the main item. + + # If new scripts are added, please visit Item.cpp (ItemInfo::InitializeScripts()) to implement them. # Restores stats. # Parameter 1: The amount to restore per tick. If parameter 2 is zero, restores this amount instantly. diff --git a/Adventures in Lestoria/assets/gamepack.pak b/Adventures in Lestoria/assets/gamepack.pak index 2b7fee13..f5584e8e 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/place_down.ogg b/Adventures in Lestoria/assets/sounds/place_down.ogg new file mode 100644 index 00000000..24dfacc0 Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/place_down.ogg differ diff --git a/Adventures in Lestoria/assets/sounds/trap_hit.ogg b/Adventures in Lestoria/assets/sounds/trap_hit.ogg new file mode 100644 index 00000000..f8af4e15 Binary files /dev/null and b/Adventures in Lestoria/assets/sounds/trap_hit.ogg differ diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index ae189892..7933ff27 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ