From 60e24ca8b41bcfa92ab579b178d2c7adf51c3bcf Mon Sep 17 00:00:00 2001 From: LogicParrot Date: Wed, 30 Aug 2017 15:08:57 +0300 Subject: BehaviorAttacker --- src/Mobs/Behaviors/BehaviorAttacker.cpp | 45 +++++++++++++++++++++------- src/Mobs/Behaviors/BehaviorAttacker.h | 25 ++++++++++++---- src/Mobs/Behaviors/BehaviorAttackerMelee.cpp | 11 +++++++ src/Mobs/Behaviors/BehaviorAttackerMelee.h | 11 +++++++ src/Mobs/Behaviors/CMakeLists.txt | 2 ++ 5 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/Mobs/Behaviors/BehaviorAttackerMelee.cpp create mode 100644 src/Mobs/Behaviors/BehaviorAttackerMelee.h (limited to 'src/Mobs/Behaviors') 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 ) -- cgit v1.2.3