mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-23 06:57:23 +00:00
277 lines
6.1 KiB
C++
277 lines
6.1 KiB
C++
#include "ht.h"
|
|
|
|
namespace wi {
|
|
|
|
static MobileUnitConsts gmuntcAndy;
|
|
|
|
#if defined(DEBUG_HELPERS)
|
|
char *AndyGob::GetName()
|
|
{
|
|
return "Andy";
|
|
}
|
|
#endif
|
|
|
|
static int s_anFiringStripIndices[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
static int s_anMovingStripIndices[8] = { 17, 18, 19, 20, 21, 22, 23, 24 };
|
|
static int s_anIdleStripIndices[8] = { 9, 10, 11, 12, 13, 14, 15, 16 };
|
|
|
|
bool AndyGob::InitClass(IniReader *pini)
|
|
{
|
|
gmuntcAndy.gt = kgtAndy;
|
|
gmuntcAndy.ut = kutAndy;
|
|
gmuntcAndy.wf |= kfUntcNotifyEnemyNearby | kfUntcLargeDefog;
|
|
|
|
// Initialize the frame indices arrays
|
|
|
|
gmuntcAndy.anFiringStripIndices = s_anFiringStripIndices;
|
|
gmuntcAndy.anMovingStripIndices = s_anMovingStripIndices;
|
|
gmuntcAndy.anIdleStripIndices = s_anIdleStripIndices;
|
|
|
|
// Sound effects
|
|
|
|
gmuntcAndy.sfxFire = ksfxAndyFire;
|
|
gmuntcAndy.sfxImpact = ksfxNothing;
|
|
gmuntcAndy.sfxcDestroyed = ksfxcAndyDestroyed;
|
|
gmuntcAndy.sfxcSelect = ksfxcAndySelect;
|
|
gmuntcAndy.sfxcMove = ksfxcAndyMove;
|
|
gmuntcAndy.sfxcAttack = ksfxcAndyAttack;
|
|
|
|
return MobileUnitGob::InitClass(&gmuntcAndy, pini);
|
|
}
|
|
|
|
void AndyGob::ExitClass()
|
|
{
|
|
MobileUnitGob::ExitClass(&gmuntcAndy);
|
|
}
|
|
|
|
AndyGob::AndyGob() : MobileUnitGob(&gmuntcAndy)
|
|
{
|
|
}
|
|
|
|
// For the benefit of Fox
|
|
|
|
AndyGob::AndyGob(MobileUnitConsts *pmuntc) : MobileUnitGob(pmuntc)
|
|
{
|
|
}
|
|
|
|
bool AndyGob::Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName)
|
|
{
|
|
bool f = MobileUnitGob::Init(wx, wy, pplr, fxHealth, ff, pszName);
|
|
|
|
// Start the healing process
|
|
|
|
gsmm.SendDelayedMsg(kmidHeal, 100, m_gid, m_gid); // 1 second
|
|
|
|
return f;
|
|
}
|
|
|
|
bool AndyGob::Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy)
|
|
{
|
|
// MobileUnitGob handles rotating towards the target, firing delay,
|
|
// and starting the fire animation
|
|
|
|
if (!MobileUnitGob::Fire(puntTarget, wx, wy, wdx, wdy))
|
|
return false;
|
|
|
|
// Fire off the shot!
|
|
|
|
WCoord wdxRnd = ((GetRandom() & 7) - 3) * kwcTile16th;
|
|
WCoord wdyRnd = ((GetRandom() & 7) - 3) * kwcTile16th;
|
|
Point ptSpecial;
|
|
m_ani.GetSpecialPoint(&ptSpecial, 1); // frame #1 (second frame) has the firing point
|
|
|
|
CreateAndyShotGob(m_wx + WcFromPc(ptSpecial.x), m_wy + WcFromPc(ptSpecial.y), wx + wdxRnd, wy + wdyRnd,
|
|
GetDamageTo(puntTarget), m_gid, puntTarget->GetId());
|
|
|
|
// Play sound
|
|
|
|
gsndm.PlaySfx(m_pmuntc->sfxFire);
|
|
|
|
return true;
|
|
}
|
|
|
|
void AndyGob::Idle()
|
|
{
|
|
// 1/4 of the time we pivot left, 1/4 we pivot right, and 1/2 we play the idle
|
|
|
|
switch (GetRandom() & 3) {
|
|
case 0:
|
|
m_dir--;
|
|
if (m_dir < 0)
|
|
m_dir = 7;
|
|
StartAnimation(&m_ani, m_pmuntc->anIdleStripIndices[m_dir], 0, kfAniResetWhenDone);
|
|
break;
|
|
|
|
case 1:
|
|
m_dir++;
|
|
if (m_dir > 7)
|
|
m_dir = 0;
|
|
StartAnimation(&m_ani, m_pmuntc->anIdleStripIndices[m_dir], 0, kfAniResetWhenDone);
|
|
break;
|
|
|
|
default:
|
|
StartAnimation(&m_ani, m_pmuntc->anIdleStripIndices[m_dir], 0, kfAniResetWhenDone);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int AndyGob::ProcessStateMachineMessage(State st, Message *pmsg)
|
|
{
|
|
BeginStateMachine
|
|
|
|
// Andy recovers full health in 1 minute
|
|
|
|
OnMsg(kmidHeal)
|
|
if (m_ff & kfGobActive)
|
|
gsmm.SendDelayedMsg(kmidHeal, 100, m_gid, m_gid); // 1 second
|
|
|
|
fix fxArmorStrength = m_pmuntc->GetArmorStrength();
|
|
if (m_fxHealth < fxArmorStrength) {
|
|
// Add 1/60th of total health
|
|
fix fxHealth = addfx(m_fxHealth, divfx(fxArmorStrength, itofx(60)));
|
|
if (fxHealth > fxArmorStrength)
|
|
fxHealth = fxArmorStrength;
|
|
SetHealth(fxHealth);
|
|
}
|
|
|
|
State(kstDying)
|
|
OnEnter
|
|
TRect trc;
|
|
GetTileRect(&trc);
|
|
|
|
Deactivate();
|
|
|
|
// Redraw this part of minimap. It will skip inactive munts
|
|
|
|
gpmm->RedrawTRect(&trc);
|
|
|
|
m_ff ^= kfGobLayerDepthSorted | kfGobLayerSurfaceDecal;
|
|
|
|
gsndm.PlaySfx(SfxFromCategory(m_pmuntc->sfxcDestroyed));
|
|
m_ani.Start("die 3", kfAniIgnoreFirstAdvance);
|
|
MarkRedraw();
|
|
|
|
// Remove corpse after 10 seconds
|
|
|
|
gsmm.SendDelayedMsg(kmidDelete, 1000, m_gid, m_gid);
|
|
|
|
OnUpdate
|
|
AdvanceAnimation(&m_ani);
|
|
|
|
#if 0
|
|
EndStateMachineInherit(MobileUnitGob)
|
|
#else
|
|
return knHandled;
|
|
}
|
|
} else {
|
|
return (int)MobileUnitGob::ProcessStateMachineMessage(st, pmsg);
|
|
}
|
|
|
|
return (int)MobileUnitGob::ProcessStateMachineMessage(st, pmsg);
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// Fox is a clone of Andy with tweaked GobTemplates.ini parameters
|
|
//
|
|
|
|
static MobileUnitConsts gmuntcFox;
|
|
|
|
#if defined(DEBUG_HELPERS)
|
|
char *FoxGob::GetName()
|
|
{
|
|
return "Fox";
|
|
}
|
|
#endif
|
|
|
|
FoxGob::FoxGob() : AndyGob(&gmuntcFox)
|
|
{
|
|
}
|
|
|
|
bool FoxGob::InitClass(IniReader *pini)
|
|
{
|
|
gmuntcFox.gt = kgtFox;
|
|
gmuntcFox.ut = kutFox;
|
|
gmuntcFox.wf |= kfUntcNotifyEnemyNearby | kfUntcLargeDefog;
|
|
|
|
// Initialize the frame indices arrays
|
|
|
|
gmuntcFox.anFiringStripIndices = s_anFiringStripIndices;
|
|
gmuntcFox.anMovingStripIndices = s_anMovingStripIndices;
|
|
gmuntcFox.anIdleStripIndices = s_anIdleStripIndices;
|
|
|
|
// Sound effects
|
|
|
|
|
|
//gmuntcFox.sfxFire = ksfxAndyFire; he never shoots
|
|
|
|
gmuntcFox.sfxFire = ksfxLightTankFire;
|
|
gmuntcFox.sfxImpact = ksfxNothing;
|
|
|
|
gmuntcFox.sfxcDestroyed = ksfxcFoxDestroyed;
|
|
gmuntcFox.sfxcSelect = ksfxcMale03Select;
|
|
gmuntcFox.sfxcMove = ksfxcMale03Move;
|
|
gmuntcFox.sfxcAttack = ksfxcMale03Attack;
|
|
|
|
return MobileUnitGob::InitClass(&gmuntcFox, pini);
|
|
}
|
|
|
|
void FoxGob::ExitClass()
|
|
{
|
|
MobileUnitGob::ExitClass(&gmuntcFox);
|
|
}
|
|
|
|
//
|
|
// AndyShotGob implementation
|
|
//
|
|
|
|
AnimationData *AndyShotGob::s_panidShot = NULL;
|
|
|
|
// this will actually create & fire
|
|
AndyShotGob *CreateAndyShotGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget, bool fEagle)
|
|
{
|
|
if (!ggobm.IsBelowLimit(knLimitSupport))
|
|
return NULL;
|
|
|
|
AndyShotGob *pgob = new AndyShotGob();
|
|
Assert(pgob != NULL, "out of memory!");
|
|
if (pgob == NULL)
|
|
return NULL;
|
|
|
|
if (!pgob->Init(AndyShotGob::s_panidShot, wx, wy, wxTarget, wyTarget, nDamage, gidOwner, gidTarget, kwcTile)) {
|
|
delete pgob;
|
|
return NULL;
|
|
}
|
|
|
|
pgob->Launch();
|
|
return pgob;
|
|
}
|
|
|
|
bool AndyShotGob::InitClass(IniReader *pini)
|
|
{
|
|
s_panidShot = LoadAnimationData("andyshot.anir");
|
|
if (s_panidShot == NULL)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void AndyShotGob::ExitClass()
|
|
{
|
|
delete s_panidShot;
|
|
s_panidShot = NULL;
|
|
}
|
|
|
|
GobType AndyShotGob::GetType()
|
|
{
|
|
return kgtAndyShot;
|
|
}
|
|
|
|
#if defined(DEBUG_HELPERS)
|
|
char *AndyShotGob::GetName()
|
|
{
|
|
return "AndyShot";
|
|
}
|
|
#endif
|
|
|
|
} // namespace wi
|