1
0

Fix mob attack interval

This commit is contained in:
LogicParrot 2016-01-12 12:11:10 +02:00
parent e2a053263f
commit 21df3cb0d8
7 changed files with 28 additions and 24 deletions

View File

@ -75,7 +75,6 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (TargetIsInRange() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast<int>(AttackDirection.Length())) && (GetHealth() > 0.0)) if (TargetIsInRange() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast<int>(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) // 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); 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) bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt)
{ {
m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate; if ((m_Target == nullptr) || (m_AttackCoolDownTicksLeft != 0))
if ((m_Target == nullptr) || (m_AttackInterval < 3.0))
{ {
return false; return false;
} }
// Setting this higher gives us more wiggle room for attackrate // Setting this higher gives us more wiggle room for attackrate
m_AttackInterval = 0.0; ResetAttackCooldown();
m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0); m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
return true; return true;

View File

@ -34,9 +34,7 @@ void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer)
bool cBlaze::Attack(std::chrono::milliseconds a_Dt) bool cBlaze::Attack(std::chrono::milliseconds a_Dt)
{ {
m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate; if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{ {
// Setting this higher gives us more wiggle room for attackrate // Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20; Vector3d Speed = GetLookVector() * 20;
@ -53,7 +51,7 @@ bool cBlaze::Attack(std::chrono::milliseconds a_Dt)
return false; return false;
} }
m_World->BroadcastSpawnEntity(*FireCharge); m_World->BroadcastSpawnEntity(*FireCharge);
m_AttackInterval = 0.0; ResetAttackCooldown();
// ToDo: Shoot 3 fireballs instead of 1. // ToDo: Shoot 3 fireballs instead of 1.
return true; return true;
} }

View File

@ -34,9 +34,7 @@ void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer)
bool cGhast::Attack(std::chrono::milliseconds a_Dt) bool cGhast::Attack(std::chrono::milliseconds a_Dt)
{ {
m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate; if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{ {
// Setting this higher gives us more wiggle room for attackrate // Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20; Vector3d Speed = GetLookVector() * 20;
@ -53,8 +51,7 @@ bool cGhast::Attack(std::chrono::milliseconds a_Dt)
return false; return false;
} }
m_World->BroadcastSpawnEntity(*GhastBall); m_World->BroadcastSpawnEntity(*GhastBall);
m_AttackInterval = 0.0; ResetAttackCooldown();
return true; return true;
} }
return false; return false;

View File

@ -88,7 +88,7 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A
, m_AttackRate(3) , m_AttackRate(3)
, m_AttackDamage(1) , m_AttackDamage(1)
, m_AttackRange(1) , m_AttackRange(1)
, m_AttackInterval(0) , m_AttackCoolDownTicksLeft(0)
, m_SightDistance(25) , m_SightDistance(25)
, m_DropChanceWeapon(0.085f) , m_DropChanceWeapon(0.085f)
, m_DropChanceHelmet(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); super::Tick(a_Dt, a_Chunk);
GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT); GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT);
if (m_AttackCoolDownTicksLeft > 0)
{
m_AttackCoolDownTicksLeft -= 1;
}
if (m_Health <= 0) if (m_Health <= 0)
{ {
// The mob is dead, but we're still animating the "puff" they leave when they die // 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<int>(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) void cMonster::SetCustomName(const AString & a_CustomName)
{ {
m_CustomName = a_CustomName; m_CustomName = a_CustomName;

View File

@ -101,6 +101,7 @@ public:
void SetDropChanceLeggings(float a_DropChanceLeggings) { m_DropChanceLeggings = a_DropChanceLeggings; } void SetDropChanceLeggings(float a_DropChanceLeggings) { m_DropChanceLeggings = a_DropChanceLeggings; }
void SetDropChanceBoots(float a_DropChanceBoots) { m_DropChanceBoots = a_DropChanceBoots; } void SetDropChanceBoots(float a_DropChanceBoots) { m_DropChanceBoots = a_DropChanceBoots; }
void SetCanPickUpLoot(bool a_CanPickUpLoot) { m_CanPickUpLoot = a_CanPickUpLoot; } 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 */ /** Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick */
void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; }
@ -220,7 +221,7 @@ protected:
float m_AttackRate; float m_AttackRate;
int m_AttackDamage; int m_AttackDamage;
int m_AttackRange; int m_AttackRange;
float m_AttackInterval; int m_AttackCoolDownTicksLeft;
int m_SightDistance; int m_SightDistance;
float m_DropChanceWeapon; float m_DropChanceWeapon;

View File

@ -50,9 +50,9 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) 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; cFastRandom Random;
m_AttackInterval += (static_cast<float>(a_Dt.count()) / 1000) * m_AttackRate; if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
if ((m_Target != nullptr) && (m_AttackInterval > 3.0))
{ {
Vector3d Inaccuracy = Vector3d(Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25); 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; Vector3d Speed = (m_Target->GetPosition() + Inaccuracy - GetPosition()) * 5;
@ -69,8 +69,8 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt)
return false; return false;
} }
m_World->BroadcastSpawnEntity(*Arrow); m_World->BroadcastSpawnEntity(*Arrow);
m_AttackInterval = 0.0; ResetAttackCooldown();
return true; return true;
} }
return false; return false;

View File

@ -228,15 +228,11 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} }
else else
{ {
MoveToPosition(m_Target->GetPosition());
if (TargetIsInRange()) if (TargetIsInRange())
{ {
StopMovingToPosition();
Attack(a_Dt); Attack(a_Dt);
} }
else
{
MoveToPosition(m_Target->GetPosition());
}
} }
} }