2019-07-07 20:56:15 +00:00
|
|
|
#include <StdAfx.h>
|
2018-03-29 17:01:57 -04:00
|
|
|
#include "AttackManager.h"
|
|
|
|
|
#include "WeenieObject.h"
|
|
|
|
|
#include "World.h"
|
|
|
|
|
#include "Player.h"
|
|
|
|
|
#include "WeenieFactory.h"
|
|
|
|
|
#include "Ammunition.h"
|
|
|
|
|
#include "CombatFormulas.h"
|
|
|
|
|
|
2018-11-09 13:39:05 -06:00
|
|
|
#include "combat/MeleeAttackEventData.h"
|
2018-11-09 17:38:56 -06:00
|
|
|
#include "combat/DualWieldAttackEventData.h"
|
2018-11-09 13:39:05 -06:00
|
|
|
#include "combat/MissileAttackEventData.h"
|
2018-03-29 17:01:57 -04:00
|
|
|
|
2018-11-09 13:39:05 -06:00
|
|
|
// TODO fix memory leak with attack data
|
2018-03-29 17:01:57 -04:00
|
|
|
|
2018-07-12 14:41:21 -07:00
|
|
|
AttackManager::AttackManager(CWeenieObject *weenie)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
_weenie = weenie;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AttackManager::~AttackManager()
|
|
|
|
|
{
|
|
|
|
|
SafeDelete(_attackData);
|
|
|
|
|
SafeDelete(_cleanupData);
|
2018-08-17 11:17:11 +01:00
|
|
|
SafeDelete(_queuedAttackData);
|
2018-03-29 17:01:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AttackManager::MarkForCleanup(CAttackEventData *data)
|
|
|
|
|
{
|
|
|
|
|
if (_cleanupData && _cleanupData != data)
|
|
|
|
|
{
|
|
|
|
|
delete _cleanupData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_cleanupData = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AttackManager::Cancel()
|
|
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
_attackData->Cancel();
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::OnAttackCancelled(uint32_t error)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
{
|
2018-07-11 04:53:32 +00:00
|
|
|
_weenie->NotifyAttackDone();
|
|
|
|
|
_weenie->DoForcedMotion(_weenie->get_minterp()->InqStyle());
|
|
|
|
|
_weenie->unstick_from_object();
|
2018-03-29 17:01:57 -04:00
|
|
|
|
|
|
|
|
MarkForCleanup(_attackData);
|
|
|
|
|
_attackData = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AttackManager::RepeatAttacks()
|
|
|
|
|
{
|
2018-07-12 14:41:21 -07:00
|
|
|
if (_weenie->AsPlayer())
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
2018-07-12 14:41:21 -07:00
|
|
|
CPlayerWeenie *player = (CPlayerWeenie *)_weenie;
|
2018-03-29 17:01:57 -04:00
|
|
|
return player->ShouldRepeatAttacks();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::OnAttackDone(uint32_t error)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
2019-09-14 12:53:36 -07:00
|
|
|
if (_weenie->AsPlayer())
|
2019-10-06 08:35:22 -07:00
|
|
|
{
|
2019-10-27 17:58:43 +00:00
|
|
|
_weenie->AsPlayer()->m_Qualities.SetFloat(ATTACK_TIMESTAMP_FLOAT, Timer::cur_time);
|
2019-10-06 08:35:22 -07:00
|
|
|
}
|
2018-07-12 14:41:21 -07:00
|
|
|
//if(_weenie->_blockNewAttacksUntil < Timer::cur_time) //fix for cancelling reload animation making attacking faster
|
|
|
|
|
//_weenie->_blockNewAttacksUntil = Timer::cur_time + 1.0;
|
2018-03-29 17:01:57 -04:00
|
|
|
if (_attackData)
|
|
|
|
|
{
|
|
|
|
|
if (RepeatAttacks() && _attackData->IsValidTarget())
|
|
|
|
|
{
|
2018-07-11 04:53:32 +00:00
|
|
|
|
2018-03-29 17:01:57 -04:00
|
|
|
if (_queuedAttackData != NULL)
|
|
|
|
|
{
|
|
|
|
|
//we have a queued attack, change to that.
|
|
|
|
|
SafeDelete(_attackData);
|
|
|
|
|
_attackData = _queuedAttackData;
|
|
|
|
|
_queuedAttackData = NULL;
|
|
|
|
|
}
|
2018-07-11 04:53:32 +00:00
|
|
|
|
2019-02-07 05:59:21 -06:00
|
|
|
if (_attackData->ShouldNotifyAttackDone())
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
2018-07-11 04:53:32 +00:00
|
|
|
_weenie->NotifyAttackDone();
|
2019-02-07 05:59:21 -06:00
|
|
|
_weenie->NotifyCommenceAttack();
|
2018-03-29 17:01:57 -04:00
|
|
|
}
|
|
|
|
|
|
2019-02-07 05:59:21 -06:00
|
|
|
_attackData->_attack_charge_time = Timer::cur_time + (_attackData->_attack_power * _attackData->AttackTimeMod());
|
2019-03-07 03:53:59 +00:00
|
|
|
_attackData->_attack_speed *= _attackData->AttackSpeedMod();
|
2018-03-29 17:01:57 -04:00
|
|
|
_attackData->Begin();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-07-12 14:41:21 -07:00
|
|
|
_weenie->NotifyAttackDone();
|
2018-03-29 17:01:57 -04:00
|
|
|
|
2019-03-07 03:53:59 +00:00
|
|
|
if (_weenie->_IsPlayer())
|
|
|
|
|
_weenie->AsPlayer()->m_bCancelAttack = true;
|
|
|
|
|
|
2018-03-29 17:01:57 -04:00
|
|
|
MarkForCleanup(_attackData);
|
|
|
|
|
_attackData = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AttackManager::Update()
|
|
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
{
|
|
|
|
|
_attackData->Update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SafeDelete(_cleanupData);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::OnDeath(uint32_t killer_id)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
Cancel();
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::HandleMoveToDone(uint32_t error)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
{
|
|
|
|
|
_attackData->HandleMoveToDone(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AttackManager::HandleAttackHook(const AttackCone &cone)
|
|
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
{
|
|
|
|
|
_attackData->HandleAttackHook(cone);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::OnMotionDone(uint32_t motion, BOOL success)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
if (_attackData)
|
|
|
|
|
{
|
|
|
|
|
_attackData->OnMotionDone(motion, success);
|
2018-06-27 22:48:55 +01:00
|
|
|
|
|
|
|
|
if (motion == Motion_Reload)
|
|
|
|
|
{
|
2018-07-11 04:53:32 +00:00
|
|
|
_weenie->NotifyAttackDone();
|
2019-02-07 05:59:21 -06:00
|
|
|
_weenie->NotifyCommenceAttack();
|
2018-06-27 22:48:55 +01:00
|
|
|
}
|
2018-03-29 17:01:57 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AttackManager::IsAttacking()
|
|
|
|
|
{
|
|
|
|
|
return _attackData != NULL ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AttackManager::BeginAttack(CAttackEventData *data)
|
|
|
|
|
{
|
|
|
|
|
if (_attackData != NULL)
|
|
|
|
|
{
|
|
|
|
|
//we're already attacking, queue this, or change current queued attack to this.
|
|
|
|
|
SafeDelete(_queuedAttackData);
|
|
|
|
|
_queuedAttackData = data;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_attackData = data;
|
|
|
|
|
_attackData->Begin();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::BeginMeleeAttack(uint32_t target_id, ATTACK_HEIGHT height, float power, float chase_distance, uint32_t motion)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
2018-11-09 13:39:05 -06:00
|
|
|
CMeleeAttackEvent *attackEvent = nullptr;
|
|
|
|
|
|
2018-11-22 23:37:16 -06:00
|
|
|
CWeenieObject *left = _weenie->GetWieldedCombat(COMBAT_USE_OFFHAND);
|
|
|
|
|
|
2018-11-09 13:39:05 -06:00
|
|
|
if (_weenie->GetWieldedCombat(COMBAT_USE_TWO_HANDED))
|
|
|
|
|
attackEvent = new CTwoHandAttackEvent();
|
2018-11-22 23:37:16 -06:00
|
|
|
else if (left && left->InqIntQuality(LOCATIONS_INT, 0) != SHIELD_LOC)
|
2018-11-09 17:38:56 -06:00
|
|
|
attackEvent = new CDualWieldAttackEvent();
|
2018-11-09 13:39:05 -06:00
|
|
|
else
|
|
|
|
|
attackEvent = new CMeleeAttackEvent();
|
2018-03-29 17:01:57 -04:00
|
|
|
|
2018-07-12 14:41:21 -07:00
|
|
|
attackEvent->_weenie = _weenie;
|
2018-03-29 17:01:57 -04:00
|
|
|
attackEvent->_manager = this;
|
|
|
|
|
attackEvent->_target_id = target_id;
|
|
|
|
|
attackEvent->_attack_height = height;
|
|
|
|
|
attackEvent->_attack_power = power;
|
|
|
|
|
attackEvent->_do_attack_animation = motion;
|
|
|
|
|
attackEvent->_fail_distance = chase_distance;
|
|
|
|
|
|
|
|
|
|
BeginAttack(attackEvent);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 20:56:15 +00:00
|
|
|
void AttackManager::BeginMissileAttack(uint32_t target_id, ATTACK_HEIGHT height, float power, uint32_t motion)
|
2018-03-29 17:01:57 -04:00
|
|
|
{
|
|
|
|
|
CMissileAttackEvent *attackEvent = new CMissileAttackEvent();
|
|
|
|
|
|
2018-07-12 14:41:21 -07:00
|
|
|
attackEvent->_weenie = _weenie;
|
2018-03-29 17:01:57 -04:00
|
|
|
attackEvent->_manager = this;
|
|
|
|
|
attackEvent->_target_id = target_id;
|
|
|
|
|
attackEvent->_attack_height = height;
|
|
|
|
|
attackEvent->_attack_power = power;
|
|
|
|
|
attackEvent->_do_attack_animation = motion;
|
|
|
|
|
|
|
|
|
|
BeginAttack(attackEvent);
|
|
|
|
|
}
|