gdle/Source/AttackManager.cpp

214 lines
4.6 KiB
C++
Raw Permalink Normal View History

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);
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
{
if (_weenie->AsPlayer())
{
_weenie->AsPlayer()->m_Qualities.SetFloat(ATTACK_TIMESTAMP_FLOAT, Timer::cur_time);
}
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
if (_attackData->ShouldNotifyAttackDone())
2018-03-29 17:01:57 -04:00
{
2018-07-11 04:53:32 +00:00
_weenie->NotifyAttackDone();
_weenie->NotifyCommenceAttack();
2018-03-29 17:01:57 -04:00
}
_attackData->_attack_charge_time = Timer::cur_time + (_attackData->_attack_power * _attackData->AttackTimeMod());
_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
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);
if (motion == Motion_Reload)
{
2018-07-11 04:53:32 +00:00
_weenie->NotifyAttackDone();
_weenie->NotifyCommenceAttack();
}
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;
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();
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);
}