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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  *
22  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #ifndef SAGA2_TILE_H
28 #define SAGA2_TILE_H
29 
30 #include "common/memstream.h"
31 #include "saga2/fta.h"
32 #include "saga2/tileload.h"
33 #include "saga2/annoy.h"
34 #include "saga2/terrain.h"
35 #include "saga2/property.h"
36 #include "saga2/tcoords.h"
37 
38 namespace Saga2 {
39 
40 /* ===================================================================== *
41    Tile ID's and asociated functions
42  * ===================================================================== */
43 
44 class   TileBank;
45 typedef TileBank    *TileBankPtr;           // pointer to tile bank
46 
47 
makeTileID(int bank,int num)48 inline TileID makeTileID(int bank, int num) {
49 	return (TileID)((bank << 10) | num);
50 }
51 
TileID2Bank(TileID t,int16 & bank,int16 & num)52 inline void TileID2Bank(TileID t, int16 &bank, int16 &num) {
53 	bank = (int16)(t >> 10);
54 	num = (int16)(t & 0x3ff);
55 }
56 
57 /* ===================================================================== *
58    Inline functions
59  * ===================================================================== */
60 
61 //  Given a U between 0 and 3, and a V between 0 and 3, compute
62 //  a terrain mask for the subtile at (U,V)
63 
calcSubTileMask(int u,int v)64 inline int16 calcSubTileMask(int u, int v) {
65 	return (int16)(1 << ((u << 2) + v));
66 }
67 
68 /* ===================================================================== *
69    Tile Attributes
70  * ===================================================================== */
71 
72 struct TileAttrs {
73 
74 
75 	//  Height above base of tile below which terrain has effect
76 	uint8           terrainHeight;
77 
78 	//  Visual information
79 	uint8           height;                 // height of tile bitmap
80 
81 	//  Terrain information
82 
83 	uint16          terrainMask;            // 16 terrain selector bits
84 	uint8           fgdTerrain,
85 	                bgdTerrain;
86 
87 	//  Reserved bytes
88 	uint8           reserved0[8];         // auto-terrain data
89 
90 	//  Masking information
91 
92 	uint8           maskRule,               // which tile masking rule to use
93 	                altMask;                // for tiles with special masks
94 
95 	//  Altitude information
96 
97 	uint8           cornerHeight[4];
98 
99 	//  Animation information
100 
101 	uint8           cycleRange;             // cycle range for tile
102 	uint8           tileFlags;              // various flags for tile
103 
104 	//  Reserved bytes
105 	uint16          reserved1;
106 
testTerrainTileAttrs107 	int32 testTerrain(int16 mask) {
108 		int32       terrain = 0;
109 
110 		if (terrainMask & mask)  terrain |= (1 << fgdTerrain);
111 		if (~terrainMask & mask) terrain |= (1 << bgdTerrain);
112 		return terrain;
113 	}
114 };
115 
116 enum tile_flags {
117 	//  This tile has been used in at least one activity group
118 	tileInGroup     = (1 << 0),
119 
120 	//  Indicates that an activity group should be placed in lieu
121 	//  of the tile.
122 	tileAutoGroup   = (1 << 1),
123 
124 	//  Indicates that the tile is sensitive to being walked on
125 	tileWalkSense   = (1 << 2),
126 
127 	//  Indicates that tile has been recently modified
128 	tileModified    = (1 << 3)
129 };
130 
131 /* ===================================================================== *
132    Terrain types
133  * ===================================================================== */
134 
135 enum terrainTypes {
136 	terrNumNormal   = 0,
137 	terrNumEasy,
138 	terrNumRough,
139 	terrNumStone,
140 	terrNumWood,
141 	terrNumHedge,
142 	terrNumTree,
143 	terrNumWater,
144 	terrNumFall,
145 	terrNumRamp,
146 	terrNumStair,
147 	terrNumLadder,
148 	terrNumObject,
149 	terrNumActive,
150 	terrNumSlash,
151 	terrNumBash,
152 	terrNumIce,
153 	terrNumCold,
154 	terrNumHot,
155 	terrNumFurniture
156 };
157 
158 enum terrainBits {
159 	terrainNormal       = (1 << terrNumNormal), // clear terrain
160 	terrainEasy         = (1 << terrNumEasy),   // easy terrain (path)
161 	terrainRough        = (1 << terrNumRough),  // rough terrain (shrub)
162 	terrainStone        = (1 << terrNumStone),  // stone obstacle
163 	terrainWood         = (1 << terrNumWood),   // wood obstacle
164 	terrainHedge        = (1 << terrNumHedge),  // penetrable obstacle
165 	terrainTree         = (1 << terrNumTree),   // tree obstacle
166 	terrainWater        = (1 << terrNumWater),  // water (depth given by height)
167 	terrainFall         = (1 << terrNumFall),   // does not support things
168 	terrainRamp         = (1 << terrNumRamp),   // low friction slope
169 	terrainStair        = (1 << terrNumStair),  // high friction slope
170 	terrainLadder       = (1 << terrNumLadder), // vertical climb
171 	terrainObject       = (1 << terrNumObject), // collision with other object
172 	terrainActive       = (1 << terrNumActive), // tile is sensitive to walking on
173 	terrainSlash        = (1 << terrNumSlash),  // Slide Down Slope Left
174 	terrainBash         = (1 << terrNumBash),   // Slide Down Slope Left
175 	terrainIce          = (1 << terrNumIce),
176 	terrainCold         = (1 << terrNumCold),
177 	terrainHot          = (1 << terrNumHot),
178 	terrainFurniture    = (1 << terrNumFurniture)
179 };
180 
181 //  A combination mask of all the terrain types which can have
182 //  sloped surfaces. (Water is a negative sloped surface)
183 
184 const int           terrainSurface  = terrainNormal
185                                       | terrainEasy
186                                       | terrainRough
187                                       | terrainWater
188                                       | terrainRamp
189                                       | terrainCold
190                                       | terrainStair;
191 
192 const int           terrainSolidSurface
193     = terrainNormal
194       | terrainEasy
195       | terrainRough
196       | terrainRamp
197       | terrainCold
198       | terrainStair;
199 
200 //  A combination mask of all terrain types which can have
201 //  raised surfaces.
202 
203 const int           terrainRaised   = terrainStone
204                                       | terrainWood
205                                       | terrainTree
206                                       | terrainHedge
207                                       | terrainFurniture;
208 
209 const int           terrainSupportingRaised = terrainStone
210         | terrainWood
211         | terrainFurniture;
212 
213 const int           terrainImpassable = terrainStone
214                                         | terrainWood
215                                         | terrainTree
216                                         | terrainHedge
217                                         | terrainFurniture;
218 
219 const int           terrainSlow     = terrainRough
220                                       | terrainWater
221                                       | terrainLadder;
222 
223 const int           terrainAverage  = terrainNormal
224                                       | terrainRamp
225                                       | terrainStair;
226 
227 const int           terrainInsubstantial = terrainFall
228         | terrainLadder
229         | terrainSlash
230         | terrainBash;
231 
232 const int           terrainTransparent = terrainSurface
233         | terrainInsubstantial;
234 
235 
236 /* ===================================================================== *
237    Describes an individual tile
238  * ===================================================================== */
239 
240 struct TileInfo {
241 	uint32          offset;                 // offset in tile list
242 	TileAttrs       attrs;                  // tile attributes
243 
combinedTerrainMaskTileInfo244 	int32 combinedTerrainMask(void) {
245 		return (1 << attrs.fgdTerrain) | (1 << attrs.bgdTerrain);
246 	}
247 
hasPropertyTileInfo248 	bool hasProperty(const TileProperty &tileProp) {
249 		return tileProp.operator()(this);
250 	}
251 
252 	static TileInfo *tileAddress(TileID id);
253 	static TileInfo *tileAddress(TileID id, uint8 **imageData);
254 };
255 
256 /* ===================================================================== *
257    Describes a bank of tiles
258  * ===================================================================== */
259 
260 class TileBank {
261 public:
262 	uint32          _numTiles;               // number of tiles in list
263 	TileInfo        *_tileArray;         // variable-sized array
264 
TileBank()265 	TileBank() {
266 		_numTiles = 0;
267 		_tileArray = nullptr;
268 	}
269 
270 	TileBank(Common::SeekableReadStream *stream);
271 	~TileBank();
272 
tile(uint16 index)273 	TileInfo *tile(uint16 index) {
274 		return &_tileArray[index];
275 	}
276 };
277 
278 
279 /* ===================================================================== *
280    TileRef: This structure is used whenever a tile is positioned on a
281    map or TAG. It contains the tile, the tile height, and various flags.
282  * ===================================================================== */
283 
284 struct TileRef {
285 	TileID tile;		// which tile
286 	uint8 flags;		// tile flags
287 	uint8 tileHeight;	// height of tile above platform
288 };
289 
290 enum tileRefFlags {
291 	trTileTAG = (1 << 0),		// this tile part of a TAG
292 	trTileHidden = (1 << 1),	// tile hidden when covered
293 	trTileFlipped = (1 << 2),	// draw tile flipped horizontal
294 	trTileSensitive = (1 << 3)	// tile is triggerable (TAG only)
295 };
296 
297 typedef TileRef *TileRefPtr, **TileRefHandle;
298 
299 void drawMainDisplay(void);
300 
301 /* ===================================================================== *
302    TileCycleData: This structure is used to define continously cycling
303    tiles such as waves on the ocean or a flickering torch.
304  * ===================================================================== */
305 
306 class TileCycleData {
307 public:
308 	int32           counter;                // cycling counter
309 	uint8           pad;                    // odd-byte pad
310 	uint8           numStates,              // number of animated states
311 	                currentState,           // current state of animation
312 	                cycleSpeed;             // speed of cycling (0=none)
313 
314 	TileID          cycleList[16];        // array of tiles
315 
load(Common::SeekableReadStream * stream)316 	void load(Common::SeekableReadStream *stream) {
317 		counter = stream->readSint32LE();
318 		pad = stream->readByte();
319 		numStates = stream->readByte();
320 		currentState = stream->readByte();
321 		cycleSpeed = stream->readByte();
322 
323 		for (int i = 0; i < 16; ++i)
324 			cycleList[i] = stream->readUint16LE();
325 	}
326 };
327 
328 typedef TileCycleData
329 *CyclePtr,              // pointer to cycle data
330 * *CycleHandle;         // handle to cycle data
331 
332 const int maxCycleRanges = 128;             // 128 should do for now...
333 
334 /* ===================================================================== *
335    ActiveTileItem: This is the base class for all of the behavioral
336    objects which can be placed on a tilemap.
337  * ===================================================================== */
338 
339 enum ActiveItemTypes {
340 	activeTypeGroup = 0,
341 	activeTypeInstance
342 };
343 
344 //  A pointer to the array of active item state arrays
345 extern byte **stateArray;
346 
347 class ActiveItemList;
348 
349 class ActiveItem;
350 
351 #include "common/pack-start.h"
352 
353 struct ActiveItemData {
354 	uint32 nextHashDummy;	// next item in hash chain
355 	uint16 scriptClassID;          // associated script object
356 	uint16 associationOffset;      // offset into association table
357 	uint8 numAssociations;        // number of associated items
358 	uint8 itemType;               // item type code.
359 
360 	union {
361 		struct {
362 			uint16  grDataOffset;           // offset to group data
363 			uint8   numStates,              // number of animated states
364 			        uSize,                  // dimensions of group
365 			        vSize,
366 			        animArea,               // uSize * vSize
367 			        triggerWeight,          // sensitivity
368 			        pad;
369 			uint16  reserved0;
370 			uint16  reserved1;
371 		} group;
372 
373 		struct {
374 			int16   groupID;                // id of defining group
375 			int16   u, v, h;
376 			uint16  stateIndex;             // for state-based anims.
377 			uint16  scriptFlags;
378 			uint16  targetU,                // U-coord of target
379 			        targetV;                // V-coord of target
380 			uint8   targetZ,                // Z-coord of target
381 			        worldNum;               // Add 0xf000 to get world Object ID
382 		} instance;
383 	};
384 
385 	ActiveItem *aItem; // active item this ActiveItemData is a part of
386 } PACKED_STRUCT;
387 
388 #include "common/pack-end.h"
389 
390 class ActiveItem {
391 public:
392 	ActiveItem *_nextHash;		// next item in hash chain
393 	int _index;
394 	ActiveItemList *_parent;
395 	ActiveItemData _data;
396 
397 	enum {
398 		activeItemLocked    = (1 << 8),     // The door is locked
399 		activeItemOpen      = (1 << 9),     // The door is open (not used)
400 		activeItemExclusive = (1 << 10)     // Script semaphore
401 	};
402 
403 	ActiveItem(ActiveItemList *parent, int ind, Common::SeekableReadStream *stream);
404 
405 	//  Return the map number of this active item
406 	int16 getMapNum(void);
407 
408 	//  Return the address of an active item, given its ID
409 	static ActiveItem *activeItemAddress(ActiveItemID id);
410 
411 	//  Return this active items ID
412 	ActiveItemID thisID(void);
413 
414 	//  Return this active items ID
415 	ActiveItemID thisID(int16 mapNum);
416 
417 	//  Return a pointer to this TAI's group
getGroup(void)418 	ActiveItem *getGroup(void) {
419 		assert(_data.itemType == activeTypeInstance);
420 		return  activeItemAddress(ActiveItemID(getMapNum(), _data.instance.groupID));
421 	}
422 
423 	enum BuiltInBehaviorType {
424 		builtInNone = 0,                    // TAG handled by SAGA
425 		builtInLamp,                        // TAG has lamp behavior
426 		builtInDoor,                        // TAG has door behavior
427 		builtInTransporter                  // TAG has transporter behavior
428 	};
429 
430 	//  Return the state number of this active item instance
getInstanceState(int16 mapNum)431 	uint8 getInstanceState(int16 mapNum) {
432 		return stateArray[mapNum][_data.instance.stateIndex];
433 	}
434 
435 	//  Set the state number of this active item instance
setInstanceState(int16 mapNum,uint8 state)436 	void setInstanceState(int16 mapNum, uint8 state) {
437 		stateArray[mapNum][_data.instance.stateIndex] = state;
438 	}
439 
builtInBehavior(void)440 	uint8 builtInBehavior(void) {
441 		return (uint8)(_data.instance.scriptFlags >> 13);
442 	}
443 
444 	//  Access to the locked bit
isLocked(void)445 	bool isLocked(void) {
446 		return (bool)(_data.instance.scriptFlags & activeItemLocked);
447 	}
setLocked(bool val)448 	void setLocked(bool val) {
449 		if (val)
450 			_data.instance.scriptFlags |= activeItemLocked;
451 		else
452 			_data.instance.scriptFlags &= ~activeItemLocked;
453 	}
454 
455 	//  Access to the exclusion semaphore
isExclusive(void)456 	bool isExclusive(void) {
457 		return (bool)(_data.instance.scriptFlags & activeItemExclusive);
458 	}
setExclusive(bool val)459 	void setExclusive(bool val) {
460 		if (val)
461 			_data.instance.scriptFlags |= activeItemExclusive;
462 		else
463 			_data.instance.scriptFlags &= ~activeItemExclusive;
464 	}
465 
lockType(void)466 	uint8 lockType(void) {
467 		return (uint8)_data.instance.scriptFlags;
468 	}
469 
470 	//  ActiveItem instance methods
471 	bool use(ObjectID enactor);
472 	bool trigger(ObjectID enactor, ObjectID objID);
473 	bool release(ObjectID enactor, ObjectID objID);
474 	bool acceptLockToggle(ObjectID enactor, uint8 keyCode);
475 
476 	bool inRange(const TilePoint &loc, int16 range);
477 
478 	//  ActiveItem group methods
479 	bool use(ActiveItem *ins, ObjectID enactor);
480 	bool trigger(ActiveItem *ins, ObjectID enactor, ObjectID objID);
481 	bool release(ActiveItem *ins, ObjectID enactor, ObjectID objID);
482 	bool acceptLockToggle(ActiveItem *ins, ObjectID enactor, uint8 keyCode);
483 
inRange(ActiveItem * ins,const TilePoint & loc,int16 range)484 	bool inRange(ActiveItem *ins, const TilePoint &loc, int16 range) {
485 		return      loc.u >= ins->_data.instance.u - range
486 		            &&  loc.v >= ins->_data.instance.v - range
487 		            &&  loc.u <  ins->_data.instance.u + _data.group.uSize + range
488 		            &&  loc.v <  ins->_data.instance.v + _data.group.vSize + range;
489 	}
490 
491 	ObjectID getInstanceContext(void);
492 	Location getInstanceLocation(void);
493 
494 	static void playTAGNoise(ActiveItem *ai, int16 tagNoiseID);
495 
496 };
497 
498 typedef ActiveItem  *ActiveItemPtr,
499         *ActiveItemHandle;
500 
501 struct WorldMapData;
502 
503 class ActiveItemList {
504 public:
505 	int _count;
506 	ActiveItem **_items;
507 	WorldMapData *_parent;
508 
509 	ActiveItemList(WorldMapData *parent, int count, Common::SeekableReadStream *stream);
510 	~ActiveItemList();
511 };
512 
513 #if 0
514 
515 /* ===================================================================== *
516    TileHitZone: This object represents a large region which overlays the
517    tile map without affecting it's appearance. It does not contain any
518    tiles or animation information, it is a behavioral region only.
519    It can be much larger and more complex in shape than an activity group.
520  * ===================================================================== */
521 
522 class TileHitZone : public ActiveItem {
523 public:
524 
525 	//  REM: Allow discontiguous regions??
526 	int16           numVertices;
527 	XArray<Point16> vertexList;
528 
529 	int16 type(void) {
530 		return activeTypeHitZone;
531 	}
532 };
533 
534 class ObjectClass : public ActiveItem {
535 public:
536 	// A general type of object
537 
538 	int16 type(void) {
539 		return activeTypeObjectType;
540 	}
541 };
542 
543 class ObjectInstance : public ActiveItem {
544 public:
545 	TileGroupID     classID;                // ID of object class
546 
547 	// An instance of a specific object.
548 
549 	uint16          u, v, h;                // where the instance lies
550 	uint8           facing;                 // which direction it's facing
551 
552 	int16 type(void) {
553 		return activeTypeObject;
554 	}
555 };
556 #endif
557 
558 
559 /* ============================================================================ *
560    TileActivityTask class
561  * ============================================================================ */
562 
563 //  This class handles the built-in movement of active terrain items. It
564 //  includes things like opening/closing doors, and toggling lamps.
565 //
566 //  Since most things in the game aren't moving at a given point, the
567 //  variables for simulating motion don't need to always be present.
568 
569 class TileActivityTask {
570 	friend class    TileActivityTaskList;
571 	friend class    ActiveItem;
572 
573 	uint8           activityType;           // open or close
574 	uint8           targetState;
575 	ActiveItem      *tai;                   // the tile activity instance
576 	ThreadID        script;                 // script to wake up when task done
577 
578 	enum activityTypes {
579 		activityTypeNone,                   // no activity
580 
581 		activityTypeOpen,                   // open door
582 		activityTypeClose,                  // close door
583 
584 		activityTypeScript                  // scriptable activity
585 	};
586 
587 	void remove(void);                   // tile activity task is finished.
588 
589 public:
590 
591 	//  Functions to create a new tile activity task.
592 	static void openDoor(ActiveItem &activeInstance);
593 	static void closeDoor(ActiveItem &activeInstance);
594 	static void doScript(ActiveItem &activeInstance, uint8 finalState, ThreadID id);
595 
596 	static void updateActiveItems(void);
597 
598 	static void initTileActivityTasks(void);
599 
600 	static TileActivityTask *find(ActiveItem *tai);
601 	static bool setWait(ActiveItem *tai, ThreadID script);
602 };
603 
604 /* ============================================================================ *
605    TileActivityTaskList class
606  * ============================================================================ */
607 
608 class TileActivityTaskList {
609 	friend class    TileActivityTask;
610 
611 public:
612 	Common::List<TileActivityTask *> _list;
613 
614 	//  Constructor -- initial construction
615 	TileActivityTaskList(void);
616 
617 	//  Reconstruct the TileActivityTaskList from an archive buffer
618 	TileActivityTaskList(Common::SeekableReadStream *stream);
619 
620 	void read(Common::InSaveFile *in);
621 	void write(Common::MemoryWriteStreamDynamic *out);
622 
623 	//  Cleanup this list
624 	void cleanup(void);
625 
626 	// get new tile activity task
627 	TileActivityTask    *newTask(ActiveItem *activeInstance);
628 };
629 
630 void moveActiveTerrain(int32 deltaTime);
631 
632 /* ===================================================================== *
633    A structure to record special return values from tileSlopeHeight
634  * ===================================================================== */
635 
636 struct StandingTileInfo {
637 	TileInfo        *surfaceTile;
638 	ActiveItemPtr   surfaceTAG;
639 	TileRef         surfaceRef;
640 	int16           surfaceHeight;
641 };
642 
643 /* ======================================================================= *
644    Platform struct
645  * ======================================================================= */
646 
647 const int           maxPlatforms = 8;
648 
649 struct Platform {
650 	uint16          height,                 // height above ground
651 	                highestPixel;           // tallest tile upper extent
652 	uint16          flags;                  // platform flags
653 	TileRef         tiles[kPlatformWidth][kPlatformWidth];
654 
loadPlatform655 	void load(Common::SeekableReadStream *stream) {
656 		height = stream->readUint16LE();
657 		highestPixel = stream->readUint16LE();
658 		flags = stream->readUint16LE();
659 
660 		for (int j = 0; j < kPlatformWidth; ++j) {
661 			for (int i = 0; i < kPlatformWidth; ++i) {
662 				tiles[j][i].tile = stream->readUint16LE();
663 				tiles[j][i].flags = stream->readByte();
664 				tiles[j][i].tileHeight = stream->readByte();
665 			}
666 		}
667 	}
668 
getTileRefPlatform669 	TileRef &getTileRef(const TilePoint p) {
670 		return tiles[p.u][p.v];
671 	}
672 
getTileRefPlatform673 	TileRef &getTileRef(int16 u, int16 v) {
674 		return tiles[u][v];
675 	}
676 
677 	//  fetch the REAL tile terrain info
678 	TileInfo *fetchTile(int16           mapNum,
679 	                    const TilePoint &pt,
680 	                    const TilePoint &origin,
681 	                    int16           &height,
682 	                    int16           &trFlags);
683 
684 	//  Fetch the tile and the active item it came from...
685 	TileInfo *fetchTAGInstance(
686 	    int16           mapNum,
687 	    const TilePoint &pt,
688 	    const TilePoint &origin,
689 	    StandingTileInfo &sti);
690 
691 	//  fetch the REAL tile terrain info and image data
692 	TileInfo *fetchTile(int16           mapNum,
693 	                    const TilePoint &pt,
694 	                    const TilePoint &origin,
695 	                    uint8           **imageData,
696 	                    int16           &height,
697 	                    int16           &trFlags);
698 
699 	//  Fetch the tile and image data and the active item it came from...
700 	TileInfo *fetchTAGInstance(
701 	    int16           mapNum,
702 	    const TilePoint &pt,
703 	    const TilePoint &origin,
704 	    uint8           **imageData,
705 	    StandingTileInfo &sti);
706 
roofRipIDPlatform707 	uint16   roofRipID(void) {
708 		return (uint16)(flags & 0x0FFF);
709 	}
710 };
711 
712 typedef Platform    *PlatformPtr,
713         * *PlatformHandle;
714 
715 enum platformFlags {
716 	plCutaway = (1 << 0),                   // remove when player underneath
717 
718 	//  Cutaway directions: When platform is cut away, also cut
719 	//  away any adjacent platforms in these directions.
720 	plVisible = (1 << 15),                      // platform is visible
721 	plModified = (1 << 14),                     // platform has been changed
722 	plCutUPos = (1 << 13),
723 	plCutUNeg = (1 << 13),
724 	plCutVPos = (1 << 13),
725 	plCutVNeg = (1 << 13)
726 };
727 
728 #if OLDPLATFLAAGS
729 enum platformFlags {
730 	plCutaway = (1 << 0),                   // remove when player underneath
731 
732 	//  Cutaway directions: When platform is cut away, also cut
733 	//  away any adjacent platforms in these directions.
734 
735 	plCutUPos = (1 << 1),
736 	plCutUNeg = (1 << 2),
737 	plCutVPos = (1 << 3),
738 	plCutVNeg = (1 << 4),
739 
740 	plVisible = (1 << 5),                   // platform is visible
741 	plEnabled = (1 << 6)                    // enforce platform terrain.
742 };
743 #endif
744 
745 /* ======================================================================= *
746    PlatformCacheEntry struct
747  * ======================================================================= */
748 
749 struct PlatformCacheEntry {
750 	uint16          platformNum,            // original platform num
751 	                layerNum;               // index of this plat in mt.
752 	MetaTileID      metaID;                 // pointer to parent metatile
753 	Platform        pl;                     // actual platform data
754 
755 	enum {
756 		kPlatformCacheSize = 256
757 	};
758 };
759 
760 /* ======================================================================= *
761    RipTable struct
762  * ======================================================================= */
763 
764 //  An object roof ripping "z-buffer" type structure
765 
766 typedef int16       RipTableID;
767 
768 struct RipTable {
769 	MetaTileID  metaID;
770 	uint16      ripID;
771 	int16       zTable[kPlatformWidth][kPlatformWidth];
772 	int _index;
773 
774 	enum {
775 		kRipTableSize = 25
776 	};
777 
778 	//  Constructor
RipTableRipTable779 	RipTable(void) : metaID(NoMetaTile), ripID(0), _index(-1) {
780 		for (int i = 0; i < kPlatformWidth; i++)
781 			for (int j = 0; j < kPlatformWidth; j++)
782 				zTable[i][j] = 0;
783 	}
784 
785 	//  Return a pointer to a rip table, given the rip table's ID
786 	static RipTable *ripTableAddress(RipTableID id);
787 
788 	//  Return the rip table's ID
789 	RipTableID thisID(void);
790 };
791 
792 typedef RipTable    *RipTablePtr;
793 typedef RipTableID  *RipTableIDPtr,
794                     **RipTableIDHandle;
795 
796 typedef uint16 metaTileNoise;
797 
798 /* ======================================================================= *
799    MetaTile struct
800  * ======================================================================= */
801 
802 //  A "Metatile" is a larger tile made up of smaller tiles.
803 
804 class MetaTileList;
805 
806 class MetaTile {
807 public:
808 	uint16          _highestPixel;           // more drawing optimization
809 	BankBits        _banksNeeded;            // which banks are needed
810 	uint16          _stack[maxPlatforms];    // pointer to platforms
811 	uint32          _properties;             // more drawing optimization
812 	int             _index;
813 	MetaTileList   *_parent;
814 
815 	MetaTile(MetaTileList *parent, int ind, Common::SeekableReadStream *stream);
816 
817 	//  Return a pointer to a meta tile given its ID
818 	static MetaTile *metaTileAddress(MetaTileID id);
819 
820 	//  Return this meta tile's ID
821 	MetaTileID thisID(int16 mapNum);
822 
823 	//  Return a pointer to the specified platform
824 	Platform *fetchPlatform(int16 mapNum, int16 index);
825 
826 	//  Return a pointer to this metatile's current object ripping
827 	//  table
828 	RipTable *ripTable(int16 mapNum);
829 
830 	//  Return a reference to this meta tile's rip table ID
831 	RipTableID &ripTableID(int16 mapNum);
832 
833 	metaTileNoise HeavyMetaMusic(void);
834 
hasProperty(const MetaTileProperty & metaTileProp,int16 mapNum,const TilePoint & mCoords)835 	bool hasProperty(
836 	    const MetaTileProperty &metaTileProp,
837 	    int16 mapNum,
838 	    const TilePoint &mCoords) {
839 		return metaTileProp(this, mapNum, mCoords);
840 	}
841 };
842 
843 typedef MetaTile    *MetaTilePtr,
844         * *MetaTileHandle;
845 
846 class MetaTileList {
847 public:
848 	int _count;
849 	MetaTile **_tiles;
850 
851 	MetaTileList(int count, Common::SeekableReadStream *stream);
852 	~MetaTileList();
853 };
854 
855 /* ===================================================================== *
856    MapHeader struct
857  * ===================================================================== */
858 
859 struct MapHeader {
860 	int16           size;                   // size of map
861 	int16           edgeType;               // edge type of map
862 	uint16          *mapData;           // start of map array
863 
864 	MapHeader(Common::SeekableReadStream *stream);
865 	~MapHeader();
866 };
867 
868 enum mapEdgeTypes {
869 	edgeTypeBlack = 0,
870 	edgeTypeFill0,
871 	edgeTypeFill1,
872 	edgeTypeRepeat,
873 	edgeTypeWrap
874 };
875 
876 typedef MapHeader   *MapPtr,
877         * *MapHandle;
878 
879 /* ===================================================================== *
880    WorldMapData struct
881  * ===================================================================== */
882 
883 const uint16            metaTileVisited = (1 << 15);
884 
885 struct WorldMapData {
886 	ObjectID            worldID;            //  The number of this map
887 
888 	MapPtr              map;                //  Map data
889 	MetaTileList        *metaList;          //  MetaTile list
890 	TileRefPtr          activeItemData;     //  ActiveItem tileRefs
891 	ActiveItemList      *activeItemList;    //  ActiveItem list
892 	uint16              *assocList;          //  Associations
893 	RipTableIDPtr       ripTableIDList;     //  MetaTile object ripping
894 
895 	ActiveItem          *instHash[513];   //  ActiveItem hash table
896 
897 	int16               metaCount,          //  Number of MetaTiles
898 	                    activeCount;        //  Number of ActiveItems
899 	int16               mapSize;            //  Size of map in meta tiles
900 	int32               mapHeight;          //  Height of map in Y
901 
902 
903 	//  Lookup metatile on map.
904 	MetaTilePtr lookupMeta(TilePoint coords);
905 
906 	//  Build active item instance hash table
907 	void buildInstanceHash(void);
908 
909 	//  Return a pointer to an active item instance based upon the
910 	//  group ID and the MetaTile's coordinates
911 	ActiveItem *findHashedInstance(TilePoint &tp, int16 group);
912 };
913 
914 /* ===================================================================== *
915    MetaTileIterator class
916  * ===================================================================== */
917 
918 class MetaTileIterator {
919 	TilePoint   mCoords;
920 	TileRegion  region;
921 
922 	int16       mapNum;
923 
924 	bool iterate(void);
925 
926 public:
MetaTileIterator(int16 map,const TileRegion & reg)927 	MetaTileIterator(int16 map, const TileRegion &reg) : mapNum(map) {
928 		region.min.u = reg.min.u >> kPlatShift;
929 		region.max.u = (reg.max.u + kPlatMask) >> kPlatShift;
930 		region.min.v = reg.min.v >> kPlatShift;
931 		region.max.v = (reg.max.v + kPlatMask) >> kPlatShift;
932 		region.min.z = region.max.z = 0;
933 	}
934 
935 	MetaTile *first(TilePoint *loc = NULL);
936 	MetaTile *next(TilePoint *loc = NULL);
937 
getMapNum(void)938 	int16 getMapNum(void) {
939 		return mapNum;
940 	}
941 };
942 
943 /* ===================================================================== *
944    TileIterator class
945  * ===================================================================== */
946 
947 class TileIterator {
948 	MetaTileIterator    metaIter;
949 	MetaTile            *mt;
950 	int16               platIndex;
951 	Platform            *platform;
952 	TilePoint           tCoords,
953 	                    origin;
954 	TileRegion          region,
955 	                    tCoordsReg;
956 
957 	bool iterate(void);
958 
959 public:
TileIterator(int16 mapNum,const TileRegion & reg)960 	TileIterator(int16 mapNum, const TileRegion &reg) :
961 		metaIter(mapNum, reg),
962 		region(reg) {
963 			mt = nullptr;
964 			platIndex = 0;
965 			platform = nullptr;
966 	}
967 
968 	TileInfo *first(TilePoint *loc, StandingTileInfo *stiResult = NULL);
969 	TileInfo *next(TilePoint *loc, StandingTileInfo *stiResult = NULL);
970 };
971 
972 /* ===================================================================== *
973    Exports
974  * ===================================================================== */
975 
976 extern StaticTilePoint viewCenter;             // coordinates of view on map
977 
978 //  These two variables define which sectors overlap the view rect.
979 
980 extern uint16       rippedRoofID;
981 
982 /* ===================================================================== *
983    Prototypes
984  * ===================================================================== */
985 
986 //  Initialize map data
987 void initMaps(void);
988 
989 //  Cleanup map data
990 void cleanupMaps(void);
991 
992 void setCurrentMap(int mapNum);              // set which map is current
993 
994 //  Initialize the platform cache
995 void initPlatformCache(void);
996 
997 //  Initialize the tile activity task list
998 void initTileTasks(void);
999 
1000 void saveTileTasks(Common::OutSaveFile *outS);
1001 void loadTileTasks(Common::InSaveFile *in, int32 chunkSize);
1002 
1003 //  Cleanup the tile activity task list
1004 void cleanupTileTasks(void);
1005 
1006 TilePoint getClosestPointOnTAI(ActiveItem *TAI, GameObject *obj);
1007 
1008 void initActiveItemStates(void);
1009 void saveActiveItemStates(Common::OutSaveFile *outS);
1010 void loadActiveItemStates(Common::InSaveFile *in);
1011 void cleanupActiveItemStates(void);
1012 
1013 void initTileCyclingStates(void);
1014 void saveTileCyclingStates(Common::OutSaveFile *outS);
1015 void loadTileCyclingStates(Common::InSaveFile *in);
1016 void cleanupTileCyclingStates(void);
1017 
1018 void initAutoMap(void);
1019 void saveAutoMap(Common::OutSaveFile *outS);
1020 void loadAutoMap(Common::InSaveFile *in, int32 chunkSize);
cleanupAutoMap(void)1021 inline void cleanupAutoMap(void) { /* nothing to do */ }
1022 
1023 //  Determine if a platform is ripped
platformRipped(Platform * pl)1024 inline bool platformRipped(Platform *pl) {
1025 	if (rippedRoofID != 0)
1026 		return pl->roofRipID() == rippedRoofID;
1027 
1028 	return false;
1029 }
1030 
1031 //  Compute visible area in U/V coords
1032 TilePoint XYToUV(const Point32 &pt);
1033 void TileToScreenCoords(const TilePoint &tp, Point16 &p);
1034 void TileToScreenCoords(const TilePoint &tp, StaticPoint16 &p);
1035 
1036 //  Determine height of point on a tile based on four corner heights
1037 int16 ptHeight(const TilePoint &tp, uint8 *cornerHeight);
1038 
1039 
1040 /* --------------------------------------------------------------------- *
1041    Prototypes for TERRAIN.CPP moved to terrain.h
1042  * --------------------------------------------------------------------- */
1043 
1044 
1045 //  Determine which roof is above object
1046 uint16 objRoofID(GameObject *obj);
1047 uint16 objRoofID(GameObject *obj, int16 objMapNum, const TilePoint &objCoords);
1048 
1049 //  Determine if roof over an object is ripped
1050 bool objRoofRipped(GameObject *obj);
1051 
1052 //  Determine if two objects are both under the same roof
1053 bool underSameRoof(GameObject *obj1, GameObject *obj2);
1054 
1055 //  Determine the distance between a point and a line
1056 uint16 lineDist(
1057     const TilePoint &p1,
1058     const TilePoint &p2,
1059     const TilePoint &m);
1060 
1061 /* ============================================================================ *
1062    Misc prototypes
1063  * ============================================================================ */
1064 
1065 //  Converts Local XY to UV coordinates
1066 StaticTilePoint pickTilePos(Point32 pos, const TilePoint &protagPos);
1067 StaticTilePoint pickTile(Point32 pos,
1068                    const TilePoint &protagPos,
1069                    StaticTilePoint *floor = NULL,
1070                    ActiveItemPtr *pickTAI = NULL);
1071 
1072 //  Function to select a nearby site
1073 TilePoint selectNearbySite(
1074     ObjectID        worldID,
1075     const TilePoint &startingCoords,
1076     int32           minDist,
1077     int32           maxDist,
1078     bool            offScreenOnly = false);     // true if we want it off-screen
1079 
1080 void drawMetaTiles(gPixelMap &drawMap);
1081 
1082 } // end of namespace Saga2
1083 
1084 #endif
1085