diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index 56500309d..faee4a049 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -75,7 +75,6 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) if (TargetIsInRange() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast(AttackDirection.Length())) && (GetHealth() > 0.0)) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) - StopMovingToPosition(); Attack(a_Dt); } } @@ -86,14 +85,13 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt) { - m_AttackInterval += (static_cast(a_Dt.count()) / 1000) * m_AttackRate; - if ((m_Target == nullptr) || (m_AttackInterval < 3.0)) + if ((m_Target == nullptr) || (m_AttackCoolDownTicksLeft != 0)) { return false; } // Setting this higher gives us more wiggle room for attackrate - m_AttackInterval = 0.0; + ResetAttackCooldown(); m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0); return true; diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp index cb1ed23cb..a772d830c 100644 --- a/src/Mobs/Blaze.cpp +++ b/src/Mobs/Blaze.cpp @@ -34,9 +34,7 @@ void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer) bool cBlaze::Attack(std::chrono::milliseconds a_Dt) { - m_AttackInterval += (static_cast(a_Dt.count()) / 1000) * m_AttackRate; - - if ((m_Target != nullptr) && (m_AttackInterval > 3.0)) + if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { // Setting this higher gives us more wiggle room for attackrate Vector3d Speed = GetLookVector() * 20; @@ -53,7 +51,7 @@ bool cBlaze::Attack(std::chrono::milliseconds a_Dt) return false; } m_World->BroadcastSpawnEntity(*FireCharge); - m_AttackInterval = 0.0; + ResetAttackCooldown(); // ToDo: Shoot 3 fireballs instead of 1. return true; } diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp index fe3cc8be3..9ac16866e 100644 --- a/src/Mobs/Ghast.cpp +++ b/src/Mobs/Ghast.cpp @@ -34,9 +34,7 @@ void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer) bool cGhast::Attack(std::chrono::milliseconds a_Dt) { - m_AttackInterval += (static_cast(a_Dt.count()) / 1000) * m_AttackRate; - - if ((m_Target != nullptr) && (m_AttackInterval > 3.0)) + if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { // Setting this higher gives us more wiggle room for attackrate Vector3d Speed = GetLookVector() * 20; @@ -53,8 +51,7 @@ bool cGhast::Attack(std::chrono::milliseconds a_Dt) return false; } m_World->BroadcastSpawnEntity(*GhastBall); - m_AttackInterval = 0.0; - + ResetAttackCooldown(); return true; } return false; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 7d8c3de02..a24df6bc2 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -88,7 +88,7 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A , m_AttackRate(3) , m_AttackDamage(1) , m_AttackRange(1) - , m_AttackInterval(0) + , m_AttackCoolDownTicksLeft(0) , m_SightDistance(25) , m_DropChanceWeapon(0.085f) , m_DropChanceHelmet(0.085f) @@ -214,6 +214,11 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT); + if (m_AttackCoolDownTicksLeft > 0) + { + m_AttackCoolDownTicksLeft -= 1; + } + if (m_Health <= 0) { // The mob is dead, but we're still animating the "puff" they leave when they die @@ -690,6 +695,15 @@ void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +void cMonster::ResetAttackCooldown() +{ + m_AttackCoolDownTicksLeft = static_cast(3 * 20 * m_AttackRate); // A second has 20 ticks, an attack rate of 1 means 1 hit every 3 seconds +} + + + + + void cMonster::SetCustomName(const AString & a_CustomName) { m_CustomName = a_CustomName; diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 43ea91471..1304863b5 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -101,6 +101,7 @@ public: void SetDropChanceLeggings(float a_DropChanceLeggings) { m_DropChanceLeggings = a_DropChanceLeggings; } void SetDropChanceBoots(float a_DropChanceBoots) { m_DropChanceBoots = a_DropChanceBoots; } void SetCanPickUpLoot(bool a_CanPickUpLoot) { m_CanPickUpLoot = a_CanPickUpLoot; } + void ResetAttackCooldown(); /** Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick */ void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } @@ -220,7 +221,7 @@ protected: float m_AttackRate; int m_AttackDamage; int m_AttackRange; - float m_AttackInterval; + int m_AttackCoolDownTicksLeft; int m_SightDistance; float m_DropChanceWeapon; diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp index 27e038e1e..5032ec5b0 100644 --- a/src/Mobs/Skeleton.cpp +++ b/src/Mobs/Skeleton.cpp @@ -50,9 +50,9 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) { + StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing cFastRandom Random; - m_AttackInterval += (static_cast(a_Dt.count()) / 1000) * m_AttackRate; - if ((m_Target != nullptr) && (m_AttackInterval > 3.0)) + if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { Vector3d Inaccuracy = Vector3d(Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25); Vector3d Speed = (m_Target->GetPosition() + Inaccuracy - GetPosition()) * 5; @@ -69,8 +69,8 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) return false; } m_World->BroadcastSpawnEntity(*Arrow); - m_AttackInterval = 0.0; - + ResetAttackCooldown(); + return true; } return false; diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index c755e9058..6e0431d16 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -228,15 +228,11 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) } else { + MoveToPosition(m_Target->GetPosition()); if (TargetIsInRange()) { - StopMovingToPosition(); Attack(a_Dt); } - else - { - MoveToPosition(m_Target->GetPosition()); - } } }