hostile-takeover/game/ht.h
2016-08-24 21:34:48 -04:00

8979 lines
231 KiB
C++

#ifndef __HT_H__
#define __HT_H__
namespace wi {
#define HOSTILE_TAKEOVER
// Beta timeout
//#define BETA_TIMEOUT
#ifdef DEBUG
#define INCL_TRACE
#define MP_DEBUG // Multiplayer debugging
#endif
// Build types
// These flags are passed in by makefiles / devenv configurations
//#define ESD_BUILD // ESD release builds
//#define RETAIL_BUILD // Retail release builds
//#define DEV_BUILD // Developer build
// ESD_BUILD settings
#if defined(ESD_BUILD)
#define DRM
#endif
// RETAIL_BUILD settings
#if defined(RETAIL_BUILD)
#define DRM
#define DRM_KEYONLY
#endif
// DEV_BUILD settings
#if defined(DEV_BUILD)
#ifdef DEBUG
//#define INCL_VALIDATEHEAP
//#define INCL_TESTS
//#define INCL_MEMTRACE
#if defined(WIN) && !defined(CE)
//#define MP_DEBUG_SHAREDMEM
#define DEBUG_HELPERS
#endif
#endif
// MP stress
#if !defined(PIL) && !defined(CE) && !defined(IPHONE) && !defined(SDL)
#define MP_STRESS
#endif
// Enable stress testing
#define STRESS
// Enable this to allow little arrows to be drawn showing the paths being followed
#define DRAW_PATHS
// Enable this to draw a box around each tile a unit believes it is occupying
//#define DRAW_OCCUPIED_TILE_INDICATOR
// Enable this to draw a white pixel at the upper left corner of each tile
//#define MARK_TILE_BOUNDARIES
// Enable this to see which tiles are occupied according to the terrain map
//#define MARK_OCCUPIED_TILES
// Enable this to allow stats display to be toggled via the Find button
// <broken>
//#define STATS_DISPLAY
// Draw rects around invalid tiles
#define DRAW_UPDATERECTS
// Enable this to have HostOutputDebugString echo to hotsync log on Palm devices
//#define TRACE_TO_HOTSYNC_LOG
// Enable this to have HostOutputDebugString echo to database log
#define TRACE_TO_DB_LOG
// Maintain and check a ring buffer of old allocs
#if defined(WIN) && defined(DEBUG)
//#define CHECK_OLD_ALLOCS
#endif
#endif // defined(DEV_BULD)
// Things that are permanently on
#define DRAW_LINES // Enable this to allow lines to be drawn to visualize unit targeting
#define STATUS_LINE // Enable this to get certain status displayed at the bottom of the screen
//#define RALLY_POINTS
// Enable this to sychronize Updates between server and all clients and validate
// the Update results
//#define DETECT_SYNC_ERRORS
#ifdef DEBUG_HELPERS
class TriggerViewer;
class UnitGroupViewer;
class DelayedMessageViewer;
class CommandQueueViewer;
#endif
} // namespace wi
#include "inc/basictypes.h"
//#include "base/log.h"
#include "base/misc.h"
#include "mpshared/mpht.h"
#include "mpshared/misc.h"
#include "mpshared/enum.h"
#include "mpshared/ini.h"
#include "mpshared/decompress.h"
#include "game/missionlist.h"
#include "mpshared/netmessage.h"
#include "game/dragrect.h"
#include "base/thread.h"
//#include "yajl/wrapper/jsontypes.h"
namespace wi {
class StateFrame;
class StateTracker;
class RefMap;
typedef void *FileHandle; // hf
typedef word CacheHandle; // hc
// Game version
#define knVersion 1
#define MAKEDWORD(x) ((((dword)x) << 24) | (((dword)x) << 16) | (((dword)x) << 8) | (x))
#if defined(PIL) && defined(__CPU_68K) && defined(__GNUC__)
#define secCode1
#define secCode2 __attribute__((section("code2")))
#define secCode3 __attribute__((section("code3")))
#define secCode4 __attribute__((section("code4")))
#define secCode5 __attribute__((section("code5")))
#define secCode6 __attribute__((section("code6")))
#define secCode7 __attribute__((section("code7")))
#define secCode8 __attribute__((section("code8")))
#define secCode9 __attribute__((section("code9")))
#define secCode10 __attribute__((section("code10")))
#define secCode11 __attribute__((section("code11")))
#define secCode12 __attribute__((section("code12")))
#define secCode13 __attribute__((section("code13")))
#define secCode14 __attribute__((section("code14")))
#define secCode15 __attribute__((section("code15")))
#define secCode16 __attribute__((section("code16")))
#define secCode17 __attribute__((section("code17")))
#else
#define secCode1
#define secCode2
#define secCode3
#define secCode4
#define secCode5
#define secCode6
#define secCode7
#define secCode8
#define secCode9
#define secCode10
#define secCode11
#define secCode12
#define secCode13
#define secCode14
#define secCode15
#define secCode16
#define secCode17
#endif
#define secGame secCode9
#define secHost secCode17
#define secRect secCode5
#define secDibBitmap secCode5
#define secTBitmap secCode16
#define secIni secCode16
#define secFormMgr secCode5
#define secForm secCode10
#define secControl secCode2
#define secTimer secCode16
#define secTimerMgr secCode11
#define secEventMgr secCode4
#define secEmptyForm secCode4
#define secFont secCode6
#define secButtonControl secCode4
#define secPresetButtonControl secCode8
#define secLabelControl secCode4
#define secEditControl secCode4
#define secHelpControl secCode16
#define secHelpForm secCode13
#define secListControl secCode6
#define secSliderControl secCode13
#define secMisc secCode16
#define secGameOptionsForm secCode2
#define secInputPanelForm secCode2
#define secTileMap secCode2
#define secSimulation secCode12
#define secSimUIForm secCode8
#define secGob secCode12
#define secTankGob secCode5
#define secInfantryGob secCode5
#define secStructures secCode3
#define secLevel secCode11
#define secStateMachine secCode13
#define secAnimation secCode12
#define secFogMap secCode4
#define secTerrainMap secCode2
#define secSoundMgr secCode6
#define secSoundDevice secCode6
#define secColorMgr secCode2
#define secPackFile secCode13
#define secCacheMgr secCode13
#define secCheckBoxControl secCode11
#define secDisplay secCode7
#define secWaveOut secCode2
#define secMemMgr secCode16
#define secMultiplayer secCode7
#define secCommandQueue secCode11
#define secComm secCode7
#define secPlayer secCode13
#define secBitmapControl secCode2
#define secMiner secCode6
#define secUpdateMap secCode4
#define secGraffitiScrollControl secCode10
#define secInputUIForm secCode10
#define secMiniMapControl secCode10
#define secThunks secCode11
#define secArmThunks secCode11
#define secLoadSave secCode5
#define secStream secCode5
#define secOvermindGob secCode8
#define secGobMgr secCode4
#define secAnimGob secCode11
#define secScorchGob secCode11
#define secSurfaceDecalGob secCode4
#define secSceneryGob secCode4
#define secUnitGob secCode15
#define secTrigger secCode16
#define secAction secCode14
#define secCondition secCode11
#define secUnitGroup secCode13
#define secBuildMgr secCode14
#define secShell secCode13
#define secRawBitmap secCode13
#define secEcom secCode12
#define secPipMeterControl secCode13
#define secDamageMeterControl secCode13
#define secTowers secCode13
#define secStringTable secCode5
#define secAlertControl secCode16
#define secArtilleryGob secCode5
#define secCreditsControl secCode16
#define secPowerControl secCode16
#define secRadar secCode14
#define secWarehouse secCode14
#define secReplicatorGob secCode4
#define secObjectives secCode14
#define secCutScene secCode14
#define secBuildQueue secCode12
#define secBuilderGob secCode12
#define secDrm secCode16
#define secBtTransport secCode17
// Performance options
const word kfPerfRocketShots = 0x0001;
const word kfPerfRocketTrails = 0x0002;
const word kfPerfRocketImpacts = 0x0004;
const word kfPerfShots = 0x0008;
const word kfPerfShotImpacts = 0x0010;
const word kfPerfSelectionBrackets = 0x0020;
const word kfPerfSmoke = 0x0040;
const word kfPerfEnemyDamageIndicator = 0x0080;
const word kfPerfScorchMarks = 0x0100;
const word kfPerfSymbolFlashing = 0x0200;
const word kfPerfAll = 0x03ff;
const word kfPerfMax = 0xffff;
// Handicap flags and values
const word kfHcapIncreasedFirePower = 0x0001;
const word kfHcapDecreasedTimeToBuild = 0x0002;
const word kfHcapIncreasedMinerLoadValue = 0x0004;
const word kfHcapShowEnemyBuildProgress = 0x0010; // build progress & upgrading
const word kfHcapShowEnemyResourceStatus = 0x0020; // power & credit symbol flash
const word kfHcapIncreasedArmor = 0x0040;
const word kfHcapEasy = kfHcapDecreasedTimeToBuild | kfHcapIncreasedArmor | kfHcapIncreasedFirePower | kfHcapIncreasedMinerLoadValue | kfHcapShowEnemyBuildProgress | kfHcapShowEnemyResourceStatus;
const word kfHcapNormal = kfHcapDecreasedTimeToBuild | kfHcapIncreasedArmor | kfHcapShowEnemyBuildProgress | kfHcapShowEnemyResourceStatus;
const word kfHcapHard = kfHcapShowEnemyBuildProgress;
const word kfHcapDefault = kfHcapNormal;
const int knDecreasedTimeToBuildPercent = -20;
const int knIncreasedFirePowerPercent = 20;
const int knIncreasedMinerLoadValuePercent = 20;
const int knDecreasedDamagePercent = 90;
// Color type
typedef word Color; // clr
// Dib bitmap
#define kfDibFreeMem 0x0001
#define kfDibBackWindow 0x0002
#define kfDibWantScrolls 0x0004
class Rect;
class UpdateMap;
class DibBitmap // bm
{
public:
DibBitmap() secDibBitmap;
virtual ~DibBitmap() secDibBitmap;
bool Init(byte *pb, int cx, int cy) secDibBitmap;
virtual byte *GetBits() secDibBitmap;
virtual void Clear(Color clr) secDibBitmap;
virtual void Fill(int x, int y, int cx, int cy, Color clr) secDibBitmap;
virtual void Shadow(int x, int y, int cx, int cy) secDibBitmap;
virtual void GetSize(Size *psiz) secDibBitmap;
virtual int GetRowBytes() secDibBitmap;
virtual void DrawLine(short x1, short y1, short x2, short y2, Color clr) secDibBitmap;
virtual void Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst) secDibBitmap;
virtual void BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst) secDibBitmap;
virtual void Scroll(Rect *prcSrc, int xDst, int yDst);
virtual DibBitmap *Suballoc(int yTop, int cy) secDibBitmap;
word GetFlags() {
return m_wf;
}
protected:
word m_wf;
Size m_siz;
byte *m_pb;
dword m_cb;
int m_cbRow;
};
DibBitmap *CreateDibBitmap(byte *pb, int cx, int cy) secDibBitmap;
// Network stuff
class ITransportCallback;
class IRoomCallback;
class ILobbyCallback;
class NetMessage;
class Transport;
const int kcbTransportName = 100;
enum TransportType {
ktratBluetoothPAN,
ktratBluetoothSer,
ktratIR,
ktratIP,
ktratX,
};
const dword knTransportOpenResultSuccess = 0;
const dword knTransportOpenResultFail = 1;
const dword knTransportOpenResultNoNetwork = 2;
const dword knTransportOpenResultCantConnect = 3;
const dword knTransportOpenResultNotResponding = 4;
const dword knTransportOpenResultProtocolMismatch = 5;
const dword knTransportOpenResultServerFull = 6;
struct TransportDescription // trad
{
TransportType trat;
char szName[kcbTransportName];
dword (*pfnOpen)(TransportDescription *ptrad, Transport **pptra);
dword dwTransportSpecific;
};
struct DeleteRecord {
DeleteRecord *pdrNext;
bool fDeleted;
};
#define knWaitStrConnectToHost 1
#define knWaitStrClientDisconnecting 2
#define knWaitStrDisconnectingClients 3
#define knWaitStrDisconnectingClient 4
#define knWaitStrClosingTransport 5
#define knWaitStrBeginGameSearch 6
#define knWaitStrAdvertisingGame 7
const int kcbBluetoothMtuMin = 100; // something >= our largest message but less than BT_L2CAP_MTU (672)
const int kctradMax = 10;
class Event;
class IGameCallback;
class Transport // tra
{
public:
Transport();
virtual ~Transport() {}
virtual dword Open() = 0;
virtual void Close() = 0;
virtual bool IsClosed() = 0;
virtual dword Login(const char *username, const char *token) = 0;
virtual dword SignOut() = 0;
virtual const char *GetAnonymousUsername() = 0;
virtual dword JoinLobby(ILobbyCallback *plcb) = 0;
virtual bool LeaveLobby() = 0;
virtual dword CreateRoom(const char *roomname, const char *password,
dword *roomid) = 0;
virtual dword CanJoinRoom(dword roomid, const char *password) = 0;
virtual dword JoinRoom(dword roomid, const char *password,
IRoomCallback *prcb) = 0;
virtual bool SendChat(const char *chat) = 0;
virtual dword CreateGame(GameParams *params, PackId *ppackidUpgrade,
dword *gameid) = 0;
virtual dword CanJoinGame(dword gameid) = 0;
virtual void LeaveRoom(dword hint) = 0;
virtual dword JoinGame(dword gameid, dword roomid) = 0;
virtual bool SendNetMessage(NetMessage *pnm) = 0;
virtual void LeaveGame() = 0;
virtual void OnEvent(Event *pevt) = 0;
virtual ITransportCallback *SetCallback(ITransportCallback *ptcb);
virtual ITransportCallback *GetCallback();
virtual IGameCallback *SetGameCallback(IGameCallback *pgcb);
virtual IGameCallback *GetGameCallback();
protected:
ITransportCallback *m_ptcb;
ILobbyCallback *m_plcb;
IRoomCallback *m_prcb;
IGameCallback *m_pgcb;
};
class TransportMgr // tram
{
public:
virtual int GetTransportDescriptions(TransportDescription *atrad, int ctradMax);
};
extern TransportMgr gtram;
class IGameCallback {
public:
virtual void OnReceiveChat(const char *player, const char *chat) = 0;
virtual void OnNetMessage(NetMessage **ppnm) = 0;
virtual void OnGameDisconnect() = 0;
};
class IRoomCallback {
public:
virtual void OnAddGame(const char *player, dword gameid,
const GameParams& params, dword minplayers, dword maxplayers,
const char *title, dword ctotal) = 0;
virtual void OnRemoveGame(dword gameid, dword ctotal) = 0;
virtual void OnGameInProgress(dword gameid) = 0;
virtual void OnGamePlayerNames(dword gameid, dword cnames,
const PlayerName *anames) = 0;
virtual void OnAddPlayer(const char *player) = 0;
virtual void OnRemovePlayer(dword hint, const char *player) = 0;
virtual void OnReceiveChat(const char *player, const char *chat) = 0;
virtual void OnStatusComplete() = 0;
};
class ILobbyCallback {
public:
virtual void OnLurkerCount(dword count) = 0;
virtual void OnAddRoom(const char *name, dword roomid, bool priv,
dword cPlayers, dword cGames) = 0;
virtual void OnRemoveRoom(dword roomid) = 0;
virtual void OnUpdateRoom(dword roomid, dword cPlayers, dword cGames) = 0;
};
class ITransportCallback {
public:
virtual void OnStatusUpdate(char *pszStatus) = 0;
virtual void OnConnectionClose() = 0;
virtual void OnShowMessage(const char *message) = 0;
};
// Timer support
class Timer;
class TimerMgr // timm
{
public:
TimerMgr() secTimerMgr;
~TimerMgr() secTimerMgr;
void AddTimer(Timer *ptmr, long ct) secTimerMgr;
void RemoveTimer(Timer *ptmr) secTimerMgr;
void SetTimerRate(Timer *ptmr, long ct) secTimerMgr;
void BoostTimer(Timer *ptmr, long ct);
long ScanDispatch(long tCurrent) secTimerMgr;
virtual long GetTickCount() secTimerMgr;
void Enable(bool fEnable) {
m_fEnabled = fEnable;
}
void TriggerTimer(Timer *ptmr) secTimerMgr;
bool IsAdded(Timer *ptmr) secTimerMgr;
private:
Timer *m_ptmrFirst;
Timer *m_ptmrNotifying;
Timer *m_ptmrTriggerNext;
bool m_fForceScan;
bool m_fEnabled;
};
extern TimerMgr gtimm;
// Timer
class Timer // tmr
{
public:
Timer() { m_ptimm = NULL; }
virtual ~Timer();
virtual void OnTimer(long tCurrent) = 0;
private:
TimerMgr *m_ptimm;
Timer *m_ptmrNext;
Timer *m_ptmrPrev;
long m_ctRate;
long m_tTrigger;
friend class TimerMgr;
};
// CONSIDER: add id to Timer instead
class ITimeout {
public:
virtual void OnTimeout(int id) = 0;
};
class TimeoutTimer : public Timer {
public:
TimeoutTimer() secMisc;
~TimeoutTimer() {
if (m_ptimo != NULL) {
Stop();
}
}
void Start(ITimeout *ptimo, int cms, int id = 0, bool fOneShot = true) {
if (m_ptimo != NULL) {
Stop();
}
m_id = id;
m_fOneShot = fOneShot;
m_ptimo = ptimo;
gtimm.AddTimer(this, cms / 10);
}
void Stop() {
if (m_ptimo == NULL) {
return;
}
gtimm.RemoveTimer(this);
m_ptimo = NULL;
}
bool IsStarted() {
return m_ptimo != NULL;
}
virtual void OnTimer(long tCurrent) {
ITimeout *ptimo = m_ptimo;
if (m_fOneShot) {
Stop();
}
ptimo->OnTimeout(m_id);
}
private:
ITimeout *m_ptimo;
bool m_fOneShot;
int m_id;
};
// Point
struct Point // pt
{
int x, y;
};
// Rectangle class
class WRect;
class TRect;
class Rect // rc
{
public:
int left;
int top;
int right;
int bottom;
bool Intersect(Rect *prcSrc1, Rect *prcSrc2) secRect;
void Set(Point pt1, Point pt2) secRect;
bool Subtract(Rect *prcSrc1, Rect *prcSrc2) secRect;
void Add(Rect *prcSrc1, Rect *prcSrc2) secRect;
void FromWorldRect(WRect *pwrc) secRect;
void FromTileRect(TRect *ptrc) secRect;
void Union(Rect *prc) secRect;
bool Equal(Rect *prc) secRect;
void GetCenter(Point *ppt) secRect;
int GetDistance(int x, int y) secRect;
void Offset(int dx, int dy)
{
left += dx;
right += dx;
top += dy;
bottom += dy;
}
void Inflate(int cx, int cy)
{
left -= cx;
right += cx;
top -= cy;
bottom += cy;
}
bool PtIn(int x, int y)
{
return (x >= left && x < right && y >= top && y < bottom);
}
bool RectIn(Rect *prc)
{
return (prc->left >= left && prc->top >= top && prc->right <= right && prc->bottom <= bottom);
}
void Set(int l, int t, int r, int b)
{
left = l;
top = t;
right = r;
bottom = b;
}
void SetEmpty()
{
left = 0;
right = 0;
bottom = 0;
top = 0;
}
bool IsEmpty()
{
return ((left >= right) || (top >= bottom));
}
int Width()
{
return right - left;
}
int Height()
{
return bottom - top;
}
};
// Palette
struct Palette // pal
{
word cEntries;
byte argb[1][3];
};
} // namespace wi
#include <htplatform.h>
#include "game/sprite.h"
#include "soundeffects.h"
#include "mpshared/packfile.h"
#include <rip.h>
#include "game/res.h"
namespace wi {
// PalmOS sdk 3.5 has min/max but sdk 4.0 doesn't
#if 0
#undef min
#undef max
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
// Ensures the same types are being compared
template<class T> inline T _min(const T a, const T b) { return (a > b) ? b : a; }
template<class T> inline T _max(const T a, const T b) { return (a < b) ? b : a; }
#define sign(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
// For forward references
class Level;
class Gob;
class SimUIForm;
typedef int GobType; // gt
typedef word UpgradeMask;
struct StructConsts;
class UnitGob;
class Player;
class Trigger;
class UnitGroup;
const StateMachineId ksmidNull = (word)-1;
#ifdef MP_DEBUG_SHAREDMEM
extern Side gsideCurrent;
extern Gid ggidCurrent;
extern long gcupdCurrent;
extern GobType ggtCurrent;
extern bool gfInsideUpdate;
#endif
extern bool gfMultiplayer;
extern bool gfLockStep;
#ifdef DEBUG_HELPERS
char *PszFromUnitMask(UnitMask um);
char *PszFromCaSideMask(word wfCaSideMask);
#endif
class UpdateInterval // unvl
{
public:
UpdateInterval() {
m_cSkip = 0;
m_cDecrementsLast = 0;
m_cDecrements = 0;
}
void MinSkip() {
m_cSkip = 0;
}
void MinSkip(int cSkip) {
m_cSkip = _min(m_cSkip, cSkip);
}
bool Decrement() {
if (gfMultiplayer) {
// Can't gracefully support update intervals in the multiplayer
// version due to synchronization issues caused by differing
// client-side state such as visibility and gpplrLocal conditionals
return true;
}
if (m_cSkip <= 0) {
m_cSkip = 0x7fff;
m_cDecrementsLast = m_cDecrements;
m_cDecrements = 0;
return true;
}
// Count Decs separately since m_cSkip can be arbitrarily Min'ed
m_cSkip--;
m_cDecrements++;
return false;
}
int GetUpdateCount() {
// A skip of 0 (meaning next update) is an update count of 1
return m_cDecrementsLast + 1;
}
private:
int m_cSkip;
int m_cDecrementsLast;
#ifdef DEV_BUILD
public:
#endif
int m_cDecrements;
};
// World coordinates are high-byte = tile coord, low-byte = sub-tile coord
// Coordinate types and macros
const short ktcMax = 64;
const short kpcMax = ktcMax * 32; // + 1 to allow for conversion of inclusive/exclusive rects
const WCoord kwcMax = ktcMax * 256;
const WCoord kwcTile = 0x0100;
const WCoord kwcTileHalf = kwcTile / 2;
const WCoord kwcTile16th = kwcTile / 16;
#ifdef IPHONE
// IPhone titlebar area eats input; this is compensation
#define kwcScrollLeftExtra WcFromTile16ths(5)
#else
#define kwcScrollLeftExtra 0
#endif
#define kwcScrollBorderSize WcFromTile16ths(5)
#define kwcScrollStepSize kwcTileHalf
extern short *gmpPcFromWc; // [64 * 256]; // 16,384 * 2 = 32,768 bytes
extern WCoord *gmpWcFromPc; // [64 * 32]; // 2,048 * 2 = 4,096 bytes
inline TCoord TcFromWc(WCoord wc) {
return wc >> 8;
}
inline int PcFracFromUpc(int pc) {
return gmpPcFromWc[gmpWcFromPc[pc] & 0xff];
}
inline WCoord WcFromPc(int pc) {
// gmpWcFromPc has one extra entry to allow an exclusive bottom/right coord
// to be mapped, hence the "<=" below
Assert(abs(pc) <= kpcMax);
if (pc >= 0)
return gmpWcFromPc[pc];
else
return -gmpWcFromPc[-pc];
}
inline int PcFromWc(WCoord wc) {
Assert(abs(wc) < kwcMax);
if (wc >= 0)
return gmpPcFromWc[wc];
else
return -gmpPcFromWc[-wc];
}
inline TCoord TcFromPc(int pc) {
return TcFromWc(WcFromPc(pc));
}
inline WCoord WcFromUpc(int pc) {
Assert(pc >= 0 && pc < kpcMax);
return gmpWcFromPc[pc];
}
inline int PcFromUwc(WCoord wc) {
Assert(wc >= 0 && wc < kwcMax);
return gmpPcFromWc[wc];
}
inline TCoord TcFromUpc(int pc) {
return TcFromWc(WcFromUpc(pc));
}
inline WCoord WcFromTc(TCoord tc) {
return tc << 8;
}
inline WCoord WcFromTile16ths(int n) {
return kwcTile16th * n;
}
inline WCoord WcTrunc(WCoord wc) {
return wc & 0xff00;
}
inline WCoord WcFrac(WCoord wc) {
return wc & 0x00ff;
}
inline int PcFromTc(TCoord tc) {
return PcFromWc(WcFromTc(tc));
}
extern int gcxFullScreenFormDiv10;
inline int PcFromFc(int fc) {
return (fc * gcxFullScreenFormDiv10) / 16;
}
struct TPoint // pt
{
TCoord tx, ty;
};
class WRect : public Rect
{
public:
void Set(WPoint wpt1, WPoint wpt2) secRect;
#if 0 // UNUSED
void FromPixelRect(Rect *prc) secRect;
#endif
void FromTileRect(TRect *ptrc) secRect;
};
class TRect : public Rect
{
public:
void FromWorldRect(WRect *wrc) secRect;
};
// Specialized TRect. Its specialty is being 1/2 the size
struct TRectSmall
{
char txLeft;
char tyTop;
char txRight;
char tyBottom;
void Union(TRectSmall *ptrc) {
if (ptrc->txLeft >= ptrc->txRight || ptrc->tyTop >= ptrc->tyBottom)
return;
if (txLeft > ptrc->txLeft)
txLeft = ptrc->txLeft;
if (tyTop > ptrc->tyTop)
tyTop = ptrc->tyTop;
if (txRight < ptrc->txRight)
txRight = ptrc->txRight;
if (tyBottom < ptrc->tyBottom)
tyBottom = ptrc->tyBottom;
}
void Offset(char tx, char ty) {
txLeft += tx;
tyTop += ty;
txRight += tx;
tyBottom += ty;
}
};
// NOTE: predefined iclr constants (e.g., kiclrBlack) are in res.h
// except for these non-index-type virtual colors
#define kiclrShadow -1
#define kiclrShadow2x -2
// Fixed point number types and macros
#define INTBITS 11
#define FRACBITS 5
#define INTBITS32 (INTBITS + 16)
typedef long fix32; // INTBITS32 integer bits, FRACBITS fractional bits
typedef short fix; // INTBITS integer bits, FRACBITS fractional bits
#define itofx(x) ((x) << 5) // Integer to fixed point
#define itofx32(x) (((long)(x)) << 5) // Integer to fixed point
#define ftofx(x) ((fix)((x) * 32)) // Float to fixed point
#define ftofx32(x) ((fix32)((x) * 32)) // Float to fixed point
#define dtofx(x) ((fix)((x) * 32)) // Double to fixed point
#define fxtoi(x) ((x) >> 5) // Fixed point to integer
#define fx32toi(x) ((x) >> 5) // Fixed point to integer
#define fxtof(x) ((float) (x) / 32) // Fixed point to float
#define fxtod(x) ((double)(x) / 32) // Fixed point to double
#define mulfx(x, y) ((((fix32)(x)) * (y)) >> 5) // Multiply a fixed by a fixed
#define mulfx32(x, y) ((((fix32)(x)) * (y)) >> 5) // Multiply a fixed by a fixed
#define divfx(x, y) ((((fix32)(x)) << 5) / (y)) // Divide a fixed by a fixed
#define divfx32(x, y) ((((fix32)(x)) << 5) / (y)) // Divide a fixed by a fixed
#define addfx(x, y) ((fix)(x) + (fix)(y))
#define addfx32(x, y) ((fix32)(x) + (fix32)(y))
#define subfx(x, y) ((x) - (y))
#define fracfx(x) ((x) & ((1 << FRACBITS) - 1)) // Fraction of a fixed point
fix32 sqrtfx(fix32 x) secMisc;
unsigned int isqrt(unsigned long val) secMisc;
int isqrt(int val1, int val2) secMisc;
#ifdef OLD_LINE_ITERATOR
// For iterating along a line at arbitrary (possibly fractional) increments
class LineIterator {
public:
void Init(int x1, int y1, int x2, int y2, fix nStep) secMisc;
bool Step() {
if (m_cStepsRemaining == 0)
return false;
m_cStepsRemaining--;
m_fx = addfx(m_fx, m_fdx);
m_fy = addfx(m_fy, m_fdy);
return true;
}
int GetX() {
return fxtoi(m_fx);
}
int GetY() {
return fxtoi(m_fy);
}
fix GetFixedX() {
return m_fx;
}
fix GetFixedY() {
return m_fy;
}
private:
fix m_fx, m_fy;
fix m_fdx, m_fdy;
int m_cStepsRemaining;
};
#endif // OLD_LINE_ITERATOR
// For iterating along a line at arbitrary increments
class WLineIterator {
public:
void Init(WCoord wx1, WCoord wy1, WCoord wx2, WCoord wy2, int nIncr) secMisc;
bool Step() {
if (m_cStepsRemaining == 0)
return false;
m_cStepsRemaining--;
m_wx += m_wdx;
m_wy += m_wdy;
return true;
}
int GetWX() {
return m_wx;
}
int GetWY() {
return m_wy;
}
int GetStepsRemaining() {
return m_cStepsRemaining;
}
private:
// OPT: can save space by using caller's m_wx, m_wy
WCoord m_wx, m_wy;
WCoord m_wdx, m_wdy;
int m_cStepsRemaining;
};
// Handy functions for dealing with time and update conversions
const int kcmsUpdate = 80; // 80ms per Update
const int kctUpdate = 8;
const int kctMapScrollRate = 8; // TUNE:
inline int UpdFromSec(int csec) {
// This is to catch any overflows. If we find ourselves concerned with
// intervals > 327 seconds we can add a cast to LONG in here.
Assert(csec < (32768 / 100));
// We assume kcmsUpdate can be divided by 10 without loss of precision
Assert(((kcmsUpdate / 10) * 10) == kcmsUpdate);
return (csec * 100) / (kcmsUpdate / 10);
}
inline int UpdFromMsec(int cms) {
return cms / kcmsUpdate;
}
// Transparent bitmap
struct ScanData // sd
{
word ibaiclr;
word cbaiclrUnpacked;
};
struct TBitmapEntry // tbe
{
word cx;
word cy;
word yBaseline;
word ibsd;
word cbsd;
};
#define kcbTBitmapEntry (sizeof(word) * 5)
struct TBitmapHeader // tbh
{
word ctbm;
TBitmapEntry atbe[1];
};
// Abstract base bitmap class so TBitmaps and RawBitmaps can be used
// interchangeably in certain basic situations
class HtBitmap
{
public:
virtual ~HtBitmap() secRawBitmap;
virtual bool Init(char *pszFn) = 0;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc = NULL) = 0;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc = NULL) = 0;
virtual void GetSize(Size *psiz) = 0;
};
#define kfTbCloseFile 1
#define kfTbShared 2
#define kcCopyBy4Procs 32
#define kcColoredSides 6
class TBitmap : public HtBitmap
{
public:
TBitmap() secTBitmap;
bool Init(File *pfil, word ib) secTBitmap;
void BltTo(int itbm, class DibBitmap *pbmDst, int xDst, int yDst, Side side = ksideNeutral, Rect *prcSrc = NULL) secTBitmap;
void GetSize(int itbm, Size *psiz) secTBitmap;
void FillTo(int itbm, class DibBitmap *pbmDst, int xDst, int yDst,
int cxDst, int cyDst, int xOrigin = 0, int yOrigin = 0) secTBitmap;
int GetBaseline() {
return (int)m_atbe[0].yBaseline;
}
int GetBaseline(int itbm) {
Assert(itbm >= 0 && itbm < m_ctbm);
return (int)m_atbe[itbm].yBaseline;
}
void SetShared() {
m_wf |= kfTbShared;
}
void ClearShared() {
m_wf &= ~kfTbShared;
}
static bool InitClass() secTBitmap;
static void ExitClass() secTBitmap;
// HtBitmap overrides
virtual ~TBitmap() secTBitmap;
virtual bool Init(char *pszFn) secTBitmap;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc = NULL) secTBitmap;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc = NULL) secTBitmap;
virtual void GetSize(Size *psiz) secTBitmap;
private:
byte *GetCompiledBits(int itbm, bool fOdd) secTBitmap;
static void MakeSideCodeMapping(Color *aclr, dword *mpscaiclrSide) secTBitmap;
void BltToScan(byte *pbDraw, int cx, int cy, DibBitmap *pbmDst,
int xDst, int yDst, Side side, Rect *prcSrc);
File *m_pfil;
word m_ibtbh;
word m_wf;
int m_ctbm;
TBitmapEntry *m_atbe;
CacheHandle *m_ahc;
public:
static dword *s_ampscaiclrSide[kcColoredSides];
};
TBitmap *LoadTBitmap(char *pszFn) secTBitmap;
void FreeSharedTBitmaps() secTBitmap;
TBitmap *GetSharedTBitmap(char *pszFn) secTBitmap;
void FindSharedTBitmapFilename(TBitmap *ptbm, char *psz, int cb) secTBitmap;
// For bltting raw bitmaps in a non-clipped, streamed manner
class RawBitmap : public HtBitmap // rbm
{
public:
RawBitmap() secRawBitmap;
// HtBitmap overrides
virtual ~RawBitmap() secRawBitmap;
virtual bool Init(char *pszFn) secRawBitmap;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc = NULL) secRawBitmap;
virtual void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc = NULL) secRawBitmap;
virtual void GetSize(Size *psiz) secRawBitmap;
public:
File *m_pfil;
int m_cx;
int m_cy;
};
RawBitmap *LoadRawBitmap(char *pszFn) secRawBitmap;
// Font / Text output
struct FontHeader // fnth
{
word cy;
byte acxChar[256];
word mpchibsd[256];
ScanData asd[1];
};
class Font // fnt
{
public:
Font() secFont;
~Font() secFont;
bool Load(char *pszFont) secFont;
int GetHeight() {
return BigWord(m_pfnth->cy);
}
void SetGlyphOverlap(int nGlyphOverlap) {
m_nGlyphOverlap = nGlyphOverlap;
}
void SetLineOverlap(int nLineOverlap) {
m_nLineOverlap = nLineOverlap;
}
int GetGlyphOverlap() {
return m_nGlyphOverlap;
}
int GetLineOverlap() {
return m_nLineOverlap;
}
int GetTextExtent(const char *psz) secFont;
int GetTextExtent(const char *psz, int cch) secFont;
int DrawText(DibBitmap *pbm, char *psz, int x, int y, int cch = -1,
dword *mpscaiclr = NULL) secFont;
void DrawText(DibBitmap *pbm, char *psz, int x, int y, int cx,
int cy, bool fEllipsis = false) secFont;
void DrawTextWithEllipsis(DibBitmap *pbm, char *psz, int cch,
int x, int y, int cx, bool fForce = false);
int CalcMultilineHeight(char *psz, int cxMultiline) secFont;
int CalcBreak(int cx, char **psz, bool fChop = true) secFont;
private:
char *FindNextNonBreakingChar(char *psz) secFont;
FileMap m_fmap;
FontHeader *m_pfnth;
byte **m_mpchpbCodeEven;
byte **m_mpchpbCodeOdd;
int m_nGlyphOverlap;
int m_nLineOverlap;
int m_cxEllipsis;
};
Font *LoadFont(char *pszFont) secFont;
struct TileSetHeader // tseth
{
word cTiles;
word cxTile;
word cyTile;
};
#define kcbTileSetHeader 6
struct MiniTileSetHeader // mtseth
{
word offNext;
word cTiles;
word cxTile;
word cyTile;
};
#define kcchFnTset 28
struct TileMapHeader // tmaph
{
char szFnTset[kcchFnTset];
word ctx;
word cty;
};
#define kfTmapMapped 1
#define kfMiniTsetMapped 2
#define kcTileSetsMax 64
class TileMap // tmap
{
public:
TileMap() secTileMap;
~TileMap() secTileMap;
bool Load(char *psz, Size *psizPlayfield) secTileMap;
void GetMapSize(Size *psiz) secTileMap;
void GetTCoordMapSize(Size *psiz) {
psiz->cx = BigWord(m_ptmaph->ctx);
psiz->cy = BigWord(m_ptmaph->cty);
}
void GetTileSize(Size *psiz) secTileMap;
void Draw(DibBitmap *pbm, int x, int y, int cx, int cy, int xMap, int yMap, byte *pbFogMap, UpdateMap *pupd) secTileMap;
MiniTileSetHeader *GetMiniTileSetHeader(int nScale) secTileMap;
private:
FileMap m_fmapTmap;
TileMapHeader *m_ptmaph;
FileMap m_afmapTset[kcTileSetsMax];
TileSetHeader *m_aptseth[kcTileSetsMax];
MiniTileSetHeader *m_pmtseth;
FileMap m_fmapMiniTset;
int m_cTileSets;
int m_cTiles;
int m_cxTile;
int m_cyTile;
word m_wf;
public:
byte **m_apbTileData;
word *m_pwMapData;
int m_ctx;
int m_cty;
byte **m_apbDrawMap;
};
TileMap *LoadTileMap(char *pszFn, Size *psizPlayfield) secTileMap;
// Fog map
struct RevealPattern // rvlp
{
byte ctx;
byte cty;
byte ab[1];
};
#define kbOpaque 0
#define kbEmpty 15
const word kbfFogMask = 0x000f;
const int kcFogShift = 0;
#define IsFogOpaque(bFog) (((bFog) & kbfFogMask) == kbOpaque)
const word kbfGalaxiteMask = 0x00f0;
const int kcGalaxiteShift = 4;
#define HasGalaxite(bFog) (((bFog) & kbfGalaxiteMask) != 0)
//#define HasWall(wFog) (((wFog) & kwfWallMask) != 0)
//const word kwfWallMask = 0x0f00;
//const int kcWallShift = 8;
class Stream;
class AnimationData;
class FogMap // fogm
{
public:
FogMap() secFogMap;
~FogMap() secFogMap;
bool Init(Size *psizTile, Size *psizMap) secFogMap;
bool LoadState(Stream *pstm) secFogMap;
bool SaveState(Stream *pstm) secFogMap;
bool IsCovered(TRect *ptrc) secFogMap;
void RevealAll(UpdateMap *pupd) secFogMap;
void Reveal(TCoord txMap, TCoord tyMap, RevealPattern *prvlp, UpdateMap *pupd, WCoord wxView, WCoord wyView) secFogMap;
void Reveal(TRect *ptrc, UpdateMap *pupd, WCoord wxView, WCoord wyView) secFogMap;
void Draw(DibBitmap *pbm, int xMap, int yMap, UpdateMap *pupd) secFogMap;
void DrawGalaxite(DibBitmap *pbm, int xMap, int yMap, UpdateMap *pupd, byte *pbTrMap) secFogMap;
byte *GetMapPtr() {
return m_pbMap;
}
// Galaxite methods
int GetGalaxite(TCoord tx, TCoord ty) secFogMap;
void SetGalaxite(int nGx, TCoord tx, TCoord ty) secFogMap;
bool DecGalaxite(TCoord tx, TCoord ty) secFogMap;
void IncGalaxite(TCoord tx, TCoord ty) secFogMap;
bool FindNearestGalaxite(TCoord tx, TCoord ty, TPoint *ptpt, bool fIgnoreFog) secFogMap;
// Wall methods
int GetWallHealth(TCoord tx, TCoord ty) secFogMap;
void SetWallHealth(int nHealth, TCoord tx, TCoord ty) secFogMap;
private:
int m_ctxMap;
int m_ctyMap;
int m_cxTile;
int m_cyTile;
byte m_mpSrcDstResult[256];
byte *m_pbMap;
TBitmap *m_aptbm[16];
TBitmap *m_aptbmGalax[9];
AnimationData *m_panidWalls;
};
// Directions
typedef char Direction; // dir
const Direction kdirInvalid = -1;
const Direction kdirN = 0;
const Direction kdirNE = 1;
const Direction kdirE = 2;
const Direction kdirSE = 3;
const Direction kdirS = 4;
const Direction kdirSW = 5;
const Direction kdirW = 6;
const Direction kdirNW = 7;
typedef int Direction16; // dir16
const Direction16 kdir16Invalid = -1;
// TerrainMap
struct PathHead // pathh
{
PathHead *ppathhNext;
int txLast;
int tyLast;
int cSteps;
word offHead;
word wScoreKnown;
word wScore;
};
#define kbfMobileUnit 0x80
#define kbfStructure 0x40
#define kbfReserved 0x20
#define kbfLinked 0x10
#define kbfHead 0x08
#define kbfDirMask 0x07
class Path;
class TrackPoint
{
public:
bool Init(Path *ppath, TCoord txFrom, TCoord tyFrom, int itptStart, int ctptFurtherStop) secTerrainMap;
void InitFrom(TrackPoint *ptrkp) secTerrainMap;
bool IsProgress(TrackPoint *ptrkpA) secTerrainMap;
bool IsCloser(TrackPoint *ptrkpA) secTerrainMap;
bool IsBetterSort(TrackPoint *ptrkpA) secTerrainMap;
void GetClosestPoint(TPoint *ptpt) {
*ptpt = m_tptClosest;
}
int GetClosestPointIndex() {
return m_itptClosest;
}
void GetAfterPoint(TPoint *ptpt) {
*ptpt = m_tptAfter;
}
void GetInitialPoint(TPoint *ptpt) {
*ptpt = m_tptInitial;
}
protected:
TPoint m_tptInitial;
TPoint m_tptClosest;
TPoint m_tptBefore;
TPoint m_tptAfter;
int m_itptClosest;
int m_n2Before;
int m_n2After;
};
class TerrainMap;
class Path
{
public:
Path() secTerrainMap;
~Path() secTerrainMap;
bool Init(TerrainMap *ptrmap, TCoord txStart, TCoord tyStart, Direction *adir, int cdir) secTerrainMap;
int GetCount() secTerrainMap;
bool GetPoint(int itpt, TPoint *ptpt, byte bf) secTerrainMap;
bool GetPointRaw(int itpt, TPoint *ptpt) secTerrainMap;
void SetCacheIndex(int itpt) secTerrainMap;
int FindClosestPoint(TCoord txFrom, TCoord tyFrom, int itptStart, int ctptFurtherStop, TPoint *ptptClosest) secTerrainMap;
bool LoadState(TerrainMap *ptrmap, Stream *pstm) secTerrainMap;
bool SaveState(Stream *pstm) secTerrainMap;
bool Append(Path *ppath) secTerrainMap;
bool TrimEnd(int itptStart) secTerrainMap;
Path *Clone() secTerrainMap;
void GetStartPoint(TPoint *ptpt) secTerrainMap;
#ifdef DRAW_PATHS
void Draw(DibBitmap *pbm, int xView, int yView, Side side) secTerrainMap;
#endif
protected:
void CalcTo(int idir, TCoord *ptx, TCoord *pty) secTerrainMap;
TerrainMap *m_ptrmap;
int m_cdirs;
Direction *m_adir;
TCoord m_txStart, m_tyStart;
int m_idirCache;
TCoord m_txCache, m_tyCache;
};
Path *CreatePath(TerrainMap *ptrmap, TCoord txStart, TCoord tyStart, TPoint *ptpt, int ctpt) secTerrainMap;
Path *CreatePath(TerrainMap *ptrmap, TCoord txStart, TCoord tyStart, Direction *adir, int cdir) secTerrainMap;
// 0 = area
// 1 = open
// 2 = wall
// 3 = blocked
#define kttArea 0
#define kttOpen 1
#define kttWall 2
#define kttBlocked 3
struct TerrainMapHeader // trmaph
{
word ctx;
word cty;
};
class TerrainMap // trmap
{
public:
TerrainMap() secTerrainMap;
~TerrainMap() secTerrainMap;
bool Init(char *pszFn) secTerrainMap;
bool LoadState(Stream *pstm) secTerrainMap;
bool SaveState(Stream *pstm) secTerrainMap;
void SetFlags(int tx, int ty, int ctx, int cty, byte bf) secTerrainMap;
bool TestFlags(int tx, int ty, int ctx, int cty, byte bf) secTerrainMap;
void ClearFlags(int tx, int ty, int ctx, int cty, byte bf) secTerrainMap;
bool IsOccupied(int tx, int ty, int ctx, int cty, byte bf) secTerrainMap;
Path *FindPath(int txFrom, int tyFrom, int txTo, int tyTo, byte bfTerrainAvoid) secTerrainMap;
Path *FindLinePath(TCoord txFrom, TCoord tyFrom, TCoord txTo, TCoord tyTo, byte bfTerrainAvoid) secTerrainMap;
bool IsLineOccupied(TCoord txFrom, TCoord tyFrom, TCoord txTo, TCoord tyTo, byte bfTerrainAvoid) secTerrainMap;
bool FindFirstUnoccupied(TCoord txFrom, TCoord tyFrom, TCoord txTo, TCoord tyTo, TCoord *ptxFree, TCoord *ptyFree) secTerrainMap;
bool FindLastUnoccupied(TCoord txFrom, TCoord tyFrom, TCoord txTo, TCoord tyTo, TCoord *ptxFree, TCoord *ptyFree) secTerrainMap;
bool IsBlocked(TCoord tx, TCoord ty, byte bf) secTerrainMap;
bool GetFlags(int tx, int ty, byte *pbf) secTerrainMap;
int GetTerrainType(TCoord tx, TCoord ty) secTerrainMap;
byte *GetMapPtr() {
return (byte *)(m_ptrmaph + 1);
}
TCoord GetWidth() {
return m_ctx;
}
TCoord GetHeight() {
return m_cty;
}
#ifdef MP_DEBUG
dword GetChecksum() secTerrainMap;
#endif
private:
PathHead *AddPathHead(word wScoreKnown, word wScore, int cSteps, word offHead, int txNew, int tyNew) secTerrainMap;
void RemovePathHead(PathHead *ppathh) secTerrainMap;
Path *MakePath(TCoord txStart, TCoord tyStart, word off) secTerrainMap;
FileMap m_fmap;
TerrainMapHeader *m_ptrmaph;
byte *m_abBuffer;
int m_cbBuffer;
int m_ctx;
int m_cty;
word *m_pwSquared;
PathHead *m_ppathhList;
PathHead *m_ppathhFreeList;
int m_mpDirDelta[8];
static word s_anScoreTerrain[4];
static word s_anScoreVector[8];
int m_cNodes;
friend class Path;
};
// Animation & AnimationData
struct FrameData // frmd
{
byte ibm; // bitmap index
byte ibm2; // second bitmap index
byte cHold; // frame delay
char xOrigin; // x offset for drawing
char yOrigin; // y offset for drawing
char xOrigin2; // x offset for drawing second bitmap
char yOrigin2; // y offset for drawing second bitmap
byte bCustomData1; // first custom data value
byte bCustomData2; // second custom data value
};
#define kcbFrameData 9
class StripData // stpd
{
private:
char szName[26]; // name of the Strip
byte cDelay; // inter-frame delay (in ??? units)
byte bfFlags; // e.g., fLoop
word cfrmd; // count of FrameData structures
FrameData afrmd[1]; // array of FrameData structures
public:
const char *GetName() {
return szName;
}
int GetDefaultDelay() {
return cDelay;
}
byte GetFlags() {
return bfFlags;
}
word GetFrameCount() {
return BigWord(cfrmd);
}
FrameData *GetFrameData(int ifrmd) {
return (FrameData *)(((byte *)afrmd) + ifrmd * kcbFrameData);
//return &afrmd[ifrmd];
}
};
// NOTE: All values are stored big-endian
struct AnimationFileHeader // anih
{
word cstpd; // count of StripData structures
word aoffStpd[1]; // array of offsets to StripData structures
};
class AnimationData // anid
{
public:
AnimationData() secAnimation;
~AnimationData() secAnimation;
bool Init(const char *pszAniName) secAnimation;
int GetStripCount() secAnimation;
int GetFrameCount(int nStrip) secAnimation;
int GetStripIndex(const char *pszStripName) secAnimation;
void GetFrameOrigin(int nStrip, int nFrame, Point *pptOrigin) secAnimation;
void GetSpecialPoint(int nStrip, int nFrame, Point *pptSpecial) secAnimation;
void GetBounds(int nStrip, int nFrame, Rect *prc) secAnimation;
void DrawFrame(int nStrip, int nFrame, DibBitmap *pbm, int x, int y, Side side, Rect *prcSrc = NULL) secAnimation;
int GetStripDelay(int nStrip) secAnimation;
int GetFrameDelay(int nStrip, int nFrame) secAnimation;
private:
TBitmap *m_ptbm;
FileMap m_fmap;
AnimationFileHeader *m_panih;
};
AnimationData *LoadAnimationData(const char *pszAniName) secAnimation;
const word kfAniLoop = 0x0001;
const word kfAniDone = 0x0002;
const word kfAniIgnoreFirstAdvance = 0x0004;
const word kfAniResetWhenDone = 0x0008;
const word kfAniFreeAnimationData = 0x8000;
class Animation // ani
{
public:
Animation() {
m_panid = NULL;
m_nStrip = 0;
m_nFrame = 0;
m_cDelay = 0;
m_wf = kfAniDone;
}
~Animation() {
if (m_wf & kfAniFreeAnimationData)
delete m_panid;
}
void Init(AnimationData *panid) secAnimation;
bool Start(int nStrip = 0, int nFrame = 0, word wf = 0) secAnimation;
bool Start(const char *pszStripName, word wf = 0) secAnimation;
bool LoadState(Stream *pstm) secAnimation;
bool SaveState(Stream *pstm) secAnimation;
#ifdef MP_DEBUG_SHAREDMEM
void MPValidate(Animation *paniRemote);
#endif
void Stop() {
m_wf |= kfAniDone;
}
bool IsDone() {
return (m_wf & kfAniDone) != 0;
}
void SetStrip(int nStrip) {
Assert(nStrip >= 0 && nStrip < m_panid->GetStripCount());
m_nStrip = nStrip;
}
void SetStrip(const char *pszStripName) secAnimation;
int GetStrip() {
return m_nStrip;
}
void SetFrame(int nFrame) {
Assert(nFrame >= 0 && nFrame < m_panid->GetFrameCount(m_nStrip));
m_nFrame = nFrame;
}
int GetFrame() {
return m_nFrame;
}
void SetDelay(int cDelay) {
m_cDelay = cDelay;
}
void GetSpecialPoint(Point *pptSpecial, int nFrame = -1) {
if (nFrame < 0)
nFrame = m_nFrame;
m_panid->GetSpecialPoint(m_nStrip, nFrame, pptSpecial);
}
void GetBounds(Rect *prc) {
m_panid->GetBounds(m_nStrip, m_nFrame, prc);
}
void Draw(DibBitmap *pbm, int x, int y, Side side = ksideNeutral, Rect *prcSrc = NULL) {
m_panid->DrawFrame(m_nStrip, m_nFrame, pbm, x, y, side, prcSrc);
}
word GetFlags() {
return m_wf;
}
int GetRemainingFrameTime() {
return m_cCountdown;
}
AnimationData *GetAnimationData() {
return m_panid;
}
bool Advance(int cAdvance) secAnimation;
long GetRemainingStripTime() secAnimation;
private:
AnimationData *m_panid;
int m_nStrip;
int m_nFrame;
word m_wf;
byte m_cCountdown;
byte m_cDelay;
};
// Event Manager
struct Event { // evt
int idf;
int eType;
union {
int chr;
};
int x;
int y;
dword dw;
dword ff;
long ms;
};
#define kfEvtFinger 0x00000001
#define kfEvtCoalesce 0x00000002
// Custom events
#define gamePaintEvent 0x6000
#define penHoldEvent 0x6001
#define gameOverEvent 0x6002
#define penHoverEvent 0x6003
#define updateTriggersEvent 0x6004
#define gameSuspendEvent 0x6005
#define gameResumeEvent 0x6006
#define resizeEvent 0x6007
#define hidePinEvent 0x6008
#define cancelModeEvent 0x6009
#define nullEvent 0x600a
#define transportEvent 0x600b
#define runUpdatesNowEvent 0x600c
#define askStringEvent 0x600d
#define mpEndMissionWinEvent 0x600e
#define mpEndMissionLoseEvent 0x600f
#define mpShowObjectivesEvent 0x6010
#define checkGameOverEvent 0x6011
#define connectionCloseEvent 0x6012
#define showMessageEvent 0x6013
#define enableSoundEvent 0x6014
#define disableSoundEvent 0x6015
// gameOverEvent constants (placed in Event::dw)
enum {
knGoSuccess,
knGoFailure,
knGoInitFailure,
knGoAbortLevel,
knGoRetryLevel,
knGoAppStop,
knGoLoadSavedGame,
};
#define knAppExit 0xBEEFFEED // modifer to AppStopEvent, used only in windows for WM_CLOSE.
#define kcevtPostMax 20
#define kfRedrawDirty 1
#define kfRedrawMax 2
#define kfRedrawBeforeTimer 4
#define kfRedrawBeforeInput 8
struct FlickVector {
int GetMagnitude() {
return dx * dx + dy * dy;
}
int dx;
int dy;
dword cms;
};
#define kcevtPenHistory 32 // keep power of 2
#define kcmsFlickQuantum 150
class EventMgr // evm
{
public:
EventMgr() secEventMgr;
~EventMgr() secEventMgr;
bool PeekEvent(Event *pevt, long cWait = 0) secEventMgr;
bool GetEvent(Event *pevt, long cWait = -1, bool fCheckPaints = true) secEventMgr;
void PostEvent(Event *pevt, bool fCoalesce = true) secEventMgr;
void PostEvent(int eType, bool fCoalesce = true) secEventMgr;
bool DispatchEvent(Event *pevt) secEventMgr;
void Init() secEventMgr;
void SetPenEventInterval(word ctInterval) secEventMgr;
void ClearAppStopping() secEventMgr;
bool GetFlickVector(int nPen, FlickVector *pfliv);
void SetAppStopping() {
m_fAppStopping = true;
}
bool IsAppStopping() {
return m_fAppStopping;
}
void SetRedrawFlags(word wfRedraw)
{
m_wfRedraw |= wfRedraw;
}
void ClearRedrawFlags(word wfRedraw)
{
m_wfRedraw &= ~wfRedraw;
}
word GetRedrawFlags()
{
return m_wfRedraw;
}
private:
void UpdatePenHistory(Event *pevt) secEventMgr;
bool QueryPenHistory(int nPen, long t, Point *ppt);
int m_ievtPen1Next;
Event m_aevtPen1History[kcevtPenHistory];
int m_ievtPen2Next;
Event m_aevtPen2History[kcevtPenHistory];
bool m_fPenHistoryInitialized;
Event m_evtPeek;
bool m_fPeekKeep;
Event m_aevtQ[kcevtPostMax];
int m_cevt;
bool m_fAppStopping;
word m_wfRedraw;
bool m_fTimingPenHold;
long m_tPenDown;
int m_xHold, m_yHold;
word m_ctMoveEventInterval;
word m_nctMoveEventFraction;
long m_tLastMoveEvent;
};
extern EventMgr gevm;
//---------------------------------------------------------------------------
// StateMachine
// Portions Copyright (C) Steve Rabin, 2000
class StateMachine;
class StateMachineMgr;
// NOTE: be sure to update the corresponding string table in StateMachine.cpp
enum State { // st
kstReservedNull,
kstReservedZombie,
kstReservedGlobal,
kstGuard,
kstMove,
kstAttack,
kstChase,
kstIdle,
kstDying,
kstBuildOtherCompleting,
kstBeingBuilt,
kstHuntEnemies,
kstProcessorGetMiner,
kstProcessorPutMiner,
kstProcessorTakeGalaxite,
kstMinerMoveToProcessor,
kstMinerRotateForEntry,
kstMinerMine,
kstMinerFindGalaxite,
kstMinerFaceGalaxite,
kstMinerApproachGalaxite,
kstMinerSuck,
kstMinerStepAside,
kstChangeStatePendingFireComplete,
kstContinueActionPendingFireComplete,
};
STARTLABEL(StateNames)
LABEL(kstReservedNull)
LABEL(kstReservedZombie)
LABEL(kstReservedGlobal)
LABEL(kstGuard)
LABEL(kstMove)
LABEL(kstAttack)
LABEL(kstChase)
LABEL(kstIdle)
LABEL(kstDying)
LABEL(kstBuildOtherCompleting)
LABEL(kstBeingBuilt)
LABEL(kstHuntEnemies)
LABEL(kstProcessorGetMiner)
LABEL(kstProcessorPutMiner)
LABEL(kstProcessorTakeGalaxite)
LABEL(kstMinerMoveToProcessor)
LABEL(kstMinerRotateForEntry)
LABEL(kstMinerMine)
LABEL(kstMinerFindGalaxite)
LABEL(kstMinerFaceGalaxite)
LABEL(kstMinerApproachGalaxite)
LABEL(kstMinerSuck)
LABEL(kstMinerStepAside)
LABEL(kstChangeStatePendingFireComplete)
LABEL(kstContinueActionPendingFireComplete)
ENDLABEL(StateNames)
STARTLABEL(GobTypes)
LABEL(kgtNone)
LABEL(kgtShortRangeInfantry)
LABEL(kgtLongRangeInfantry)
LABEL(kgtHumanResourceCenter)
LABEL(kgtSurfaceDecal)
LABEL(kgtScenery)
LABEL(kgtAnimation)
LABEL(kgtReactor)
LABEL(kgtProcessor)
LABEL(kgtStructure)
LABEL(kgtUnit)
LABEL(kgtGalaxMiner)
LABEL(kgtHeadquarters)
LABEL(kgtResearchCenter)
LABEL(kgtVehicleTransportStation)
LABEL(kgtRadar)
LABEL(kgtLightTank)
LABEL(kgtMediumTank)
LABEL(kgtMachineGunVehicle)
LABEL(kgtRocketVehicle)
LABEL(kgtTakeoverSpecialist)
LABEL(kgtWarehouse)
LABEL(kgtMobileHeadquarters)
LABEL(kgtOvermind)
LABEL(kgtTankShot)
LABEL(kgtRocket)
LABEL(kgtMachineGunTower)
LABEL(kgtRocketTower)
LABEL(kgtScorch)
LABEL(kgtSmoke)
LABEL(kgtPuff)
LABEL(kgtBullet)
LABEL(kgtArtillery)
LABEL(kgtArtilleryShot)
LABEL(kgtAndy)
LABEL(kgtReplicator)
LABEL(kgtActivator)
LABEL(kgtFox)
LABEL(kgtAndyShot)
ENDLABEL(GobTypes)
// Helper macros for sending messages
// (would be better as inline functions but I don't trust gcc to do the right thing)
#if 0 // not used
#define SendHitMsg(_gidReceiver, _pplrAttacker, _nDamage) { \
Message msgT; \
msgT.mid = kmidHit; \
msgT.smidSender = _gidAttacker; \
msgT.smidReceiver = _gidReceiver; \
msgT.Hit.gidAssailant = _pplrAttacker->GetId(); \
msgT.Hit.sideAttacker = _pplrAttacker->GetSide(); \
msgT.Hit.nDamage = _nDamage; \
gsmm.SendMsg(&msgT); \
}
#endif
#define SendMoveAction(_gidReceiver, _wx, _wy, _tcRadius, _wcMoveDistPerUpdate) { \
Message msgT; \
msgT.mid = kmidMoveAction; \
msgT.smidSender = kgidNull; \
msgT.smidReceiver = _gidReceiver; \
msgT.MoveCommand.wptTarget.wx = _wx; \
msgT.MoveCommand.wptTarget.wy = _wy; \
msgT.MoveCommand.gidTarget = kgidNull; \
msgT.MoveCommand.wptTargetCenter.wx = _wx; \
msgT.MoveCommand.wptTargetCenter.wy = _wy; \
msgT.MoveCommand.tcTargetRadius = _tcRadius; \
msgT.MoveCommand.wcMoveDistPerUpdate = _wcMoveDistPerUpdate; \
gsmm.SendMsg(&msgT); \
}
#define SendGuardAreaAction(_gidReceiver, _nArea) { \
Message msgT; \
msgT.mid = kmidGuardAreaAction; \
msgT.smidSender = kgidNull; \
msgT.smidReceiver = _gidReceiver; \
msgT.GuardAreaCommand.nArea = _nArea; \
gsmm.SendMsg(&msgT); \
}
#define SendGuardVicinityAction(_gidReceiver) { \
Message msgT; \
msgT.mid = kmidGuardVicinityAction; \
msgT.smidSender = kgidNull; \
msgT.smidReceiver = _gidReceiver; \
gsmm.SendMsg(&msgT); \
}
#define SendMineCommand(_gidReceiver, _wx, _wy) { \
Message msgT; \
msgT.mid = kmidMineCommand; \
msgT.smidSender = kgidNull; \
msgT.smidReceiver = _gidReceiver; \
msgT.MoveCommand.wptTarget.wx = _wx; \
msgT.MoveCommand.wptTarget.wy = _wy; \
msgT.MoveCommand.gidTarget = kgidNull; \
msgT.MoveCommand.wptTargetCenter.wx = _wx; \
msgT.MoveCommand.wptTargetCenter.wy = _wy; \
msgT.MoveCommand.tcTargetRadius = 0; \
msgT.MoveCommand.wcMoveDistPerUpdate = 0; \
gsmm.SendMsg(&msgT); \
}
#define SendHuntEnemiesAction(_gidReceiver, _um) { \
Message msgT; \
msgT.mid = kmidHuntEnemiesAction; \
msgT.smidSender = kgidNull; \
msgT.smidReceiver = _gidReceiver; \
msgT.HuntEnemiesCommand.um = _um; \
gsmm.SendMsg(&msgT); \
}
// NOTE: The upgrade bits must not overlap the ksum bits used for structures
// because they are used as prerequisites. The InProgress version don't matter.
const word kfUpgradeHrc = 0x0001;
const word kfUpgradeVts = 0x0002;
const word kfUpgradeHrcInProgress = 0x0004;
const word kfUpgradeVtsInProgress = 0x0008;
struct DelayedMessage // dmsg
{
Message msg;
DelayedMessage *pdmsgNext;
};
const int knHandled = 1;
const int knNotHandled = 0;
const int knDeleted = -1;
// StateMachine block macros. One version with embedded tracing, one without.
#define BeginStateMachine if (st == kstReservedGlobal) { if(0) {
#define State(stTest) return knHandled; } } else if (st == stTest) { if(0) {
#if defined(DEBUG_HELPERS)
void Log(StateMachine *psm, Message *pmsg);
void Log(StateMachine *psm, State stOld, State stNew);
#define OnEnter return knHandled; } else if (pmsg->mid == kmidReservedEnter) { \
Log(this, pmsg);
#define OnExit return knHandled; } else if (pmsg->mid == kmidReservedExit) { \
Log(this, pmsg);
#define OnUpdate return knHandled; } else if (pmsg->mid == kmidReservedUpdate) { \
Log(this, pmsg); \
if (m_fDebug) DebugBreak();
#define OnMsg(midTest) return knHandled; } else if (pmsg->mid == midTest) { \
Log(this, pmsg); \
if (m_fDebug) DebugBreak();
#define SetState(stNext) { m_stNext = stNext; m_fForceStateChange = true; m_unvl.MinSkip(); \
Log(this, m_st, stNext); }
#define DiscardMsgs return knHandled; } else { \
Log(this, pmsg); \
if (m_fDebug) DebugBreak();
#else
#define OnEnter return knHandled; } else if (pmsg->mid == kmidReservedEnter) {
#define OnExit return knHandled; } else if (pmsg->mid == kmidReservedExit) {
#define OnUpdate return knHandled; } else if (pmsg->mid == kmidReservedUpdate) {
#define OnMsg(midTest) return knHandled; } else if (pmsg->mid == midTest) {
#define SetState(stNext) { m_stNext = stNext; m_fForceStateChange = true; m_unvl.MinSkip(); }
#define DiscardMsgs return knHandled; } else {
#endif
#define EndStateMachineInherit(base) return knHandled; } } else { \
return (int)##base::ProcessStateMachineMessage(st, pmsg); } return (int)##base::ProcessStateMachineMessage(st, pmsg);
#if 0
#define EndStateMachine return knHandled; } } else { Assert("Invalid State"); \
return knNotHandled; } return knNotHandled;
#else
#define EndStateMachine return knHandled; } } else { return knNotHandled; } return knNotHandled;
#endif
class StateMachine // sm
{
friend class StateMachineMgr;
public:
StateMachine() secStateMachine;
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStateMachine;
#if defined(DEBUG_HELPERS)
virtual char *GetName() = 0;
#endif
UpdateInterval *GetUpdateInterval() {
return &m_unvl;
}
protected:
int ProcessMessage(State st, Message *pmsg) {
return ProcessStateMachineMessage(st, pmsg);
}
UpdateInterval m_unvl;
#ifdef MP_STRESS
public:
#endif
State m_st;
#ifdef MP_STRESS
protected:
#endif
State m_stNext;
bool m_fForceStateChange;
#ifdef DEBUG_HELPERS
public:
friend void Log(StateMachine *psm, Message *pmsg);
bool m_fDebug;
void EnableDebug(bool fDebug) {
m_fDebug = fDebug;
}
friend void paint();
#endif
};
class StateMachineMgr // smm
{
public:
StateMachineMgr() secStateMachine;
~StateMachineMgr() secStateMachine;
bool Init(TimerMgr *ptimm) secStateMachine;
bool SaveState(Stream *pstm) secStateMachine;
bool LoadState(Stream *pstm) secStateMachine;
void ClearDelayedMessages() secStateMachine;
void SendMsg(MessageId mid, StateMachineId smidReceiver) secStateMachine;
void SendMsg(MessageId mid, StateMachineId smidSender, StateMachineId smidReceiver) secStateMachine;
void SendMsg(Message *pmsg) secStateMachine;
void PostMsg(Message *pmsg) secStateMachine;
void PostMsg(MessageId mid, StateMachineId smidSender, StateMachineId smidReceiver) secStateMachine;
void SendDelayedMsg(Message *pmsg, long tDelay) secStateMachine;
void SendDelayedMsg(MessageId mid, long tDelay, StateMachineId smidSender, StateMachineId smidReceiver) secStateMachine;
void DispatchDelayedMessages() secStateMachine;
void RouteMessage(Message *pmsg) secStateMachine;
virtual StateMachineId GetId(StateMachine *psm) = 0;
virtual StateMachine *GetStateMachine(StateMachineId smid) = 0;
private:
void ProcessStateChange(StateMachine *psm) secStateMachine;
bool StoreDelayedMessage(Message *pmsg) secStateMachine;
private:
DelayedMessage *m_pdmsgHead;
TimerMgr *m_ptimm;
#ifdef DEBUG_HELPERS
friend class DelayedMessageViewer;
#endif
#ifdef TRACKSTATE
void TrackState(StateFrame *frame, Message *pmsg);
#endif
};
const int kcmsgCommandQueueMax = 300;
class CommandQueue // cmdq
{
public:
CommandQueue() secCommandQueue;
~CommandQueue() secCommandQueue;
bool Init(int cmsgMax = kcmsgCommandQueueMax) secCommandQueue;
void Exit() secCommandQueue;
bool LoadState(Stream *pstm) secCommandQueue;
bool SaveState(Stream *pstm) secCommandQueue;
void Enqueue(MessageId mid, StateMachineId smidReceiver) secCommandQueue;
void Enqueue(Message *pmsg) secCommandQueue;
void Clear() {
m_cmsg = 0;
}
Message *GetFirst() {
return m_amsg;
}
int GetCount() {
return m_cmsg;
}
private:
void SetEntry(Message *pqmsg) secCommandQueue;
private:
int m_cmsg;
int m_cmsgMax;
Message *m_amsg;
};
#define kcbPvarNameMax 21
#define kcbPvarValueMax kcbFilename
struct DictionaryEntry // de
{
DictionaryEntry *pdeNext;
char szName[kcbPvarNameMax];
char szValue[kcbPvarValueMax];
};
class Dictionary // dict
{
public:
Dictionary() secMisc;
~Dictionary() secMisc;
bool Init(Dictionary *pdict) secMisc;
void Clear() secMisc;
const char *Get(const char *pszName) secMisc;
bool Set(const char *pszName, const char *pszValue) secMisc;
bool Remove(const char *pszName) secMisc;
bool LoadState(Stream *pstm) secMisc;
bool SaveState(Stream *pstm) secMisc;
private:
DictionaryEntry **Find(const char *pszName) secMisc;
int m_cde;
DictionaryEntry *m_pdeHead;
};
// Game
struct ModeMatch
{
int imode;
int nDepthData;
int nSizeData;
};
#define kfGameRoleServer 2
#define kfGameMultiplayer 4
#define kfGameInitFonts 0x10
#define kfGameInitBitmap 0x20
#define kfGameInitDone 0x40
class MultiFormMgr;
class InputUIForm;
class Form;
class Chatter;
struct PreferencesV100;
struct PreferencesV101;
class Game // game
{
public:
Game() secGame;
~Game() secGame;
bool Init(int imm) secGame;
void Exit() secGame;
void Shell() secGame;
int RunSimulation(Stream *pstm, char *pszLevel, word wfRole, dword gameid,
Chatter *chatter);
bool FilterEvent(Event *pevt) secGame;
void GetPlayfieldSize(Size *psiz) secGame;
void RequestModeChange(int imm) secGame;
SimUIForm *GetSimUIForm() secGame;
InputUIForm *GetInputUIForm() secGame;
Form *GetMiniMapForm() secGame;
void SaveGame(Stream *pstm = NULL) secGame;
char *GetNextLevel() secGame;
void SetNextLevel(char *pszLevel) secGame;
int PlayLevel(MissionIdentifier *pmiid, Stream *pstmSavedGame = NULL,
int nRank = 0) secGame;
int PlaySavedGame(Stream *pstm) secGame;
bool IsMultiplayer() secGame;
void SetGameSpeed(int t) secGame;
void SavePreferences() secGame;
bool SaveReinitializeGame() secGame;
bool GetFormattedVersionString(char *pszVersion, char *pszOut) secGame;
void ClearDisplay() secGame;
bool GetVar(const char *pszName, char *pszBuff, int cbBuff) secGame;
bool SetVar(const char *pszName, const char *pszValue) secGame;
void CalcUnitCountDeltas(Level *plvl) secGame;
bool IsVersionCompatibleWithExe(int nVersionCompareShip, int nVersionCompareMajor, char chVersionCompareMinor, bool fUpwardCompatOK) secGame;
void ParseVersion(char *pszVersion, int *pnShipVersion, int *pnMajorVersion, char *pchMinorVersion) secGame;
bool AskResignGame(bool fTellHost = true) secGame;
bool AskObserveGame() secGame;
bool CheckDatabaseVersion(const char *pszDir, char *pszPdb,
bool fUpwardCompatOK) secGame;
// ModeMatch helpers
int GetModeMatchBest() {
return m_immBest;
}
int GetModeMatchCurrent() {
return m_immCurrent;
}
int GetModeMatchCount() {
return m_cmm;
}
void GetModeMatch(int imm, ModeMatch *pmm) {
*pmm = m_amm[imm];
}
word GetFlags() {
return m_wf;
}
const MissionIdentifier& GetLastMissionIdentifier() {
return m_miid;
}
void SkipSaveReinitializeGame() {
m_fSkipSaveReinitialize = true;
}
dword GetGameId() {
return m_gameid;
}
void ScheduleUpdateTriggers();
void UpdateTriggers();
private:
bool CheckMemoryAvailable() secGame;
void Suspend() secGame;
void LoadPreferences() secGame;
bool LoadPreferences2() secGame;
bool LoadPreferencesV100(PreferencesV100 *pprefsV100);
bool LoadPreferencesV101(PreferencesV101 *pprefsV101);
bool InitDisplay(int imm) secGame;
int FindBestModeMatch2(int nDepthData, int nSizeData, int nDepthMode, int cxWidthModeMin, int cxWidthModeMax, byte bfMatch) secGame;
int FindBestModeMatch(int nSizeDataAbove) secGame;
void AddModeMatches(int nDepthData, int nSizeData, int nDepthOrGreater, int cxWidthOrGreater) secGame;
bool LoadGameData() secGame;
bool InitCoordMappingTables() secGame;
bool InitSimulation(Stream *pstm, char *pszLevel, word wfRole,
dword gameid, Chatter *chatter);
void ExitSimulation() secGame;
ddword IsDataPresent(int cBpp) secGame;
bool InitMemMgr() secGame;
bool InitMultiFormMgr() secGame;
dword m_gameid;
int m_cmm;
int m_cmmAlloc;
ModeMatch *m_amm;
int m_immCurrent;
int m_immBest;
SimUIForm *m_pfrmSimUI;
InputUIForm *m_pfrmInputUI;
Form *m_pfrmMiniMap;
Size m_sizPlayfield;
word m_wf;
bool m_fSimUninitialized;
char m_szNextLevel[kcbFilename];
MissionIdentifier m_miid;
Dictionary m_dictPvars;
bool m_fSkipSaveReinitialize;
bool m_fUpdateTriggers;
};
extern Game ggame;
void GameMain(char *psz) secGame;
enum PlayMode {
kpmSavedGame,
kpmNormal
};
class Shell
{
public:
Shell() secShell;
bool Init() secShell;
void Exit() secShell;
void Launch(bool fLoadReinitializeSave = false,
MissionIdentifier *pmiid = NULL) secShell;
int PlayGame(PlayMode pm, MissionIdentifier *pmiid, Stream *pstm,
int nRank) secShell;
void SetPalette() secShell;
private:
bool DoPlay();
bool PlayChallengeLevel(bool fStory = false) secShell;
bool BeginNewGame() secShell;
bool PlaySinglePlayer(const PackId *ppackid) secShell;
bool PlayMultiplayer(const PackId *ppackid) secShell;
void DownloadMissionPack() secShell;
FileMap m_fmapPalette;
FileMap m_fmapShadowMap;
Palette *m_ppal;
byte *m_mpiclriclrShadow;
};
extern Shell gshl;
#define knStageNone 0
#define knStageCollect 1
#define knStageCheckDraw 2
// UpdateMap
struct MapInfo
{
int cxLeftTile;
int cyTopTile;
int cxRightTile;
int cyBottomTile;
int ctxInside;
int ctyInside;
};
class UpdateMap
{
public:
UpdateMap() secUpdateMap;
~UpdateMap() secUpdateMap;
bool Init(Size *psiz) secUpdateMap;
void Reset() secUpdateMap;
void InvalidateRect(Rect *prc = NULL) secUpdateMap;
void InvalidateMapTileRect(TRectSmall *ptrc) secUpdateMap;
bool EnumUpdateRects(bool fFirst, Rect *prcBounds, Rect *prc) secUpdateMap;
bool Scroll(int dx, int dy) secUpdateMap;
bool *GetInvalidMap() secUpdateMap;
void GetMapSize(Size *psiz) secUpdateMap;
MapInfo *GetMapInfo() secUpdateMap;
bool IsInvalid() secUpdateMap;
void SetViewOrigin(int xOrigin, int yOrigin) secUpdateMap;
void Validate() secUpdateMap;
void InvalidateTile(TCoord tx, TCoord ty) secUpdateMap;
void StartMergeDamagedInvalid() secUpdateMap;
void EndMergeDamagedInvalid() secUpdateMap;
bool IsDamagedInvalid()
{
return m_fInvalidDamage;
}
bool IsRectInvalid(Rect *prc)
{
TRectSmall trc;
CalcTileRect(prc, &trc);
return IsTileRectInvalid(&trc);
}
bool IsRectInvalidAndTrackDamage(Rect *prc)
{
TRectSmall trc;
CalcTileRect(prc, &trc);
bool fNewInvalid;
return IsTileRectInvalidAndTrackDamage(&trc, &fNewInvalid);
}
bool IsMapTileRectInvalidAndTrackDamage(TRectSmall *ptrc, bool *pfNewInvalid) secUpdateMap;
private:
bool EnumRowRects(bool fFirst, Rect *prcBounds, Rect *prc) secUpdateMap;
void InvalidateTileRect(TRectSmall *ptrc) secUpdateMap;
bool IsTileRectInvalidAndTrackDamage(TRectSmall *ptrc, bool *pfNewInvalid) secUpdateMap;
bool IsTileRectInvalid(TRectSmall *ptrc) secUpdateMap;
void CalcTileRect(Rect *prc, TRectSmall *ptrc) secUpdateMap;
void SetMapOffset(int xMapOffset, int yMapOffset, bool fInvalidate = true) secUpdateMap;
Rect m_rcDib;
int m_ctx;
int m_cty;
int m_txOrigin;
int m_tyOrigin;
int m_xOriginView;
int m_yOriginView;
bool *m_afInvalid;
bool *m_afInvalidDamage;
int m_xMapOffset;
int m_yMapOffset;
bool m_fInvalid;
bool m_fInvalidDamage;
bool m_fMergeDamage;
MapInfo m_mnfo;
};
class FlickScroller // flics
{
public:
FlickScroller();
bool Init(int nPen, float flMultiplier = 1.0f,
float flDecayPercent = 0.01f,
float cmsDecaySpan = kcmsFlickQuantum / 10, bool fChoose = true);
void Clear();
bool GetPosition(Point *ppt);
bool HasMagnitude();
private:
bool CheckMagnitude(float dx, float dy);
FlickVector m_fliv;
long m_msStart;
float m_flMultiplier;
float m_flDecayPercent;
dword m_cmsDecaySpan;
bool m_fHasMagnitude;
};
// Form Manager
#define kcFormsMax 16
#define kfFrmmNoScroll 1
class Form;
class FormMgr // frmm
{
public:
FormMgr() secFormMgr;
virtual ~FormMgr() secFormMgr;
virtual bool Init(DibBitmap *pbm, bool fFreeDib) secFormMgr;
virtual void AddForm(Form *pfrm) secFormMgr;
virtual void RemoveForm(Form *pfrm) secFormMgr;
virtual bool EcomSuppressed() secFormMgr;
virtual bool CookEvent(Event *pevt) secFormMgr;
virtual Form *GetFormPtr(word idf) secFormMgr;
virtual Form *LoadForm(IniReader *pini, word idf, Form *pfrm) secFormMgr;
virtual void Paint(bool fScrolled, Rect *prcOpaqueStart) secFormMgr;
virtual void Scroll(int dx, int dy) secFormMgr;
virtual bool HasCapture() secFormMgr;
virtual Form *GetFormCapture() secFormMgr;
virtual Form *GetModalForm() secFormMgr;
virtual void InvalidateRect(Rect *prc) secFormMgr;
virtual DibBitmap *GetDib() secFormMgr;
virtual void CalcOpaqueRect(Form *pfrmStop, Rect *prcOpaqueStart, Rect *prcResult) secFormMgr;
virtual Form *GetFocus() secFormMgr;
virtual void FrameStart() secFormMgr;
virtual void FrameComplete() secFormMgr;
virtual void BreakCapture();
void SetFlags(word wf) {
m_wf = wf;
}
word GetFlags() {
return m_wf;
}
int GetFormCount() {
return m_cfrm;
}
protected:
Form *FindPen2Form();
bool CookPenEvent(Event *pevt) secFormMgr;
bool CookKeyEvent(Event *pevt) secFormMgr;
virtual bool BltTo(DibBitmap *pbmDst, int yTop, bool fScrolled) secFormMgr;
virtual bool ScrollBits() secFormMgr;
word m_wf;
word m_idfCapture;
int m_cCaptureDowns;
int m_cfrm;
Form *m_apfrm[kcFormsMax];
DibBitmap *m_pbm;
UpdateMap *m_pupd;
bool m_fFreeDib;
int m_dxScrollAccumulate;
int m_dyScrollAccumulate;
public:
UpdateMap *GetUpdateMap() {
return m_pupd;
}
friend class MultiFormMgr;
};
#define kcFormMgrMax 5
class MultiFormMgr : public FormMgr
{
public:
MultiFormMgr() secFormMgr;
virtual ~MultiFormMgr() secFormMgr;
void AddFormMgr(FormMgr *pfrmm, Rect *prc) secFormMgr;
void RemoveFormMgr(FormMgr *pfrmm) secFormMgr;
void DrawFrame(bool fForceBackBufferValid, bool fPaint = true) secFormMgr;
void CheckSetRedrawDirty() secFormMgr;
bool IsInvalid() secFormMgr;
bool GetFormMgrRect(FormMgr *pfrmm, Rect *prc) secFormMgr;
#ifdef STATS_DISPLAY
int GetUpdateRectCount() secFormMgr;
#endif
virtual void AddForm(Form *pfrm) secFormMgr;
virtual void RemoveForm(Form *pfrm) secFormMgr;
virtual bool EcomSuppressed() secFormMgr;
virtual bool CookEvent(Event *pevt) secFormMgr;
virtual Form *GetFormPtr(word idf) secFormMgr;
virtual bool Paint(bool fForceBackBufferValid) secFormMgr;
virtual void InvalidateRect(Rect *prc) secFormMgr;
virtual void CalcOpaqueRect(Form *pfrmStop, Rect *prcOpaqueStart, Rect *prcResult) secFormMgr;
virtual Form *GetFocus() secFormMgr;
private:
#ifdef DRAW_UPDATERECTS
void DrawUpdateRects(UpdateMap *pupd, int yTop) secFormMgr;
#endif
virtual bool BltTo(DibBitmap *pbmDst, int yTop, bool fScrolled) secFormMgr;
bool StealCapturePen2(Event *pevt, FormMgr *pfrmmChildCapture);
int m_cfrmm;
FormMgr *m_apfrmm[kcFormMgrMax];
Rect m_arcFormMgr[kcFormMgrMax];
Event m_evtPen1Down;
};
// Form
#define kcControlsMax 32
#define kfFrmDeleted 0x01
#define kfFrmDoModal 0x02
#define kfFrmVisible 0x04
#define kfFrmPenInside 0x08
#define kfFrmHasPalette 0x10
#define kfFrmHasShadowMap 0x20
#define kfFrmScaleCoords 0x40
#define kfFrmAutoTakedown 0x80
#define kfFrmTranslucent 0x100
#define kfFrmNoFocus 0x200
#define kfFrmShowSound 0x400
#define kfFrmNoEcom 0x800
#define kfFrmTopMost 0x1000
#define kfFrmDemandPen2 0x2000
#define knNotifySelectionChange 0
#define knNotifySelectionTap 1
class IControlEventHandler {
public:
virtual void OnControlSelected(word nSelect) = 0;
virtual bool OnControlHeld(word idc) = 0;
virtual void OnControlNotify(word idc, int nNotify) = 0;
};
class Control;
class Form : public IControlEventHandler
{
public:
Form() secForm;
virtual ~Form() secForm;
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secForm;
virtual bool OnFilterEvent(Event *pevt) { return false; }
virtual bool EventProc(Event *pevt) secForm;
virtual bool DoModal(int *pnResult = NULL, Sfx sfxShow = ksfxGuiFormShow, Sfx sfxHide = ksfxGuiFormHide) secForm;
virtual bool OnHitTest(Event *pevt) secForm;
virtual bool OnKeyTest(Event *pevt) secForm;
virtual bool OnPenEvent(Event *pevt) secForm;
virtual void OnUpdateMapInvalidate(UpdateMap *pupd, Rect *prcOpaque) secForm;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secForm;
virtual void OnPaint(DibBitmap *pbm) secForm;
virtual void OnPaintControls(DibBitmap *pbm, UpdateMap *pupd) secForm;
virtual void OnScroll(int dx, int dy) secForm;
virtual void ScrollInvalidate(UpdateMap *pupd) secForm;
virtual void InvalidateRect(Rect *prc) secForm;
virtual void FrameStart() secForm;
virtual void FrameComplete() secForm;
virtual Control *HitTestControls(Event *pevt);
virtual void BreakCapture();
// IControlEventHandler methods
virtual void OnControlSelected(word idc) secForm;
virtual bool OnControlHeld(word idc) secForm;
virtual void OnControlNotify(word idc, int nNotify) secForm;
FormMgr *GetFormMgr() secForm;
word GetId() secForm;
word GetFlags() secForm;
void SetFlags(word wf) secForm;
void GetRect(Rect *prc) secForm;
void SetRect(Rect *prc) secForm;
void Show(bool fShow) secForm;
void EndForm(int nResult = 0) secForm;
Control *GetControlPtr(word idc) secForm;
bool IsControlInside(Control *pctl) secForm;
bool AddControl(Control *pctl) secForm;
void SetUserDataPtr(void *pUserData) secForm;
void *GetUserDataPtr() secForm;
Form *FindPen2Form();
bool HasCapture() {
return m_pfrmm->GetFormCapture() == this;
}
Control *GetControlCapture() {
return m_pctlCapture;
}
int GetResult() {
return m_nResult;
}
protected:
bool InitFromProperties(FormMgr *pfrmm, word idf, IniReader *pini, char *pszForm) secForm;
FormMgr *m_pfrmm;
TBitmap *m_ptbm;
Control *m_pctlCapture;
Rect m_rc;
int m_nResult;
word m_wf;
word m_idf;
word m_idcDefault;
word m_idcLast;
int m_cctl;
Sfx m_sfxShow;
Sfx m_sfxHide;
Control *m_apctl[kcControlsMax];
FileMap m_fmapPalette;
FileMap m_fmapShadowMap;
int m_iclrBack;
void* m_pUserData;
friend class FormMgr;
};
inline FormMgr *Form::GetFormMgr()
{
return m_pfrmm;
}
// DialogForm
#define kcyTitle 10
class DialogForm : public Form
{
public:
DialogForm() secForm;
~DialogForm() secForm;
void SetBackgroundColorIndex(int iclr) secForm;
void SetTitleColor(Color clr) secForm;
void SetBorderColorIndex(int iclr) secForm;
void SetClearDibFlag() secForm;
// Form overrides
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secForm;
virtual void OnPaint(DibBitmap *pbm) secForm;
virtual bool OnPenEvent(Event *pevt) secForm;
virtual bool DoModal(int *pnResult = NULL, Sfx sfxShow = ksfxGuiFormShow, Sfx sfxHide = ksfxGuiFormHide) secForm;
private:
Color m_clrTitle;
int m_iclrBorder;
int m_iclrBackground;
bool m_fClearDib;
};
inline void DialogForm::SetTitleColor(Color clr) {
m_clrTitle = clr;
}
inline void DialogForm::SetBorderColorIndex(int iclr) {
m_iclrBorder = iclr;
}
inline void DialogForm::SetClearDibFlag() {
m_fClearDib = true;
}
// ShellForm
class ShellForm : public Form, public Timer
{
public:
ShellForm() secForm;
virtual ~ShellForm() secForm;
// Doesn't match Form's DoModal signature so it's not really an override
virtual bool DoModal(int *pnResult = NULL, bool fAnimate = true, bool fShowSound = true) secForm;
// Form overrides
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secForm;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secForm;
// Timer interface
virtual void OnTimer(long tCurrent) secForm;
virtual void OnZipDone() {}
protected:
bool m_fAnimate;
private:
bool m_fCached;
int m_axDst[kcControlsMax];
bool m_fTimerEnabled;
int m_cctlToZip;
long m_tLast;
};
// InGameOptions
class InGameOptionsForm : public ShellForm
{
public:
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf);
virtual void OnControlSelected(word idc);
private:
void InitResettableControls();
void UpdateLabels();
bool m_fLassoSelection;
long m_tGameSpeed;
word m_wfHandicap;
double m_nScrollSpeed;
};
// Control
#define knSelDownInside 0
#define knSelUpInside 1
#define knSelUpOutside 2
#define knSelMoveInside 3
#define knSelMoveOutside 4
#define knSelHoldInside 5
#define kfCtlVisible 1
#define kfCtlSet 2
#define kfCtlRedraw 4
#define kfCtlDisabled 8
#define kfCtlUseSide1Colors 16
class Control
{
public:
Control() secControl;
virtual ~Control() secControl;
virtual bool Init(Form *pfrm, word idc, int x, int y, int cx, int cy) secControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secControl;
virtual void OnPaint(DibBitmap *pbm) secControl;
virtual void OnPenEvent(Event *pevt) secControl;
virtual void OnSelect(int nSelect) secControl;
virtual int OnHitTest(Event *pevt) secControl;
virtual void Invalidate() secControl;
virtual void GetFingerRect(Rect *prc) secControl;
virtual void OnBreakCapture() secControl;
word GetId() secControl;
void GetRect(Rect *prc) secControl;
void SetRect(Rect *prc, bool fCompareRect = true) secControl;
void SetPosition(int x, int y) secControl;
void Show(bool fShow) secControl;
word GetFlags() secControl;
void SetFlags(word wf) secControl;
void SetEventHandler(IControlEventHandler *pceh) secControl;
void Enable(bool fEnable) secControl;
protected:
Rect m_rc;
word m_wf;
word m_idc;
Form *m_pfrm;
IControlEventHandler *m_pceh;
friend class Form;
};
inline void Control::SetEventHandler(IControlEventHandler *pceh) {
m_pceh = pceh;
}
// Button Control
class ButtonControl : public Control // btn
{
public:
static bool InitClass() secButtonControl;
static void ExitClass() secButtonControl;
ButtonControl() secButtonControl;
virtual ~ButtonControl() secButtonControl;
virtual bool Init(Form *pfrm, word idc, int x, int y, int cx, int cy,
char *pszLabel, int nfnt, char *szFnUp = NULL, char *szFnDown = NULL, char *szFnDisabled = NULL) secButtonControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secButtonControl;
virtual void OnPaint(DibBitmap *pbm) secButtonControl;
virtual void OnSelect(int nSelect) secButtonControl;
void SetText(char *psz) secButtonControl;
private:
virtual bool Init(char *pszLabel, int nfnt, char *szFnUp, char *szFnDown, char *szFnDisabled, bool fCenter) secButtonControl;
protected:
TBitmap *m_ptbmUp;
TBitmap *m_ptbmDown;
TBitmap *m_ptbmDisabled;
int m_nfnt;
char *m_szLabel;
private:
static TBitmap *s_ptbmLeftUp;
static TBitmap *s_ptbmMidUp;
static TBitmap *s_ptbmRightUp;
static TBitmap *s_ptbmLeftDown;
static TBitmap *s_ptbmMidDown;
static TBitmap *s_ptbmRightDown;
};
class RadioButtonBarControl : public Control
{
public:
RadioButtonBarControl();
virtual ~RadioButtonBarControl();
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind);
virtual bool Init(const char *pszLabel, int ifnt, int isel);
virtual void OnPaint(DibBitmap *pbm);
virtual void OnPenEvent(Event *pevt);
int GetSelectionIndex();
void SetSelectionIndex(int isel);
private:
void AddLabel(const char *psz, int cch);
void GetCellRects(int icell, Rect *prcInner, Rect *prcOuter);
void GetOuterCellSize(int icell, Size *psiz);
int m_ifnt;
int m_isel;
int m_cLabels;
const char *m_apszLabels[20];
};
class SilkButtonControl : public Control
{
public:
~SilkButtonControl() secButtonControl;
public:
virtual void OnSelect(int nSelect) secButtonControl;
};
inline SilkButtonControl::~SilkButtonControl() {
}
#if 0 // not used now
// PresetButtonControl
class PresetButtonControl : public ButtonControl // btn
{
public:
virtual void OnPaint(DibBitmap *pbm) secPresetButtonControl;
static bool InitClass() secPresetButtonControl;
static void ExitClass() secPresetButtonControl;
private:
virtual bool Init(char *pszLabel, int nfnt, char *szFnUp, char *szFnDown, bool fCenter) secPresetButtonControl;
};
#endif
// Checkbox Control
class CheckBoxControl : public Control // cbox
{
public:
CheckBoxControl() secCheckBoxControl;
virtual ~CheckBoxControl() secCheckBoxControl;
virtual bool Init(Form *pfrm, word idc, int x, int y, char *pszLabel, int nfnt, bool fChecked) secCheckBoxControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secCheckBoxControl;
virtual void OnPaint(DibBitmap *pbm) secCheckBoxControl;
virtual void OnSelect(int nSelect) secCheckBoxControl;
void SetText(char *psz) secCheckBoxControl;
bool IsChecked() secCheckBoxControl;
void SetChecked(bool fChecked) secCheckBoxControl;
static bool InitClass() secCheckBoxControl;
static void ExitClass() secCheckBoxControl;
private:
bool Init(char *pszLabel, int nfnt, bool fChecked) secButtonControl;
static TBitmap *s_ptbmOnUp;
static TBitmap *s_ptbmOnDown;
static TBitmap *s_ptbmOffUp;
static TBitmap *s_ptbmOffDown;
int m_ifnt;
char m_szLabel[64];
bool m_fChecked;
};
// Label Control
#define kfLblCenterText 0x8000
#define kfLblMultiLine 0x4000
#define kfLblRightText 0x2000
#define kfLblClipVertical 0x1000
#define kfLblEllipsis 0x0800
#define kfLblHitTest 0x0400
const int kcbLabelTextMax = 1000;
class LabelControl : public Control // lbl
{
public:
LabelControl() secLabelControl;
virtual ~LabelControl() secLabelControl;
bool Init(int nfnt, char *pszLabel, char *pszFlags1, char *pszFlags2) secLabelControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secLabelControl;
virtual void OnPaint(DibBitmap *pbm) secLabelControl;
virtual int OnHitTest(Event *pevt) secLabelControl;
virtual void SetText(const char *psz) secLabelControl;
const char *GetText() secLabelControl;
protected:
virtual void CalcRect() secLabelControl;
char *m_szLabel;
int m_nfnt;
};
inline const char *LabelControl::GetText() {
return m_szLabel;
}
class EcomTextControl : public LabelControl // ect
{
public:
EcomTextControl() secEcom;
virtual ~EcomTextControl() secEcom;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secEcom;
virtual void OnPaint(DibBitmap *pbm) secEcom;
virtual int OnHitTest(Event *pevt) secEcom;
virtual void SetText(char *psz) secEcom;
// new methods
bool ShowMoreText() secEcom;
void ShowAll() secEcom;
void DrawText(DibBitmap *pbm, Font *pfnt, char *psz, int x, int y, int cx, int cchMax) secEcom;
private:
void CalcRect() secEcom;
int m_cchCur;
dword m_aiclrEcom[4];
long m_ctPrevTime;
};
const int kctEcomOutputInterval = kctUpdate; // how often we call the timer
// Help Control
// define types
#define knChunkRawText 0
#define knChunkBitmap 1
#define knChunkLinkText 2
#define knChunkLargeText 3
#define knChunkGenericTag 4
#define knChunkAniData 5
#define knChunkHRTag 6
typedef struct Chunk {
int nType;
char *psz;
int cch;
DibBitmap *pbm;
void *pv;
char szText[30];
bool fLargeFont;
} Chunk;
typedef struct HitTest {
int x;
int y;
int nchBuffer;
int cch;
int dBest;
bool fHit;
char szText[30];
} HitTest;
// Positioning Constants
#define knFindPosRunToIndex 0
#define knFindPosAtLeastY 1
#define knFindPosAtMostY 2
#define knFindPosFingerScroll 3
typedef struct FindPositionHelper {
int nDistY;
int nIndex;
int cyControl;
int cySpan;
bool fLargeFontSpanMet;
int nchSpanMet;
bool fLargeFontLastHR;
int nchLastHR;
bool fLargeFontFirstHR;
int nchFirstHR;
int nCondition;
bool fLargeFont;
} FindPositionHelper;
#define knHelpControlBRHeight (gapfnt[kifntDefault]->GetHeight() * 3)
typedef bool (*ChunkProc)(int x,int y, int cx, int cy, int nchBuffer, int yCurrent, int nyBottom, Chunk *pchk, void *pv);
#define kfHelpScrollPosition 0x8000
class HelpControl : public Control, Timer
{
public:
HelpControl() secHelpControl;
~HelpControl() secHelpControl;
bool FollowLink(const char *pszLink, int cch = -1) secHelpControl;
void DoNextPage() secHelpControl;
void DoPrevPage() secHelpControl;
void DoIndex() secHelpControl;
void DoBack() secHelpControl;
bool SetFile(const char *pszFile) secHelpControl;
// Control overrides
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secHelpControl;
virtual void OnPaint(DibBitmap *pbm) secHelpControl;
virtual void OnPenEvent(Event *pevt) secHelpControl;
private:
virtual void OnTimer(long tCurrent);
bool Layout(dword nchStart, bool fLargeFont, DibBitmap *pbm, ChunkProc pfn, void *pv) secHelpControl;
int LineHeight(bool) secHelpControl;
int FindPrevPosition(int nchFrom, int cyAmount, bool *pfLargeFont) secHelpControl;
int FindNextPosition(int nchFrom, int cySpan, bool *pfLargeFont,
bool fCondition, bool fSmooth) secHelpControl;
void GetSubRects(Rect *prcInterior, Rect *prcScrollPos = NULL);
void DragScroll(int y);
File *m_pfil;
int m_cb;
bool m_fLargeFont;
char m_szText[129];
int m_nchCurrent;
int m_nchBack[10];
int m_cyPageAmount;
bool m_fDrag;
int m_yDrag;
FlickScroller m_flics;
int m_yDragUp;
bool m_fTimerAdded;
HitTest m_hittest;
};
void Help(const char *pszAnchor = NULL, bool fPauseSimulation = false, const char *pszFile = NULL) secHelpControl;
void CutScene(const char *pszScene, bool fPauseSimulation) secCutScene;
// Edit Control
class EditControl : public Control // edc
{
public:
EditControl() secEditControl;
~EditControl() secEditControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secEditControl;
virtual void OnPaint(DibBitmap *pbm) secEditControl;
void SetText(const char *psz) secEditControl;
void GetText(char *psz, int cb) secEditControl;
private:
char m_szText[100];
int m_nfnt;
};
inline EditControl::~EditControl() {
}
// List Control
#define kfLstcBorder 0x8000
#define kfLstcScrollPosition 0x4000
#define kfLstcKeepInteriorPositioning 0x2000
#define kfLstTabEllipsis 1
#define kfLstTabCenter 2
#define kfLstTabCenterOn 4
#define kfLstTabRight 8
struct ListItem;
class ListControl : public Control, IControlEventHandler, Timer // lstc
{
public:
static bool InitClass() secListControl;
static void ExitClass() secListControl;
ListControl() secListControl;
virtual ~ListControl() secListControl;
Font *GetFont() secListControl;
void Clear() secListControl;
bool Add(ListItem *pli) secListControl;
bool Add(const char *psz, void *pvData = NULL) secListControl;
// ListItem *EnumItemPtr(Enum *penum) secListControl;
int GetSelectedItemIndex() secListControl;
ListItem *GetSelectedItem() secListControl;
void *GetSelectedItemData() secListControl;
void SetSelectedItemData(void *pvData) secListControl;
bool GetSelectedItemText(char *psz, int cb) secListControl;
bool SetSelectedItemText(const char *psz) secListControl;
void Select(int iItem, bool fOnly = false, bool fMakeCenter = false) secListControl;
int GetCount() secListControl;
void SetTabStops(int x0, int x1 = -1, int x2 = -1, int x3 = -1);
void SetTabFlags(word wf0, word wf1 = 0, word wf2 = 0, word wf3 = 0);
virtual void GetSubRects(Rect *prcInterior, Rect *prcUpArrow = NULL,
Rect *prcDownArrow = NULL, Rect *prcScrollPosition = NULL);
void SetScrollPosColorIndex(int iclr) { m_iclrScrollPos = iclr; }
// IControlEventHandler methods
virtual void OnControlSelected(word idc) secForm;
virtual bool OnControlHeld(word idc) secForm;
virtual void OnControlNotify(word idc, int nNotify) secForm;
// Control overrides
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secListControl;
virtual void OnPaint(DibBitmap *pbm) secListControl;
virtual void OnSelect(int nSelect) secListControl;
virtual void OnPenEvent(Event *pevt) secListControl;
// Timer methods
virtual void OnTimer(long tCurrent);
static TBitmap *s_ptbmScrollUpUp;
static TBitmap *s_ptbmScrollUpDown;
static TBitmap *s_ptbmScrollDownUp;
static TBitmap *s_ptbmScrollDownDown;
protected:
virtual void OnPenEvent2(Event *pevt);
virtual void DrawItem(DibBitmap *pbm, ListItem *pli, int x, int y,
int cx, int cy) secListControl;
virtual void DrawText(DibBitmap *pbm, char *psz, int x, int y,
int cx, int cy, word wf);
private:
bool NeedsScrollUpArrow() secListControl;
bool NeedsScrollDownArrow() secListControl;
int GetVisibleItemCount() secListControl;
void DragScroll(int y);
private:
ListItem *m_pliFirst, *m_pliLast;
int m_nfnt;
int m_cli;
int m_iliTop;
int m_cxEllipsis;
int m_yDrag;
int m_yDragUp;
bool m_fTimerAdded;
bool m_fDrag;
int m_iliTopDrag;
FlickScroller m_flics;
int m_iclrScrollPos;
bool m_fPenDown;
protected:
int m_cyItem;
int m_axTab[4];
word m_awfTab[4];
};
const int kidcScrollDownButton = 0x7fff;
const int kidcScrollUpButton = 0x7ffe;
struct ListItem {
ListItem *pliNext;
union {
char szText[80];
struct {
AnimationData *panid;
int nStrip;
int nFrame;
} Anim;
};
void *pvData;
bool fSelected;
bool fDisabled;
};
class BuilderGob;
class BuildQueue;
// Animation List Control
class BuildListControl : public ListControl // alc
{
public:
// ListControl overrides
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secListControl;
virtual void OnPaint(DibBitmap *pbm) secListControl;
virtual void DrawItem(DibBitmap *pbm, ListItem *pli, int x, int y, int cx, int cy) secListControl;
virtual void GetSubRects(Rect *prcInterior, Rect *prcUpArrow = NULL,
Rect *prcDownArrow = NULL, Rect *prcScrollPos = NULL);
bool Add(AnimationData *panid, int nStrip, int nFrame, void *pvData, bool fDisabled = false) secListControl;
void SetQueueInfo(BuilderGob *pbldr, BuildQueue *pbq) { m_pbldr = pbldr; m_pbq = pbq;}
private:
BuilderGob *m_pbldr;
BuildQueue *m_pbq;
};
// Bitmap Control
class BitmapControl : public Control // bmc
{
public:
BitmapControl() secBitmapControl;
virtual ~BitmapControl() secBitmapControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secBitmapControl;
virtual void OnPaint(DibBitmap *pbm) secBitmapControl;
void SetBitmap(HtBitmap *phtbm) secBitmapControl;
private:
HtBitmap *m_phtbm;
};
// Slider Control
class SliderControl : public Control // sldr
{
public:
SliderControl() secSliderControl;
~SliderControl() secSliderControl;
virtual void OnPaint(DibBitmap *pbm) secSliderControl;
virtual void OnSelect(int nSelect) secSliderControl;
virtual void OnPenEvent(Event *pevt) secSliderControl;
void SetRange(int nMin, int nMax) secSliderControl;
void SetValue(int n) secSliderControl;
int GetValue() secSliderControl;
private:
int m_nMin, m_nMax;
int m_nValue;
};
inline SliderControl::~SliderControl() {
};
class GraffitiScrollControl : public Control // grfs
{
public:
GraffitiScrollControl() secGraffitiScrollControl;
bool IsPainting() secGraffitiScrollControl;
virtual void OnPenEvent(Event *pevt) secGraffitiScrollControl;
virtual void OnPaint(DibBitmap *pbm) secGraffitiScrollControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secGraffitiScrollControl;
private:
int m_nScale;
int m_xDragStart;
int m_yDragStart;
WCoord m_wxViewStart;
WCoord m_wyViewStart;
bool m_fFrame;
};
// MiniMap Control
#define kfMmVertBorderInside 1
#define kfMmRedraw 2
#define kfMmHasPoweredRadar 4
#define kfMmPenDownTimeout 8
class MiniMapControl : public Control // mmc
{
public:
MiniMapControl() secMiniMapControl;
virtual ~MiniMapControl() secMiniMapControl;
virtual int OnHitTest(Event *pevt) secMiniMapControl;
virtual void OnPaint(DibBitmap *pbm) secMiniMapControl;
virtual void OnPenEvent(Event *pevt) secMiniMapControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secMiniMapControl;
virtual void OnBreakCapture();
void Redraw() secMiniMapControl;
void RedrawTRect(TRect *ptrc) secMiniMapControl;
void RedrawTile(TCoord tx, TCoord ty) secMiniMapControl;
void Update() secMiniMapControl;
bool CalcPoweredRadar() secMiniMapControl;
static int CalcWidth() secMiniMapControl;
private:
void OnPenEvent2(Event *pevt);
long m_tPenDown;
Event m_evtPenDown;
long m_tInvalidateLast;
int m_nScale;
int m_cyInputUI;
int m_cxyBorder;
DibBitmap *m_pbm;
word m_wfMm;
int m_xOff;
int m_yOff;
TCoord m_ctx;
TCoord m_cty;
byte *m_pbTileData;
word *m_pwTileMap;
int m_cbRowBytes;
byte *m_pbFogMap;
byte m_clrWhite;
byte m_clrBlack;
byte m_clrGalaxite;
byte m_aclrSide[kcSides];
};
// Pip Meter Control
class PipMeterControl : public Control // btn
{
public:
static bool InitClass() secPipMeterControl;
static void ExitClass() secPipMeterControl;
PipMeterControl() secPipMeterControl;
virtual ~PipMeterControl() secPipMeterControl;
virtual bool Init(Form *pfrm, word idc, int x, int y, int cx, int cy,
char *szPip = NULL) secPipMeterControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secPipMeterControl;
virtual void OnPaint(DibBitmap *pbm) secPipMeterControl;
void SetValue(int nValue) secPipMeterControl;
private:
virtual bool Init(char *szPip) secPipMeterControl;
protected:
TBitmap *m_ptbmPip;
int m_nValue;
private:
static TBitmap *s_ptbmPip;
};
// Damge Meter Control
struct UnitConsts;
class DamageMeterControl : public Control // btn
{
public:
static bool InitClass() secDamageMeterControl;
static void ExitClass() secDamageMeterControl;
DamageMeterControl() secDamageMeterControl;
virtual ~DamageMeterControl() secDamageMeterControl;
virtual void OnPaint(DibBitmap *pbm) secDamageMeterControl;
void SetUnitConsts(UnitConsts *puntc) secDamageMeterControl;
private:
UnitConsts *m_puntc;
static TBitmap *s_ptbmInfantry;
static TBitmap *s_ptbmVehicle;
static TBitmap *s_ptbmStructure;
};
// Credits Control
class CreditsControl : public Control
{
public:
CreditsControl() {m_cCreditNeeders = 0;m_fDrawCreditSymbol = true;};
void Update(long nCredits, word cCreditNeeders) secCreditsControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secCreditsControl;
virtual void OnPaint(DibBitmap *pbm) secCreditsControl;
private:
long m_nCredits;
bool m_fDrawCreditSymbol;
word m_cCreditNeeders;
};
// Power Control
class PowerControl : public Control
{
public:
PowerControl() {m_fShowPowerSymbol = true; m_fPowerLow = false;};
void Update(int nDemand, int nSupply) secPowerControl;
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secPowerControl;
virtual void OnPaint(DibBitmap *pbm) secPowerControl;
private:
int m_nDemand, m_nSupply;
int m_nDemandMax;
bool m_fShowPowerSymbol;
bool m_fPowerLow;
};
// InputUIForm
class InputUIForm : public Form, public Timer
{
public:
InputUIForm(Chatter *chatter) secInputUIForm;
~InputUIForm() secInputUIForm;
void Update() secInputUIForm;
// form
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secInputUIForm;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secInputUIForm;
virtual bool EventProc(Event *pevt) secInputUIForm;
virtual void OnControlSelected(word idc) secInputUIForm;
virtual bool OnControlHeld(word idc) secInputUIForm;
// timer
virtual void OnTimer(long tCurrent) secInputUIForm;
private:
Chatter *m_pchatter;
bool m_fTimerAdded;
void InGameMenu() secInputUIForm;
void TestOptions() secInputUIForm;
};
const int kfMasSelect = 1;
const int kfMasMove = 2;
const int kfMasAttack = 4;
const int kfMasShowMenu = 8;
// SimUIForm
struct UpdateNetMessageRecord { // unmr
long msReceived;
UpdateNetMessage *punm;
UpdateNetMessageRecord *punmrNext;
};
class CommandQueue;
class MobileUnitGob;
class UnitMenu;
enum UIType { kuitFinger, kuitStylus };
const dword kfPhFinger1Down = 0x8000;
const dword kfPhFinger2Down = 0x4000;
class SimUIForm : public Form, public Timer, IGameCallback, ITransportCallback
{
public:
SimUIForm(word wfRole, dword gameid, Chatter *chatter);
virtual ~SimUIForm() secSimUIForm;
void Update() secSimUIForm;
void SendUpdateResult(int cUpdatesBlock, int cmsLatency, dword hash);
void CalcLevelSpecificConstants() secSimUIForm;
void InvalidateDragSelection() secSimUIForm;
Gob *HitTestGob(int x, int y, bool fFinger, WCoord *pwx, WCoord *pwy,
bool *pfHitSurrounding);
void MoveOrAttackOrSelect(int x, int y, dword ff) secSimUIForm;
void MoveOrAttackOrSelect(Gob *pgobHit, WCoord wxTarget, WCoord wyTarget,
dword ff);
bool HasSelectedUnits();
void ShowUnitMenu(Gob *pgob);
void SelectSameUnitTypes(Gob *pgob, bool fSfx);
bool IsSelectionCommand(Gob *pgobHit);
void ClearSelection() secSimUIForm;
void SetUIType(UIType uit);
void CheckMultiplayerGameOver(Pid pid);
void SetObserving();
word GetRole() {
return m_wfRole;
}
class PenHandler {
public:
virtual ~PenHandler() {}
virtual bool OnPenEvent(Event *pevt, bool fScrollOnly) = 0;
virtual void OnPaint(DibBitmap *pbm) = 0;
virtual void CheckScroll() = 0;
virtual dword GetFlags() = 0;
virtual void SetFlags(dword ff) = 0;
};
PenHandler *GetPenHandler() {
return m_ppenh;
}
// Form methods
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secSimUIForm;
virtual bool OnFilterEvent(Event *pevt);
virtual bool OnPenEvent(Event *pevt) secSimUIForm;
virtual void OnUpdateMapInvalidate(UpdateMap *pupd, Rect *prcOpaque) secSimUIForm;
virtual void OnPaint(DibBitmap *pbm) secSimUIForm;
virtual void OnPaintControls(DibBitmap *pbm, UpdateMap *pupd) secSimUIForm;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secSimUIForm;
virtual void ScrollInvalidate(UpdateMap *pupd) secSimUIForm;
virtual bool EventProc(Event *pevt) secSimUIForm;
virtual void FrameComplete() secSimUIForm;
virtual void OnControlSelected(word idc);
// Timer methods
virtual void OnTimer(long tCurrent) secSimUIForm;
void OnChatButtonBlink(bool fOn);
void OnPlayersButton();
private:
UpdateNetMessageRecord *m_punmrFirst;
PenHandler *m_ppenh;
dword m_gameid;
Chatter *m_pchatter;
class StylusHandler : public PenHandler {
public:
StylusHandler(SimUIForm *psui);
virtual bool OnPenEvent(Event *pevt, bool fScrollOnly);
virtual void OnPaint(DibBitmap *pbm) {}
virtual void CheckScroll();
virtual dword GetFlags() { return 0; }
virtual void SetFlags(dword ff) {}
private:
SimUIForm *m_psui;
bool m_fDragging;
void OnPenDown(Event *pevt);
void OnPenUp(Event *pevt);
void OnPenDrag(Event *pevt);
void OnPenHold(Event *pevt);
void CancelModes();
};
class FingerHandler : public PenHandler {
public:
FingerHandler(SimUIForm *psui);
~FingerHandler();
virtual bool OnPenEvent(Event *pevt, bool fScrollOnly);
virtual void OnPaint(DibBitmap *pbm);
virtual void CheckScroll();
virtual dword GetFlags() { return m_ff; }
virtual void SetFlags(dword ff) { m_ff = ff; }
private:
void OnPenDown(Event *pevt, bool fScrollOnly);
void OnPenDown2(Event *pevt, bool fScrollOnly);
void OnPenUp(Event *pevt, bool fScrollOnly);
void OnPenUp2(Event *pevt, bool fScrollOnly);
void OnPenMove(Event *pevt);
void OnPenMove2(Event *pevt);
void OnPenHold(Event *pevt);
void UnhilightGob();
void EnterNone();
void EnterHilight(Gob *pgob);
bool CheckSelect(Event *pevt);
void EnterSelect(Event *pevt);
void UpdateSelect(Event *pevt);
bool CheckDragged(Event *pevt, int wcDrag);
void EnterDrag(Event *pevt);
void UpdateDrag(Event *pevt);
void ShowUnitMenu(Gob *pgob);
void ShowUnitTitle(Gob *pgob);
void SetSelection();
bool IsQuickUp(Event *pevt);
SimUIForm *m_psui;
int m_xDownLast, m_yDownLast;
WCoord m_wxTarget, m_wyTarget;
bool m_fHitSurrounding;
Gid m_gidHitLast;
Gid m_gidHilight;
long m_tDoubleTap;
int m_xDoubleTapDownLast, m_yDoubleTapDownLast;
bool m_fTimerSet;
bool m_fShowUnitMenu;
UnitMenu *m_pfrmUnitTitle;
dword m_ff;
SelectionSprite *m_pselspr;
dword m_maskA, m_maskB;
int m_x1, m_y1;
int m_x2, m_y2;
Vec2d m_vOffsetA, m_vOffsetB;
int m_xDrag, m_yDrag;
WCoord m_wxViewDrag, m_wyViewDrag;
long m_tDown;
enum State {
FHS_NONE, FHS_HILIGHT, FHS_SELECT, FHS_DRAG
};
State m_state;
};
MobileUnitGob *SetSelectionTargets(Gid gid, WCoord wxTarget,
WCoord wyTarget) secSimUIForm;
void OnLagNotify(Pid pidLagging, int cSeconds) secSimUIForm;
void ReportLaggingPlayer(Player *pplrBehind) secSimUIForm;
void ShowKillLaggyPlayerForm(Pid pidLaggy) secSimUIForm;
void TrackLocalLag() secSimUIForm;
void QueueUpdateMessage(UpdateNetMessage *punm);
bool ProcessUpdateMessage(CommandQueue *pcmdq);
void RunUpdatesNow();
void CheckLagForm();
void OnPlayerDisconnectNotify(Pid pid, int nReason);
void OnCheckWin(Pid pid);
// IGameCallback
void OnReceiveChat(const char *player, const char *chat);
void OnNetMessage(NetMessage **ppnm);
void OnGameDisconnect();
// ITransportCallback
void OnStatusUpdate(char *pszStatus);
void OnConnectionClose();
void OnShowMessage(const char *message);
static bool s_fReadyForPaint;
bool m_fTimerAdded;
#ifdef STATS_DISPLAY
bool m_fShowStats;
#endif
word m_wfRole;
CommandQueue *m_pcmdqServer;
Form *m_pfrmWaitingForAllPlayers;
long m_tLastCommunication;
long m_tStartTimeout;
Animation m_aniMoveTarget;
WCoord m_wxMoveTarget;
WCoord m_wyMoveTarget;
int m_nStateMoveTarget;
int m_cUpdatesBlock;
long m_msUpdatesBlock;
DialogForm *m_pfrmLag;
Pid m_pidLagging;
#ifdef TRACKSTATE
void ReportSyncError();
void BeginTrackState();
void EndTrackState();
StateTracker *m_ptracker;
bool m_fSyncError;
#endif
};
// Role defaults to single player client unless these flags are specified
// It is possible to be the creator, but not the server, when connecting to a dedicated game server
const word kfRoleMultiplayer = 0x0001; // client of a multiplayer game
const word kfRoleServer = 0x0002; // server of a multiplayer game
const word kfRoleCreator = 0x0004; // creator of a multiplayer game
// Pick a level form
enum LevelType // lt
{
kltMultiplayer,
kltChallenge,
kltStory,
};
int CreateLevelList(char **asz) secGame;
class PickLevelForm : public ShellForm
{
public:
PickLevelForm(LevelType lt) secGame;
// Form overrides
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secGame;
virtual void OnControlSelected(word idc) secGame;
public:
char m_szLevel[kcbFilename];
private:
LevelType m_lt;
};
class MissionList;
class SelectMissionForm : public ShellForm
{
public:
SelectMissionForm(MissionList *pml, const MissionIdentifier *pmiidFind);
bool GetSelectedMission(MissionIdentifier *pmiid);
// Form overrides
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secGame;
virtual void OnControlSelected(word idc) secGame;
virtual void OnControlNotify(word idc, int nNotify);
virtual bool OnPenEvent(Event *pevt);
private:
MissionType InitLists(int iMissionSelect);
int IndexFromMissionType(MissionType mt);
MissionType MissionTypeFromIndex(int i);
void SwitchMissionType(MissionType mt);
int GetSelectedMissionIndex(ListControl *plstc);
bool IsSelectedMissionLocked(ListControl *plstc);
void SwitchToMissionType(MissionType mt);
void UpdateDescription();
int m_fMagicUnlock;
int m_cMagic;
MissionList *m_pml;
const MissionIdentifier *m_pmiidFind;
MissionType m_mt;
ListControl *m_aplstc[3];
};
// LoadGameForm
class LoadGameForm : public ShellForm
{
public:
LoadGameForm() secLoadSave;
void SelectLast(bool fLast) secLoadSave;
// Form overrides
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secLoadSave;
virtual void OnControlSelected(word idc) secLoadSave;
private:
int m_nGameLast;
};
class TestOptionsForm : public DialogForm
{
public:
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secGameOptionsForm;
virtual void OnControlSelected(word idc) secGameOptionsForm;
};
class MemoryUseForm : public DialogForm
{
public:
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secGameOptionsForm;
virtual void OnControlSelected(word idc) secGameOptionsForm;
private:
void UpdateLabels() secGameOptionsForm;
};
//
// Triggers, Conditions, Actions and Condition/Action parameter types
//
// Condition/Action parameter types
class QualifiedNumber
{
public:
bool Parse(char **ppsz) secTrigger;
bool Compare(long nNumber) secTrigger;
#ifdef DEBUG_HELPERS
char *ToString() {
char *pszQualifier = "???";
switch (m_nQualifier) {
case knQualifierAtLeast:
pszQualifier = "at least";
break;
case knQualifierAtMost:
pszQualifier = "at most";
break;
case knQualifierExactly:
pszQualifier = "exactly";
break;
}
sprintf(s_szDebugHelpers, "%s %d", pszQualifier, m_nNumber);
return s_szDebugHelpers;
}
static char s_szDebugHelpers[200];
#endif
int m_nQualifier;
long m_nNumber;
};
// class to run a countdown timer managed by triggers and
// shown in a SimUIForm control.
#define kfCtVisibleAtStart 1
#define kfCtRunning 2
class CountdownTimer
{
public:
CountdownTimer() secTrigger;
bool LoadState(Stream *pstm) secTrigger;
bool SaveState(Stream *pstm) secTrigger;
void SetTimer(int csecs, char *pszFormatString) secTrigger;
bool GetTimer(int *psecs) secTrigger;
void StartTimer(bool fStart) secTrigger;
void ShowTimer(bool fShow) secTrigger;
void Update() secTrigger;
word GetFlags() {
return m_wf;
}
private:
void UpdateString() secTrigger;
int m_secs;
char m_szFormat[80];
word m_wf;
long m_tLast;
};
// Conditions
class Condition // cdn
{
public:
Condition() secCondition;
virtual ~Condition() {}
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) = 0;
#ifdef DEBUG_HELPERS
virtual bool SafeIsTrue(Side side) secCondition;
virtual char *ToString() {
return "Base";
}
static char s_szDebugHelpers[300];
#endif
Condition *m_pcdnNext;
};
class MissionLoadedCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
MissionLoadedCondition() secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Mission loaded";
}
#endif
};
class CreditsCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
CreditsCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "%s has %s credits", PszFromCaSideMask(m_wfCaSideMask), m_qnum.ToString());
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMask;
QualifiedNumber m_qnum;
};
class OwnsUnitsCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
OwnsUnitsCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "%s owns %s %s", PszFromCaSideMask(m_wfCaSideMask), m_qnum.ToString(), PszFromUnitMask(m_um));
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMask;
QualifiedNumber m_qnum;
UnitMask m_um;
};
class AreaContainsUnitsCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
AreaContainsUnitsCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
word m_wfCaSideMask;
QualifiedNumber m_qnum;
UnitMask m_um;
int m_nArea;
int m_nVersionLevel;
};
class PlaceStructureModeCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
PlaceStructureModeCondition() secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "place structure mode");
return s_szDebugHelpers;
}
#endif
};
class MinerCantFindGalaxiteCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
MinerCantFindGalaxiteCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "%s's Miner can't find Galaxite", PszFromCaSideMask(m_wfCaSideMask));
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMask;
};
class GalaxiteCapacityReachedCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
GalaxiteCapacityReachedCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "%s's Galaxite capacity reached", PszFromCaSideMask(m_wfCaSideMask));
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMask;
};
class ElapsedTimeCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
ElapsedTimeCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
QualifiedNumber m_qnum;
};
class SwitchCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
SwitchCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
int m_iSwitch;
bool m_fOn;
};
class PeriodicTimerCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
PeriodicTimerCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual bool SafeIsTrue(Side side) secCondition;
virtual char *ToString();
#endif
private:
int m_iTimer;
};
class CountdownTimerCondition : public Condition
{
public:
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "Coundown Timer is %s", m_qnum.ToString());
return s_szDebugHelpers;
}
#endif
private:
QualifiedNumber m_qnum;
};
class DiscoversSideCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
DiscoversSideCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
char szSideA[100];
strcpy(szSideA, PszFromCaSideMask(m_wfCaSideMaskA));
sprintf(s_szDebugHelpers, "%s discovers %s", szSideA, PszFromCaSideMask(m_wfCaSideMaskB));
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMaskA;
word m_wfCaSideMaskB;
};
class TestPvarCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
TestPvarCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "Pvar \"%s\": is %s", m_szName, m_qnum.ToString());
return s_szDebugHelpers;
}
#endif
private:
char m_szName[kcbPvarNameMax];
QualifiedNumber m_qnum;
};
class HasUpgradesCondition : public Condition
{
public:
// REMOVE_SOMEDAY: keep m68k-gcc from generating default constructor in .text section
HasUpgradesCondition() secCondition;
virtual bool Init(char *psz) secCondition;
virtual bool IsTrue(Side side) secCondition;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
sprintf(s_szDebugHelpers, "%s has ??? upgrades", PszFromCaSideMask(m_wfCaSideMask));
return s_szDebugHelpers;
}
#endif
private:
word m_wfCaSideMask;
UpgradeMask m_upgm;
};
// Actions
class TriggerAction // actn
{
public:
TriggerAction() secAction;
virtual ~TriggerAction() secAction;
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) = 0;
TriggerAction *m_pactnNext;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Action";
}
static char s_szDebugHelpers[200];
#endif
};
class PreserveTriggerAction : public TriggerAction
{
public:
virtual bool Perform(Trigger *ptgr, Side side) secAction;
};
class WaitAction : public TriggerAction
{
public:
WaitAction() secAction;
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
dword m_ctWait;
dword m_atStartSide[kcSides];
bool m_afWaitingSide[kcSides];
};
class CenterViewAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Center view";
}
#endif
private:
int m_nArea;
};
class SetNextMissionAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set next mission";
}
#endif
private:
char m_szLevel[kcbFilename];
};
class EndMissionAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "End mission";
}
#endif
static void OnMPEndMissionActionEvent(int nWinLose, Side side);
private:
int m_nWinLose;
};
class EcomAction : public TriggerAction
{
public:
virtual ~EcomAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Ecom";
}
#endif
private:
int m_nBackground;
bool m_fMore;
int m_nCharFrom;
int m_nCharTo;
char *m_pszMessage;
};
class SetAllowedUnitsAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set allowed units";
}
#endif
private:
word m_wfCaSideMask;
UnitMask m_um;
};
class SetAllowedUpgradesAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set allowed upgrades";
}
#endif
private:
word m_wfCaSideMask;
UpgradeMask m_upgm;
};
class SetUpgradesAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set upgrades";
}
#endif
private:
word m_wfCaSideMask;
UpgradeMask m_upgm;
};
class AlliesAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Allies";
}
#endif
private:
word m_wfCaSideMaskA;
word m_wfCaSideMaskB;
};
class SetObjectiveAction : public TriggerAction
{
public:
SetObjectiveAction() secAction;
virtual ~SetObjectiveAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set objective";
}
#endif
private:
word m_wfCaSideMask;
char *m_szObjective;
};
class SetSwitchAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set switch";
}
#endif
private:
int m_iSwitch;
bool m_fOn;
};
class DefogAreaAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Defog area";
}
#endif
private:
int m_nArea;
};
// This is the "CreateUnitGroup-Action", not "Create-UnitGroupAction"
class CreateUnitGroupAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Create unit group";
}
#endif
private:
int m_nUnitGroup;
};
class HuntAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Hunt";
}
#endif
private:
word m_wfCaSideMask1;
UnitMask m_um1;
word m_wfCaSideMask2;
UnitMask m_um2;
};
// This is the "CreateRandomUnitGroup-Action", not "Create-RandomUnitGroupAction"
class CreateRandomUnitGroupAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Create random unit group";
}
#endif
};
// Start Countdown Action
class StartCountdownAction : public TriggerAction
{
public:
StartCountdownAction() secAction;
virtual ~StartCountdownAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
private:
int m_nSecs;
char *m_szCountdown;
};
// Modify countdown action
class ModifyCountdownAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
int m_nAction;
};
class RepairAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Repair";
}
#endif
private:
word m_wfCaSideMask;
bool m_fOn;
};
class EnableReplicatorAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Enable Replicator";
}
#endif
private:
word m_wfCaSideMask;
bool m_fOn;
};
// Modify Credits action
class ModifyCreditsAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
word m_wfCaSideMask;
int m_nAmount;
int m_nAction;
};
// Move Units In Area action
class MoveUnitsInAreaAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "MoveUnitsInArea";
}
#endif
private:
word m_wfCaSideMask;
UnitMask m_um;
int m_nAreaSrc;
int m_nAreaDst;
};
// Set Formal Objective Text action
const int kcchObjectiveMax = 80;
const int kcchObjectiveStatusMax = 15;
const int kcchObjectiveInfoMax = 350;
class SetFormalObjectiveTextAction : public TriggerAction
{
public:
SetFormalObjectiveTextAction() secAction;
virtual ~SetFormalObjectiveTextAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "SetFormalObjectiveText";
}
#endif
private:
int m_iObjective;
char *m_szObjective;;
};
// Set Formal Objective Status action
class SetFormalObjectiveStatusAction : public TriggerAction
{
public:
SetFormalObjectiveStatusAction() secAction;
~SetFormalObjectiveStatusAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "SetFormalObjectiveStatus";
}
#endif
private:
int m_iObjective;
char *m_szStatus;
};
// Set Formal Objective Info action
class SetFormalObjectiveInfoAction : public TriggerAction
{
public:
SetFormalObjectiveInfoAction() secAction;
virtual ~SetFormalObjectiveInfoAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "SetFormalObjectiveInfo";
}
#endif
private:
char *m_szInfo;
};
// Show Objectives action
class ShowObjectivesAction : public TriggerAction
{
public:
virtual bool Perform(Trigger *ptgr, Side side) secAction;
static void OnMPShowObjectivesEvent(Side side);
};
// Show Cut Scene action
class CutSceneAction : public TriggerAction
{
public:
CutSceneAction() secAction;
virtual ~CutSceneAction() secAction;
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Cut scene";
}
#endif
private:
char *m_pszMessage;
};
// Jump To Mission action
class JumpToMissionAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Jump to mission";
}
#endif
private:
char m_szLevel[kcbFilename];
};
// For the moment, only actions can "block".
// Per-side context is stored in the actions that need it for blocking.
class Trigger
{
public:
Trigger() secTrigger;
~Trigger() secTrigger;
bool LoadState(Stream *pstm) secTrigger;
bool SaveState(Stream *pstm) secTrigger;
bool Init(IniReader *pini, FindProp *pfind) secTrigger;
void Execute(Side side, bool fForce = false) secTrigger;
void Arm(Side side) secTrigger;
void SetCurrentActionComplete(Side side) secTrigger;
private:
bool LoadCondition(IniReader *pini, FindProp *pfind) secCondition;
bool LoadAction(IniReader *pini, FindProp *pfind) secAction;
Condition *m_pcdn;
TriggerAction *m_pactn;
TriggerAction *m_apactnLast[kcSides];
bool m_afArmed[kcSides];
#ifdef DEBUG_HELPERS
friend class TriggerViewer;
#endif
};
// Modify Persistent Variable action
class ModifyPvarAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
char m_szName[kcbPvarNameMax];
int m_nAmount;
int m_nAction;
};
// Set Persistent Variable Text action
class SetPvarTextAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set Pvar Text";
}
#endif
private:
char m_szName[kcbPvarNameMax];
char m_szValue[kcbPvarValueMax];
};
// ShowAlert action
class ShowAlertAction : public TriggerAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(Trigger *ptgr, Side side) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Show Alert";
}
#endif
private:
char m_szAlert[80];
};
#define kcTriggersPerSide 128
#define kcSwitchMax 16
#define kcTriggerTimersMax 16
#define kctTimerNotStarted -100000
class TriggerMgr // tgrm
{
public:
TriggerMgr() secTrigger;
~TriggerMgr() secTrigger;
bool LoadState(Stream *pstm) secTrigger;
bool SaveState(Stream *pstm) secTrigger;
bool Init(IniReader *pini) secTrigger;
void Exit() secTrigger;
void Update() secTrigger;
void SetConditionTrue(int nCondition, SideMask sidm) secTrigger;
bool IsConditionTrue(int nCondition, SideMask sidm) secTrigger;
CountdownTimer *GetCountdownTimer() {
return &m_cdt;
}
void SetSwitch(int iSwitch, bool fOn) {
m_abSwitch[iSwitch] = (byte)fOn;
}
bool GetSwitch(int iSwitch) {
return m_abSwitch[iSwitch] != 0;
}
int AddPeriodicTimer(int ctPeriod) {
Assert(m_cTimers < kcTriggerTimersMax);
m_actPeriod[m_cTimers] = ctPeriod;
m_actCountdown[m_cTimers] = kctTimerNotStarted;
return m_cTimers++;
}
// Periodic timers only start counting the first time they are tested.
// This way they can sit 'below' other conditions and have deterministic
// firing times.
void StartPeriodicTimer(int iTimer) {
if (m_actCountdown[iTimer] == kctTimerNotStarted)
m_actCountdown[iTimer] = m_actPeriod[iTimer];
}
bool IsPeriodicTimerTriggered(int iTimer) {
return m_actCountdown[iTimer] <= 0;
}
#ifdef DEBUG_HELPERS
long GetTimerCountdown(int iTimer) {
return m_actCountdown[iTimer];
}
long GetTimerPeriod(int iTimer) {
return m_actPeriod[iTimer];
}
char *GetSwitchName(int iSwitch) {
return m_aszSwitchNames[iSwitch];
}
#endif
void Enable(bool fEnable) {
m_fEnabled = fEnable;
}
private:
bool AssignTriggerSides(int ntgr, char *psz) secTrigger;
int m_ctgr;
Trigger *m_atgr;
byte m_mpSide2nTrigger[kcSides][kcTriggersPerSide];
SideMask m_asidmCondition[knConditionMax];
byte m_abSwitch[kcSwitchMax];
int m_cTimers;
int m_actPeriod[kcTriggerTimersMax];
int m_actCountdown[kcTriggerTimersMax];
long m_tLastUpdate;
bool m_fEnabled;
CountdownTimer m_cdt;
#ifdef DEBUG_HELPERS
char m_aszSwitchNames[kcSwitchMax][50];
friend TriggerViewer;
#endif
};
// UnitGroup
// - directs the process of building all the Units in the group
// - needs to know when Units under its direction complete commands given to them (or deactivate)
// - loads Unit list and UnitGroupActions (called by UnitGroupMgr at Level load time)
// - loads/saves itself
const byte kfUleBuilt = 0x01;
const byte kfUleReplicant = 0x02;
struct UnitListEntry {
UnitType ut;
Gid gid;
byte bf;
};
class UnitGroupAction; // forward declaration
class UnitGroup
{
public:
UnitGroup() secUnitGroup;
~UnitGroup() secUnitGroup;
bool LoadState(Stream *pstm) secUnitGroup;
bool SaveState(Stream *pstm) secUnitGroup;
bool Init(IniReader *pini, int iug) secUnitGroup;
void Activate() secUnitGroup;
void Update() secUnitGroup;
void OnBuilt(UnitGob *punt) secUnitGroup;
void AddUnit(UnitGob *punt, bool fReplicant) secUnitGroup;
void RemoveReplicants() secUnitGroup;
word GetFlags() {
return m_wf;
}
void SetFlags(word wf) {
m_wf = wf;
}
Player *GetOwner() {
return m_pplr;
}
UnitListEntry *GetUnitList() {
return m_aule;
}
int GetUnitCount() {
return m_cule;
}
#ifdef DEBUG
char *GetName() {
return m_szName;
}
#endif
private:
bool LoadAction(IniReader *pini, FindProp *pfind) secUnitGroup;
word m_wf;
UnitGroupAction *m_pactn;
UnitGroupAction *m_pactnLast;
Player *m_pplr;
int m_cule;
UnitListEntry *m_aule;
word m_wfMunt; // flags for built MobileUnits
int m_nSpawnArea;
int m_nHealth; // percent
#ifdef DEBUG
char m_szName[64];
#endif
#ifdef DEBUG_HELPERS
friend class UnitGroupViewer;
#endif
};
const word kfUgNeedsUnit = 0x0001;
const word kfUgActive = 0x0002;
const word kfUgLoopForever = 0x0004;
const word kfUgCreateAtLevelLoad = 0x0008;
const word kfUgRandomGroup = 0x0010;
const word kfUgReplaceGroup = 0x0020;
const word kfUgSpawn = 0x0040;
const word kfUgWaitingToReplace = 0x0080;
const word kfUgActivatedBefore = 0x0100;
const word kfUgNotRecentlyActivated = 0x0200;
// UnitGroupMgr
// - Updates the active UnitGroups
// - deactivates groups when the contained units are all deactivated
// - loads group data from Level file
// - loads/saves itself and UnitGroups
class UnitGroupMgr // tgrm
{
public:
UnitGroupMgr() secUnitGroup;
~UnitGroupMgr() secUnitGroup;
bool LoadState(Stream *pstm) secUnitGroup;
bool SaveState(Stream *pstm) secUnitGroup;
bool Init(IniReader *pini) secUnitGroup;
void Exit() secUnitGroup;
void Update() secUnitGroup;
void ActivateUnitGroup(int iug) secUnitGroup;
void ActivateRandomUnitGroup() secUnitGroup;
bool CreateAtLevelLoadGroups() secUnitGroup;
UnitGroup *GetUnitGroup(Gid gid) secUnitGroup;
private:
int m_cug;
UnitGroup *m_aug;
#ifdef DEBUG_HELPERS
friend class UnitGroupViewer;
#endif
};
// UnitGroup Actions
class UnitGroupAction
{
public:
UnitGroupAction() secAction;
virtual ~UnitGroupAction() {}
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) = 0;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) = 0;
UnitGroupAction *m_pactnNext;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "UnitGroupAction";
}
static char s_szDebugHelpers[200];
#endif
};
class WaitUnitGroupAction : public UnitGroupAction
{
public:
WaitUnitGroupAction() secAction;
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
dword m_ctWait;
long m_tStart;
bool m_fWaiting;
};
class SetSwitchUnitGroupAction : public UnitGroupAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Set switch";
}
#endif
private:
int m_iSwitch;
bool m_fOn;
};
class MoveUnitGroupAction : public UnitGroupAction
{
public:
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
bool m_fWaiting;
int m_nArea;
};
class AttackUnitGroupAction : public UnitGroupAction
{
public:
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString();
#endif
private:
// These are initialized from the loaded level
UnitMask m_um;
word m_wfCaSideMask;
dword m_ctWait;
// These are persisted in the save game
bool m_fWaiting;
long m_tStart;
Gid m_gidTarget;
};
class GuardUnitGroupAction : public UnitGroupAction
{
public:
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Guard";
}
#endif
private:
// These are initialized from the loaded level
dword m_ctWait;
// These are persisted in the save game
bool m_fWaiting;
long m_tStart;
};
class MineUnitGroupAction : public UnitGroupAction
{
public:
virtual bool Init(char *psz) secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Mine";
}
#endif
};
class GuardVicinityUnitGroupAction : public UnitGroupAction
{
public:
virtual bool LoadState(Stream *pstm) secAction;
virtual bool SaveState(Stream *pstm) secAction;
virtual bool Init(char *psz) secAction;
virtual void Reset() secAction;
virtual bool Perform(UnitGroup *pug) secAction;
#ifdef DEBUG_HELPERS
virtual char *ToString() {
return "Guard vicinity";
}
#endif
private:
// These are initialized from the loaded level
dword m_ctWait;
// These are persisted in the save game
bool m_fWaiting;
long m_tStart;
};
// BuildMgr
// - directs BuilderGobs to build desired Units
// - keeps track of which BuilderGobs are building which Units for which UnitGroups
// - is notified when a BuilderGob completes a build (and what Unit was
// completed and for which UnitGroup)
struct BuildEntry {
BuildEntry *pbldeNext;
UnitType ut;
int nArea;
UnitGroup *pug;
Gid gidBuilder;
};
class BuildMgr
{
public:
BuildMgr() secBuildMgr;
~BuildMgr() secBuildMgr;
bool BuildUnit(UnitType ut, UnitGroup *pug, int nArea) secBuildMgr;
void OnBuilt(UnitGob *punt, BuilderGob *pbldr) secBuildMgr;
void Update() secBuildMgr;
private:
BuildEntry *m_pbldeFirst;
};
// Simulation
// Use min gob count for 68K build because of stack variables
#ifdef __CPU_68K
#define kcpgobMax 512
#else
#define kcpgobMax 768
#endif
#define kcpgobVisibleMax 200
class Simulation : public TimerMgr // sim
{
public:
Simulation() secSimulation;
~Simulation() secSimulation;
bool OneTimeInit() secSimulation;
void OneTimeExit() secSimulation;
bool PerLevelInit() secSimulation;
void PerLevelExit() secSimulation;
bool LoadLevel(const char *pszLevelName) secSimulation;
bool LoadState(Stream *pstm) secSimulation;
bool SaveState(Stream *pstm) secSimulation;
void ClearGobSelection() secSimulation;
void SetGobSelected(Gob *pgob) secSimulation;
void SelectSameUnitTypes(UnitGob *punt, TRect *ptrc) secSimulation;
Level *GetLevel() {
return m_plvl;
}
int GetUpdateCount() {
return m_cUpdates;
}
void SetMiniMapScale(int nScale) {
m_nMiniMapScale = nScale;
}
int GetMiniMapScale() {
return m_nMiniMapScale;
}
BuildMgr *GetBuildMgr() {
return m_pbldm;
}
void Update(CommandQueue *pcmdq) secSimulation;
void Draw(UpdateMap *pupd, DibBitmap *pbm) secSimulation;
void DrawBackground(UpdateMap *pupd, DibBitmap *pbm) secSimulation;
void DrawFog(UpdateMap *pupd, DibBitmap *pbm) secSimulation;
bool SetViewPos(WCoord wx, WCoord wy, bool fInit = false) secSimulation;
void GetViewPos(WCoord *pwx, WCoord *pwy) secSimulation;
bool HitTest(Enum *penm, WCoord wx, WCoord wy, word wf, Gob **ppgob) secSimulation;
Gob *FingerHitTest(WCoord wx, WCoord wy, word wf, bool *pfHitSurrounding) secSimulation;
void Pause(bool fPause) secSimulation;
bool IsPaused() secSimulation;
void FindVisibleGobs(Gob ***pppgobVisible = NULL, int *pcgobVisible = NULL) secSimulation;
void SetSelection(Rect *prc) secSimulation;
// TimerMgr override
virtual long GetTickCount() secSimulation;
virtual void AddTimer(Timer *ptmr, long ct) secSimulation; //stub
#ifdef TRACKSTATE
void TrackState(StateFrame *frame);
#endif
private:
void HandlePlayerDisconnect(Message *pmsg);
Level *m_plvl;
WCoord m_wxView, m_wyView;
bool m_fGameOver;
int m_cUpdates; // Can count 80 ms updates for 5+ years without wrapping
long m_tCurrent;
bool m_fPaused;
int m_nMiniMapScale;
BuildMgr *m_pbldm;
Gob *m_apgobVisible[kcpgobVisibleMax];
int m_cgobVisible;
WCoord m_wxViewSave;
WCoord m_wyViewSave;
int m_cUpdatesSave;
int m_cupdTriggerMgrUpdateLast;
};
extern Simulation gsim;
// Minimap coord from World coord
inline int MmcFromWc(WCoord wc) {
return ((wc + 0x007f) & 0xff80) >> (9 - gsim.GetMiniMapScale()); // == 7 for hires, 8 for lores
}
// Level
// NOTE: changing the sizes any of the 'int's used in the types and
// member variables below will break .ini and .lvl file reading which
// uses the '%d' feature of IniScanf which always stores parsed numbers
// as 'int's.
struct SideInfo // sidi
{
int nInitialCredits;
WPoint wptInitialView;
int nIntelligence;
int cStructuresInitial;
int cMobileUnitsInitial;
};
class Level // lvl
{
public:
Level() secLevel;
~Level() secLevel;
bool Init(const char *pszLevelName, bool fConstantsOnly = false) secLevel;
bool LoadState(Stream *pstm) secLevel;
bool SaveState(Stream *pstm) secLevel;
bool LoadLevelInfo(const char *pszLevelName, IniReader *piniLoaded = NULL) secLevel;
TileMap *GetTileMap() {
return m_ptmap;
}
Palette *GetPalette() {
return m_ppal;
}
byte *GetShadowMap() {
return m_mpiclriclrShadow;
}
FogMap *GetFogMap() {
return m_pfogm;
}
TerrainMap *GetTerrainMap() {
return m_ptrmap;
}
int GetMinPlayers() {
return m_nPlayersMin;
}
int GetMaxPlayers() {
return m_nPlayersMax;
}
const char *GetTitle() {
return m_szTitle;
}
SideInfo *GetSideInfo(Side side) {
return &m_asidi[side];
}
TriggerMgr *GetTriggerMgr() {
return &m_tgrm;
}
UnitGroupMgr *GetUnitGroupMgr() {
return &m_ugm;
}
char *GetFilename() {
return m_szFileLevel;
}
// This version is the "level file format" version
int GetVersion() {
return m_nVersion;
}
// This is the per-save unique revision number
dword GetRevision() {
return m_dwRevision;
}
private:
bool LoadSideInfo(IniReader *pini, char *pszSideName, SideInfo *psidi) secLevel;
bool LoadLevelConstants(const char *pszLevelName, IniReader *pini) secLevel;
bool LoadLevelVariables(IniReader *pini) secLevel;
private:
char m_szTitle[kcbLevelTitle];
char m_szFileLevel[kcbFilename];
int m_nPlayersMin, m_nPlayersMax;
TileMap *m_ptmap;
Palette *m_ppal;
FileMap m_fmapPalette;
byte *m_mpiclriclrShadow;
FileMap m_fmapShadowMap;
FogMap *m_pfogm;
TerrainMap *m_ptrmap;
bool m_fInitialized;
SideInfo m_asidi[5];
TriggerMgr m_tgrm;
UnitGroupMgr m_ugm;
// This is the "level format" version. This is versioned upward over time and is here so
// that WI knows what format the level was saved in.
int m_nVersion;
// This is the revision # of the level. So saved games with older revision numbers
// aren't loaded. Note this isn't an incrementing version number. It is a unique
// mark that every mission has.
dword m_dwRevision;
};
// Structure/Unit type values and masks
const UnitMask kumShortRangeInfantry = 1L << kutShortRangeInfantry;
const UnitMask kumLongRangeInfantry = 1L << kutLongRangeInfantry;
const UnitMask kumTakeoverSpecialist = 1L << kutTakeoverSpecialist;
const UnitMask kumAndy = 1L << kutAndy;
const UnitMask kumFox = 1L << kutFox;
const UnitMask kumInfantry = kumShortRangeInfantry | kumLongRangeInfantry | kumTakeoverSpecialist | kumAndy | kumFox;
const UnitMask kumGalaxMiner = 1L << kutGalaxMiner;
const UnitMask kumLightTank = 1L << kutLightTank;
const UnitMask kumMediumTank = 1L << kutMediumTank;
const UnitMask kumMachineGunVehicle = 1L << kutMachineGunVehicle;
const UnitMask kumRocketVehicle = 1L << kutRocketVehicle;
const UnitMask kumMobileHeadquarters = 1L << kutMobileHeadquarters;
const UnitMask kumArtillery = 1L << kutArtillery;
const UnitMask kumVehicles = kumGalaxMiner | kumLightTank | kumMediumTank | kumMachineGunVehicle |
kumRocketVehicle | kumMobileHeadquarters | kumArtillery;
const UnitMask kumMobileUnits = kumInfantry | kumVehicles;
const UnitMask kumHumanResourceCenter = 1L << kutHumanResourceCenter;
const UnitMask kumReactor = 1L << kutReactor;
const UnitMask kumProcessor = 1L << kutProcessor;
const UnitMask kumHeadquarters = 1L << kutHeadquarters;
const UnitMask kumResearchCenter = 1L << kutResearchCenter;
const UnitMask kumVehicleTransportStation = 1L << kutVehicleTransportStation;
const UnitMask kumRadar = 1L << kutRadar;
const UnitMask kumWarehouse = 1L << kutWarehouse;
const UnitMask kumReplicator = 1L << kutReplicator;
const UnitMask kumMachineGunTower = 1L << kutMachineGunTower;
const UnitMask kumRocketTower = 1L << kutRocketTower;
const UnitMask kumTowers = kumMachineGunTower | kumRocketTower;
const UnitMask kumStructures = kumHumanResourceCenter | kumReactor | kumProcessor | kumHeadquarters |
kumResearchCenter | kumVehicleTransportStation | kumRadar | kumWarehouse | kumMachineGunTower |
kumRocketTower | kumReplicator;
// NOTE: we don't count the Replicator as a Builder so the BuildMgr won't start using it
const UnitMask kumBuilder = kumHeadquarters | kumVehicleTransportStation | kumHumanResourceCenter;
const UnitMask kumAll = kumInfantry | kumVehicles | kumStructures;
const UnitMask kumImpossible = 0xffffffff;
// Upgrade type values and masks (values to be moved to res.h most likely)
struct Upgrade { // upg
UpgradeMask upgm;
char szName[50];
char szIconName[20];
UpgradeMask upgmPrerequisites;
UnitMask umPrerequisites;
int nCost;
int ctTimeToBuild;
char *szDescription;
char *szPrerequisites;
};
#define kupgtAdvancedHRC 0
#define kupgtAdvancedVTS 1
#define kupgtIncreasedBullpupSpeed 2
#define kupgtMax 2
const UpgradeMask kupgmAdvancedHRC = 1 << kupgtAdvancedHRC;
const UpgradeMask kupgmAdvancedVTS = 1 << kupgtAdvancedVTS;
const UpgradeMask kupgmIncreasedBullpupSpeed = 1 << kupgtIncreasedBullpupSpeed;
const UpgradeMask kupgmAll = kupgmAdvancedHRC | kupgmAdvancedVTS | kupgmIncreasedBullpupSpeed;
// Player-related types
class PlayerMgr;
// UNDONE: pull these from game.ini?
const long knWarehouseCapacity = 5000;
const long knProcessorCapacity = 3000;
// Who is using credits during a given update? Useful for sound effects
#define knConsumerGeneric 0
#define knConsumerRepair 1
#define knConsumerMax 1
const int kcFormalObjectivesMax = 4;
const int ksoObjectives = 1;
const int ksoWinSummary = 2;
const int ksoLoseSummary = 3;
class Player // plr
{
friend class PlayerMgr;
public:
Player() secPlayer;
~Player() secPlayer;
void Init(Pid pid) secPlayer;
bool LoadState(Stream *pstm) secPlayer;
bool SaveState(Stream *pstm) secPlayer;
void SetName(const char *pszName) secPlayer;
UnitMask GetUnitMask() secPlayer;
void SetCredits(int nCredits, bool fAffectTotals, int nConsumer = knConsumerGeneric) secPlayer;
int GetCreditsDirection() secPlayer;
int GetCreditsConsumer() secPlayer;
void AddPowerSupplyAndDemand(int nPowerSupply, int nPowerDemand) secPlayer;
void Repair(bool fOn) secPlayer;
void Update(int cUpdates) secPlayer;
void SetFormalObjectiveText(int iObjective, char *pszText) secPlayer;
void SetFormalObjectiveStatus(int iObjective, char *pszStatus) secPlayer;
void SetFormalObjectiveInfo(char *pszInfo) secPlayer;
int ShowObjectives(int so, bool fForceInfoDisplay = false, bool fAborting = false) secObjectives;
void ModifyNeedCreditsCount(int cDelta)secPlayer;
bool IsBehind(int cUpdates) secPlayer;
void SetLeftGame() {
m_fLeftGame = true;
}
bool GetLeftGame() {
return m_fLeftGame;
}
char *GetFormalObjectiveText(int iObjective) {
return m_aszFormalObjectiveText[iObjective];
}
char *GetFormalObjectiveStatus(int iObjective) {
return m_aszFormalObjectiveStatus[iObjective];
}
char *GetFormalObjectiveInfo() {
return m_szFormalObjectiveInfo;
}
const char *GetName() {
return m_szName;
}
word GetFlags() {
return m_wf;
}
void SetFlags(word wf) {
m_wf = wf;
}
Pid GetId() {
return m_pid;
}
Side GetSide() {
return m_side;
}
void SetSide(Side side) {
m_side = side;
m_sidmAllies = GetSideMask(m_side);
m_sidmDiscovered = GetSideMask(m_side);
}
SideMask GetAllies() {
return m_sidmAllies;
}
void SetAllies(SideMask sidm) {
m_sidmAllies = sidm | GetSideMask(m_side);
}
SideMask GetDiscoveredSides() {
return m_sidmDiscovered;
}
void SetDiscoveredSides(SideMask sidm) {
m_sidmDiscovered = sidm;
}
void SetDiscoverPoint(TPoint *ptpt) {
m_tptDiscover = *ptpt;
}
TPoint GetDiscoverPoint() {
return m_tptDiscover;
}
int GetCredits() {
return m_nCredits;
}
word GetNeedCreditsCount() {
return m_cStructsNeedCredits;
}
int GetCapacity() {
return (m_acut[kutWarehouse] * knWarehouseCapacity) + (m_acut[kutProcessor] * knProcessorCapacity);
}
int GetPowerSupply() {
return m_nPowerSupply;
}
int GetPowerDemand() {
return m_nPowerDemand;
}
bool IsPowerLow() {
return m_nPowerDemand > m_nPowerSupply;
}
void IncUnitCount(UnitType ut) {
m_acut[ut]++;
}
void DecUnitCount(UnitType ut) {
Assert(m_acut[ut] != 0);
m_acut[ut]--;
}
int GetUnitCount(UnitType ut) {
return m_acut[ut];
}
void IncUnitBuiltCount(UnitType ut) {
m_acutBuilt[ut]++;
}
void DecUnitBuiltCount(UnitType ut) {
m_acutBuilt[ut]--;
if (m_acutBuilt[ut] < 0) {
m_acutBuilt[ut] = 0;
}
}
int GetUnitActiveCountFromMask(UnitMask um) secPlayer;
int GetUnitInstanceCountFromMask(UnitMask um) secPlayer;
word GetUpgrades() {
return m_wfUpgrades;
}
void SetUpgrades(word wfUpgrades) secPlayer;
UnitMask GetAllowedUnits() {
return m_umAllowed;
}
void SetAllowedUnits(UnitMask um) {
m_umAllowed = um;
}
void SetObjective(char *psz) secSimulation;
char *GetObjective() {
return m_szObjective;
}
UpgradeMask GetUpgradeMask() {
return m_upgm;
}
void SetUpgradeMask(UpgradeMask upgm) {
m_upgm = upgm;
}
UpgradeMask GetAllowedUpgrades() {
return m_upgmAllowed;
}
void SetAllowedUpgrades(UpgradeMask um) {
m_upgmAllowed = um;
}
void IncEnemyMobileUnitsKilled() {
m_cmuntKilled++;
}
int GetEnemyMobileUnitsKilled() {
return m_cmuntKilled;
}
void IncEnemyStructuresKilled() {
m_cstruKilled++;
}
int GetEnemyStructuresKilled() {
return m_cstruKilled;
}
void IncMobileUnitsLost() {
m_cmuntLost++;
}
int GetMobileUnitsLost() {
return m_cmuntLost;
}
void IncStructuresLost() {
m_cstruLost++;
}
int GetStructuresLost() {
return m_cstruLost;
}
int GetTotalCreditsAcquired() {
return m_nTotalCreditsAcquired;
}
void ModifyTotalCreditsConsumed(int nAmount) {
m_nTotalCreditsConsumed += nAmount;
}
int GetTotalCreditsConsumed() {
return m_nTotalCreditsConsumed;
}
word GetHandicap() {
return m_wfHandicap;
}
void SetHandicap(word wf) {
m_wfHandicap = wf;
}
// Only valid for server-side Player proxies
long GetUpdateCount() {
return m_cUpdates;
}
void SetUpdateCount(int cUpdates) {
m_cUpdates = cUpdates;
}
bool IsLagging(long cUpdates) secPlayer;
int GetLagState() secPlayer;
void SetLagState(int nLagState) secPlayer;
int GetLagTimeout() secPlayer;
#ifdef TRACKSTATE
void TrackState(StateFrame *frame);
#endif
private:
word m_wfUpgrades;
Side m_side;
SideMask m_sidmAllies;
SideMask m_sidmDiscovered;
TPoint m_tptDiscover;
char m_szName[kcbPlayerName];
word m_wf;
Pid m_pid;
int m_nCredits;
int m_nCreditsAcquired, m_nCreditsConsumed;
int m_nDirCredits;
int m_nConsumerCredits;
int m_nPowerSupply;
int m_nPowerDemand;
int m_acut[kutMax];
int m_acutBuilt[kutMax];
UnitMask m_umAllowed;
char m_szObjective[kcchObjectiveMax];
UpgradeMask m_upgm;
UpgradeMask m_upgmAllowed;
char *m_aszFormalObjectiveText[kcFormalObjectivesMax];
char *m_aszFormalObjectiveStatus[kcFormalObjectivesMax];
char *m_szFormalObjectiveInfo;
int m_cmuntKilled;
int m_cstruKilled;
int m_cmuntLost;
int m_cstruLost;
int m_nTotalCreditsAcquired;
int m_nTotalCreditsConsumed;
int m_cUpdatesRepairLast;
word m_cStructsNeedCredits;
word m_wfHandicap;
int m_cUpdates; // only valid for server-side Player proxies
int m_nLagState;
long m_tLagStart;
long m_tLastLag;
bool m_fLeftGame;
#ifdef DETECT_SYNC_ERRORS
public:
UpdateResult m_ur;
#endif
};
class PlayersUpdateNetMessage;
class PlayerMgr // plrm
{
public:
PlayerMgr() secPlayer;
~PlayerMgr() secPlayer;
void Reset() secPlayer;
void Init(PlayersUpdateNetMessage *ppunm) secPlayer;
bool Init(char *pszLevel) secPlayer;
bool LoadState(Stream *pstm) secPlayer;
bool SaveState(Stream *pstm) secPlayer;
Player *AllocPlayer(word wf = 0) secPlayer;
void Update(int cUpdates) secPlayer;
void SetAllies(Player **applr, int cplrs, SideMask sidmAllies) secPlayer;
void FreePlayer(Player *pplr) {
pplr->m_wf = 0;
}
Player *GetPlayer(Side side) secPlayer;
Player *GetPlayerFromPid(Pid pid) {
// Pid is unsigned
if (pid != kpidNeutral && pid < kcPlayersMax) {
return &m_aplr[((int)pid)];
}
return NULL;
}
Player* GetNextPlayer(Player *pplr) secPlayer;
Player* GetNextHumanPlayer(Player *pplr) secPlayer;
Player* GetNextObservingPlayer(Player *pplr) secPlayer;
const char *GetCreatorName();
int GetPlayerCount() secPlayer;
bool DetectTransitionToSingleHumanTeam(Pid pidLeft) secPlayer;
int GetUnitInstanceCountFromMask(UnitMask um, word wfPlr) secPlayer;
void SendWinStats();
#ifdef TRACKSTATE
void TrackState(StateFrame *frame);
#endif
protected:
int GetHumanTeamCount(bool fExtra, Pid pidExtra);
Player *m_aplr;
};
// Gob
#define kfGobNoEnemiesNearby 0x00000001 // No enemies nearby so don't waste time looking
#define kfGobRedraw 0x00000002 // Something has changed that requires this gob to redraw
//#define kfGobInvalidated 0x00000004 // Gob has been invalidated
#define kfGobBeingUpgraded 0x00000008 // Gob is being upgraded
#define kfGobBeingBuilt 0x00000010 // Gob is in the process of being built, not yet ready for active duty
//#define kfGobOccupyingTerrain 0x00000020
#define kfGobFlashing 0x00000040 // Gob is flashing
#define kfGobDrawFlashed 0x00000080 // Gob will be drawn flashing
//#define kfGobRepairing 0x00000100 // unused
#define kfGobActive 0x00000200 // Gob is alive and doing its thing
#define kfGobStructure 0x00000400 // Gob is a fixed structure
#define kfGobMobileUnit 0x00000800 // Gob is a mobile unit
#define kfGobUnit 0x00001000 // Gob is a Unit (our version of RTTI!)
#define kfGobDebug 0x00002000 // Gobs DebugBreak at strategic points when this is enabled
#define kfGobSelected 0x00004000 // Gob is selected
#define kfGobStateMachine 0x00008000 // Gob has an active StateMachine that may want Update messages
#define kfGobVisibleLastFrame 0x00010000 // Gob was visible last frame
#define kfGobIncludeFindVisible 0x00020000 // Include gob in next FindVisibleGobs search
#define kfGobTransitioningToVisible 0x00040000 // Gob is going from non-visible to visible
#define kfGobAnimationChanged 0x00080000 // UpdateCount must not affect next AdvanceAnimation
#define kfGobLayerSurfaceDecal 0x00100000
#define kfGobLayerDepthSorted 0x00200000
#define kfGobLayerSmokeFire 0x00400000
#define kfGobLayerSymbols 0x00800000 // Repairing and need-power symbols draw on this layer
#define kfGobLayerSelection 0x01000000
#define kfGobLayerMask (kfGobLayerSurfaceDecal | kfGobLayerDepthSorted | kfGobLayerSmokeFire | kfGobLayerSymbols | kfGobLayerSelection)
// Layers
#define knLayerSurfaceDecal 0
#define knLayerDepthSorted 1
#define knLayerSmokeFire 2
#define knLayerSymbols 3
#define knLayerSelection 4
#define knLayerEnd 4
#define knLayerMiniMap -1
// When a y coordinate is passed to MakeSortKey as the first value and a Gob
// id (gid) is passed as the second value the resultant key when used for
// sorting will give perfect vertical ordering and stable horizontal ordering.
//
// NOTE: will become spotty when gid values wrap or exceed 1024 (more than
// 256 ids assigned) but this is deemed inconsequential.
#define MakeSortKey(a, b) (((int)(a) << 8) | (((b) >> 2) & 0xff))
class Gob : public StateMachine // gob
{
friend class StateMachineMgr;
friend class GobMgr;
public:
Gob() secGob;
virtual ~Gob() secGob;
dword GetFlags() secGob;
void Flash() secGob;
void MarkRedraw() secGob;
bool Invalidate() secGob;
bool AdvanceAnimation(Animation *pani) secGob;
void StartAnimation(Animation *pani, int nStrip, int nFrame, word wfAni) secGob;
void SetAnimationStrip(Animation *pani, int nStrip) secGob;
void SetAnimationFrame(Animation *pani, int nFrame) secGob;
void SetFlags(dword ff) secGob;
Gid GetId() secGob;
Side GetSide() secGob;
Player *GetOwner() secGob;
void SetOwner(Player *pplr) secGob;
bool IsGobWithinRange(Gob *pgobTarget, TCoord tcRange) secGob;
bool IsTargetWithinRange(WPoint *pwptTarget, Gob *pgobTarget, TCoord tcRange) secGob;
virtual void SetPosition(WCoord wx, WCoord wy) secGob;
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) = 0;
virtual bool LoadState(Stream *pstm) secGob;
virtual bool SaveState(Stream *pstm) secGob;
virtual bool IsSavable();
virtual GobType GetType() = 0;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) = 0;
virtual dword GetSortKey() secGob;
virtual void GetClippingBounds(Rect *prc) secGob;
virtual void GetUIBounds(WRect *pwrc) secGob;
virtual void GetPosition(WPoint *pwpt) secGob;
virtual void GetTilePosition(TPoint *ptpt) secGob;
virtual void GetTileRect(TRect *ptrc) secGob;
virtual void GetTilePaddedWRect(WRect *pwrc) secGob;
virtual void GetCenter(WPoint *pwpt) secGob;
virtual void PopupMenu() secGob;
virtual void InitMenu(Form *pfrm) secGob;
virtual void OnMenuItemSelected(int id) secGob;
#if defined(WIN) && defined(DEBUG)
virtual void ToString(char *psz);
#endif
#ifdef TRACKSTATE
virtual void TrackState(StateFrame *frame);
#endif
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
// Used for tracking visibility
TRectSmall m_trcBoundingLast;
protected:
Gid m_gid;
dword m_ff;
WCoord m_wx, m_wy;
Player *m_pplr;
private:
Gob *m_pgobNext;
Gid m_gidNext;
};
inline dword Gob::GetFlags() {
return m_ff;
}
inline void Gob::Flash() {
m_ff |= kfGobFlashing | kfGobRedraw;
m_unvl.MinSkip();
}
inline void Gob::SetFlags(dword ff) {
m_ff = ff;
}
inline Gid Gob::GetId() {
return m_gid;
}
inline Side Gob::GetSide() {
return m_pplr->GetSide();
}
inline Player *Gob::GetOwner() {
return m_pplr;
}
inline void Gob::SetOwner(Player *pplr) {
m_pplr = pplr;
}
Gob *CreateGob(GobType gt) secGob;
// GobMgr stuff
const Gid kgidNull = (Gid)-1;
const word kwfGidEndMarker = 0x8000;
// AreaMask; assumes 32 areas max
#define kcAreasMax 32
#define knAreaLastDiscovery -1
#if kcAreasMax > 32
#error Code assumes 32 areas max! Could change to 64 easily enough
#endif
typedef dword AreaMask;
struct AreaEntry // are
{
word iareNext;
Gid gid;
};
struct Area // ar
{
TRect trc;
word iareFree;
word iareHead;
word careAlloc;
word careUsed;
SideMask sidm;
UnitMask um;
AreaEntry *aare;
};
#define knLimitStruct 0
#define knLimitMobileUnit 1
#define knLimitScenery 2
#define knLimitScorch 3
#define knLimitSupport 4
class GobMgr // gobm
{
public:
GobMgr() secGobMgr;
~GobMgr() secGobMgr;
bool Init(TCoord ctx, TCoord cty, int cpgobMax) secGobMgr;
void Reset() secGobMgr;
bool SaveState(Stream *pstm) secGobMgr;
bool LoadState(Stream *pstm) secGobMgr;
void AddGob(Gob *pgob, Gid gid = kgidNull) secGobMgr;
void RemoveGob(Gob *pgob) secGobMgr;
bool MoveGob(Gob *pgob, WCoord wxOld, WCoord wyOld, WCoord wxNew, WCoord wyNew) secGobMgr;
Gob *GetGob(Gid gid, bool fActiveOnly = true) secGobMgr;
UnitGob *GetUnitGob(TCoord tx, TCoord ty) secGobMgr;
void ShadowGob(Gob *pgob, TCoord tx, TCoord ty, int ctx, int cty) secGobMgr;
void UnshadowGob(Gob *pgob, TCoord tx, TCoord ty, int ctx, int cty) secGobMgr;
Gob *GetShadowGob(TCoord tx, TCoord ty) secGobMgr;
void GetAreaRect(int nArea, TRect *ptrc, Side side = ksideNeutral) secGobMgr;
bool LoadAreas(IniReader *pini) secGobMgr;
Gob *EnumGobsInArea(Enum *penm, int nArea, SideMask sidm, UnitMask um) secGobMgr;
void MoveGobBetweenAreas(Gid gid, AreaMask amOld, AreaMask amNew) secGobMgr;
AreaMask CalcAreaMask(TCoord tx, TCoord ty) secGobMgr;
AreaMask CalcAreaMask(TCoord tx, TCoord ty, int ctx, int cty) secGobMgr;
bool CheckUnitsInArea(int nArea, SideMask sidm, UnitMask um) secGobMgr;
bool IsGobWithinArea(Gob *pgobTarget, int nArea) secGobMgr;
#ifdef DEBUG_HELPERS
char m_aszAreaNames[kcAreasMax][50];
char *GetAreaName(int nArea) {
return m_aszAreaNames[nArea];
}
#endif
Gob *GetFirstGob() {
return m_pgobHead;
}
// UNDONE: will making this static generate better code?
class Gob *GetNextGob(Gob *pgob) {
return pgob->m_pgobNext;
}
// First gid at TCoord
Gid GetFirstGid(TCoord tx, TCoord ty) {
Gid gid = m_pgidMap[ty * m_ctx + tx];
if (gid & kwfGidEndMarker)
return kgidNull;
return gid;
}
// Next gid in list
Gid GetNextGid(Gid gid) {
Gob *pgob = GetGob(gid, false);
if (pgob == NULL)
return kgidNull;
return pgob->m_gidNext;
}
void GetMapSize(TCoord *pctx, TCoord *pcty) {
*pctx = m_ctx;
*pcty = m_cty;
}
int GetGobCount() {
return m_cpgobActive;
}
int FindGobs(const Rect *prcBounds, Gob **apgob, int cpgobMax, byte *pbFogMap) secGobMgr;
bool IsStructurePlacementValid(StructConsts *pstruc, TCoord tx, TCoord ty, Player *pplr) secGobMgr;
#if defined(DEBUG) && defined(WIN)
Gob *FindEnemyWithinRange(UnitGob *punt, TCoord tcRange, bool fStructures = false) secGobMgr;
#endif
int FindGobs(const TRect *ptrcBounds, Gob **apgob, int cpgobMax) secGobMgr;
void TrackGobCounts(Gob *pgob, bool fIncrement) secGobMgr;
bool IsBelowLimit(int nLimit, Player *pplr = NULL) secGobMgr;
private:
void AddGobToAreas(Gid gid, AreaMask am) secGobMgr;
void RemoveGobFromAreas(Gid gid, AreaMask am) secGobMgr;
int GetAreasFromMask(AreaMask am, int *pnArea) secGobMgr;
void FreeAreas() secGobMgr;
Gob *m_pgobHead;
Gid *m_pgidMap;
int m_cpgobMax;
int m_cpgobActive; // UNDONE: _DEBUG only?
Gob **m_ppgobFreeHead;
Gob **m_ppgobFreeTail;
TCoord m_ctx, m_cty;
int m_car;
Area m_aar[kcAreasMax];
int m_cSceneryGobs;
int m_cScorchGobs;
int m_cSupportGobs;
#ifdef MP_DEBUG_SHAREDMEM
public:
#endif
Gob **m_apgobMaster;
};
extern GobMgr ggobm;
// GobStateMachineMgr
class GobStateMachineMgr : public StateMachineMgr
{
public:
virtual StateMachineId GetId(StateMachine *psm) {
return (StateMachineId)((Gob *)psm)->GetId();
};
virtual StateMachine *GetStateMachine(StateMachineId smid) {
return (StateMachine *)ggobm.GetGob((Gid)smid, false);
};
};
extern GobStateMachineMgr gsmm;
// Gob derivatives
class OvermindGob : public Gob // ovr
{
public:
OvermindGob() secOvermindGob;
virtual ~OvermindGob() secOvermindGob;
static bool InitClass(IniReader *pini) secOvermindGob;
bool Init(const char *pszName = NULL) secOvermindGob;
void Toggle() secOvermindGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secOvermindGob;
virtual bool IsSavable() secOvermindGob;
virtual GobType GetType() secOvermindGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secOvermindGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secOvermindGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secOvermindGob;
#endif
private:
bool m_fEnabled;
int m_cAttackCountdown;
int m_cBuildUnitCountdown;
bool m_fInitializationComplete;
};
class SurfaceDecalGob : public Gob // dcl
{
public:
SurfaceDecalGob() secSurfaceDecalGob;
virtual ~SurfaceDecalGob() secSurfaceDecalGob;
static bool InitClass(IniReader *pini) secSurfaceDecalGob;
bool Init(WCoord wx, WCoord wy, dword ff, const char *pszBitmap, TBitmap *ptbm = NULL, const char *pszName = NULL) secSurfaceDecalGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secSurfaceDecalGob;
virtual bool IsSavable() secSurfaceDecalGob;
virtual GobType GetType() secSurfaceDecalGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secSurfaceDecalGob;
virtual void GetClippingBounds(Rect *prc) secSurfaceDecalGob;
protected:
TBitmap *m_ptbm;
};
// ScorchGob different than SurfaceDecalGob so that m_nScorch can be persisted
class ScorchGob : public SurfaceDecalGob
{
public:
ScorchGob() secScorchGob;
bool Init(WCoord wx, WCoord wy, int nScorch) secScorchGob;
// Scorch methods
int GetSequence() secScorchGob;
// Gob methods
virtual GobType GetType() secScorchGob;
virtual bool LoadState(Stream *pstm) secScorchGob;
virtual bool SaveState(Stream *pstm) secScorchGob;
virtual bool IsSavable() secScorchGob;
private:
int m_nScorch;
int m_nSequence;
};
class SceneryGob : public Gob // scn
{
public:
SceneryGob() secSceneryGob;
virtual ~SceneryGob() secSceneryGob;
static bool InitClass(IniReader *pini) secSceneryGob;
bool Init(WCoord wx, WCoord wy, dword ff, const char *pszBitmap, const char *pszName = NULL) secSceneryGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secSceneryGob;
virtual bool LoadState(Stream *pstm) secSceneryGob;
virtual bool SaveState(Stream *pstm) secSceneryGob;
virtual GobType GetType() secSceneryGob;
virtual dword GetSortKey() secSceneryGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secSceneryGob;
virtual void GetClippingBounds(Rect *prc) secSceneryGob;
private:
TBitmap *m_ptbm;
};
class AnimGob : public Gob // anm
{
public:
AnimGob() secAnimGob;
virtual ~AnimGob() secAnimGob;
bool Init(WCoord wx, WCoord wy, word wfAnm, const char *pszAniName, AnimationData *panid = NULL,
int nStrip = 0, StateMachineId smidNotify = ksmidNull, const char *pszName = NULL) secAnimGob;
virtual bool OnStripDone() secAnimGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secAnimGob;
virtual bool IsSavable() secAnimGob;
virtual GobType GetType() secAnimGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secAnimGob;
virtual void GetClippingBounds(Rect *prc) secAnimGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secAnimGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secAnimGob;
#endif
protected:
StateMachineId m_smidNotify;
word m_wfAnm;
Animation m_ani;
};
AnimGob *CreateAnimGob(WCoord wx, WCoord wy, word wfAnm, const char *pszAniName, AnimationData *panid,
int nStrip = 0, StateMachineId smidNotify = ksmidNull, const char *pszName = NULL) secAnimGob;
const word kfAnmDeleteWhenDone = 0x0001;
const word kfAnmLoop = 0x0002;
const word kfAnmSmokeFireLayer = 0x0004;
const word kfAnmSurfaceDecalLayer = 0x0008;
const int kcbStructUnitName = 50;
struct GobConsts { // gobc
GobType gt;
};
#define GetUnitCostMin() (gfMultiplayer ? gnUnitCostMPMin : gnUnitCostMin)
#define GetUnitCostMax() (gfMultiplayer ? gnUnitCostMPMax : gnUnitCostMax)
#define kfUntcNotifyEnemyNearby 0x0001 // wants to be notified of nearby mobile enemies
#define kfUntcNotifyPowerLowHigh 0x0002 // bld is power sensitive, needs notifications
#define kfUntcLargeDefog 0x0004 // this unit defogs a larger area
#define kfUntcMobileUnitBuilder 0x0008 // builds mobile units
#define kfUntcStructureBuilder 0x0010 // builds structures
#define kfUntcHasFullnessIndicator 0x0020 // draws fullness indicator
struct UnitConsts : public GobConsts { // untc
UnitType ut;
UnitMask um;
UnitMask umPrerequisites;
UpgradeMask upgmPrerequisites;
Sfx sfxImpact;
int nCost;
int nCostMP;
fix fxArmorStrength;
fix fxArmorStrengthMP;
int nInfantryDamage;
int nInfantryDamageMP;
int nVehicleDamage;
int nVehicleDamageMP;
int nStructureDamage;
int nStructureDamageMP;
int ctFiringRate;
int tcFiringRange; // kept as int instead of TCoord to accommodate Ini::GetPropertyValue
int cupdTimeToBuild;
int cupdTimeToBuildMP;
char szAniName[kcbFilename];
AnimationData *panid;
WRect wrcUIBounds;
WRect wrcUIBoundsFinger;
int wdySortOffset;
char szName[kcbStructUnitName];
char szLongName[kcbStructUnitName];
UnitMenu *pfrmMenu;
word wf;
char *szDescription;
int GetCost() {
return gfMultiplayer ? nCostMP : nCost;
}
fix GetArmorStrength() {
return gfMultiplayer ? fxArmorStrengthMP : fxArmorStrength;
}
int GetTimeToBuild() {
return gfMultiplayer ? cupdTimeToBuildMP : cupdTimeToBuild;
}
int GetInfantryDamage() {
return gfMultiplayer ? nInfantryDamageMP : nInfantryDamage;
}
int GetVehicleDamage() {
return gfMultiplayer ? nVehicleDamageMP : nVehicleDamage;
}
int GetStructureDamage() {
return gfMultiplayer ? nStructureDamageMP : nStructureDamage;
}
};
struct StructConsts : public UnitConsts { // struc
int ctx, cty; // kept as int instead of TCoord to accommodate Ini::GetPropertyValue
int ctxReserve, ctyReserve; // kept as int instead of TCoord to accommodate Ini::GetPropertyValue
int nPowerDemand;
int nPowerSupply;
int nUpgradeCost;
Sfx sfxAbortRepair;
Sfx sfxRepair;
Sfx sfxDamaged;
Sfx sfxDestroyed;
Sfx sfxSelect;
Sfx sfxUpgrade;
Sfx sfxAbortUpgrade;
};
struct BuilderConsts : public StructConsts { // bldc
int nBuildRate;
Sfx sfxUnitBuild;
Sfx sfxUnitBuildAbort;
Sfx sfxUnitReady;
UnitMask umCanBuild;
};
struct TowerConsts : public StructConsts { // twrc
Sfx sfxAttack;
Sfx sfxFire;
int *anFiringStripIndices;
};
struct MobileUnitConsts : public UnitConsts { // muntc
Sfx sfxFire;
SfxCategory sfxcDestroyed;
SfxCategory sfxcSelect;
SfxCategory sfxcMove;
SfxCategory sfxcAttack;
WCoord wcMoveDistPerUpdate;
WCoord wcMoveDistPerUpdateMP;
int *anFiringStripIndices;
int *anMovingStripIndices;
int *anIdleStripIndices;
WCoord GetMoveDistPerUpdate() {
return gfMultiplayer ? wcMoveDistPerUpdateMP : wcMoveDistPerUpdate;
}
};
class MobileUnitBuildForm;
struct MobileUnitBuilderConsts : public BuilderConsts { // mubc
word fUpgrade;
word fUpgradeInProgress;
MobileUnitBuildForm *pfrmBuild;
};
struct SpConsts : public MobileUnitConsts { // spc
Sfx sfxStructureCaptured;
};
struct MinerConsts : public MobileUnitConsts { // mnrc
Sfx sfxMine;
Sfx sfxUnderAttack;
};
const int kcmsDamageIndicatorTimeout = 4000; // 4.0 secs TUNE:
#define kcEnemyNearbyRemember 5 // # of enemies to remember
#define kcyHealthBar 4 // Height of health bar above selection
const WCoord kwcFullnessPip = WcFromTile16ths(2);
#define kcyFullnessBar (PcFromWc(kwcFullnessPip) + 2) // Height of fullness bar below miner, processor, warehouse
class UnitGob : public Gob // unt
{
public:
UnitGob(UnitConsts *puntc) secUnitGob;
~UnitGob() secUnitGob;
static bool InitClass(UnitConsts *psubc, IniReader *pini) secUnitGob;
static void InitFingerUIBounds(UnitConsts *psubc);
static void ExitClass(UnitConsts *psubc) secUnitGob;
static bool LoadMenu(UnitConsts *psubc, IniReader *pini, char *pszTemplate, int idfDefault) secUnitGob;
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secUnitGob;
virtual void Delete() secUnitGob;
virtual void DefUpdate() secUnitGob;
virtual void Activate() secUnitGob;
virtual void Deactivate() secUnitGob;
virtual bool IsIdle() secUnitGob;
virtual bool IsValidTarget(Gob *pgobTarget) secUnitGob;
virtual void SetTarget(Gid gid, WCoord wxTarget = 0, WCoord wyTarget = 0, WCoord wxCenter = 0, WCoord wyCenter = 0, TCoord tcRadius = 0, WCoord wcMoveDistPerUpdate = 0) secUnitGob;
virtual void GetAttackPoint(WPoint *pwpt) secUnitGob;
virtual dword GetAnimationHash() secUnitGob;
virtual void GetAnimationBounds(Rect *prc, bool fBase) secUnitGob;
virtual void DrawAnimation(DibBitmap *pbm, int x, int y) secUnitGob;
virtual AnimSprite *CreateHilightSprite(); secUnitGob;
#ifdef MP_DEBUG_SHAREDMEM
virtual void MPValidate() secUnitGob;
#endif
void NotifyNearbyAlliesOfHit(Gid gidAssailant) secUnitGob;
void ShowDamageIndicator() secUnitGob;
void ClearDamageIndicator() secUnitGob;
int GetDamageTo(UnitGob *puntTarget) secUnitGob;
void RecalcEnemyNearby(bool fClearOnly) secUnitGob;
UnitConsts *GetConsts() {
return m_puntc;
}
UnitType GetUnitType() {
return m_puntc->ut;
}
word GetUnitFlags() {
return m_wfUnit;
}
void SetUnitFlags(word wf) {
m_wfUnit = wf;
}
bool IsAlly(Side side) secUnitGob;
fix GetHealth() {
return m_fxHealth;
}
AnimSprite *GetAnimSprite() {
return m_panispr;
}
void Select(bool fSelect) secUnitGob;
void Hilight(bool fHilight) secUnitGob;
virtual void SetHealth(fix fxHealth) secUnitGob;
// Gob overrides
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secUnitGob;
virtual bool LoadState(Stream *pstm) secUnitGob;
virtual bool SaveState(Stream *pstm) secUnitGob;
virtual GobType GetType() secUnitGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secUnitGob;
virtual dword GetSortKey();
virtual void GetClippingBounds(Rect *prc) secUnitGob;
virtual void GetUIBounds(WRect *pwrc) secUnitGob;
virtual void GetCenter(WPoint *pwpt) secUnitGob;
virtual void PopupMenu() secUnitGob;
protected:
void RememberEnemyNearby(Gid gidEnemy) secUnitGob;
TCoord CalcRange(TCoord tx, TCoord ty, Gob *pgob) secUnitGob;
virtual UnitGob *FindEnemyNearby(TCoord tc) secUnitGob;
void NotifyEnemyNearby() secUnitGob;
union {
UnitConsts *m_puntc;
StructConsts *m_pstruc;
TowerConsts *m_ptwrc;
SpConsts *m_pspc;
MinerConsts *m_pmnrc;
MobileUnitConsts *m_pmuntc;
BuilderConsts *m_pbldrc;
MobileUnitBuilderConsts *m_pmubc;
};
Gid m_agidEnemyNearby[kcEnemyNearbyRemember];
fix m_fxHealth;
Animation m_ani;
AnimSprite *m_panispr;
word m_wfUnit;
int m_cupdLastHitNotify;
short m_cDamageCountdown;
};
const word kfUnitInvulnerable = 0x0001;
const word kfUnitDrawHealthIndicator = 0x0002;
const word kfUnitDrawRepairingSymbol = 0x0004;
const word kfUnitRepairing = 0x0008;
const word kfUnitDrawNeedsPowerSymbol = 0x0010;
const word kfUnitDrawNeedCreditsSymbol = 0x0020;
const word kfUnitNeedCredits = 0x0040;
const word kfUnitHilighted = 0x0080;
class StructGob : public UnitGob // stru
{
public:
StructGob(StructConsts *pstruc) secStructures;
virtual ~StructGob() secStructures;
static bool InitClass(StructConsts *pstruc, IniReader *pini) secStructures;
static void ExitClass(StructConsts *pstruc) secStructures;
void Repair(bool fOn) secStructures;
bool NeedsRepair() secStructures;
void EnableOrDisableSymbolLayer() secStructures;
virtual bool IsTakeoverable(Player *pplr) secStructures;
virtual void Takeover(Player *pplr) secStructures;
static bool LoadConfirmation() secStructures;
bool PopupConfirmation(char *pszTitle) secStructures;
void TakedownConfirmation() secStructures;
void SelfDestruct(bool fRecycleValue = true) secStructures;
bool IsAccessible(TCoord tx, TCoord ty) secStructures;
// UnitGob overrides
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secStructures;
virtual void Delete() secStructures;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secStructures;
virtual void DefUpdate() secStructures;
virtual void Activate() secStructures;
virtual void Deactivate() secStructures;
virtual bool IsValidTarget(Gob *pgobTarget) secStructures;
virtual void SetHealth(fix fxHealth) secStructures;
virtual void GetAttackPoint(WPoint *pwpt) secStructures;
// Gob overrides
virtual bool LoadState(Stream *pstm) secStructures;
virtual bool SaveState(Stream *pstm) secStructures;
virtual void GetTileRect(TRect *ptrc) secStructures;
virtual void GetTilePaddedWRect(WRect *pwrc) secStructures;
virtual void InitMenu(Form *pfrm) secStructures;
virtual void OnMenuItemSelected(int id) secStructures;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStructures;
// Used to track visibility in FindGobs
word m_nSeqLastVisible;
protected:
void OnPowerLowHigh() secStructures;
void DrawSymbol(TBitmap *ptbm, DibBitmap *pbm, int xViewOrigin, int yViewOrigin) secStructures;
virtual void WaitingForCredits(bool fNeed, bool fOverride = false, Player *pplr = NULL) secStructures;
private:
ScorchGob *GetScorchGob() secStructures;
long m_tLastSmoke;
static TBitmap *s_ptbmRepairing;
static TBitmap *s_ptbmNeedsPower;
static TBitmap *s_ptbmNeedCredits;
};
// TUNE:
const fix kfxHealthUnitsRepairedPerUpdate = itofx(1);
const int knCreditsPerRepairUpdate = 1;
const long kcupdSymbolFlashRate = 8; // ideally a power of 2
#define GetReplicationCost(nCost) ((nCost) / 3)
class UnitMenu : public Form, public Timer
{
public:
void SetOwner(UnitGob *punt, bool fPerUnitInit = true) secUnitGob;
UnitGob *GetOwner() secUnitGob;
// Form overrides
virtual bool DoModal(int *pnResult = NULL, Sfx sfxShow = ksfxGuiFormShow, Sfx sfxHide = ksfxGuiFormHide) secUnitGob;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secUnitGob;
virtual void OnPaint(DibBitmap *pbm) secUnitGob;
virtual bool OnHitTest(Event *pevt) secUnitGob;
// Timer overrides
virtual void OnTimer(long tCurrent) secUnitGob;
protected:
UnitGob *m_punt;
Rect m_rcButtons;
};
enum MobileUnitAction // mua
{
kmuaNone,
kmuaGuard,
kmuaGuardVicinity,
kmuaGuardArea,
kmuaMove,
kmuaAttack,
kmuaHuntEnemies,
};
struct MoveDirections // movd
{
MobileUnitGob *pmunt;
byte idir;
byte cdir;
Direction adir[8];
};
const word kfMuntChaseEnemies = 0x0001; // Will chase enemies when attacking them
const word kfMuntReturnFire = 0x0002; // Will attack anything that hits it
const word kfMuntAttackEnemiesWhenMoving = 0x0004; // Will attack enemies in range when moving
const word kfMuntAttackEnemiesWhenGuarding = 0x0008; // Will attack enemies in range when guarding
const word kfMuntRunAwayWhenHit = 0x0010; // Will run away when hit
const word kfMuntMoveWait = 0x0020; // Is waiting for a tile to free up
const word kfMuntPathPending = 0x0040; // Will be calcing a path soon
const word kfMuntCommandPending = 0x0080; // Has a command pending
const word kfMuntFiring = 0x0100; // Is shooting at something
const word kfMuntMoveWaitingNearby = 0x0200; // Gob nearby is "move waiting" on this gob
const word kfMuntDestinationReserved = 0x0400; // Dest tile reserved
const word kfMuntStuck = 0x0800; // Stuck bit for debugging
const word kfMuntAtReplicatorInput = 0x1000; // At replicator input spot
const word kfMuntStayPut = 0x2000; // Don't move to attack enemies
// All the flags that control a MobileUnit's aggressiveness
const word kfMuntAggressivenessBits = kfMuntChaseEnemies | kfMuntReturnFire |
kfMuntAttackEnemiesWhenMoving | kfMuntAttackEnemiesWhenGuarding |
kfMuntRunAwayWhenHit | kfMuntStayPut;
// Most MobileUnits move (follow paths) and like to shoot
extern bool gfGodMode;
#define kcPathsCache 5
class MobileUnitGob : public UnitGob // munt
{
public:
MobileUnitGob(MobileUnitConsts *pmuntc) secUnitGob;
virtual ~MobileUnitGob() secUnitGob;
// NOTE: derivatives should initialize the an*StripIndices arrays of the MobileUnitConsts
static bool InitClass(MobileUnitConsts *pmuntc, IniReader *pini) secUnitGob;
static void ExitClass(MobileUnitConsts *pmuntc) secUnitGob;
static MobileUnitGob *AnyTransitionsIntoTile(TCoord tx, TCoord ty, Gob *pgobIgnore) secUnitGob;
static void FreeCachedPaths() secUnitGob;
bool IsReadyForCommand() secUnitGob;
bool IsMobile() secUnitGob;
bool IsStandingOnActivator() secUnitGob;
bool HasAttackTarget() {
return m_gidTarget != kgidNull;
}
word GetMobileUnitFlags() {
return m_wfMunt;
}
void SetMobileUnitFlags(word wf) {
m_wfMunt = wf;
}
void ClearAction() {
m_mua = kmuaNone;
}
bool IsHumanOrGodControlled() {
return !(m_pplr->GetFlags() & kfPlrComputer) || gfGodMode;
}
bool IsMoveWaiting() {
return (m_wfMunt & kfMuntMoveWait) != 0;
}
#ifdef MP_DEBUG_SHAREDMEM
virtual void MPValidate() secUnitGob;
#endif
// UnitGob overrides
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secUnitGob;
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secUnitGob;
#ifdef DRAW_PATHS
void DrawPath(DibBitmap *pbm, WCoord wxViewOrigin, WCoord wyViewOrigin) secUnitGob;
#endif
#ifdef DRAW_LINES
void DrawTargetLine(DibBitmap *pbm, int xViewOrigin, int yViewOrigin) secUnitGob;
#endif
virtual bool IsIdle() secUnitGob;
virtual void SetTarget(Gid gid, WCoord wxTarget = 0, WCoord wyTarget = 0, WCoord wxCenter = 0, WCoord wyCenter = 0, TCoord tcRadius = 0, WCoord wcMoveDistPerUpdate = 0) secUnitGob;
virtual void Activate() secUnitGob;
virtual void Deactivate() secUnitGob;
virtual void GetAttackPoint(WPoint *pwpt) secUnitGob;
// Gob overrides
virtual bool LoadState(Stream *pstm) secUnitGob;
virtual bool SaveState(Stream *pstm) secUnitGob;
virtual void SetPosition(WCoord wx, WCoord wy) secUnitGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secUnitGob;
protected:
void MoveEnter(bool fReset = false) secUnitGob;
void MoveExit() secUnitGob;
int MoveUpdate() secUnitGob;
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secUnitGob;
virtual void Idle() secUnitGob;
virtual void PerformAction(char *szAction) secUnitGob;
bool InTransition() secUnitGob;
private:
bool IsAttackPointWithinFiringRangeOfTarget(UnitGob *puntTarget) secUnitGob;
bool PendOrProcessCommand(Message *pmsg, State stNew) secUnitGob;
bool PendOrProcessAction(Message *pmsg, State stNew, MobileUnitAction mua) secUnitGob;
bool IsTargetInRange() secUnitGob;
void SetStatePendingFireComplete(State st) secUnitGob;
void ContinueActionPendingFireComplete() secUnitGob;
void ReserveTile(TCoord tx, TCoord ty, bool fReserve) secUnitGob;
bool IsTileReserved(TCoord tx, TCoord ty) secUnitGob;
byte GetTileFlags(TCoord tx, TCoord ty) secUnitGob;
MobileUnitGob *GetReservingUnit(TCoord tx, TCoord ty) secUnitGob;
int GetNextLocations(TPoint *atpt) secUnitGob;
int GetNextLocations2(Path *ppath, int *pitptStart, int cStepsFurtherStop, TPoint *atpt) secUnitGob;
int FindClosestPoint(TPoint *ptptClosest, int ctptFurtherStop) secUnitGob;
bool PrepPath(WCoord wxDst, WCoord wyDst) secUnitGob;
Path *FindPath(TCoord txFrom, TCoord tyFrom, TCoord txTo, TCoord tyTo) secUnitGob;
bool PrepareNextTransition(TPoint *ptptNext, int *pnMoveResult) secUnitGob;
void EnterTransition(TPoint *ptptNext) secUnitGob;
void ContinueTransition() secUnitGob;
bool HandleCollision(MobileUnitGob **apmunt, byte *abf, TPoint *atpt, int ctpt) secUnitGob;
bool PlanMoveAsidePath(MobileUnitGob *pmunt, TCoord tx, TCoord ty) secUnitGob;
bool GetMoveAsideDirections(Direction dirMover, MoveDirections *pmovd) secUnitGob;
bool AcceptMoveAsideRequest(Direction dir) secUnitGob;
MobileUnitGob *GetMobileUnitAt(TCoord tx, TCoord ty) secUnitGob;
bool CheckDestinationReached() secUnitGob;
bool IsMoveWaitCycle(MobileUnitGob *pmunt) secUnitGob;
bool MoveWaitForUnit(MobileUnitGob *pmunt, TCoord tx, TCoord ty) secUnitGob;
bool ContinueMoveWaiting(MobileUnitGob **apmunt, byte *abf, TPoint *atpt, int ctpt, TPoint *ptptNext) secUnitGob;
void NotifyMoveWaitingNearby(WCoord wx, WCoord wy) secUnitGob;
bool FindLocalAvoidPath(TCoord tx, TCoord ty) secUnitGob;
int FindCloserTrackPoint(TrackPoint *ptrkpStart, Direction dirBlocked, bool fClockwise, int ctpt, TPoint *atpt, TrackPoint *ptrkp) secUnitGob;
bool CheckReplicatorPoint() secUnitGob;
UnitGob *FindValidTargetInArea(int nArea) secUnitGob;
protected:
Direction m_dir, m_dirNext;
Gid m_gidTarget;
long m_tLastFire;
Message m_msgPending;
Message m_msgAction;
int m_cCountdown; // multi-purpose countdown timer
int m_cMoveStepsRemaining;
TPoint m_tptChaseInitial;
MobileUnitAction m_mua, m_muaPending;
word m_wfMunt;
State m_stPending;
int m_cupdLastHitOrNearbyAllyHit;
#ifdef DRAW_PATHS
public:
WCoord m_wxDst, m_wyDst;
protected:
#endif
#ifdef DEBUG_HELPERS
public:
#endif
TCoord m_txDst, m_tyDst;
#ifdef DEBUG_HELPERS
protected:
#endif
#ifdef DRAW_LINES
public:
#endif
WPoint m_wptTarget;
#ifdef DRAW_PATHS
public:
#endif
word m_nSeqMoveAside;
Path *m_ppathUnit;
Path *m_ppathAvoid;
int m_itptPath;
WPoint m_wptTargetCenter;
TCoord m_tcTargetRadius;
WCoord m_wcMoveDistPerUpdate;
static Path *s_apathCached[kcPathsCache];
static int s_cpathCached;
#ifdef DEBUG_HELPERS
friend void paint();
friend class UnitGroupViewer;
#endif
};
// Values returned by UnitGob::MoveUpdate()
const int knMoveMoving = 0;
const int knMoveTargetReached = 1;
const int knMoveStuck = 2;
const int knMoveWaiting = 3;
const int kxInvalid = -1000;
const WCoord kwxInvalid = -1000;
const TCoord ktxInvalid = -100;
const word kcBuildQueueMax = 10;
class BuildQueue
{
public:
BuildQueue() secBuildQueue;
BuildQueue &operator=( BuildQueue &bqRHS) secBuildQueue;
void SetSize(word cutMax) secBuildQueue;
int GetRemainingCapacity() secBuildQueue;
void Enqueue(UnitType ut) secBuildQueue;
void Dequeue() secBuildQueue;
bool RemoveUnit(UnitType ut) secBuildQueue;
UnitType Peek() secBuildQueue;
bool IsEmpty() secBuildQueue;
bool IsFull() secBuildQueue;
void Clear() secBuildQueue;
int GetUnitCount(UnitType ut) secBuildQueue;
// called by builder gob
virtual bool LoadState(Stream *pstm) secBuildQueue;
virtual bool SaveState(Stream *pstm) secBuildQueue;
private:
char m_achBuildQueue[kcBuildQueueMax];
word m_cchQueueMax;
};
class BuilderGob : public StructGob // bldr
{
public:
BuilderGob(BuilderConsts *pbldrc) secBuilderGob;
virtual ~BuilderGob() secBuilderGob;
static bool InitClass(BuilderConsts *pbldrc, IniReader *pini) secBuilderGob;
static void ExitClass(BuilderConsts *pbldrc) secBuilderGob;
void DrawUpgradeEffect(DibBitmap *pbm, int xViewOrigin, int yViewOrigin) secBuilderGob;
void AbortBuild(bool fRefundCreditsSpent = false, UnitType ut = kutNone) secBuilderGob;
static int GetGlobalQueuedCount(Player *pplr, word wfTest) secBuilderGob;
static int GetQueuedCount(Player *pplr, word wfTest) secBuilderGob;
void SetRallyPoint(TCoord tx, TCoord ty) {
m_tptRally.tx = tx;
m_tptRally.ty = ty;
}
// in builder gob so it will be tracked per-instance
void SetLastSelection(short iSel) { m_iLastSelection = iSel;}
short GetLastSelection() {return m_iLastSelection;}
// Build management methods
virtual void FindInitPosition(WPoint *pwpt) secBuilderGob;
virtual void Build(UnitType ut, Gid gid = kgidNull) secBuilderGob;
bool IsBuildInProgress() {
return !m_bq.IsEmpty();
}
UnitType UnitBuildInProgress() {return m_bq.Peek();}
void DrawBuildProgress(DibBitmap *pbm, Rect *prc) secBuilderGob;
void SyncBuildQueue(BuildQueue *pbq) secBuilderGob;
UnitGob *GetBuiltGob() secBuilderGob;
void ClearBuiltGob() secBuilderGob;
// UnitGob overrides
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secBuilderGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secBuilderGob;
virtual void DefUpdate() secBuilderGob;
virtual void Deactivate() secBuilderGob;
// Gob overrides
virtual bool LoadState(Stream *pstm) secBuilderGob;
virtual bool SaveState(Stream *pstm) secBuilderGob;
virtual void GetClippingBounds(Rect *prc);
protected:
bool ShowingBuildProgress();
short m_iLastSelection;
Gid m_gidBuildVisible;
fix m_fxHealthBuilding;
int m_nCreditsSpentOnBuilding;
int m_nCostRemainder;
TPoint m_tptRally;
#ifdef MP_STRESS
public:
#endif
BuildQueue m_bq;
};
class MobileUnitBuildForm : public Form
{
public:
BuilderGob *GetOwner() {
return m_pbldr;
}
void SetOwner(BuilderGob *pbldr) secStructures;
void UpdateUnitInfo(ListItem *pli) secStructures;
void OnUnitCompleted(BuilderGob *pbldr, UnitType ut) secStructures;
void DefUpdate(BuilderGob *pbldr, bool fBuildInProgress) secStructures;
int CountQueue(UnitType ut) secStructures;
void UpdateOrderButton(bool fCalcLimit) secStructures;
// Form overrides
void EndForm(int nResult = 0) secStructures;
virtual void OnControlSelected(word idc) secStructures;
virtual void OnControlNotify(word idc, int nNotify);
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secStructures;
private:
int m_cupdLast;
bool m_fLimitReached;
bool m_fOrderValid;
BuilderGob *m_pbldr;
BuildQueue m_bqPrivate;
static int s_iliCurrent;
};
class TankGob : public MobileUnitGob // tnk
{
public:
TankGob(MobileUnitConsts *pmuntc) secTankGob;
static bool InitClass(MobileUnitConsts *pmuntc, IniReader *pini) secTankGob;
static void ExitClass(MobileUnitConsts *pmuntc) secTankGob;
virtual void LaunchProjectile(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget) secTankGob;
// UnitGob overrides
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secTankGob;
virtual void DefUpdate() secTankGob;
// UnitGob overrides
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secTankGob;
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secTankGob;
virtual void Idle() secTankGob;
virtual dword GetAnimationHash() secTankGob;
virtual void GetAnimationBounds(Rect *prc, bool fBase) secTankGob;
virtual void DrawAnimation(DibBitmap *pbm, int x, int y) secTankGob;
// Gob overrides
virtual void GetClippingBounds(Rect *prc) secTankGob;
virtual bool LoadState(Stream *pstm) secTankGob;
virtual bool SaveState(Stream *pstm) secTankGob;
protected:
Animation m_aniTurret;
// Note: If this is a char, iphone/llvm will encounter an alignment bug
// between this member and MTankGob::m_pgobSecondShot. Direction16
// has been changed to an int for this reason.
Direction16 m_dir16Turret;
};
class SRInfantryGob : public MobileUnitGob // sri
{
public:
SRInfantryGob() secInfantryGob;
static bool InitClass(IniReader *pini) secInfantryGob;
static void ExitClass() secInfantryGob;
// UnitGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secInfantryGob;
virtual void Idle() secInfantryGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secInfantryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secInfantryGob;
#endif
};
class LRInfantryGob : public MobileUnitGob // lri
{
public:
LRInfantryGob() secInfantryGob;
static bool InitClass(IniReader *pini) secInfantryGob;
static void ExitClass() secInfantryGob;
// UnitGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secInfantryGob;
virtual void Idle() secInfantryGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secInfantryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secInfantryGob;
#endif
};
class SpInfantryGob : public MobileUnitGob // lri
{
public:
SpInfantryGob() secInfantryGob;
static bool InitClass(IniReader *pini) secInfantryGob;
static void ExitClass() secInfantryGob;
// UnitGob overrides
virtual bool IsValidTarget(Gob *pgobTarget) secInfantryGob;
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secInfantryGob;
virtual void Idle() secInfantryGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secInfantryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secInfantryGob;
#endif
};
class LTankGob : public TankGob // ltnk
{
public:
LTankGob() secTankGob;
static bool InitClass(IniReader *pini) secTankGob;
static void ExitClass() secTankGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
};
class TankShotGob; // it's down there
class MTankGob : public TankGob // mtnk
{
public:
MTankGob() secTankGob;
~MTankGob() secTankGob;
static bool InitClass(IniReader *pini) secTankGob;
static void ExitClass() secTankGob;
void LaunchProjectile(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget) secTankGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
// UnitGob overrides
virtual void DefUpdate() secTankGob;
virtual void Deactivate() secTankGob;
private:
TankShotGob *m_pgobSecondShot;
short m_cShotcountdown;
};
class RTankGob : public TankGob // rtnk
{
public:
RTankGob() secTankGob;
static bool InitClass(IniReader *pini) secTankGob;
static void ExitClass() secTankGob;
void LaunchProjectile(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget) secTankGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
};
class GTankGob : public TankGob // gtnk
{
public:
GTankGob() secTankGob;
static bool InitClass(IniReader *pini) secTankGob;
static void ExitClass() secTankGob;
// MobileUnitGob overrides
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secTankGob;
// TankGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secTankGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
};
class MinerGob : public MobileUnitGob // mnr
{
public:
MinerGob() secMiner;
static bool InitClass(IniReader *pini) secMiner;
static void ExitClass() secMiner;
int GetGalaxiteAmount() secMiner;
void SetGalaxiteAmount(int nAmount) secMiner;
void SetFavoriteProcessor(Gid gid) secMiner;
void Hide(bool fHide) secMiner;
void SendDeliverCommand(Gid gidProcessor) secMiner;
bool IsAttemptingToDeliver(Gid gid) {
if (m_fAttemptingToDeliver && gid == m_gidFavoriteProcessor)
return true;
return false;
}
// Gob overrides
virtual void InitMenu(Form *pfrm) secMiner;
virtual void OnMenuItemSelected(int id) secMiner;
virtual bool LoadState(Stream *pstm) secMiner;
virtual bool SaveState(Stream *pstm) secMiner;
virtual void GetClippingBounds(Rect *prc) secMiner;
// UnitGob overrides
virtual bool IsValidTarget(Gob *pgobTarget) secMiner;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secMiner;
virtual void Deactivate() secMiner;
virtual void SetTarget(Gid gid, WCoord wxTarget = 0, WCoord wyTarget = 0, WCoord wxCenter = 0, WCoord wyCenter = 0, TCoord tcRadius = 0, WCoord wcMoveDistPerUpdate = 0) secMiner;
#ifdef MP_DEBUG_SHAREDMEM
virtual void MPValidate() secMiner;
#endif
// MobileUnitGob overrides
void PerformAction(char *szAction) secMiner;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secMiner;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
private:
void Mine(WCoord wx, WCoord wy) secMiner;
Gid FindClosestProcessor() secMiner;
private:
Animation m_aniVacuum;
int m_nGalaxiteAmount;
char m_cDelay;
Gid m_gidFavoriteProcessor;
TPoint m_tptGalaxite;
bool m_fMinerUnderAttack;
static AnimationData *s_panidVacuum;
bool m_fAttemptingToDeliver;
#ifdef MP_STRESS
public:
#endif
bool m_fHidden;
};
inline void MinerGob::SetGalaxiteAmount(int nAmount)
{
m_nGalaxiteAmount = nAmount;
}
inline int MinerGob::GetGalaxiteAmount()
{
return m_nGalaxiteAmount;
}
inline void MinerGob::SetFavoriteProcessor(Gid gid)
{
m_gidFavoriteProcessor = gid;
}
// TUNE:
const int knMinerGalaxiteMax = 100; // two full patches of Galaxite
const int knGalaxiteValue = 10;
const int kcMinerSuckDelay = 7; // number of updates between Galaxite decrements
class MobileHqGob : public MobileUnitGob // mhq
{
public:
MobileHqGob() secGob;
static bool InitClass(IniReader *pini) secGob;
static void ExitClass() secGob;
bool CanTransform(TPoint *ptp = NULL) secGob;
// Gob overrides
virtual void InitMenu(Form *pfrm) secGob;
virtual void OnMenuItemSelected(int id) secGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
};
class MobileUnitBuilderGob : public BuilderGob // mub
{
public:
MobileUnitBuilderGob(MobileUnitBuilderConsts *pmubc) secStructures;
// Gob overrides
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secStructures;
virtual void InitMenu(Form *pfrm) secStructures;
virtual void OnMenuItemSelected(int id) secStructures;
virtual void DefUpdate() secStructures;
// UnitGob overrides
virtual void Deactivate() secStructures;
// StructGob overrides
virtual void Takeover(Player *pplr) secStructures;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStructures;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
};
class HrcGob : public MobileUnitBuilderGob // hrc
{
public:
HrcGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
private:
static MobileUnitBuildForm *s_pfrmBuild;
};
class ReactorGob : public StructGob // rctr
{
public:
ReactorGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
};
class ProcessorGob : public StructGob // prcr
{
public:
ProcessorGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
// UnitGob overrides
virtual dword GetAnimationHash();
virtual void GetAnimationBounds(Rect *prc, bool fBase);
virtual void DrawAnimation(DibBitmap *pbm, int x, int y);
// StructGob overrides
virtual bool IsTakeoverable(Player *pplr) secStructures;
virtual void Takeover(Player *pplr) secStructures;
// Gob overrides
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secStructures;
virtual bool LoadState(Stream *pstm) secStructures;
virtual bool SaveState(Stream *pstm) secStructures;
virtual void GetClippingBounds(Rect *prc) secStructures;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStructures;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
private:
void NotifyMinersAttemptingDelivery(bool fDying) secStructures;
Animation m_aniOverlay;
Gid m_gidMiner;
WPoint m_wptFakeMiner;
bool m_fProcessingAnimationInProgress;
bool m_fDoorMoving;
};
class StructureBuildForm;
class HqGob : public BuilderGob // hq
{
public:
HqGob() secStructures;
virtual ~HqGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
// Gob overrides
virtual void InitMenu(Form *pfrm) secGob;
virtual void OnMenuItemSelected(int id) secGob;
// UnitGob overrides
virtual void Deactivate() secStructures;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStructures;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
private:
void RemoveScorch(StructGob *pstru) secStructures;
static StructureBuildForm *s_pfrmBuild;
};
class PlaceStructureForm : public Form, Timer
{
public:
PlaceStructureForm() secStructures;
void SetOwner(BuilderGob *pgobOwner, UnitType ut) secStructures;
BuilderGob *GetOwner() {
return m_pgobOwner;
}
void UpdatePlacementIndicator(WCoord wxViewStart, WCoord wyViewStart, WCoord wxView, WCoord wyView) secStructures;
void SetPassOnInput(bool fPassOn) { m_fPassOnInput = fPassOn; }
bool IsBusy() { return m_pgobOwner != NULL; }
void OnPaintSimUI(DibBitmap *pbm) secStructures;
void OnPaintControlsSimUI(DibBitmap *pbm, UpdateMap *pupd) secStructures;
void UpdatePosition(Event *pevt);
// Timer implementation
virtual void OnTimer(long tCurrent) secStructures;
// Form overrides
virtual void OnControlSelected(word idc) secStructures;
virtual bool OnPenEvent(Event *pevt) secStructures;
virtual void OnScroll(int dx, int dy) secStructures;
virtual bool OnHitTest(Event *pevt) secStructures;
private:
bool FingerHitTest(Event *pevt);
void GetSubRects(WCoord wx, WCoord wy, Rect *prcInside, Rect *prcOutside);
BuilderGob *m_pgobOwner;
StructConsts *m_pstruc;
TCoord m_tx, m_ty;
TCoord m_wxPen, m_wyPen;
int m_wxDragStart, m_wyDragStart;
TCoord m_txStart, m_tyStart;
bool m_fDragging;
bool m_fPassOnInput;
};
class WaitForm : public Form
{
public:
WaitForm(char *pszTitle, bool fFullScreen = false) secForm;
// Form overrides
virtual bool Init(FormMgr *pfrmm, IniReader *pini, word idf) secForm;
virtual void OnPaintBackground(DibBitmap *pbm, UpdateMap *pupd) secForm;
private:
dword m_ctWaitPopup;
char *m_pszTitle;
bool m_fFullScreen;
Rect m_rcOrig;
};
class TransportWaitingUI
{
public:
TransportWaitingUI(int nWaitStr, bool fShow = true) secComm;
TransportWaitingUI(char *psz, bool fShow = true) secComm;
~TransportWaitingUI() secComm;
void Show() secComm;
void Hide() secComm;
private:
Form *m_pfrm;
char *m_psz;
};
class RadarGob : public StructGob // rdr
{
public:
RadarGob() secRadar;
static bool InitClass(IniReader *pini) secRadar;
static void ExitClass() secRadar;
// Struct gob methods
virtual void Activate() secRadar;
virtual void Deactivate() secRadar;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secRadar;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secRadar;
#endif
};
class ResearchGob : public StructGob // rsrch
{
public:
ResearchGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
virtual void UpgradeUpdate() secStructures;
virtual void AbortUpgrade() secStructures;
// Gob overrides - these need to become virtual if this gets a derived class!
virtual void InitMenu(Form *pfrm) secStructures;
virtual void OnMenuItemSelected(int id) secStructures;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secStructures;
virtual void Deactivate() secStructures;
virtual bool LoadState(Stream *pstm) secStructures;
virtual bool SaveState(Stream *pstm) secStructures;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secStructures;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secStructures;
#endif
private:
int m_nCreditsSpentOnUpgrade;
UnitType m_utTarget;
};
class VtsGob : public MobileUnitBuilderGob // vts
{
public:
VtsGob() secStructures;
static bool InitClass(IniReader *pini) secStructures;
static void ExitClass() secStructures;
private:
static MobileUnitBuildForm *s_pfrmBuild;
};
// TUNE: tankshot movement rate
const WCoord kwcTankShotRate = kwcTile / 2;
class TankShotGob : public Gob
{
public:
TankShotGob() secGob;
static bool InitClass(IniReader *pini) secGob;
static void ExitClass() secGob;
bool Init(AnimationData *panid, WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget, WCoord wcMoveRate) secGob;
void Launch() secGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secGob;
virtual GobType GetType() secGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secGob;
virtual void GetClippingBounds(Rect *prc) secGob;
virtual bool IsSavable() secGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
private:
Gid m_gidOwner;
Gid m_gidTarget;
WLineIterator m_li;
Animation m_ani;
int m_nDamage;
public:
static AnimationData *s_panidShot;
};
TankShotGob *CreateTankShotGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord yTarget, int nDamage, Gid gidOwner, Gid gidTarget) secGob;
class BulletGob : public TankShotGob
{
public:
static bool InitClass(IniReader *pini) secGob;
static void ExitClass() secGob;
// Gob methods
virtual GobType GetType() secGob;
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
public:
static AnimationData *s_panidShot;
};
BulletGob *CreateBulletGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord yTarget, int nDamage, Gid gidOwner, Gid gidTarget, bool fEagle = false) secGob;
class AndyShotGob : public TankShotGob
{
public:
static bool InitClass(IniReader *pini) secGob;
static void ExitClass() secGob;
// Gob methods
virtual GobType GetType() secGob;
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
public:
static AnimationData *s_panidShot;
};
AndyShotGob *CreateAndyShotGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord yTarget, int nDamage, Gid gidOwner, Gid gidTarget, bool fEagle = false) secGob;
class RocketGob : public Gob
{
public:
RocketGob() secGob;
static bool InitClass(IniReader *pini) secGob;
static void ExitClass() secGob;
bool Init(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget) secGob;
// Gob methods
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secGob;
virtual bool IsSavable() secGob;
virtual GobType GetType() secGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secGob;
virtual void GetClippingBounds(Rect *prc) secGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secGob;
#endif
private:
Gid m_gidOwner;
Gid m_gidTarget;
WLineIterator m_li;
Animation m_ani;
int m_nDamage;
static AnimationData *s_panidRocket;
static int s_nTrailStrip;
};
RocketGob *CreateRocketGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord wyTarget, int nDamage, Gid gidOwner, Gid gidTarget) secGob;
// SmokeGob
class SmokeGob : public AnimGob
{
public:
SmokeGob(int cLoops) secGob;
bool Init(WCoord wx, WCoord wy, StateMachineId smidNotify) secGob;
// Gob overrides
virtual bool LoadState(Stream *pstm) secGob;
virtual bool SaveState(Stream *pstm) secGob;
virtual bool IsSavable() secGob;
virtual GobType GetType() secGob;
// AnimGob overrides
virtual bool OnStripDone() secGob;
private:
int m_cLoops;
};
// PuffGob
class PuffGob : public AnimGob
{
public:
PuffGob() secGob;
bool Init(WCoord wx, WCoord wy, StateMachineId smidNotify) secGob;
// Gob overrides
virtual bool LoadState(Stream *pstm) secGob;
virtual bool SaveState(Stream *pstm) secGob;
virtual bool IsSavable() secGob;
virtual GobType GetType() secGob;
};
#if 0 // not used anymore
class RicochetGob : public AnimGob
{
public:
bool Init(WCoord wx, WCoord wy, word wfAnm, const char *pszAniName, AnimationData *panid = NULL,
StateMachineId smidNotify = ksmidNull, const char *pszName = NULL) secGob;
// AnimGob overrides
virtual bool OnStripDone() secGob;
private:
bool m_fNew;
};
#endif
// WarehouseGob
class WarehouseGob : public StructGob
{
public:
WarehouseGob() secWarehouse;
static bool InitClass(IniReader *pini) secWarehouse;
static void ExitClass() secWarehouse;
// StructGob overrides
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secWarehouse;
virtual void Takeover(Player *pplr) secWarehouse;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secWarehouse;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secWarehouse;
#endif
};
// TowerGob
class TowerGob : public StructGob
{
public:
TowerGob(TowerConsts *ptwrc) secTowers;
static bool InitClass(TowerConsts *ptwrc, IniReader *pini) secTowers;
static void ExitClass(TowerConsts *ptwrc) secTowers;
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) = 0;
#ifdef DRAW_LINES
void DrawTargetLine(DibBitmap *pbm, int xViewOrigin, int yViewOrigin) secTowers;
#endif
// Gob overrides
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secTowers;
virtual bool LoadState(Stream *pstm) secTowers;
virtual bool SaveState(Stream *pstm) secTowers;
virtual void GetClippingBounds(Rect *prc) secTowers;
// UnitGob overrides
virtual void Activate() secTowers;
virtual void DefUpdate() secTowers;
virtual void SetTarget(Gid gid, WCoord wxTarget = 0, WCoord wyTarget = 0, WCoord wxCenter = 0, WCoord wyCenter = 0, TCoord tcRadius = 0, WCoord wcMoveDistPerUpdate = 0) secTowers;
virtual bool IsValidTarget(Gob *pgobTarget) secTowers;
virtual dword GetAnimationHash() secTowers;
virtual void GetAnimationBounds(Rect *prc, bool fBase) secTowers;
virtual void DrawAnimation(DibBitmap *pbm, int x, int y) secTowers;
// StructGob override
virtual bool IsTakeoverable(Player *pplr) secTowers;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secTowers;
protected:
// UnitGob protected override
virtual UnitGob *FindEnemyNearby(TCoord tcRange) secTowers;
// members
Animation m_aniTurret;
Direction16 m_dir16Turret;
Gid m_gidTargetPrimary;
Gid m_gidTargetSecondary;
long m_tLastFire;
#ifdef DRAW_LINES
public:
#endif
WPoint m_wptTarget;
};
// GunTowerGob
class GunTowerGob : public TowerGob
{
public:
GunTowerGob() secTowers;
static bool InitClass(IniReader *pini) secTowers;
static void ExitClass() secTowers;
// TowerGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secTowers;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secTowers;
#endif
};
// RocketTowerGob
class RocketTowerGob : public TowerGob
{
public:
RocketTowerGob() secTowers;
static bool InitClass(IniReader *pini) secTowers;
static void ExitClass() secTowers;
// TowerGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secTowers;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secTowers;
#endif
};
class ArtilleryGob : public MobileUnitGob // art
{
public:
ArtilleryGob() secArtilleryGob;
static bool InitClass(IniReader *pini) secArtilleryGob;
static void ExitClass() secArtilleryGob;
// UnitGob overrides
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secArtilleryGob;
// StateMachine methods
// virtual int ProcessStateMachineMessage(State st, Message *pmsg) secArtilleryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secArtilleryGob;
#endif
};
class ArtilleryShotGob : public TankShotGob
{
public:
static bool InitClass(IniReader *pini) secArtilleryGob;
static void ExitClass() secArtilleryGob;
// Gob methods
virtual GobType GetType() secArtilleryGob;
// StateMachine methods
#if defined(DEBUG_HELPERS)
virtual char *GetName() secArtilleryGob;
#endif
public:
static AnimationData *s_panidShot;
};
ArtilleryShotGob *CreateArtilleryShotGob(WCoord wx, WCoord wy, WCoord wxTarget, WCoord yTarget, int nDamage, Gid gidOwner, Gid gidTarget) secArtilleryGob;
class AndyGob : public MobileUnitGob
{
public:
AndyGob() secInfantryGob;
AndyGob(MobileUnitConsts *pmuntc) secInfantryGob;
static bool InitClass(IniReader *pini) secInfantryGob;
static void ExitClass() secInfantryGob;
// UnitGob overrides
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secInfantryGob;
virtual bool Fire(UnitGob *puntTarget, WCoord wx, WCoord wy, WCoord wdx, WCoord wdy) secInfantryGob;
virtual void Idle() secInfantryGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secInfantryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secInfantryGob;
#endif
};
class FoxGob : public AndyGob // fox
{
public:
FoxGob() secInfantryGob;
static bool InitClass(IniReader *pini) secInfantryGob;
static void ExitClass() secInfantryGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secInfantryGob;
#endif
};
class ReplicatorGob : public StructGob // rep
{
public:
ReplicatorGob() secReplicatorGob;
static bool InitClass(IniReader *pini) secReplicatorGob;
static void ExitClass() secReplicatorGob;
void GetInputTilePosition(TPoint *ptpt) secReplicatorGob;
void Enable(bool fEnable) secReplicatorGob;
// UnitGob overrides
virtual bool Init(WCoord wx, WCoord wy, Player *pplr, fix fxHealth, dword ff, const char *pszName) secReplicatorGob;
virtual void Draw(DibBitmap *pbm, int xViewOrigin, int yViewOrigin, int nLayer) secReplicatorGob;
virtual void GetClippingBounds(Rect *prc) secReplicatorGob;
virtual bool LoadState(Stream *pstm) secReplicatorGob;
virtual bool SaveState(Stream *pstm) secReplicatorGob;
virtual AnimSprite *CreateHilightSprite() { return NULL; }
// StructGob overrides
virtual void Activate() secReplicatorGob;
virtual void Deactivate() secReplicatorGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secReplicatorGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secReplicatorGob;
#endif
// For query of replicator input points
static void ClearReplicatorCount() {
s_cReplicators = 0;
}
static int GetReplicatorCount() {
return s_cReplicators;
}
static void GetReplicatorInputPoint(int n, TPoint *ptpt) {
*ptpt = s_atptInput[n];
}
protected:
virtual void WaitingForCredits(bool fNeed, bool fOverride = false, Player *pplr = NULL) secReplicatorGob;
private:
bool ClearOutputBay(TCoord txBay, TCoord tyBay, TCoord txOut, TCoord tyOut) secReplicatorGob;
bool m_fEnabled;
bool m_fReplicating;
int m_ifrmLights;
Player *m_pplrNeedCredits;
// For management of replicator input points
static void AddReplicatorInputPoint(TCoord tx, TCoord ty) secReplicatorGob;
static void RemoveReplicatorInputPoint(TCoord tx, TCoord ty) secReplicatorGob;
static int s_cReplicators;
static TPoint s_atptInput[10];
};
const int kdtxReplicatorInput = 2;
const int kdtyReplicatorInput = 0;
const int kdtxReplicatorOutput1 = 1;
const int kdtyReplicatorOutput1 = 2; // 1;
const int kdtxReplicatorOutput2 = 3;
const int kdtyReplicatorOutput2 = 2; // 1;
// ActivatorGob
class ActivatorGob : public AnimGob
{
public:
// Gob overrides
ActivatorGob() {m_fActivated = false;};
virtual bool Init(IniReader *pini, FindProp *pfind, const char *pszName) secReplicatorGob;
virtual bool LoadState(Stream *pstm) secReplicatorGob;
virtual bool SaveState(Stream *pstm) secReplicatorGob;
virtual bool IsSavable() secReplicatorGob;
virtual GobType GetType() secReplicatorGob;
// StateMachine methods
virtual int ProcessStateMachineMessage(State st, Message *pmsg) secReplicatorGob;
#if defined(DEBUG_HELPERS)
virtual char *GetName() secReplicatorGob;
#endif
private:
bool m_fActivated;
};
// MemMgr - for allocs that are mostly read-only.
typedef void *HMem;
typedef word HandleEntry;
typedef word HandleEntryRef;
struct HMemStruct
{
word her;
byte iheap;
};
struct MemHeader
{
word w;
word cbBlock;
};
#define kcHandlesPerTable 64
struct HandleTable
{
int iheFree;
HandleEntry ahe[kcHandlesPerTable];
};
struct Heap
{
byte *pbHeap;
word cbHeap;
MemHeader *pmhdrFreeFirst;
word cbLargestFreeBlock;
word wf;
word nRec;
void *hMem;
};
#define kfHintWillLock 0x1
class MemMgr
{
public:
MemMgr() secMemMgr;
~MemMgr() secMemMgr;
void Init(dword cbDynReserve, dword cbMaxNeeded, dword *pcbTotal) secMemMgr;
void Exit() secMemMgr;
HMem AllocHandle(word cb, word wfHints = 0) secMemMgr;
void FreeHandle(HMem hmem) secMemMgr;
void SetLocked(HMem hmem) secMemMgr;
void ClearLocked(HMem hmem) secMemMgr;
void *GetPtr(HMem hmem) secMemMgr;
void WriteHandle(HMem hmem, word ib, void *pvSrc, word cb) secMemMgr;
void *AllocPtr(word cb) secMemMgr;
void FreePtr(void *pv) secMemMgr;
void WritePtr(void *pvDst, word ib, void *pvSrc, word cb) secMemMgr;
dword GetFreeSize(word *pcbLargestFree = NULL) secMemMgr;
dword GetTotalSize(dword *pcbDyn, dword *pcbDb) secMemMgr;
static void GetInitSize(dword cbDynReserve, dword *pcbDyn, dword *pcbStorage) secMemMgr;
static void OnRebootFreeStorageDatabase(); // must remain in .text section
#ifdef INCL_VALIDATEHEAP
void Validate() secMemMgr;
void ValidateHandleTableFreeEntries() secMemMgr;
#endif
private:
HandleTable *NewHandleTable() secMemMgr;
bool AllocHandleEntry(word *pher) secMemMgr;
void FreeHandleEntry(word her) secMemMgr;
Heap *NewHeap(void *pvHeap, word cbHeap, bool fDbRam, word nRec, void *hMem) secMemMgr;
void WriteHeader(Heap *pheap, MemHeader *pmhdrDst, MemHeader *pmhdrSrc, word cb = sizeof(MemHeader)) secMemMgr;
HMem AllocBlock(int iheap, MemHeader *pmhdr, MemHeader *pmhdrFreeLast, word cbBlock, word wfHints) secMemMgr;
MemHeader *Compact(Heap *pheap, word cbBlock, MemHeader **ppmhdrFreeLast, word wfHints) secMemMgr;
MemHeader *SplitFreeBlock(Heap *pheap, MemHeader *pmhdr, MemHeader *pmhdrFreeLast, MemHeader *pmhdrNew, word wfHints) secMemMgr;
word GetLargestFreeBlockSize(Heap *pheap) secMemMgr;
#ifdef INCL_VALIDATEHEAP
void ValidateHandle(HMem hmem) secMemMgr;
#endif
Heap *m_apheap[64];
int m_cheap;
HandleTable **m_aphtab;
int m_chtab;
int m_chtabAlloced;
dword m_cbTotalFreeBlocks;
#ifdef PIL
LocalID m_lid;
DmOpenRef m_pdb;
#endif
};
extern MemMgr gmmgr;
// Cache Manager.
// 16 bytes for quick lookup
struct CacheEntry // ce
{
CacheEntry *pceNext;
CacheEntry *pcePrev;
word wUniqueLock;
word cbSize;
HMem hmem;
};
#define kcCacheEntries 512
#define kwIndexMask 0x1ff
#define kwUniqueMask 0xfe00
#define kwLockMask 0x001ff
#define kwIncUnique 0x0200
#define kwIncLock 0x0001
class CacheMgr {
public:
CacheMgr() secCacheMgr;
~CacheMgr() secCacheMgr;
bool Init() secCacheMgr;
void Exit() secCacheMgr;
void *GetPtr(CacheHandle hc) secCacheMgr;
void *Lock(CacheHandle hc) secCacheMgr;
void Unlock(CacheHandle hc) secCacheMgr;
bool IsValid(CacheHandle hc) secCacheMgr;
CacheHandle NewObject(void *pv, word cb, word wfHints = 0) secCacheMgr;
void Write(CacheHandle hc, word ib, void *pvSrc, word cb) secCacheMgr;
word GetSize(CacheHandle hc) secCacheMgr;
bool MakeSpace(dword cb) secCacheMgr;
dword GetTotalSize() secCacheMgr;
dword GetLimit() secCacheMgr;
void SetLimit(dword cbLimit) secCacheMgr;
private:
CacheEntry *m_pceList;
CacheEntry *m_pceFirst;
CacheEntry *m_pceFree;
dword m_cbTotalSize;
dword m_cbLimit;
inline CacheHandle MakeHandle(CacheEntry *pce)
{
return (CacheHandle)((pce - m_pceList) | (pce->wUniqueLock & kwUniqueMask));
}
inline CacheEntry *ValidateHandle(CacheHandle hc)
{
if (hc == 0)
return NULL;
word ice = (hc & kwIndexMask);
if (ice >= kcCacheEntries)
return NULL;
CacheEntry *pce = &m_pceList[ice];
if ((pce->wUniqueLock & kwUniqueMask) != (hc & kwUniqueMask))
return NULL;
return pce;
}
inline void Add(CacheEntry *pce)
{
if (m_pceFirst != NULL) {
pce->pceNext = m_pceFirst;
m_pceFirst->pcePrev->pceNext = pce;
pce->pcePrev = m_pceFirst->pcePrev;
m_pceFirst->pcePrev = pce;
} else {
pce->pceNext = pce;
pce->pcePrev = pce;
}
m_pceFirst = pce;
}
inline void Remove(CacheEntry *pce)
{
pce->pcePrev->pceNext = pce->pceNext;
pce->pceNext->pcePrev = pce->pcePrev;
if (pce == m_pceFirst) {
m_pceFirst = pce->pceNext;
if (m_pceFirst == pce)
m_pceFirst = NULL;
}
}
inline void AddToFreeList(CacheEntry *pce)
{
if (m_pceFree != NULL) {
pce->pceNext = m_pceFree;
m_pceFree->pcePrev->pceNext = pce;
pce->pcePrev = m_pceFree->pcePrev;
m_pceFree->pcePrev = pce;
} else {
pce->pceNext = pce;
pce->pcePrev = pce;
}
m_pceFree = pce;
}
inline void RemoveFromFreeList(CacheEntry *pce)
{
pce->pcePrev->pceNext = pce->pceNext;
pce->pceNext->pcePrev = pce->pcePrev;
if (pce == m_pceFree) {
m_pceFree = pce->pceNext;
if (m_pceFree == pce)
m_pceFree = NULL;
}
}
void Discard(CacheEntry *pce) secCacheMgr;
};
extern CacheMgr gcam;
// SoundMgr
#define kcChannelsMax 16
} // namespace wi
#include "sounddevice.h"
namespace wi {
struct PcmHeader // pcmh
{
byte *pb;
word cb;
};
struct SfxEntry // sfxe
{
byte nSound;
byte nChannel; // unused
byte nPriority;
};
#define kcbSfxEntry 3
class SoundMgr // sndm
{
public:
SoundMgr() secSoundMgr;
~SoundMgr() secSoundMgr;
bool Init() secSoundMgr;
void Exit() secSoundMgr;
void Enable(bool fEnable) secSoundMgr;
bool IsEnabled() secSoundMgr;
void PlaySfx(Sfx sfx) secSoundMgr;
void WaitSilence() secSoundMgr;
long FilterSleepTicks(long ct) secSoundMgr;
void SetVolume(int nVolume) secSoundMgr;
int GetVolume() secSoundMgr;
bool SaveStateAndClear() secSoundMgr;
void RestoreState() secSoundMgr;
private:
int m_cChannels;
byte m_anPriorityChannel[kcChannelsMax];
FileMap *m_afmap;
PcmHeader *m_apcmh;
int m_cpcmh;
SfxEntry *m_asfxe;
int m_csfxe;
FileMap m_fmapSfxEntries;
SoundDevice *m_psndd;
bool m_fStateSaved;
bool m_fEnabledSav;
int m_nVolumeSav;
};
extern SoundMgr gsndm;
// StringTable Class
class StringTable
{
public:
StringTable() secStringTable;
~StringTable() secStringTable;
bool Init(char *pszFilename) secStringTable;
bool GetString(int id, char *psz, int cb) secStringTable;
private:
File *m_pfil;
};
extern StringTable *gpstrtbl;
// AlertControl
#define kcchAlertText 64
class AlertControl : public LabelControl, public Timer
{
public:
AlertControl() secAlertControl;
~AlertControl() secAlertControl;
void AddText(const char *psz) secAlertControl;
// Control methods
virtual bool Init(Form *pfrm, IniReader *pini, FindProp *pfind) secAlertControl;
// Timer methods
virtual void OnTimer(long tCurrent) secAlertControl;
private:
word m_wf;
};
// DRM stuff
struct Key // key
{
byte ab[9];
};
extern Key gkey;
bool DrmValidate() secDrm;
//
// Preferences support
//
// Preferences structures change over time. They get backed up by HotSync.
// By carefully versioning the structure HT can load older preference versions
// successfully. Every prefs structure has a version; these are meant to be supported
// versions of preferences; meaning HT will load older versions of each versioned prefs
// structure. They are also sub-versioned by size; this allows us during development to
// add / remove fields and not have HT crash because it is assuming the wrong thing.
// prefs flags
#define kfPrefSoundMuted 1 // must be 1 for compatibility with fMute
#define kfPrefIgnoreBluetoothWarning 2
// Preferences is stored in pack 2 alignment
#pragma pack(push, 2)
// The header necessary on all preferences structures
struct PreferencesVersion
{
dword dwVersion;
dword cbSize;
};
// The versions of preferences structures HT can successfully read
// Use fixed size datatypes
struct PreferencesV100 // prefs
{
PreferencesVersion prefv;
char szUsername[kcbPlayerName];
char szPassword[kcbPlayerName];
char szToken[kcbTokenMax];
word fAnonymous;
word nYearLastRun; // demo time check
word nMonthLastRun;
word nDayLastRun;
word nVolume; // volume
word wfPrefs;
word wfPerfOptions;
word wfHandicap; // Difficulty-affecting flags
int ctGameSpeed; // game speed
word fLassoSelection;
short nHueOffset; // HSL settings
short nSatMultiplier;
short nLumOffset;
word cxModeBest; // Remember what mode / data is best. Check against in case config changes
word cyModeBest;
word nDepthModeBest;
word nDepthDataBest;
word nSizeDataBest;
word nDegreeOrientationBest;
word cxModeLast; // Remember what mode / data was chosen
word cyModeLast;
word nDepthModeLast;
word nDepthDataLast;
word nSizeDataLast;
word nDegreeOrientationLast;
Key key; // DRM key
short nDemoRank;
#if defined(WIN) && !defined(CE)
short nScale;
#endif
double nScrollSpeed;
char szAskURL[512];
};
struct PreferencesV101 : public PreferencesV100
{
// md5 hash (16 bytes) to hex chars (32 bytes) plus zero terminator, rounded up to even number
char szDeviceId[34];
};
typedef PreferencesV101 Preferences;
#pragma pack(pop)
// The current version
#define knVersionPreferencesV100 0x100
#define knVersionPreferencesV101 0x101
#define knVersionPreferences knVersionPreferencesV101
extern Preferences gprefsInit;
bool HostSavePreferences(void *pv, int cb) secHost;
int HostLoadPreferences(void *pv, int cb) secHost;
// Our in-game MessageBox
bool HtMessageBox(word wf, const char *pszTitle, const char *pszFormat, ...) secMisc;
bool HtMessageBox(word idf, word wf, const char *pszTitle, const char *pszBody) secMisc;
DialogForm *CreateHtMessageBox(word idf, word wf, const char *pszTitle, const char *pszBody) secMisc;
const word kfMbWhiteBorder = 0x0001;
const word kfMbClearDib = 0x0002;
const word kfMbKeepTimersEnabled = 0x0004;
// For Wc14Transport.dll to utilize external functionality
struct TransportHost
{
void *(*New)(int size);
void (*Delete)(void *pv);
void (*strncpyz)(char *pszDst, const char *pszSrc, int cb);
void (*Status)(const char *psz);
bool (*HtMessageBox)(unsigned short wf, const char *pszTitle, const char *pszFormat, ...);
TimerMgr *ptimm;
};
// Globals
extern byte grvlp[];
extern byte grvlpLarge[];
extern IniReader *gpiniForms;
extern IniReader *gpiniGame;
extern Font *gapfnt[];
extern Player *gpplrLocal;
extern byte *gmpiclriclrShadow;
extern UnitConsts *gapuntc[kutMax];
extern PlaceStructureForm *gpfrmPlace;
#ifdef DRAW_PATHS
extern bool gfDrawPaths;
#endif
#ifdef DRAW_LINES
extern bool gfDrawLines;
#endif
extern bool gfPlayingBack;
extern CommandQueue gcmdq;
extern bool gfOvermindEnabled;
extern PlayerMgr gplrm;
extern Player gplrDummy;
extern TBitmap *gaptbmScorches[4];
extern BuilderConsts gbldcHq;
extern byte *gpbScratch;
extern word gcbScratch;
extern bool gfLassoSelection;
extern int g_mpDirToDx[8];
extern int g_mpDirToDy[8];
extern int gcxTile;
extern int gcyTile;
extern int gcxyBorder;
extern char gszPlayerName[kcbPlayerName];
extern char gszUsername[kcbPlayerName];
extern char gszPassword[kcbPlayerName];
extern char gszToken[kcbTokenMax];
extern bool gfAnonymous;
extern bool gfDrawUpdateRects;
extern bool gfAutosave;
extern DibBitmap *gpbmClip;
extern FormMgr *gpfrmmSim;
extern FormMgr *gpfrmmInput;
extern MultiFormMgr *gpmfrmm;
extern SpriteManager *gpsprm;
#ifdef STATS_DISPLAY
extern long gcPathScoresCalced;
#endif
extern int gnHueOffset;
extern int gnSatMultiplier;
extern int gnLumOffset;
extern int gnDemoRank;
extern double gnScrollSpeed;
extern char gszAskURL[512];
extern char gszDeviceId[34];
extern int gtGameSpeed;
extern AnimationData *g_panidMoveTarget;
extern UpdateMap *gpupdSim;
extern Color *gaclrFixed;
extern Color gaclr8bpp[];
extern Color gaclr4bpp[];
extern byte gmpDistFromDxy[10][10];
extern TRect *gptrcMapOpaque;
extern TRect gtrcMapOpaque;
extern Upgrade gaupg[kupgtMax];
extern MiniMapControl *gpmm;
#ifdef STRESS
extern bool gfStress;
extern long gtStressTimeout;
#endif
extern byte gmpdirdirOpposite[8];
extern int ganSquared[64];
extern bool gfClearFog;
extern int gnUnitCostMin;
extern int gnUnitCostMax;
extern int gnUnitCostMPMin;
extern int gnUnitCostMPMax;
extern fix gfxMobileUnitArmorStrengthMin;
extern fix gfxMobileUnitArmorStrengthMax;
extern fix gfxStructureArmorStrengthMin;
extern fix gfxStructureArmorStrengthMax;
extern fix gfxStructureDamageMin;
extern fix gfxStructureDamageMax;
extern fix gfxVehicleDamageMin;
extern fix gfxVehicleDamageMax;
extern fix gfxInfantryDamageMin;
extern fix gfxInfantryDamageMax;
extern TCoord gtcFiringRangeMin;
extern TCoord gtcFiringRangeMax;
extern WCoord gwcMoveDistPerUpdateMin;
extern WCoord gwcMoveDistPerUpdateMax;
extern int gnPowerSupplyMin;
extern int gnPowerSupplyMax;
extern int gnPowerDemandMin;
extern int gnPowerDemandMax;
extern int gaiclrSide[kcSides];
extern char *gszVersion;
extern char gszBuildDate[];
extern char gszBuildTime[];
extern bool gfDragSelecting;
extern WPoint s_wptSelect1, s_wptSelect2;
extern WRect gwrcSelection;
extern WPoint s_awptSelection[];
extern int s_cwptSelection;
extern word gwfPerfOptions;
extern word gwfHandicap;
extern int gcStructGobsHumanLimitSP;
extern int gcStructGobsComputerLimitSP;
extern int gcMuntGobsHumanLimitSP;
extern int gcMuntGobsComputerLimitSP;
extern int gcStructGobsComputerDeltaSP;
extern int gcStructGobsHumanDeltaSP;
extern int gcStructGobsLimitMP;
extern int gcMuntGobsLimitMP;
extern int gcSceneryGobsLimit;
extern int gcScorchGobsLimit;
extern int gcSupportGobsLimit;
extern bool gfGrayscale;
extern bool gfDemo;
extern Transport *gptra;
#ifdef MP_STRESS
extern bool gfMPStress;
extern int gnMPPos;
#endif
extern char *gpszDataDir;
extern bool gfIgnoreBluetoothWarning;
inline Color GetColor(int iclr) {
return gaclrFixed[iclr];
}
inline Color GetSideColor(Side side) {
return GetColor(gaiclrSide[side]);
}
// Helpers
inline UnitType UnitTypeFromPVoid(void *pv) {
return *((UnitType *)&pv);
}
inline int IntFromPVoid(void *pv) {
return *((int *)&pv);
}
// Out-of-band data for gameOverEvent (knGoLoadSavedGame case)
extern Stream *gpstmSavedGame;
extern int gimodeReinitialize;
extern bool gfLoadReinitializeSave;
char *_fgets(char *psz, int cch, File *pfil) secMisc;
void HtStrupr(char *psz) secMisc;
#ifdef DEBUG
int _GetRandom(char *pszFile, int nLine) secMisc;
#define GetRandom() _GetRandom(__FILE__, __LINE__)
#else
int _GetRandom() secMisc;
#define GetRandom() _GetRandom()
#endif
void SetRandomSeed(unsigned long nSeed) secMisc;
unsigned long GetRandomSeed() secMisc;
int GetAsyncRandom() secMisc;
void DrawBuildProgressIndicator(DibBitmap *pbm, Rect *prc, int nNumerator, int nDenominator) secGob;
void DrawSelectionIndicator(DibBitmap *pbm, Rect *prc, int nNumerator, int nDenominator) secGob;
void DrawHealthIndicator(DibBitmap *pbm, Rect *prc, int nNumerator, int nDenominator) secGob;
void DrawFullnessIndicator(DibBitmap *pbm, Rect *prc, int nPips, int nPipsMax) secMiner;
void DrawBorder(DibBitmap *pbm, Rect *prc, int nThickness, Color clr, UpdateMap *pupd = NULL) secDibBitmap;
void DrawBitmapBorder(DibBitmap *pbm, UpdateMap *pupd, Rect *prc, AnimationData *panid, int ifrm = 0, Side side = ksideNeutral) secDibBitmap;
int DrawFancyText(DibBitmap *pbm, Font *pfntDefault, char *psz, int x, int y, int cch = 0) secLabelControl;
int GetFancyTextExtent(Font *pfntDefault, char *psz, int cch = 0) secLabelControl;
Direction CalcDir(int dx, int dy) secGob;
Direction16 CalcDir16(int dx, int dy) secGob;
bool FormDragger(Form *pfrm, Event *pevt) secForm;
bool HostMultiplayerGame() secMultiplayer;
bool JoinOrHostMultiplayerGame(const PackId *ppackid) secMultiplayer;
Direction TurnToward(Direction dirTo, Direction dirFrom) secMisc;
int CalcCreditsShare(Player *pplr) secStructures;
void DrawTileMap(byte **ppbMap, int ctx, int cty, byte *pbDst, int cbDstStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside, int cxTile, int cyTile) secTileMap;
FormMgr *CreateFormMgr(DibBitmap *pbm) secFormMgr;
void ShadowHelper(DibBitmap *pbm, UpdateMap *pupd, Rect *prc) secForm;
void FillHelper(DibBitmap *pbm, UpdateMap *pupd, Rect *prc, Color clr) secForm;
void BltHelper(DibBitmap *pbm, HtBitmap *phtbm, UpdateMap *pupd, int xDst, int yDst) secForm;
void RgbToHsl(byte bR, byte bG, byte bB, word *pnH, word *pnS, word *pnL) secMisc;
void HslToRgb(word nH, word nS, word nL, byte *pbR, byte *pbG, byte *pbB) secMisc;
void SetHslAdjustedPalette(Palette *ppal, short nHueOffset, short nSatMultiplier, short nLumOffset) secMisc;
UnitConsts *GetUnitConsts(GobType gt) secGob;
Sfx SfxFromCategory(SfxCategory sfxc) secMisc;
bool ParseNumber(char **ppsz, int *pn) secTrigger;
bool ParseLong(char **ppsz, long *pn) secTrigger;
bool ParseArea(char **ppsz, int *pn) secTrigger;
bool ParseUnitMask(char **ppsz, UnitMask *pum) secTrigger;
bool ParseUpgradeMask(char **ppsz, UpgradeMask *pupgm) secTrigger;
bool ParseString(char **ppsz, char *psz) secTrigger;
SideMask GetSideMaskFromCaSideMask(Side sideCur, word wfCaSideMask) secTrigger;
int GetPlayersListFromCaSideMask(Side sideCur, word wfMask, Player **applr) secTrigger;
void Ecom(int nCharFrom, int nCharTo, char *pszMessage, int nBackground, bool fMore) secEcom;
bool DoModalGameOptionsForm(Palette *ppal, bool fInGame) secGameOptionsForm;
bool ShowDownloadMissionPackForm(PackId *ppackid);
bool DownloadMissionPack(const PackId *ppackid, const char *pszTitle,
bool fPlayButton);
bool DownloadMissionPackFromURL(const char *pszURL, PackId *ppackid,
bool *play);
bool AskInstallMissionPack(const PackId *ppackid, const char *pszUITitle,
const char *pszPackTitle);
bool IsTileFree(TCoord tx, TCoord ty, byte bf = kbfStructure, Gob **ppgob = NULL) secMisc;
void ShowAlert(int id) secAlertControl;
void ShowAlert(const char *psz) secAlertControl;
void SendAttackCommand(Gid gidReceiver, Gid gidTarget) secUnitGob;
word AggBitsFromAgg(int nAggressiveness) secUnitGob;
void FindNearestFreeTile(TCoord tx, TCoord ty, WPoint *pwpt, byte bf = kbfStructure | kbfMobileUnit) secMisc;
void GetPrerequisiteString(char *psz, UnitConsts *puntc) secUnitGob;
void BringInBounds(WCoord *pwx, WCoord *pwy) secMisc;
Direction DirectionFromLocations(TCoord txOld, TCoord tyOld, TCoord txNew, TCoord tyNew) secTerrainMap;
int RadiusFromUnitCount(int cUnits) secMisc;
void MoveUnitsToArea(MobileUnitGob **apmunt, int cpmunt, TRect *ptrc) secTrigger;
void AddPointToLassoSelection(WPoint wpt) secSimUIForm;
void ExpandVars(char *pszSrc, char *pszBuff, int cbBuff) secMisc;
void GetRankTitle(char *psz, int cb) secMisc;
void DoRegisterNowForm() secShell;
bool PickTransport(Transport **pptra) secMultiplayer;
void FormatButtons(Form *pfrm, word *aidc, int cidc, int idcRef, int idcRefNext) secGameOptionsForm;
bool DoInputPanelForm(char **ppszChars, int cRows, const char *pszLabel,
const char *pszEdit, char *pszOut, int cbOut,
bool (*pfnValidateInput)(const char *psz) = NULL) secInputPanelForm;
void DoInputPanelForm(Form *pfrm, word idcLabel, word idcEdit) secInputPanelForm;
void GetSpeedMultiplierString(char *psz, long tGameSpeed) secGameOptionsForm;
bool PtInPolygon(WPoint *awpt, int cwpt, WCoord wx, WCoord wy);
void AddPointToLassoSelection(WPoint wpt);
//const char *GetString(const json::JsonMap *map, const char *key);
#ifdef MP_DEBUG_SHAREDMEM
void MPInitSharedMemoryWindow(bool fServer);
void MPExitSharedMemoryWindow(bool fServer);
void MPUpdateState();
void MPValidateState();
Gob *MPGetGobPtr(Gid gid);
void MPCopyMem(void *pvTo, void *pvFrom, int cb);
void MPValidateMemory(void *pvRemote, void *pvLocal, int cb);
void MPValidateMember2(void *pvLocal, void *pvRemote, int cbThis, int cbOffsetMem, int cbMem);
#define MPValidateMember(c, m, pr) MPValidateMember2(this, pr, sizeof(c), OFFSETOF(c, m), sizeof(m))
#define MPValidateGobMember(c, m) MPValidateMember(c, m, MPGetGobPtr(GetId()))
struct SharedMemWindow
{
bool fDetectSyncErrors;
DWORD pidProcess;
Gob *apgobMaster[kcpgobMax + 1];
};
extern SharedMemWindow gsmw;
extern HANDLE ghSharedMem;
extern SharedMemWindow *gpsmw;
#endif
// Misc runtime stuff
int strnicmp(const char *psz1, const char *psz2, int cch);
char *itoa (int val, char *buf, int radix);
#ifdef DRAW_PATHS
void LoadArrows() secGob;
void FreeArrows() secGob;
void DrawArrow(DibBitmap *pbm, int x, int y, Direction dir, Side side) secGob;
#endif
#ifdef BETA_TIMEOUT
bool CheckBetaTimeout() secMisc;
#endif
struct ClipInfo
{
int cxClip;
int cx;
int cbRowDst;
int cyClip;
};
#ifdef __CPU_68K
extern "C" void DrawTileMap816(byte **ppbMap, int ctx, int cty, byte *pbDst, int cbDstStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside) secCode7;
extern "C" void DrawTileMap824(byte **ppbMap, int ctx, int cty, byte *pbDst, int cbDstStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside) secCode9;
extern "C" void CopyToScreen4bpp(byte *pbSrc, byte *pbDst, byte *mp8to4, int c) secCode14;
extern "C" void FillShadow68K(byte *pbDst, int cbRowDst, int cx, int cy, byte *aclrMap) secCode14;
extern "C" void Fill68K(byte *pbRow, int cx, int cy, int cbStride, byte bFill) secCode11;
extern "C" void LeftToRightBlt68K(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secCode10;
extern "C" void RightToLeftBlt68K(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secCode10;
extern "C" dword DecodeAndMix8BitAdpcmChannelsBy4(MixerState *pmxst, bool fZeroSilence) secCode6;
extern "C" void Decode8BitAdpcmTable() secCode6;
extern "C" word Compile868K(byte *pb, ScanData *psd, bool fOdd) secCode8;
extern "C" void DrawDispatch68K(byte *pb, byte *pbSrc, byte *pbDst, int cbReturn, dword *mpscaiclrSide, byte *mpiclriclrShadow) secCode8;
extern "C" void DrawSelection68k(byte *pbDst, int cxDib, int cxSel, int cySel, int cxTab, int cyTab, byte clrSel, int cxHealth, byte clrHealth, byte *mpclrclrShadow, bool fBrackets) secCode14;
extern "C" void DebugBreak() secCode14;
extern "C" void CopyToScreen2bpp(byte *pbSrc, byte *pbDst, byte *mp8to2Low, byte *mp8to2High) secCode14;
extern "C" void CopyToScreen4bpp(byte *pbSrc, byte *pbDst, byte *mp8to4, int c) secCode14;
extern "C" void CopyToScreen8bpp(byte *pbSrc, byte *pbDst, int cx, int cy) secCode14;
extern "C" void FastMemSet(void *pv, long cb, byte b) secCode14;
extern "C" void UpdateScreen824(bool *pfMap, int ctx, int cty, byte *pbSrc, byte *pbDst, int cbStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside) secCode10;
extern "C" void UpdateScreen816(bool *pfMap, int ctx, int cty, byte *pbSrc, byte *pbDst, int cbStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside) secCode10;
extern "C" void UpdateScreen416(byte *mp8to4, bool *pfMap, int ctx, int cty, byte *pbSrc, byte *pbDst, int cbStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside) secCode11;
#endif
extern "C" word DecompressChunk(byte **ppbCompressed, byte *pbDecompressed, byte *pbCacheEnd, word cbMax) secPackFile;
extern "C" void DecompressToCache(byte *pbCompressed, CacheHandle hc, CompressionHeader *pcoh) secPackFile;
// Thunks
void FillShadowThunk(byte *pbDst, int cbRowDst, int cx, int cy, byte *aclrMap) secThunks;
void FillThunk(byte *pbDst, int cx, int cy, int cbStride, byte bFill) secThunks;
void LeftToRightBltThunk(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secThunks;
void RightToLeftBltThunk(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secThunks;
void DrawTileMapThunk(byte **ppbMap, int ctx, int cty, byte *pbDst, int cbDstStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside, int cxTile, int cyTile) secThunks;
word Compile8Thunk(byte *pb, ScanData *psd, bool fOdd) secThunks;
void DrawDispatchThunk(byte *pb, byte *pbSrc, byte *pbDst, int cbReturn, dword *mpscaiclrSide, byte *mpiclriclrShadow) secThunks;
int YClipToScan(int yClip, int cx, byte*& pop, byte*& pbSrc, word*& psc);
int DrawScan(byte *pbDst, int cx, byte*& pbSrc, byte*& pop, word*& psc,
dword *mpscaiclr, byte *mpiclriclrShadow);
// ARM stuff
void InitArmCode() secArmThunks;
void ExitArmCode() secArmThunks;
void DrawTileMapArm(byte **ppbMap, int ctx, int cty, byte *pbDst, int cbDstStride, int cxLeftTile, int cyTopTile, int cxRightTile, int cyBottomTile, int ctxInside, int ctyInside, int cxTile, int cyTile) secArmThunks;
void LeftToRightBltArm(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secArmThunks;
void RightToLeftBltArm(byte *pbSrc, int cxSrcStride, byte *pbDst, int cxDstStride, int cx, int cy) secArmThunks;
void memsetArm(byte *pbDst, byte b, dword cb) secArmThunks;
void FillArm(byte *pbDst, int cx, int cy, int cbStride, byte bFill) secArmThunks;
void FillShadowArm(byte *pbDst, int cbRowDst, int cx, int cy, byte *aclrMap) secArmThunks;
word Compile8Arm(byte *pb, ScanData *psd, bool fOdd) secArmThunks;
void DrawDispatchArm(byte *pb, byte *pbSrc, byte *pbDst, int cbReturn, dword *mpscaiclrSide, byte *mpiclriclrShadow) secArmThunks;
extern bool gfArmPresent;
// Host stuff
bool HostInit();
void HostExit();
void HostOpenUrl(const char *pszUrl);
bool HostGetEvent(Event *pevt, long ctWait = -1) secHost;
void HostServiceGetEvent() secHost;
void HostOutputDebugString(char *pszFormat, ...) secHost;
long HostGetTickCount() secHost;
long HostGetMillisecondCount() secHost;
long HostRunSpeedTests(DibBitmap *pbmSrc) secHost;
dword HostGetCurrentKeyState(dword keyBit) secHost;
void HostMessageBox(TCHAR *pszFormat, ...) secHost;
Display *HostCreateDisplay() secDisplay;
bool HostIsPenDown() secHost;
const char *HostGetMainDataDir() secHost;
void HostSuspendModalLoop(DibBitmap *pbm) secHost;
void HostNotEnoughMemory(bool fStorage, dword cbFree, dword cbNeed) secHost;
bool HostGetOwnerName(char *pszBuff, int cb, bool fShowError) secHost;
bool HostEnumAddonFiles(Enum *penm, char *pszAddonDir, int cbDir,
char *pszAddon, int cb) secHost;
bool HostIsPOSE() secHost;
void HostGetUserName(char *pszBuff, int cbMax) secHost;
SoundDevice *HostOpenSoundDevice() secSoundDevice;
bool HostSoundServiceProc() secSoundDevice;
void HostSleep(dword ct) secHost;
void HostSetGameThread(base::Thread *thread);
base::Thread& HostGetGameThread();
base::Thread *HostGetGameThreadPointer();
const int knKeyboardAskDefault = 0;
const int knKeyboardAskURL = 1;
void HostInitiateAsk(const char *title, int max, const char *def,
int keyboard = knKeyboardAskDefault, bool secure = false);
void HostGetAskString(char *psz, int cb);
class IChatController;
IChatController *HostGetChatController();
void HostInitiateWebView(const char *title, const char *url);
const char *HostGenerateDeviceId();
// Date
struct Date
{
int nYear;
int nMonth;
int nDay;
};
int CompareDates(Date *pdate1, Date *pdate2) secMisc;
void HostGetCurrentDate(Date *pdate) secHost;
// Silk rects
#define kircSilkGraffiti 0
#define kircSilkApps 1
#define kircSilkMenu 2
#define kircSilkCalc 3
#define kircSilkFind 4
void HostGetSilkRect(int irc, Rect *prc) secHost;
// Host file IO
const word kfOfRead = 0x0001; // same as "rb"
const word kfOfWrite = 0x0002; // same as "wb"
FileHandle HostOpenFile(const char *pszFilename, word wf) secHost;
void HostCloseFile(FileHandle hf) secHost;
dword HostWriteFile(FileHandle hf, void *pv, dword cb) secHost;
dword HostReadFile(FileHandle hf, void *pv, dword cb) secHost;
// Save game
class Stream
{
public:
virtual ~Stream() {}
virtual void Close() = 0;
virtual dword Read(void *pv, dword cb) = 0;
virtual dword Write(void *pv, dword cb) = 0;
virtual bool IsSuccess() = 0;
// Helpers
void ReadString(char *psz, int cb) secStream;
void ReadBytesRLE(byte *pb, int cb) secStream;
inline byte ReadByte()
{
byte b = 0;
Read(&b, sizeof(b));
return b;
}
inline word ReadWord()
{
word w = 0;
Read(&w, sizeof(w));
return w;
}
inline dword ReadDword()
{
dword dw = 0;
Read(&dw, sizeof(dw));
return dw;
}
void WriteString(char *psz) secStream;
void WriteBytesRLE(byte *pb, int cb) secStream;
inline void WriteByte(byte b)
{
Write(&b, sizeof(b));
}
inline void WriteWord(word w)
{
Write(&w, sizeof(w));
}
inline void WriteDword(dword dw)
{
Write(&dw, sizeof(dw));
}
private:
byte *FindRLERepeat(byte *pbStart, byte *pbMax, int cbMin) secStream;
void WriteRLEChunk(byte *pb, int cb, bool fRepeat) secStream;
};
const int knGameReinitializeSave = -3;
const int knGameAutosave = 10;
#define kszTempName "htsavetemp"
int HostGetSaveGameCount() secHost;
bool HostGetSaveGameName(int nGame, char *psz, int cb, Date *pdate, int *pnHours24, int *pnMinutes, int *pnSeconds) secHost;
Stream *HostNewSaveGameStream(int nGame, char *pszName) secHost;
Stream *HostOpenSaveGameStream(int nGame, bool fDelete = false) secHost;
Stream *PickLoadGameStream() secLoadSave;
bool PickSaveGameStream(Stream **ppstm) secLoadSave;
void DeleteStaleSaveGames() secLoadSave;
bool CheckSaveGameVersion(char *pszVersion, byte bPlatform) secLoadSave;
bool HostDeleteSaveGame(char *psz, int nGame) secLoadSave;
// Debug stuff
#if defined(MP_DEBUG) && defined(INCL_TRACE)
#define MpTrace ::wi::HostOutputDebugString
//#define MpTrace(fmt, args...) LOG() << base::Log::Format(fmt, ## args)
#else
#define MpTrace 1 ? (void)0 : ::wi::HostOutputDebugString
#endif
#ifdef INCL_TRACE
#define Trace ::wi::HostOutputDebugString
//#define Trace(fmt, args...) LOG() << base::Log::Format(fmt, ## args)
#else
#define Trace 1 ? (void)0 : ::wi::HostOutputDebugString
#endif
#ifdef STATUS_LINE
void Status(const char *psz) secMisc;
#else
#define Status(psz)
#endif
#ifdef DEBUG_HELPERS
void InitDebugHelpers();
void ExitDebugHelpers();
#endif
#if 0
// Don't need this now that we discovered CE's COREDLL takes care of this.
// However, if we ever build a Windows desktop version of Wc14Transport.dll
// we will want to do this.
// Transport DLLs must call back to the WI .exe for memory management
// This allows us to continue our practice of having the Transport and
// its Connections perform 'new' operations and leave it to the rest
// of the game to 'delete' them.
#if defined(CE) && defined(DLL)
extern TransportHost *gptrah;
inline void* operator new(size_t size)
{
if (size == 0)
size = 1;
return gptrah->New(size);
}
inline void operator delete(void* ptr)
{
if (ptr != NULL)
gptrah->Delete(ptr);
}
#endif
#endif
} // namespace wi
#endif // __HT_H__