ScummVM API documentation
colony.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  * Based on the original sources
21  * https://github.com/Croquetx/thecolony
22  * Copyright (C) 1988, David A. Smith
23  *
24  * Distributed under Apache Version 2.0 License
25  *
26  */
27 
28 #ifndef COLONY_H
29 #define COLONY_H
30 
31 #include "common/array.h"
32 #include "common/random.h"
33 #include "common/rect.h"
34 #include "common/rendermode.h"
35 #include "engines/advancedDetector.h"
36 #include "engines/engine.h"
37 #include "graphics/pixelformat.h"
38 #include "graphics/surface.h"
39 
40 namespace Common {
41 class MacResManager;
42 class SeekableReadStreamEndian;
43 }
44 
45 namespace Graphics {
46 class Cursor;
47 class Font;
48 class FrameLimiter;
49 class MacMenu;
50 struct MacMenuItem;
51 class MacWindowManager;
52 class ManagedSurface;
53 }
54 
55 namespace Colony {
56 
57 class Renderer;
58 class Sound;
59 
60 // Engine-wide color packing. The OpenGL renderer's useColor() treats values
61 // with the high byte == 0xFF as direct ARGB (R=bits 16-23, G=8-15, B=0-7) and
62 // values with high byte 0 as palette indices. The PixelFormat below matches
63 // that direct-ARGB layout exactly so we can build colors via ARGBToColor.
64 inline const Graphics::PixelFormat &renderColorFormat() {
65  static const Graphics::PixelFormat fmt(4, 8, 8, 8, 8, 16, 8, 0, 24);
66  return fmt;
67 }
68 
69 inline uint32 packRGB(byte r, byte g, byte b) {
70  return renderColorFormat().ARGBToColor(255, r, g, b);
71 }
72 
73 // Mac native QuickDraw stores RGB as 16-bit-per-channel; we collapse to 8 bits.
74 inline uint32 packMacColor(const uint16 rgb[3]) {
75  return packRGB((byte)(rgb[0] >> 8), (byte)(rgb[1] >> 8), (byte)(rgb[2] >> 8));
76 }
77 
78 enum ColonyAction {
79  kActionNone,
80  kActionMoveForward,
81  kActionMoveBackward,
82  kActionStrafeLeft,
83  kActionStrafeRight,
84  kActionRotateLeft,
85  kActionRotateRight,
86  kActionLookLeft,
87  kActionLookRight,
88  kActionLookBehind,
89  kActionFaceForward,
90  kActionToggleMouselook,
91  kActionToggleDashboard,
92  kActionToggleWireframe,
93  kActionToggleFullscreen,
94  kActionEscape,
95  kActionFire,
96  kActionAutomapZoomIn,
97  kActionAutomapZoomOut
98 };
99 
100 enum GameMode {
101  kModeColony = 2,
102  kModeBattle = 1
103 };
104 
105 enum WallFeatureType {
106  kWallFeatureNone = 0,
107  kWallFeatureDoor = 2,
108  kWallFeatureWindow = 3,
109  kWallFeatureShelves = 4,
110  kWallFeatureUpStairs = 5,
111  kWallFeatureDnStairs = 6,
112  kWallFeatureChar = 7,
113  kWallFeatureGlyph = 8,
114  kWallFeatureElevator = 9,
115  kWallFeatureTunnel = 10,
116  kWallFeatureAirlock = 11,
117  kWallFeatureColor = 12
118 };
119 
120 enum MapDirection {
121  kDirNorth = 0,
122  kDirEast = 1,
123  kDirWest = 2,
124  kDirSouth = 3,
125  kDirCenter = 4
126 };
127 
128 enum RobotType {
129  kRobEye = 1,
130  kRobPyramid = 2,
131  kRobCube = 3,
132  kRobUPyramid = 4,
133  kRobFEye = 5,
134  kRobFPyramid = 6,
135  kRobFCube = 7,
136  kRobFUPyramid = 8,
137  kRobSEye = 9,
138  kRobSPyramid = 10,
139  kRobSCube = 11,
140  kRobSUPyramid = 12,
141  kRobMEye = 13,
142  kRobMPyramid = 14,
143  kRobMCube = 15,
144  kRobMUPyramid = 16,
145  kRobQueen = 17,
146  kRobDrone = 18,
147  kRobSoldier = 19,
148  kRobSnoop = 20
149 };
150 
151 // 3D bounding radius (max XY extent from center) for each robot type.
152 // Used by clampToWalls to keep robot geometry from intersecting wall polygons.
153 // The original 2D wireframe renderer drew walls over robots (painter's algorithm);
154 // in OpenGL 3D both exist as real geometry, so padding is needed.
155 // Capped at 112 so the robot keeps at least 32 units of movement freedom
156 // within a 256-unit cell (256 - 2*112 = 32).
157 inline int robotWallPad(int robotType) {
158  static const int kMaxPad = 112;
159  switch (robotType) {
160  case kRobEye: return 66;
161  case kRobPyramid:
162  case kRobUPyramid: return 85;
163  case kRobCube: return 100;
164  case kRobQueen: return kMaxPad; // actual 120
165  case kRobDrone:
166  case kRobSoldier: return kMaxPad; // actual 130
167  case kRobSnoop: return kMaxPad; // actual 180
168  default: return 40; // eggs and other small types
169  }
170 }
171 
172 enum ObjectType {
173  kObjDesk = 21,
174  kObjPlant = 22,
175  kObjCChair = 23,
176  kObjBed = 24,
177  kObjTable = 25,
178  kObjCouch = 26,
179  kObjChair = 27,
180  kObjTV = 28,
181  kObjScreen = 29,
182  kObjConsole = 30,
183  kObjPowerSuit = 31,
184  kObjForkLift = 32,
185  kObjCryo = 33,
186  kObjBox1 = 34,
187  kObjBox2 = 35,
188  kObjTeleport = 36,
189  kObjDrawer = 37,
190  kObjTub = 38,
191  kObjSink = 39,
192  kObjToilet = 40,
193  kObjBench = 41,
194  kObjPToilet = 43,
195  kObjCBench = 44,
196  kObjProjector = 45,
197  kObjReactor = 46,
198  kObjFWall = 48,
199  kObjCWall = 49,
200  kObjBBed = 42
201 };
202 
203 enum ObjColor {
204  kColorClear = 0,
205  kColorBlack = 1,
206  kColorBlue = 2,
207  kColorGreen = 3,
208  kColorCyan = 4,
209  kColorRed = 5,
210  kColorMagenta = 6,
211  kColorBrown = 7,
212  kColorWhite = 8,
213  kColorDkGray = 9,
214  kColorLtBlue = 10,
215  kColorLtGreen = 11,
216  kColorLtCyan = 12,
217  kColorLtRed = 13,
218  kColorLtMagenta = 14,
219  kColorYellow = 15,
220  kColorIntWhite = 16,
221  kColorBath = 17,
222  kColorWater = 18,
223  kColorSilver = 19,
224  kColorReactor = 20,
225  kColorBlanket = 21,
226  kColorSheet = 22,
227  kColorBed = 23,
228  kColorBox = 24,
229  kColorBench = 25,
230  kColorChair = 26,
231  kColorChairBase = 27,
232  kColorCouch = 28,
233  kColorConsole = 29,
234  kColorTV = 30,
235  kColorTVScreen = 31,
236  kColorDrawer = 32,
237  kColorDesk = 37,
238  kColorDeskTop = 38,
239  kColorDeskChair = 39,
240  kColorMac = 40,
241  kColorMacScreen = 41,
242  kColorCryo = 33,
243  kColorCryoGlass = 34,
244  kColorCryoBase = 35,
245  kColorForklift = 49,
246  kColorTread1 = 50,
247  kColorTread2 = 51,
248  kColorPot = 52,
249  kColorPlant = 53,
250  kColorPower = 54,
251  kColorPBase = 55,
252  kColorPSource = 56,
253  kColorTable = 61,
254  kColorTableBase = 62,
255  kColorPStand = 63,
256  kColorPLens = 64,
257  kColorProjector = 65,
258  kColorTele = 66,
259  kColorTeleDoor = 67,
260  kColorWall = 77,
261  kColorRainbow1 = 80,
262  kColorRainbow2 = 81,
263  kColorRainbow3 = 82,
264  kColorRainbow4 = 83,
265  // Robot colors
266  kColorCube = 36,
267  kColorDrone = 42,
268  kColorClaw1 = 43,
269  kColorClaw2 = 44,
270  kColorEyes = 45,
271  kColorEye = 46,
272  kColorIris = 47,
273  kColorPupil = 48,
274  kColorPyramid = 57,
275  kColorQueen = 58,
276  kColorTopSnoop = 59,
277  kColorBottomSnoop = 60,
278  kColorUPyramid = 68,
279  kColorShadow = 74,
280  kColorLtGray = 75,
281  kColorGray = 76,
282  // Animated reactor/power suit colors (Mac: c_hcore1..c_hcore4, c_ccore, c_color0..c_color3)
283  kColorHCore1 = 100,
284  kColorHCore2 = 101,
285  kColorHCore3 = 102,
286  kColorHCore4 = 103,
287  kColorCCore = 104,
288  // Semantic robot colors that need platform- or level-specific mapping.
289  kColorEyeball = 105,
290  kColorEyeIris = 106,
291  kColorMiniEyeIris = 107,
292  kColorDroneEye = 108,
293  kColorSoldierBody = 109,
294  kColorSoldierEye = 110,
295  kColorQueenBody = 111,
296  kColorQueenEye = 112,
297  kColorQueenWingRed = 113,
298  // The monolith is cBLACK in the DOS table but has its own Mac entry
299  // (c_monolith), so it cannot share the generic kColorBlack mapping.
300  kColorMonolith = 114
301 };
302 
303 enum {
304  kColonyDebugMove = 1 << 0,
305  kColonyDebugRender = 1 << 1,
306  kColonyDebugAnimation = 1 << 2,
307  kColonyDebugMap = 1 << 3,
308  kColonyDebugSound = 1 << 4,
309  kColonyDebugUI = 1 << 5,
310  kColonyDebugCombat = 1 << 6,
311 };
312 
313 // Mac menu action IDs (matching original Mac Colony menu structure)
314 enum MenuAction {
315  kMenuActionAbout = 1,
316  kMenuActionNew,
317  kMenuActionOpen,
318  kMenuActionSave,
319  kMenuActionSaveAs,
320  kMenuActionQuit,
321  kMenuActionSound,
322  kMenuActionCrosshair,
323  kMenuActionPolyFill,
324  kMenuActionCursorShoot
325 };
326 
327 // Menu bar order, matching inits.c:43-48 (myMenus[0..3]).
328 enum MenuIndex {
329  kMenuApple = 0,
330  kMenuFile,
331  kMenuEdit,
332  kMenuOptions
333 };
334 
335 // Object and robot angles keep the original's convention, where the sine table's
336 // own 45-degree phase supplied the last 32 steps; player angles are already
337 // world-absolute. Convert whenever one is used as the other.
338 uint8 objWorldAng(uint8 objectAng);
339 uint8 objAngFromPlayer(uint8 playerAng);
340 
341 static const int kBaseObject = 20;
342 static const int kMeNum = 101;
343 
344 struct Locate {
345  uint8 ang = 0;
346  uint8 look = 0;
347  int8 lookY = 0;
348  int lookx = 0;
349  int delta = 0;
350  int xloc = 0;
351  int yloc = 0;
352  int xindex = 0;
353  int yindex = 0;
354  int xmx = 0, xmn = 0;
355  int zmx = 0, zmn = 0;
356  int32 power[3] = {};
357  int type = 0;
358  int dx = 0, dy = 0;
359  int dist = 0;
360  int wallPad = 0; // 3D bounding radius for wall clamping (0 = use default kWallPad)
361 };
362 
363 struct Thing {
364  int type = 0;
365  int visible = 0;
366  int alive = 0;
367  Common::Rect clip;
368  int count = 0;
369  Locate where;
370  int opcode = 0;
371  int counter = 0;
372  int time = 0;
373  int grow = 0;
374  // void (*make)(); // To be implemented as virtual functions or member function pointers
375  // void (*think)();
376 };
377 
378 // PATCH.C: Tracks object relocations across levels (forklift carry/drop).
379 struct PatchEntry {
380  struct { uint8 level, xindex, yindex; } from;
381  struct { uint8 level, xindex, yindex; int xloc, yloc; uint8 ang; } to;
382  uint8 type;
383  uint8 mapdata[5];
384 };
385 
386 // Temporary location reference for carrying objects.
387 struct PassPatch {
388  uint8 level, xindex, yindex;
389  int xloc, yloc;
390  uint8 ang;
391 };
392 
393 // Per-level persistence: wall state changes (airlock locks) and visit flags.
394 struct LevelData {
395  uint8 visit;
396  uint8 queen;
397  uint8 object[kBaseObject + 1];
398  uint8 count; // airlock open count (termination check)
399  uint8 size; // number of saved wall changes (max 10)
400  uint8 location[10][3]; // [x, y, direction] of each changed wall
401  uint8 data[10][5]; // saved wall feature bytes (5 per location)
402 };
403 
404 struct MacColor {
405  uint16 fg[3];
406  uint16 bg[3];
407  uint16 pattern;
408 };
409 
410 struct Image {
411  int16 width;
412  int16 height;
413  int16 align;
414  int16 rowBytes;
415  int8 bits;
416  int8 planes;
417  byte *data;
418 
419  Image() : width(0), height(0), align(0), rowBytes(0), bits(0), planes(0), data(nullptr) {}
420  ~Image() { delete[] data; }
421 };
422 
423 struct Sprite {
424  Image *fg;
425  Image *mask;
426  Common::Rect clip;
427  Common::Rect locate;
428  bool used;
429 
430  // Per-sprite render cache: bit-pattern + mask are baked into an
431  // alpha-keyed RGBA surface and uploaded once via drawSurface, instead
432  // of issuing setPixel per pixel each frame. Invalidated when the
433  // (fgColor, bgColor) pair changes (level/palette transition).
434  Graphics::Surface *baked;
435  uint64 bakedKey;
436 
437  Sprite() : fg(nullptr), mask(nullptr), used(false), baked(nullptr), bakedKey(0) {}
438  ~Sprite() {
439  delete fg;
440  delete mask;
441  if (baked) {
442  baked->free();
443  delete baked;
444  }
445  }
446 };
447 
449  struct SubObject {
450  int16 spritenum;
451  int16 xloc, yloc;
452  };
453  Common::Array<SubObject> objects;
454  Common::Rect bounds;
455  bool visible;
456  int16 current;
457  int16 xloc, yloc;
458  int16 acurrent;
459  int16 axloc, ayloc;
460  uint8 type;
461  uint8 frozen;
462  uint8 locked;
463  int16 link;
464  int16 key;
465  int16 lock;
466  bool onoff;
467 
468  ComplexSprite() : visible(false), current(0), xloc(0), yloc(0), acurrent(0), axloc(0), ayloc(0), type(0), frozen(0), locked(0), link(0), key(0), lock(0), onoff(true) {}
469 };
470 
471 class Debugger;
472 
473 class ColonyEngine : public Engine {
474  friend class Debugger;
475 public:
476  ColonyEngine(OSystem *syst, const ADGameDescription *gd);
477  virtual ~ColonyEngine();
478 
479  Common::Error run() override;
480  bool hasFeature(EngineFeature f) const override;
481  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
482  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
483  Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
484  Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
485  void pauseEngineIntern(bool pause) override;
486  void applyGameSettings() override;
487  Common::Platform getPlatform() const { return _gameDescription->platform; }
488  bool isSoundEnabled() const { return _soundOn; }
489  const Graphics::Surface *getSavedScreen() const { return _savedScreen; }
490  bool isMacRenderMode() const { return _renderMode == Common::kRenderMacintosh || _renderMode == Common::kRenderMacintoshBW; }
491  bool isMacColorMode() const { return _renderMode == Common::kRenderMacintosh && _hasMacColors; }
492 
493  void initTrig();
494  void loadMacColors();
495  void loadMap(int mnum);
496  void startNewGame();
497  void corridor();
498  void quadrant();
499  bool hasInteractiveWallFeature(int cx, int cy, int dir) const;
500  void clampToWalls(Locate *p);
501  void clampToDiagonalWalls(Locate *p);
502  int checkwallMoveTo(int xnew, int ynew, int xind2, int yind2, Locate *pobject, uint8 trailCode);
503  int checkwallTryFeature(int xnew, int ynew, int xind2, int yind2, Locate *pobject, int dir);
504  int checkwall(int xnew, int ynew, Locate *pobject);
505  void clearPlayerCellMarker();
506  void setPlayerCellMarker();
507  bool playerIntersectsObjectFootprint(const Thing &obj, int xloc, int yloc) const;
508  bool playerStartsInsideObject(int rnum) const;
509  void cCommand(int xnew, int ynew, bool allowInteraction);
510  bool scrollInfo(const Graphics::Font *macFont = nullptr);
511  bool checkSkipRequested();
512  bool checkClickRequested();
513  bool waitForInput();
514  bool waitForMessageInput();
515  void checkCenter();
516  void fallThroughHole();
517  void playTunnelEffect(bool falling);
518  int rideTunnel(const uint8 *map, Locate *pobject);
519  void doDnStairs();
520 
521  void doText(int entry, int center);
522  void inform(const char *text, bool hold);
523  void printMessage(const char *text[], bool hold);
524  void makeMessageRect(Common::Rect &r);
525  int runMacEndgameDialog(const Common::String &message);
526  int runMacSaveQuery();
527  void runMacAbout();
528 
529 private:
530  const ADGameDescription *_gameDescription;
531 
532  uint8 _wall[32][32];
533  uint8 _mapData[31][31][5][5];
534  uint8 _robotArray[32][32];
535  uint8 _foodArray[32][32];
536  uint8 _dirXY[32][32];
537  bool _visited[8][32][32]; // per-level fog-of-war: _visited[level-1][x][y]
538  bool _showAutomap;
539  float _automapZoom; // automap scale factor, 1.0 = default cell size
540 
541  Locate _me;
542  Common::Array<Thing> _objects;
543  int _level;
544  int _robotNum;
545  int _dynamicObjectBase = 0;
546 
547  Renderer *_gfx = nullptr;
548  Sound *_sound = nullptr;
549  Graphics::FrameLimiter *_frameLimiter = nullptr;
550  Common::RenderMode _renderMode;
551  Graphics::Surface *_savedScreen = nullptr;
552  Graphics::Surface *_flIconSurf[5] = {};
553  bool _flIconsLoaded = false;
554 
555 
556  int _tsin = 0, _tcos = 0;
557  int _sint[256];
558  int _cost[256];
559  int _centerX, _centerY;
560  int _width, _height;
561  float _mouseSensitivity;
562  bool _mouseLocked;
563  bool _invertY;
564  bool _soundOn = true;
565  bool _showDashBoard;
566  bool _crosshair;
567  bool _cursorShoot = false;
568  bool _insight;
569  bool _hasKeycard;
570  bool _unlocked;
571  int _weapons;
572  bool _wireframe;
573  bool _widescreen;
574  bool _fullscreen;
575  int _speedShift; // 1-5, movement speed = 1 << (_speedShift - 1)
576 
577  // Continuous movement flags (set/cleared by keymapper action events)
578  bool _moveForward;
579  bool _moveBackward;
580  bool _strafeLeft;
581  bool _strafeRight;
582  bool _rotateLeft;
583  bool _rotateRight;
584  bool _sprint;
585 
586  // Sub-unit accumulators for deltaTime-based smooth movement.
587  // Position uses 256-units-per-cell integers, angles are uint8 — these
588  // retain fractional progress between frames so low speeds aren't lost.
589  float _moveAccumX;
590  float _moveAccumY;
591  float _rotAccum;
592 
593  Common::RandomSource _randomSource;
594  Common::Point _mousePos;
595  uint8 _decode1[4];
596  uint8 _decode2[4];
597  uint8 _decode3[4];
598  uint8 _animDisplay[6];
599  int _coreState[2];
600  int _coreHeight[2];
601  int _corePower[3];
602  int _epower[3]; // log2 display levels for power bars (from qlog)
603  int _coreIndex;
604  int _orbit = 0;
605  int _armor = 0;
606  bool _gametest = false;
607  uint32 _blackoutColor = 0;
608  uint32 _lastClickTime = 0;
609  uint32 _displayCount = 0; // Frame counter for COLOR wall animation (Mac: count)
610  uint32 _lastColonyThinkTime = 0; // Last 125ms CThink tick, for render-only interpolation
611  uint32 _lastHotfootTime = 0; // Time-gate for HOTFOOT damage (~8fps)
612  uint32 _lastAnimUpdate = 0;
613  uint32 _lastWarningChimeTime = 0;
614  uint32 _lastCollisionSoundTime = 0;
615  int _bumpedObject = 0;
616  int _action0 = 0, _action1 = 0;
617  int _creature = 0;
618  bool _allGrow = false;
619  bool _suppressCollisionSound = false;
620 
621  // Battle state (battle.c)
622  int _gameMode = kModeColony;
623  Locate _bfight[16]; // 16 battle enemies
624  Locate _battleEnter; // entrance structure
625  Locate _battleShip; // shuttle
626  Locate _battleProj; // enemy projectile
627  bool _projon = false; // projectile active
628  int _pcount = 0; // projectile countdown
629  int _mountains[256]; // mountain height profile
630  int _battledx = 0; // mountain parallax divisor (Width/59)
631  int _battleRound = 0; // AI round-robin counter
632  Locate *_battlePwh[100] = {}; // visible object pointers (for hit detection)
633  int _battleMaxP = 0; // count of visible objects
634  Locate _pyramids[4][4][15]; // pyramid obstacles: 4x4 quadrants, 15 each
635 
636  // PATCH.C: object relocation + wall state persistence
637  Common::Array<PatchEntry> _patches;
638  PassPatch _carryPatch[2]; // [0]=forklift, [1]=carried object
639  int _carryType; // type of object being carried
640  int _fl; // 0=not in forklift, 1=in forklift empty, 2=carrying object
641  LevelData _levelData[8]; // per-level wall state persistence
642 
643  MacColor _macColors[145];
644  bool _hasMacColors;
645  Graphics::Cursor *_macCrossCursor = nullptr;
646  Graphics::Cursor *_macArrowCursor = nullptr;
647  int _lastLoggedCursorMode = -1;
648 
649  // Mac menu bar (MacWindowManager overlay)
650  Graphics::MacWindowManager *_wm = nullptr;
651  Graphics::MacMenu *_macMenu = nullptr;
652  Graphics::ManagedSurface *_menuSurface = nullptr;
653  int _menuBarHeight = 0;
654  void initMacMenus();
655  void loadMacCursorResources();
656  void handleMenuAction(int action);
657  static void menuCommandsCallback(int action, Common::String &text, void *data);
658  // getSubMenuItem() indexes a submenu; our ids are actions. Look up by action.
659  Graphics::MacMenuItem *macMenuItemForAction(int menuIndex, int action);
660  bool showSaveDialog();
661 
662  int _frntxWall = 0, _frntyWall = 0;
663  int _sidexWall = 0, _sideyWall = 0;
664  int _frntx = 0, _frnty = 0;
665  int _sidex = 0, _sidey = 0;
666  int _front = 0, _side = 0;
667  int _direction = 0;
668 
669  float _eyeDepthPull = 0.0f; // world units the eye parts are pulled at the camera
670  // think.c: the snoop's snout bobs while it hunts (sniff/csniff).
671  int _snoopSnoutZ = 0;
672  int _snoopSniff = 5;
673  int _snoopSniffCount = 0;
674 
675  Common::Rect _clip;
676  Common::Rect _screenR;
677  Common::Rect _dashBoardRect;
678  Common::Rect _compassRect; // DOS: compOval (after shrink); Mac: moveWindow
679  Common::Rect _headsUpRect; // DOS: floorRect; Mac: minimap inside moveWindow
680  Common::Rect _powerRect; // DOS: powerRect; Mac: infoWindow
681 
682  // DOS dashboard layout (from original MetaWINDOW pix_per_Qinch values)
683  int _pQx = 0; // pixels per quarter-inch X (24 for EGA 640x350)
684  int _pQy = 0; // pixels per quarter-inch Y (18 for EGA 640x350)
685  int _powerWidth = 0; // width of each of the 3 power bar columns
686  int _powerHeight = 0; // pixel height per power bar unit (max 5)
687 
688  // Cached decoded PICT surfaces for dashboard panels (Mac color mode)
689  Graphics::Surface *_pictPower = nullptr; // PICT -32755 (normal) or -32760 (trouble)
690  Graphics::Surface *_pictPowerNoArmor = nullptr; // PICT -32761 (no armor, color)
691  Graphics::Surface *_pictCompass = nullptr; // PICT -32757
692  int _pictPowerID = 0; // Track which PICT is cached
693  Graphics::Surface *loadPictSurface(int resID);
694  void drawPictAt(Graphics::Surface *surf, int destX, int destY);
695 
696  uint8 wallAt(int x, int y) const;
697  const uint8 *mapFeatureAt(int x, int y, int direction) const;
698  bool _visibleCell[32][32] = {};
699  void computeVisibleCells();
700  void drawStaticObjects();
701 
702 public:
703  struct PrismPartDef {
704  int pointCount;
705  const int (*points)[3];
706  int surfaceCount;
707  const int (*surfaces)[8];
708  };
709 
710 private:
711  void draw3DPrism(Thing &obj, const PrismPartDef &def, bool useLook, int colorOverride = -1, bool accumulateBounds = false, bool forceVisible = false);
712  void draw3DLeaf(const Thing &obj, const PrismPartDef &def);
713  void draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
714  int pt1x, int pt1y, int pt1z, uint32 fillColor, uint32 outlineColor,
715  bool accumulateBounds = false, bool dosFill = true);
716  void drawPrismOval3D(Thing &thing, const PrismPartDef &def, bool useLook, int colorOverride,
717  bool forceVisible = false, bool dosFill = true);
718  void drawEyeOverlays3D(Thing &thing, const PrismPartDef &irisDef, int irisColorOverride,
719  const PrismPartDef &pupilDef, int pupilColorOverride, bool useLook, bool dosFill = true);
720  void drawDOSEyeSlit3D(Thing &thing, const PrismPartDef &irisDef, bool useLook);
721  void drawBodyEye3D(Thing &obj, int eyeballColor, int pupilColor, float pull);
722  void drawEnemyEye3D(Thing &obj, Thing &eye, int eyeballColor, int irisColor, int pupilColor);
723  void pullTowardCamera(float *px, float *py, float *pz, int count) const;
724  float growRenderTickFraction() const;
725  bool drawInterpolatedGrowRobot(Thing &obj, int eyeballColor, int pupilColor);
726  void drawInterpolatedGrowPrism(Thing &obj, const PrismPartDef &fromDef, const PrismPartDef &toDef, float progress);
727  void drawInterpolatedGrowEye(Thing &obj, int fromStage, int toStage, float progress, int eyeballColor, int pupilColor);
728  bool drawStaticObjectPrisms3D(Thing &obj);
729  void initRobots();
730  void renderCorridor3D();
731  void drawWallFeatures3D();
732  void drawWallFeature3D(int cellX, int cellY, int direction);
733  void drawCellFeature3D(int cellX, int cellY);
734  void getWallFace3D(int cellX, int cellY, int direction, float corners[4][3]);
735  bool isRecessFeature(int x, int y, int direction) const;
736  bool wallSegmentIsOpenWell(int x, int y, uint8 bit) const;
737  void getWallRecess3D(const float corners[4][3], float farC[4][3]) const;
738  void recessPoint(const float nearC[4][3], const float farC[4][3], float u, float v, float depth, float out[3]) const;
739  void recessLine(const float nearC[4][3], const float farC[4][3], float u1, float v1, float d1,
740  float u2, float v2, float d2, uint32 color);
741  void recessQuad(const float nearC[4][3], const float farC[4][3], const float *u, const float *v,
742  const float *d, int count, uint32 color);
743  void clipToWallFace(const float corners[4][3]);
744  void macFillRecess(const float nearC[4][3], const float farC[4][3], const float *u, const float *v,
745  const float *d, int count, int macIdx, bool macColors);
746  void getCellFace3D(int cellX, int cellY, bool ceiling, float corners[4][3]);
747 
748  int occupiedObjectAt(int xnew, int ynew, int x, int y, const Locate *pobject);
749  void interactWithObject(int objNum);
750 
751  // Mouse events (and warpMouse) speak window pixels, because we declare
752  // kSupportsArbitraryResolutions; the hit-test math (whichSprite, _screenR)
753  // is in logical coords. Convert both ways.
754  Common::Point eventMouseToLogical(const Common::Point &p) const;
755  void warpMouseLogical(int x, int y);
756 
757  // shoot.c: shooting and power management
758  void setPower(int p0, int p1, int p2);
759  void cShoot();
760  bool isShootableRobotType(int type) const;
761  bool isShotBlockingObjectType(int type) const;
762  int findAimedObject(const Common::Point &aim, bool *isBlocker = nullptr, int *targetDist = nullptr) const;
763  bool hasAimedRobotTarget() const;
764  void destroyRobot(int num);
765  void explodeFlash(int silentFlips);
766  void invertViewport();
767  void doShootCircles(int cx, int cy);
768  void doBurnHole(int cx, int cy, int radius);
769  void meGetShot();
770 
771  // battle.c: outdoor battle system (OpenGL 3D)
772  void battleInit();
773  void battleSet();
774  void battleThink();
775  void normalizeBattlePlayerPosition();
776  void enterColonyFromBattle(int mapNum, int xloc, int yloc);
777  void battleCommand(int xnew, int ynew);
778  void battleShoot();
779  void battleProjCommand(int xcheck, int ycheck);
780  void renderBattle();
781  void draw3DBattlePrism(const PrismPartDef &def, int worldX, int worldY, uint8 ang, int zShift = 0);
782  void battleBackdrop();
783  void battleDrawPyramids();
784  void battleDrawTanks();
785 
786  // PATCH.C: object relocation + wall state persistence
787  void resetObjectSlot(int slot, int type, int xloc, int yloc, uint8 ang);
788  bool createObject(int type, int xloc, int yloc, uint8 ang);
789  void saveLevelState();
790  void doPatch();
791  void saveWall(int x, int y, int direction);
792  void getWall();
793  void newPatch(int type, const PassPatch &from, const PassPatch &to, const uint8 *mapdata);
794  bool patchMapTo(const PassPatch &to, uint8 *mapdata);
795  bool patchMapFrom(const PassPatch &from, uint8 *mapdata);
796  void exitForklift();
797  void dropCarriedObject();
798  bool stepOutOfCell(uint8 angle, bool backwards = false);
799  bool exitTeleport();
800  void teleportPlayer();
801  bool setDoorState(int x, int y, int direction, int state);
802  int openAdjacentDoors(int x, int y);
803  int goToDestination(const uint8 *map, Locate *pobject);
804  int tryPassThroughFeature(int fromX, int fromY, int direction, Locate *pobject);
805  void playTunnelAirlockEffect();
806  void syncMacMenuChecks();
807  void updateMouseCapture(bool recenter = true);
808  Common::Point getAimPoint() const;
809  void updateViewportLayout();
810  void drawDashboardStep1();
811  void drawDashboardMac();
812  void drawDOSBarGraph(int x, int y, int height);
813  void updateDOSPowerBars();
814  static int qlog(int32 x);
815  void drawMiniMapMarker(int x, int y, int halfSize, uint32 color, bool isMac, const Common::Rect *clip = nullptr);
816  bool hasRobotAt(int x, int y) const;
817  bool hasFoodAt(int x, int y) const;
818  void drawMiniMap(uint32 lineColor);
819  void drawAutomap();
820  void changeAutomapZoom(bool zoomIn);
821  void drawAutomapCryoMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
822  void drawAutomapTeleportMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
823  void drawAutomapForkliftMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
824  void drawAutomapQueenMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
825  void drawAutomapSnoopMarker(int x, int y, int halfSize, int dirX, int dirY, uint32 color, const Common::Rect &clip);
826  void drawAutomapDroneMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
827  void drawAutomapRobotMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
828  void drawAutomapObjectMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
829  void markVisited();
830  void automapCellCorner(int dx, int dy, int xloc, int yloc, int lExt, int tsin, int tcos, int ccx, int ccy, int &sx, int &sy);
831  void automapDrawWall(const Common::Rect &vp, int x1, int y1, int x2, int y2, uint32 color);
832  int automapWallFeature(int fx, int fy, int dir);
833  void automapDrawWallWithFeature(const Common::Rect &vp, int wx1, int wy1, int wx2, int wy2, int feat, int lExt, uint32 color);
834  void drawForkliftOverlay();
835  void loadForkliftIcons();
836  void drawCrosshair();
837  bool clipLineToRect(int &x1, int &y1, int &x2, int &y2, const Common::Rect &clip) const;
838  void wallLine(const float corners[4][3], float u1, float v1, float u2, float v2, uint32 color);
839  void wallPolygon(const float corners[4][3], const float *u, const float *v, int count, uint32 color);
840  void wallChar(const float corners[4][3], uint8 cnum);
841 
842  struct TextIndex {
843  uint32 offset;
844  uint16 ch;
845  uint16 lines;
846  };
847 
848  // Animation system
849  Common::Array<Sprite *> _cSprites;
851  Image *_backgroundMask = nullptr;
852  Image *_backgroundFG = nullptr;
853  // Same render cache convention as Sprite::baked, applied to the
854  // per-animation background image (no Sprite owner, so it lives here).
855  Graphics::Surface *_backgroundBaked = nullptr;
856  uint64 _backgroundBakedKey = 0;
857  Common::Rect _backgroundClip;
858  Common::Rect _backgroundLocate;
859  bool _backgroundActive;
860  Common::MacResManager *_resMan = nullptr;
861  Common::MacResManager *_colorResMan = nullptr;
862  byte _topBG[8] = {};
863  byte _bottomBG[8] = {};
864  int16 _divideBG;
865 
866  // Cache for the animation background pattern. Regenerated only when
867  // pattern bytes / colors / split point change. Replaces a 110k-pixel
868  // setPixel loop with one texture upload, fixing cursor choppiness
869  // during animations on the OpenGL renderer.
870  Graphics::Surface *_animPatternSurface = nullptr;
871  byte _animPatternKeyTopBG[8] = {};
872  byte _animPatternKeyBottomBG[8] = {};
873  int16 _animPatternKeyDivide = -1;
874  uint32 _animPatternKeyTopColor = 0;
875  uint32 _animPatternKeyBotColor = 0;
876  int _animPatternKeyMode = -1; // 0=DOS, 1=Mac B&W, 2=Mac color
877  bool _animPatternValid = false;
878  Common::String _animationName;
879  Common::Array<int16> _animBMColors;
880  bool _animationRunning;
881  int _animationResult;
882  bool _animExitPressed = false;
883  bool _animExitInside = false;
884  Common::Rect _animExitStrip;
885  Common::Rect _animExitButton;
886  Common::Rect _messageSourceRect;
887  int _coderPick[4] = {};
888  int _coderCursor = 0;
889  int _coderPressed = -1;
890  bool _coderPressInside = false;
891  Image *_coderTiles[4] = {};
892  Image *_coderBtnUp = nullptr;
893  Image *_coderBtnDown = nullptr;
894  bool _coderTilesLoaded = false;
895  Common::Rect _coderWin;
896  Common::Rect _coderIconRects[4];
897  bool _doorOpen;
898  int _liftObject = 0; // sprite index for the carried object in lift animation
899  bool _liftUp = false; // current lift state: true=raised, false=lowered
900  int _elevatorFloor;
901  int _airlockX = -1;
902  int _airlockY = -1;
903  int _airlockDirection = -1;
904  bool _airlockTerminate = false;
905  int _teleportX = -1;
906  int _teleportY = -1;
907  bool _teleportInside = false;
908  bool _teleportDone = false;
909 
910  void playIntro();
911  bool makeStars(const Common::Rect &r, int btn);
912  bool makeBlackHole();
913  bool makePlanet();
914  bool timeSquare(const Common::String &str, const Graphics::Font *macFont = nullptr, bool gameOver = false);
915  bool drawPict(int resID);
916  bool loadAnimation(const Common::String &name);
917  bool loadLiftAnimation(int objectType);
918  void deleteAnimation();
919  void takeOff();
920  void fullOfStars();
921  void gameOver(bool kill);
922  void gameOver(bool kill, int savedCryos);
923  int countSavedCryos() const;
924  void playAnimation();
925  void updateAnimation();
926  void drawAnimation();
927  void drawAnimationExitButton(int ox, int oy);
928  void drawColonyCoder(int animOx, int animOy);
929  void loadCoderTiles();
930  bool handleColonyCoderClick(const Common::Point &pt);
931  void drawComplexSprite(int index, int ox, int oy);
932  void drawAnimationImage(Image *img, Image *mask, int x, int y, uint32 fillColor,
933  Graphics::Surface *&bakedCache, uint64 &bakedCacheKey);
934  uint32 resolveAnimColor(int16 bmEntry) const;
935  Image *loadImage(Common::SeekableReadStreamEndian &file);
936  void unpackBytes(Common::SeekableReadStreamEndian &file, byte *dst, uint32 len);
938  int whichSprite(const Common::Point &p);
939  void handleAnimationClick(int item);
940  void playCollisionSound();
941  void handleDeskClick(int item);
942  void handleVanityClick(int item);
943  void handleSlidesClick(int item);
944  void handleTeleshowClick(int item);
945  void handleKeypadClick(int item);
946  void handleSuitClick(int item);
947  void handleDoorClick(int item);
948  void handleAirlockClick(int item);
949  void handleElevatorClick(int item);
950  void handleTeleportClick(int item);
951  void flashTeleportBooth();
952  void handleControlsClick(int item);
953  void dolSprite(int index);
954  void moveObject(int index);
955  void setObjectState(int num, int state);
956  int objectState(int num) const;
957  void setObjectOnOff(int num, bool on);
958  void refreshAnimationDisplay();
959  void cryptArray(uint8 sarray[6], int i, int j, int k, int l);
960  void terminateGame(bool blowup);
961 
962  // think.c / shoot.c: colony robot AI, egg growth, and egg eating
963  void cThink();
964  void cubeThink(int num);
965  void pyramidThink(int num);
966  void upyramidThink(int num);
967  void eyeThink(int num);
968  void queenThink(int num);
969  void droneThink(int num);
970  void snoopThink(int num);
971  void eggThink(int num);
972  int getColonyActiveRobotLimit() const;
973  void copyOverflowObjectToSlot(int num);
974  bool layEgg(int type, int xindex, int yindex);
975  void moveThink(int num);
976  void bigGrow(int num);
977  void growRobot(int num);
978  int scanForPlayer(int num);
979  void robotShoot(int num);
980  void meEat();
981  void respawnObject(int num, int type);
982 };
983 
984 } // End of namespace Colony
985 
986 #endif // COLONY_H
Definition: managed_surface.h:51
Definition: framelimiter.h:40
Definition: macresman.h:126
Definition: str.h:59
Definition: font.h:83
Definition: surface.h:67
EngineFeature
Definition: engine.h:282
Definition: stream.h:77
Definition: error.h:81
Definition: array.h:52
Definition: pixelformat.h:138
Definition: advancedDetector.h:164
Definition: colony.h:379
Definition: random.h:44
RenderMode
Definition: rendermode.h:48
Definition: rect.h:536
Definition: colony.h:703
Definition: stream.h:745
Definition: macwindowmanager.h:149
Definition: colony.h:55
Definition: colony.h:387
Definition: colony.h:363
Definition: ustr.h:57
Definition: atari-cursor.h:35
Definition: colony.h:394
Definition: renderer.h:41
Definition: colony.h:449
Definition: cursor.h:42
Definition: algorithm.h:29
Definition: formatinfo.h:28
Definition: rect.h:144
Definition: colony.h:473
Definition: sound.h:40
Definition: macmenu.h:95
Definition: stream.h:944
Definition: console.h:37
uint32 ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b) const
Definition: pixelformat.h:278
Definition: colony.h:344
Definition: system.h:166
Definition: colony.h:423
Definition: movie_decoder.h:32
Definition: macmenu.h:59
Definition: engine.h:149
Definition: colony.h:448
Platform
Definition: platform.h:93
Definition: colony.h:404