summaryrefslogtreecommitdiffstats
path: root/src/Mobs/Behaviors
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs/Behaviors')
-rw-r--r--src/Mobs/Behaviors/BehaviorAttacker.cpp45
-rw-r--r--src/Mobs/Behaviors/BehaviorAttacker.h25
-rw-r--r--src/Mobs/Behaviors/BehaviorAttackerMelee.cpp11
-rw-r--r--src/Mobs/Behaviors/BehaviorAttackerMelee.h11
-rw-r--r--src/Mobs/Behaviors/CMakeLists.txt2
5 files changed, 79 insertions, 15 deletions
diff --git a/src/Mobs/Behaviors/BehaviorAttacker.cpp b/src/Mobs/Behaviors/BehaviorAttacker.cpp
index 3113516ff..30c18019e 100644
--- a/src/Mobs/Behaviors/BehaviorAttacker.cpp
+++ b/src/Mobs/Behaviors/BehaviorAttacker.cpp
@@ -43,7 +43,7 @@ bool cBehaviorAttacker::IsControlDesired(std::chrono::milliseconds a_Dt, cChunk
UNUSED(a_Chunk);
// If we have a target, we have something to do! Return true and control the mob Ticks.
// Otherwise return false.
- return (GetTarget() != nullptr);
+ return (m_IsStriking || (GetTarget() != nullptr));
}
@@ -55,10 +55,23 @@ void cBehaviorAttacker::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
UNUSED(a_Dt);
UNUSED(a_Chunk);
- if (m_IsStriking) return;
- // If we're striking, return. This allows derived classes to implement multi-tick strikes
- // E.g. a blaze shooting 3 fireballs in consequative ticks.
- // Derived class is expected to set m_IsStriking to false when the strike is done.
+ if (m_IsStriking)
+ {
+ if (StrikeTarget(a_Dt, a_Chunk, ++m_StrikeTickCnt))
+ {
+ m_Parent->UnpinBehavior(this);
+ m_IsStriking = false;
+ ResetStrikeCooldown();
+ }
+ #ifdef _DEBUG
+ if (m_StrikeTickCnt > 100)
+ {
+ LOGD("Sanity check failed. An attack took more than 5 seconds. Hmm");
+ ASSERT(1 == 0);
+ }
+ #endif
+ return;
+ }
if ((GetTarget() != nullptr))
{
@@ -75,7 +88,6 @@ void cBehaviorAttacker::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
ASSERT((GetTarget() == nullptr) || (GetTarget()->IsPawn() && (GetTarget()->GetWorld() == m_Parent->GetWorld())));
- // Stop targeting out of range targets
if (GetTarget() != nullptr)
{
if (TargetOutOfSight())
@@ -91,7 +103,7 @@ void cBehaviorAttacker::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
else
{
m_Parent->MoveToPosition(m_Target->GetPosition());
- // todo BehaviorApproacher
+ // todo BehaviorApproacher for creeper sneaking, etc
}
}
}
@@ -190,6 +202,21 @@ void cBehaviorAttacker::SetTarget(cPawn * a_Target)
+void cBehaviorAttacker::StrikeTarget()
+{
+ if (m_IsStriking || (m_Target == nullptr))
+ {
+ return;
+ }
+ m_IsStriking = true;
+ m_StrikeTickCnt = 0;
+ m_Parent->PinBehavior(this);
+}
+
+
+
+
+
bool cBehaviorAttacker::TargetIsInStrikeRadius(void)
{
ASSERT(GetTarget() != nullptr);
@@ -254,8 +281,6 @@ void cBehaviorAttacker::StrikeTargetIfReady()
{
if (m_AttackCoolDownTicksLeft != 0)
{
- m_IsStriking = true;
- StrikeTarget(); // Different derived classes implement strikes in different ways
- ResetStrikeCooldown();
+ StrikeTarget();
}
}
diff --git a/src/Mobs/Behaviors/BehaviorAttacker.h b/src/Mobs/Behaviors/BehaviorAttacker.h
index 4573f9a4a..099cb1987 100644
--- a/src/Mobs/Behaviors/BehaviorAttacker.h
+++ b/src/Mobs/Behaviors/BehaviorAttacker.h
@@ -24,25 +24,38 @@ public:
void SetAttackDamage(int a_AttackDamage);
// Behavior functions
- virtual bool IsControlDesired(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ bool IsControlDesired(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
void Destroyed() override;
- virtual void PostTick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ void PostTick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
void DoTakeDamage(TakeDamageInfo & a_TDI) override;
/** Returns the target pointer, or a nullptr if we're not targeting anyone. */
cPawn * GetTarget();
- /** Sets a new target. Forgets the older target if present. */
+ /** Sets a new target. Forgets the older target if present. Set this to nullptr to unset target. */
void SetTarget(cPawn * a_Target);
+
+ /** Makes the mob strike a target the next tick. Ignores the strike cooldown.
+ * Ignored if already striking or if no target is set. */
+ void StrikeTarget();
+
+ /** Makes the mob strike a target the next tick only if the strike cooldown permits it.
+ * Ignored if already striking or if no target is set. */
+ void StrikeTargetIfReady();
protected:
- virtual void StrikeTarget() = 0;
+
+ /** Called when the actual attack should be made. Will be called again and again every tick until
+ it returns false. a_StrikeTickCnt tracks how many times it was called. It is 1 the first call.
+ It increments by 1 each call. This mechanism allows multi-tick attacks, like blazes shooting multiple
+ fireballs, but most attacks are single tick and return true the first call. */
+ virtual bool StrikeTarget(std::chrono::milliseconds a_Dt, cChunk & a_Chunk, int a_StrikeTickCnt) = 0;
// Target related methods
bool TargetIsInStrikeRadius();
bool TargetIsInStrikeRadiusAndLineOfSight();
bool TargetOutOfSight();
- void StrikeTargetIfReady();
+ void StrikeTargetIfReady(std::chrono::milliseconds a_Dt, cChunk & a_Chunk);
// Cooldown stuff
void ResetStrikeCooldown();
@@ -64,4 +77,6 @@ private:
// The mob we want to attack
cPawn * m_Target;
+ int m_StrikeTickCnt;
+
};
diff --git a/src/Mobs/Behaviors/BehaviorAttackerMelee.cpp b/src/Mobs/Behaviors/BehaviorAttackerMelee.cpp
new file mode 100644
index 000000000..42e88c637
--- /dev/null
+++ b/src/Mobs/Behaviors/BehaviorAttackerMelee.cpp
@@ -0,0 +1,11 @@
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "BehaviorAttackerMelee.h"
+#include "../Monster.h"
+#include "../../Entities/Pawn.h"
+
+bool cBehaviorAttackerMelee::StrikeTarget(std::chrono::milliseconds a_Dt, cChunk & a_Chunk, int a_StrikeTickCnt)
+{
+ GetTarget()->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
+ return true;
+}
diff --git a/src/Mobs/Behaviors/BehaviorAttackerMelee.h b/src/Mobs/Behaviors/BehaviorAttackerMelee.h
new file mode 100644
index 000000000..6bfda0aa3
--- /dev/null
+++ b/src/Mobs/Behaviors/BehaviorAttackerMelee.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "BehaviorAttacker.h"
+
+/** Makes the mob fight back any other mob that damages it. Mob should have BehaviorAttacker to work.
+This behavior does not make sense in combination with BehaviorCoward. */
+class cBehaviorAttackerMelee : cBehaviorAttacker
+{
+public:
+ bool StrikeTarget(std::chrono::milliseconds a_Dt, cChunk & a_Chunk, int a_StrikeTickCnt) override;
+};
diff --git a/src/Mobs/Behaviors/CMakeLists.txt b/src/Mobs/Behaviors/CMakeLists.txt
index 9aa3a1a4a..686d0937b 100644
--- a/src/Mobs/Behaviors/CMakeLists.txt
+++ b/src/Mobs/Behaviors/CMakeLists.txt
@@ -16,6 +16,7 @@ SET (SRCS
BehaviorItemDropper.cpp
BehaviorItemFollower.cpp
BehaviorItemReplacer.cpp
+ BehaviorAttackerMelee.cpp
BehaviorStriker.cpp
BehaviorWanderer.cpp
)
@@ -32,6 +33,7 @@ SET (HDRS
BehaviorItemDropper.h
BehaviorItemFollower.h
BehaviorItemReplacer.h
+ BehaviorAttackerMelee.h
BehaviorStriker.h
BehaviorWanderer.h
)