mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
634 lines
17 KiB
C++
634 lines
17 KiB
C++
#include "ht.h"
|
|
#include "wistrings.h"
|
|
|
|
namespace wi {
|
|
|
|
//
|
|
// ProcessorGob implementation
|
|
//
|
|
|
|
static StructConsts gConsts;
|
|
|
|
//
|
|
// Gob methods
|
|
//
|
|
|
|
bool ProcessorGob::InitClass(IniReader *pini)
|
|
{
|
|
gConsts.gt = kgtProcessor;
|
|
gConsts.ut = kutProcessor;
|
|
gConsts.umPrerequisites = kumReactor;
|
|
gConsts.wf |= kfUntcHasFullnessIndicator;
|
|
|
|
// Sound effects
|
|
|
|
gConsts.sfxAbortRepair = ksfxGalaxiteProcessorAbortRepair;
|
|
gConsts.sfxRepair = ksfxGalaxiteProcessorRepair;
|
|
gConsts.sfxDamaged = ksfxGalaxiteProcessorDamaged;
|
|
gConsts.sfxSelect = ksfxGalaxiteProcessorSelect;
|
|
gConsts.sfxDestroyed = ksfxGalaxiteProcessorDestroyed;
|
|
gConsts.sfxImpact = ksfxNothing;
|
|
|
|
return StructGob::InitClass(&gConsts, pini);
|
|
}
|
|
|
|
void ProcessorGob::ExitClass()
|
|
{
|
|
StructGob::ExitClass(&gConsts);
|
|
}
|
|
|
|
ProcessorGob::ProcessorGob() : StructGob(&gConsts)
|
|
{
|
|
m_aniOverlay.Init(m_pstruc->panid);
|
|
StartAnimation(&m_aniOverlay, 3, 0, 0);
|
|
m_gidMiner = kgidNull;
|
|
m_wptFakeMiner.wx = kwxInvalid;
|
|
m_fProcessingAnimationInProgress = false;
|
|
}
|
|
|
|
#define knVerProcessorGobState 2
|
|
bool ProcessorGob::LoadState(Stream *pstm)
|
|
{
|
|
byte nVer = pstm->ReadByte();
|
|
if (nVer != knVerProcessorGobState)
|
|
return false;
|
|
m_gidMiner = pstm->ReadWord();
|
|
m_wptFakeMiner.wx = pstm->ReadWord();
|
|
m_wptFakeMiner.wy = pstm->ReadWord();
|
|
m_fProcessingAnimationInProgress = pstm->ReadByte() != 0 ? true : false;
|
|
m_fDoorMoving = pstm->ReadByte() != 0 ? true : false;
|
|
m_aniOverlay.LoadState(pstm);
|
|
return StructGob::LoadState(pstm);
|
|
}
|
|
|
|
bool ProcessorGob::SaveState(Stream *pstm)
|
|
{
|
|
pstm->WriteByte(knVerProcessorGobState);
|
|
pstm->WriteWord(m_gidMiner);
|
|
pstm->WriteWord(m_wptFakeMiner.wx);
|
|
pstm->WriteWord(m_wptFakeMiner.wy);
|
|
pstm->WriteByte(m_fProcessingAnimationInProgress);
|
|
pstm->WriteByte(m_fDoorMoving);
|
|
m_aniOverlay.SaveState(pstm);
|
|
return StructGob::SaveState(pstm);
|
|
}
|
|
|
|
int CalcCreditsShare(Player *pplr)
|
|
{
|
|
int cWarehouses = pplr->GetUnitCount(kutWarehouse);
|
|
int cProcessors = pplr->GetUnitCount(kutProcessor);
|
|
|
|
// Takeover the credits this Processor 'owns'
|
|
|
|
return pplr->GetCredits() / (cWarehouses + cProcessors);
|
|
}
|
|
|
|
void ProcessorGob::GetClippingBounds(Rect *prc)
|
|
{
|
|
UnitGob::GetClippingBounds(prc);
|
|
|
|
if (m_wptFakeMiner.wx != kwxInvalid) {
|
|
int ifrm = m_wptFakeMiner.wy < m_wy + kwcTile ? 1 : 0;
|
|
int xMiner = PcFromUwc(m_wptFakeMiner.wx);
|
|
int yMiner = PcFromWc(m_wptFakeMiner.wy);
|
|
Rect rcFakeMiner;
|
|
m_pstruc->panid->GetBounds(4, ifrm, &rcFakeMiner);
|
|
rcFakeMiner.Offset(xMiner, yMiner);
|
|
prc->Union(&rcFakeMiner);
|
|
}
|
|
}
|
|
|
|
bool ProcessorGob::IsTakeoverable(Player *pplr)
|
|
{
|
|
// Have to make sure there is limit space for the miner too
|
|
|
|
if (m_gidMiner != kgidNull) {
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
if (pgobMiner != NULL) {
|
|
if (!ggobm.IsBelowLimit(knLimitMobileUnit, pplr)) {
|
|
if (pplr == gpplrLocal)
|
|
ShowAlert(kidsUnitLimitReached);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return StructGob::IsTakeoverable(pplr);
|
|
}
|
|
|
|
// Override Takeover to funds to the new owner
|
|
|
|
void ProcessorGob::Takeover(Player *pplr)
|
|
{
|
|
// Takeover the credits this Processor 'owns'
|
|
|
|
int cCreditsTaken = CalcCreditsShare(m_pplr);
|
|
m_pplr->SetCredits(m_pplr->GetCredits() - cCreditsTaken, true);
|
|
pplr->SetCredits(pplr->GetCredits() + cCreditsTaken, true);
|
|
|
|
// if there's a miner parked inside, winner!
|
|
|
|
if (m_gidMiner != kgidNull) {
|
|
|
|
// take it over
|
|
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
if (pgobMiner != NULL) {
|
|
pgobMiner->Deactivate();
|
|
Assert(ggobm.IsBelowLimit(knLimitMobileUnit, pplr));
|
|
ggobm.TrackGobCounts(pgobMiner, false);
|
|
pgobMiner->SetOwner(pplr);
|
|
ggobm.TrackGobCounts(pgobMiner, true);
|
|
pgobMiner->Activate();
|
|
} else {
|
|
Assert(true); // there should be a miner!
|
|
}
|
|
}
|
|
|
|
// Takeover the Processor itself
|
|
|
|
StructGob::Takeover(pplr);
|
|
}
|
|
|
|
void ProcessorGob::Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer)
|
|
{
|
|
// Draw base
|
|
|
|
StructGob::Draw(pbm, xViewOrigin, yViewOrigin, nLayer);
|
|
|
|
// Draw overlay
|
|
|
|
if (nLayer == knLayerDepthSorted) {
|
|
|
|
// Don't draw the overlay on top of the destroyed base
|
|
|
|
if (m_ani.GetStrip() != 2) {
|
|
Side side = m_pplr->GetSide();
|
|
|
|
// Draw fake miner if it is meant to be
|
|
|
|
if (m_wptFakeMiner.wx != kwxInvalid) {
|
|
int ifrm = m_wptFakeMiner.wy < m_wy + kwcTile ? 1 : 0;
|
|
int xMiner = PcFromUwc(m_wptFakeMiner.wx) - xViewOrigin;
|
|
int yMiner = PcFromWc(m_wptFakeMiner.wy) - yViewOrigin;
|
|
m_pstruc->panid->DrawFrame(4, ifrm, pbm, xMiner, yMiner, side);
|
|
}
|
|
|
|
if (m_ff & kfGobDrawFlashed)
|
|
side = (Side)-1;
|
|
else if (m_ff & kfGobBeingBuilt)
|
|
side = ksideNeutral;
|
|
|
|
int x = PcFromUwc(m_wx) - xViewOrigin;
|
|
int y = PcFromUwc(m_wy) - yViewOrigin;
|
|
m_aniOverlay.Draw(pbm, x, y, side);
|
|
}
|
|
} else if (nLayer == knLayerSelection && (m_ff & kfGobSelected)) {
|
|
WRect wrcT;
|
|
GetUIBounds(&wrcT);
|
|
Rect rcT;
|
|
rcT.FromWorldRect(&wrcT);
|
|
rcT.Offset(-xViewOrigin, -yViewOrigin);
|
|
|
|
int nCapacity = m_pplr->GetCapacity();
|
|
int nPips = 0;
|
|
if (nCapacity != 0)
|
|
nPips = ((m_pplr->GetCredits() * 10) + (nCapacity / 20)) / nCapacity;
|
|
DrawFullnessIndicator(pbm, &rcT, nPips, 10);
|
|
}
|
|
}
|
|
|
|
dword ProcessorGob::GetAnimationHash()
|
|
{
|
|
dword dw = StructGob::GetAnimationHash();
|
|
int nFrame = m_aniOverlay.GetFrame();
|
|
int nStrip = m_aniOverlay.GetStrip();
|
|
dw ^= (m_wptFakeMiner.wx << 16) | m_wptFakeMiner.wy;
|
|
return dw ^ ((nFrame << 16) | nStrip);
|
|
}
|
|
|
|
void ProcessorGob::GetAnimationBounds(Rect *prc, bool fBase)
|
|
{
|
|
if (fBase) {
|
|
m_ani.GetAnimationData()->GetBounds(0, 0, prc);
|
|
return;
|
|
}
|
|
|
|
StructGob::GetAnimationBounds(prc, fBase);
|
|
if (m_wptFakeMiner.wx != kwxInvalid) {
|
|
int ifrm = m_wptFakeMiner.wy < m_wy + kwcTile ? 1 : 0;
|
|
Rect rcBounds;
|
|
m_pstruc->panid->GetBounds(4, ifrm, &rcBounds);
|
|
int xOffsetMiner = PcFromUwc(m_wptFakeMiner.wx - m_wx);
|
|
int yOffsetMiner = PcFromWc(m_wptFakeMiner.wy - m_wy);
|
|
rcBounds.Offset(xOffsetMiner, yOffsetMiner);
|
|
prc->Union(&rcBounds);
|
|
}
|
|
}
|
|
|
|
void ProcessorGob::DrawAnimation(DibBitmap *pbm, int x, int y)
|
|
{
|
|
StructGob::DrawAnimation(pbm, x, y);
|
|
|
|
// Don't go further if destroyed
|
|
|
|
if (m_ani.GetStrip() == 2) {
|
|
return;
|
|
}
|
|
Side side = m_pplr->GetSide();
|
|
if (m_wptFakeMiner.wx != kwxInvalid) {
|
|
int xOffsetMiner = PcFromUwc(m_wptFakeMiner.wx - m_wx);
|
|
int yOffsetMiner = PcFromWc(m_wptFakeMiner.wy - m_wy);
|
|
int ifrm = m_wptFakeMiner.wy < m_wy + kwcTile ? 1 : 0;
|
|
m_pstruc->panid->DrawFrame(4, ifrm, pbm, x + xOffsetMiner,
|
|
y + yOffsetMiner, side);
|
|
}
|
|
|
|
if (m_ff & kfGobDrawFlashed) {
|
|
side = (Side)-1;
|
|
} else if (m_ff & kfGobBeingBuilt) {
|
|
side = ksideNeutral;
|
|
}
|
|
m_aniOverlay.Draw(pbm, x, y, side);
|
|
}
|
|
|
|
void ProcessorGob::NotifyMinersAttemptingDelivery(bool fDying)
|
|
{
|
|
// Notify miners that are stuck attempting delivery to this processor that the
|
|
// processor is available.
|
|
|
|
for (Gob *pgobT = ggobm.GetFirstGob(); pgobT != NULL; pgobT = ggobm.GetNextGob(pgobT)) {
|
|
if (pgobT->GetType() != kgtGalaxMiner)
|
|
continue;
|
|
if (pgobT->GetOwner() != m_pplr)
|
|
continue;
|
|
if (!(pgobT->GetFlags() & kfGobActive))
|
|
continue;
|
|
MinerGob *pmnr = (MinerGob *)pgobT;
|
|
if (pmnr->IsAttemptingToDeliver(m_gid)) {
|
|
if (fDying) {
|
|
pmnr->SendDeliverCommand(kgidNull);
|
|
} else {
|
|
pmnr->SendDeliverCommand(m_gid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// StateMachine methods
|
|
//
|
|
|
|
#if defined(DEBUG_HELPERS)
|
|
char *ProcessorGob::GetName()
|
|
{
|
|
return "Processor";
|
|
}
|
|
#endif
|
|
|
|
int ProcessorGob::ProcessStateMachineMessage(State st, Message *pmsg)
|
|
{
|
|
BeginStateMachine
|
|
OnMsg(kmidGalaxiteDelivery)
|
|
// Remember the MinerGob and hide it (deselect it first)
|
|
// NOTE: It still occupies terrain and is counted in its owning
|
|
// Player's unit counts.
|
|
|
|
m_gidMiner = pmsg->smidSender;
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
pgobMiner->Hide(true);
|
|
|
|
// Set / clear reservation / occupation bits
|
|
|
|
TPoint tpt;
|
|
pgobMiner->GetTilePosition(&tpt);
|
|
gsim.GetLevel()->GetTerrainMap()->SetFlags(tpt.tx, tpt.ty, 1, 1, kbfStructure);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(tpt.tx, tpt.ty, 1, 1, kbfMobileUnit);
|
|
|
|
SetState(kstProcessorGetMiner);
|
|
|
|
OnMsg(kmidAnimationComplete)
|
|
m_fProcessingAnimationInProgress = false;
|
|
m_unvl.MinSkip();
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
State(kstBeingBuilt)
|
|
OnMsg(kmidBuildComplete)
|
|
// When a Processor is built at run time it brings a fresh Miner along with
|
|
// itself (included, free of charge!).
|
|
|
|
if (ggobm.IsBelowLimit(knLimitMobileUnit, m_pplr)) {
|
|
MinerGob *pmnr = new MinerGob();
|
|
Assert(pmnr != NULL, "out of memory!");
|
|
if (pmnr == NULL)
|
|
goto lbError;
|
|
if (!pmnr->Init(m_wx + kwcTile, m_wy + (kwcTile * 2), m_pplr, 0, 0, NULL)) {
|
|
delete pmnr;
|
|
goto lbError;
|
|
}
|
|
|
|
// Make sure the Miner prefers to return to this Processor
|
|
|
|
pmnr->SetFavoriteProcessor(m_gid);
|
|
|
|
// Hide the Miner so we can 'launch' it, same as it is launched
|
|
// after it completes a Galaxite delivery.
|
|
|
|
m_gidMiner = pmnr->GetId();
|
|
pmnr->GetCenter(&m_wptFakeMiner);
|
|
m_wptFakeMiner.wy = m_wy + WcFromTile16ths(15);
|
|
pmnr->Hide(true);
|
|
|
|
// Set / clear reservation / occupation bits
|
|
|
|
TPoint tpt;
|
|
pmnr->GetTilePosition(&tpt);
|
|
gsim.GetLevel()->GetTerrainMap()->SetFlags(tpt.tx, tpt.ty, 1, 1, kbfStructure);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(tpt.tx, tpt.ty, 1, 1, kbfMobileUnit);
|
|
|
|
StartAnimation(&m_aniOverlay, 3, -1, 0);
|
|
SetState(kstProcessorPutMiner);
|
|
} else {
|
|
lbError:
|
|
// The miner spot was reserved while the gob was being built. Since the new
|
|
// miner wasn't created, clear the spot so other miners can use the processor.
|
|
|
|
Assert(m_pstruc->ctx == 3 && m_pstruc->cty == 2);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(TcFromWc(m_wx) + 1, TcFromWc(m_wy) + m_pstruc->cty, 1, 1, kbfStructure);
|
|
SetState(kstIdle);
|
|
}
|
|
Activate();
|
|
|
|
OnEnter
|
|
// init will mark the building location as occupied.
|
|
// additionally here we'll mark the spot in front of our front door
|
|
// as occupied so the miner can exit when we're done building.
|
|
// We twiddle these flags on kmidGalaxiteDelivery and kstPutMiner
|
|
|
|
Assert(m_pstruc->ctx == 3 && m_pstruc->cty == 2);
|
|
gsim.GetLevel()->GetTerrainMap()->SetFlags(TcFromWc(m_wx) + 1,
|
|
TcFromWc(m_wy) + m_pstruc->cty, 1, 1, kbfStructure);
|
|
|
|
return StructGob::ProcessStateMachineMessage(st, pmsg);
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
State(kstProcessorGetMiner)
|
|
OnEnter
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
if (pgobMiner != NULL) {
|
|
pgobMiner->GetCenter(&m_wptFakeMiner);
|
|
pgobMiner->Select(false);
|
|
pgobMiner->Hilight(false);
|
|
StartAnimation(&m_aniOverlay, 3, 0, 0);
|
|
m_fDoorMoving = false;
|
|
}
|
|
|
|
OnExit
|
|
// To keep StructGob from attempting to handle a state it doesn't understand
|
|
|
|
OnUpdate
|
|
m_unvl.MinSkip();
|
|
|
|
// Open the door when the miner gets close
|
|
|
|
if (m_wptFakeMiner.wy < m_wy + WcFromTile16ths(35)) {
|
|
AdvanceAnimation(&m_aniOverlay);
|
|
if (!m_fDoorMoving) {
|
|
m_fDoorMoving = true;
|
|
if (m_pplr == gpplrLocal)
|
|
gsndm.PlaySfx(ksfxGalaxiteProcessorDoorOpening);
|
|
}
|
|
}
|
|
|
|
if (m_wptFakeMiner.wy > m_wy + WcFromTile16ths(15)) {
|
|
m_wptFakeMiner.wy -= kwcTile16th;
|
|
MarkRedraw();
|
|
} else {
|
|
SetState(kstProcessorTakeGalaxite);
|
|
}
|
|
|
|
DefUpdate();
|
|
|
|
State(kstProcessorTakeGalaxite)
|
|
OnEnter
|
|
OnExit
|
|
// To keep StructGob from attempting to handle a state it doesn't understand
|
|
|
|
OnUpdate
|
|
m_unvl.MinSkip();
|
|
|
|
// Add credits while taking galaxite from miner
|
|
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
Assert(pgobMiner != NULL);
|
|
int nAmount = pgobMiner->GetGalaxiteAmount();
|
|
if (nAmount > 0) {
|
|
nAmount -= 2;
|
|
int nGalaxiteValue = m_pplr->GetHandicap() & kfHcapIncreasedMinerLoadValue ?
|
|
((knGalaxiteValue * (100 + knIncreasedMinerLoadValuePercent)) + 50) / 100 : knGalaxiteValue;
|
|
int nCreditsNew = m_pplr->GetCredits() + 2 * nGalaxiteValue;
|
|
if (nCreditsNew <= m_pplr->GetCapacity()) {
|
|
MarkRedraw();
|
|
m_pplr->SetCredits(nCreditsNew, true);
|
|
pgobMiner->SetGalaxiteAmount(nAmount);
|
|
|
|
// Kick off the processing animation if it isn't already in progress
|
|
|
|
if (!m_fProcessingAnimationInProgress) {
|
|
if (ggobm.IsBelowLimit(knLimitSupport)) {
|
|
PuffGob *pgob = new PuffGob();
|
|
Assert(pgob != NULL, "out of memory!");
|
|
if (pgob != NULL)
|
|
pgob->Init(m_wx, m_wy, m_gid);
|
|
}
|
|
m_fProcessingAnimationInProgress = true;
|
|
}
|
|
} else {
|
|
// Need more storage!
|
|
|
|
gsim.GetLevel()->GetTriggerMgr()->SetConditionTrue(knGalaxiteCapacityReachedCondition,
|
|
GetSideMask(GetSide()));
|
|
|
|
// TUNE:
|
|
#define kctIntervalStorageNotify (30 * 100)
|
|
if (m_pplr == gpplrLocal) {
|
|
static long s_tLastStorageNotify = 0;
|
|
long tCurrent = HostGetTickCount();
|
|
if (s_tLastStorageNotify == 0 || (tCurrent - s_tLastStorageNotify) >= kctIntervalStorageNotify) {
|
|
s_tLastStorageNotify = tCurrent;
|
|
gsndm.PlaySfx(ksfxGalaxiteWarehouseTooFull);
|
|
ShowAlert(kidsWarehouseTooFull);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
SetState(kstProcessorPutMiner);
|
|
}
|
|
DefUpdate();
|
|
|
|
State(kstProcessorPutMiner)
|
|
OnEnter
|
|
m_fDoorMoving = false;
|
|
|
|
OnExit
|
|
// Restore the MinerGob.
|
|
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
Assert(pgobMiner != NULL);
|
|
pgobMiner->Hide(false);
|
|
|
|
// Set / clear reservation / occupation bits
|
|
|
|
TPoint tpt;
|
|
pgobMiner->GetTilePosition(&tpt);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(tpt.tx, tpt.ty, 1, 1, kbfStructure);
|
|
gsim.GetLevel()->GetTerrainMap()->SetFlags(tpt.tx, tpt.ty, 1, 1, kbfMobileUnit);
|
|
|
|
// Have the Miner resume mining
|
|
// NOTE: We send a message rather than call MinerGob::Mine method directly
|
|
// so the state change will occur immediately.
|
|
|
|
SendMineCommand(pgobMiner->GetId(), kwxInvalid, 0);
|
|
|
|
m_gidMiner = kgidNull;
|
|
m_wptFakeMiner.wx = kwxInvalid;
|
|
|
|
// Notify any miners attempting to deliver
|
|
|
|
NotifyMinersAttemptingDelivery(false);
|
|
|
|
OnUpdate
|
|
m_unvl.MinSkip();
|
|
|
|
WPoint wptDst;
|
|
((MinerGob *)ggobm.GetGob(m_gidMiner, false))->GetCenter(&wptDst);
|
|
if (m_wptFakeMiner.wy > m_wy + WcFromTile16ths(27)) {
|
|
int ifrm = m_aniOverlay.GetFrame();
|
|
if (ifrm > 0) {
|
|
SetAnimationFrame(&m_aniOverlay, --ifrm);
|
|
if (!m_fDoorMoving) {
|
|
m_fDoorMoving = true;
|
|
if (m_pplr == gpplrLocal)
|
|
gsndm.PlaySfx(ksfxGalaxiteProcessorDoorClosing);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_wptFakeMiner.wy < wptDst.wy) {
|
|
m_wptFakeMiner.wy += kwcTile16th;
|
|
MarkRedraw();
|
|
} else {
|
|
SetState(kstIdle);
|
|
}
|
|
DefUpdate();
|
|
|
|
State(kstDying)
|
|
OnEnter
|
|
#if 0 // DWM: crazy last minute change. Players don't lose credits when they sell Processors
|
|
// Sorry, player must lose some Credits along with this Processor
|
|
|
|
if (m_ff & kfGobActive)
|
|
m_pplr->SetCredits(m_pplr->GetCredits() - CalcCreditsShare(m_pplr), true);
|
|
#endif
|
|
|
|
// Remove the Miner too if it's inside the Processor
|
|
|
|
MinerGob *pgobMiner = (MinerGob *)ggobm.GetGob(m_gidMiner, false);
|
|
if (pgobMiner != NULL) {
|
|
// Clear the structure bit so the "miner tile" is free again
|
|
|
|
TPoint tpt;
|
|
pgobMiner->GetTilePosition(&tpt);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(tpt.tx, tpt.ty, 1, 1, kbfStructure);
|
|
|
|
// Deactivate the miner first which will subtract
|
|
// it from its owning Player's unit counts.
|
|
|
|
pgobMiner->Deactivate();
|
|
ggobm.RemoveGob(pgobMiner);
|
|
delete pgobMiner;
|
|
m_gidMiner = kgidNull;
|
|
}
|
|
|
|
// The miner spot is reserved while this gob is being built. Clear the bit just in case.
|
|
// We don't need to check anything, just clearing it is safe.
|
|
|
|
Assert(m_pstruc->ctx == 3 && m_pstruc->cty == 2);
|
|
gsim.GetLevel()->GetTerrainMap()->ClearFlags(TcFromWc(m_wx) + 1,
|
|
TcFromWc(m_wy) + m_pstruc->cty, 1, 1, kbfStructure);
|
|
|
|
int nHandled = StructGob::ProcessStateMachineMessage(st, pmsg);
|
|
|
|
// Now that this gob is deactivated, notify any miners attempting
|
|
// deliver to find a different processor
|
|
|
|
NotifyMinersAttemptingDelivery(true);
|
|
return nHandled;
|
|
|
|
#if 0
|
|
EndStateMachineInherit(StructGob)
|
|
#else
|
|
return knHandled;
|
|
}
|
|
} else {
|
|
return (int)StructGob::ProcessStateMachineMessage(st, pmsg);
|
|
}
|
|
return (int)StructGob::ProcessStateMachineMessage(st, pmsg);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// PuffGob implementation
|
|
// UNDONE: Consider making AnimGob savable by passing in an index
|
|
// referring to a global array of AnimData's (then the index can be saved
|
|
// and we can get rid of PuffGob).
|
|
//
|
|
|
|
PuffGob::PuffGob()
|
|
{
|
|
}
|
|
|
|
bool PuffGob::Init(WCoord wx, WCoord wy, StateMachineId smidNotify)
|
|
{
|
|
UnitConsts *puntc = gapuntc[kutProcessor];
|
|
return AnimGob::Init(wx, wy, kfAnmDeleteWhenDone | kfAnmSmokeFireLayer, NULL, puntc->panid, puntc->panid->GetStripIndex("smoke"), smidNotify, NULL);
|
|
}
|
|
|
|
#define knVerPuffGobState 1
|
|
bool PuffGob::LoadState(Stream *pstm)
|
|
{
|
|
byte nVer = pstm->ReadByte();
|
|
if (nVer != knVerPuffGobState)
|
|
return false;
|
|
UnitConsts *puntc = gapuntc[kutProcessor];
|
|
m_ani.Init(puntc->panid);
|
|
m_ani.SetStrip(puntc->panid->GetStripIndex("smoke"));
|
|
m_ani.LoadState(pstm);
|
|
m_smidNotify = pstm->ReadWord();
|
|
m_wfAnm = kfAnmDeleteWhenDone | kfAnmSmokeFireLayer;
|
|
return AnimGob::LoadState(pstm);
|
|
}
|
|
|
|
bool PuffGob::SaveState(Stream *pstm)
|
|
{
|
|
pstm->WriteByte(knVerPuffGobState);
|
|
m_ani.SaveState(pstm);
|
|
pstm->WriteWord(m_smidNotify);
|
|
return AnimGob::SaveState(pstm);
|
|
}
|
|
|
|
bool PuffGob::IsSavable()
|
|
{
|
|
// Because AnimGob is not savable, we need to override
|
|
|
|
return true;
|
|
}
|
|
|
|
GobType PuffGob::GetType()
|
|
{
|
|
return kgtPuff;
|
|
}
|
|
|
|
} // namespace wi
|