#include "pch.h"
#include "magazineIGC.h"
CmagazineIGC::CmagazineIGC(void)
:
m_ship(NULL),
m_partType(NULL),
m_missileType(NULL),
m_mountID(c_mountNA),
m_lock(0.0f)
{
}
CmagazineIGC::~CmagazineIGC(void)
{
}
HRESULT CmagazineIGC::Initialize(ImissionIGC* pMission, Time now, const void* data, int dataSize)
{
assert (pMission);
m_pMission = pMission;
ZRetailAssert (data && (dataSize == sizeof(DataPartIGC)));
{
m_partType = (IlauncherTypeIGC*)(((DataPartIGC*)data)->partType);
assert (m_partType);
m_partType->AddRef();
m_missileType = (ImissileTypeIGC*)(m_partType->GetExpendableType());
assert (m_missileType);
assert (m_missileType->GetObjectType() == OT_missileType);
m_missileType->AddRef();
m_amount = 0;
}
return S_OK;
}
void CmagazineIGC::Terminate(void)
{
AddRef();
SetShip(NULL, NA);
if (m_partType)
{
m_partType->Release();
m_partType = NULL;
}
if (m_missileType)
{
m_missileType->Release();
m_missileType = NULL;
}
Release();
}
void CmagazineIGC::Update(Time now)
{
assert (m_ship);
Time lastUpdate = m_ship->GetLastUpdate();
float dt = now - lastUpdate;
assert (dt >= 0.0f);
if (m_mountedFraction < 1.0f)
{
m_mountedFraction += dt * m_pMission->GetFloatConstant(c_fcidMountRate);
if (m_mountedFraction < 1.0f)
{
m_lock = 0.0f;
return;
}
IIgcSite* pigc = GetMission()->GetIgcSite();
pigc->PlayNotificationSound(mountedSound, m_ship);
pigc->PostNotificationText(m_ship, false, "%s ready.", GetPartType()->GetName());
m_mountedFraction = 1.0f;
}
assert (m_ship);
if ((m_timeLoaded < now) && (m_amount > 0))
{
if (m_ship->GetRipcordModel() != NULL)
m_lock = 0.0f;
else
{
ImodelIGC* ptarget = m_ship->GetCommandTarget(c_cmdCurrent);
float maxLock = m_missileType->GetMaxLock();
if (m_ship->GetStateM() & missileFireIGC)
{
float oldLock = m_lock;
m_lock = 0.0f;
m_timeLoaded = now + m_missileType->GetLoadTime();
m_pMission->GetIgcSite()->FireMissile(m_ship,
this,
now,
ptarget,
oldLock * maxLock);
}
else
{
if (ptarget && (ptarget->GetCluster() == m_ship->GetCluster()) && (ptarget->GetSide() != m_ship->GetSide()) && (m_missileType->HasCapability(c_eabmWarpBomb) ? (ptarget->GetObjectType() == OT_warp) : (ptarget->GetAttributes() & c_mtDamagable)) && m_ship->CanSee(ptarget)) {
float lifespan = m_missileType->GetLifespan();
float maxRange = m_missileType->GetInitialSpeed() * lifespan + 0.5f * m_missileType->GetAcceleration() * lifespan * lifespan;
Vector dP = (ptarget->GetPosition() - m_ship->GetPosition());
float l2 = dP.LengthSquared();
float oldLock = m_lock;
m_lock = 0.0f;
if ((l2 > 1.0f) && (l2 < maxRange * maxRange))
{
if (maxLock == 0.0f)
m_lock = 1.0f;
else
{
dP.SetNormalize();
double dot = -(dP * m_ship->GetOrientation().GetBackward());
float angleOffBow = (dot >= 1.0)
? 0.0f
: ((dot <= -1.0f)
? pi
: (float)acos(dot));
float lockTime = m_missileType->GetLockTime();
float lockAngle = m_missileType->GetLockAngle();
float v = (lockAngle - angleOffBow) / lockAngle;
if (v < 0.0)
v *= lockTime;
m_lock = oldLock + v * dt / (ptarget->GetObjectType() == OT_ship
? (lockTime * ((IshipIGC*)ptarget)->GetHullType()->GetECM())
: lockTime);
}
if (m_lock >= 1.0f)
{
m_lock = 1.0f;
}
else if (m_lock < 0.0f)
m_lock = 0.0f;
}
}
}
}
}
}
void CmagazineIGC::SetShip(IshipIGC* newVal, Mount mount)
{
AddRef();
if (m_ship)
{
m_ship->DeletePart(this);
m_ship->Release();
}
assert (m_mountID == c_mountNA);
m_ship = newVal;
if (m_ship)
{
m_ship->AddRef();
m_ship->AddPart(this);
m_emissionPt = m_ship->GetHitTest()->GetFrameOffset("missemt");
SetMountID(mount);
}
Release();
}
void CmagazineIGC::SetMountID(Mount newVal)
{
assert (m_ship);
if (newVal != m_mountID)
{
if ((newVal < 0) && (m_mountID == 0))
Deactivate();
m_ship->MountPart(this, newVal, &m_mountID);
if (newVal == 0)
Activate();
}
}