mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-08 10:51:11 +00:00
1087 lines
32 KiB
C++
1087 lines
32 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#ifndef SAGA2_TILE_H
|
|
#define SAGA2_TILE_H
|
|
|
|
#include "common/memstream.h"
|
|
#include "saga2/fta.h"
|
|
#include "saga2/tileload.h"
|
|
#include "saga2/annoy.h"
|
|
#include "saga2/terrain.h"
|
|
#include "saga2/property.h"
|
|
#include "saga2/tcoords.h"
|
|
|
|
namespace Saga2 {
|
|
|
|
/* ===================================================================== *
|
|
Tile ID's and asociated functions
|
|
* ===================================================================== */
|
|
|
|
class TileBank;
|
|
typedef TileBank *TileBankPtr; // pointer to tile bank
|
|
|
|
|
|
inline TileID makeTileID(int bank, int num) {
|
|
return (TileID)((bank << 10) | num);
|
|
}
|
|
|
|
inline void TileID2Bank(TileID t, int16 &bank, int16 &num) {
|
|
bank = (int16)(t >> 10);
|
|
num = (int16)(t & 0x3ff);
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
Inline functions
|
|
* ===================================================================== */
|
|
|
|
// Given a U between 0 and 3, and a V between 0 and 3, compute
|
|
// a terrain mask for the subtile at (U,V)
|
|
|
|
inline int16 calcSubTileMask(int u, int v) {
|
|
return (int16)(1 << ((u << 2) + v));
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
Tile Attributes
|
|
* ===================================================================== */
|
|
|
|
struct TileAttrs {
|
|
|
|
|
|
// Height above base of tile below which terrain has effect
|
|
uint8 terrainHeight;
|
|
|
|
// Visual information
|
|
uint8 height; // height of tile bitmap
|
|
|
|
// Terrain information
|
|
|
|
uint16 terrainMask; // 16 terrain selector bits
|
|
uint8 fgdTerrain,
|
|
bgdTerrain;
|
|
|
|
// Reserved bytes
|
|
uint8 reserved0[8]; // auto-terrain data
|
|
|
|
// Masking information
|
|
|
|
uint8 maskRule, // which tile masking rule to use
|
|
altMask; // for tiles with special masks
|
|
|
|
// Altitude information
|
|
|
|
uint8 cornerHeight[4];
|
|
|
|
// Animation information
|
|
|
|
uint8 cycleRange; // cycle range for tile
|
|
uint8 tileFlags; // various flags for tile
|
|
|
|
// Reserved bytes
|
|
uint16 reserved1;
|
|
|
|
int32 testTerrain(int16 mask) {
|
|
int32 terrain = 0;
|
|
|
|
if (terrainMask & mask) terrain |= (1 << fgdTerrain);
|
|
if (~terrainMask & mask) terrain |= (1 << bgdTerrain);
|
|
return terrain;
|
|
}
|
|
};
|
|
|
|
enum tile_flags {
|
|
// This tile has been used in at least one activity group
|
|
tileInGroup = (1 << 0),
|
|
|
|
// Indicates that an activity group should be placed in lieu
|
|
// of the tile.
|
|
tileAutoGroup = (1 << 1),
|
|
|
|
// Indicates that the tile is sensitive to being walked on
|
|
tileWalkSense = (1 << 2),
|
|
|
|
// Indicates that tile has been recently modified
|
|
tileModified = (1 << 3)
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
Terrain types
|
|
* ===================================================================== */
|
|
|
|
enum terrainTypes {
|
|
terrNumNormal = 0,
|
|
terrNumEasy,
|
|
terrNumRough,
|
|
terrNumStone,
|
|
terrNumWood,
|
|
terrNumHedge,
|
|
terrNumTree,
|
|
terrNumWater,
|
|
terrNumFall,
|
|
terrNumRamp,
|
|
terrNumStair,
|
|
terrNumLadder,
|
|
terrNumObject,
|
|
terrNumActive,
|
|
terrNumSlash,
|
|
terrNumBash,
|
|
terrNumIce,
|
|
terrNumCold,
|
|
terrNumHot,
|
|
terrNumFurniture
|
|
};
|
|
|
|
enum terrainBits {
|
|
terrainNormal = (1 << terrNumNormal), // clear terrain
|
|
terrainEasy = (1 << terrNumEasy), // easy terrain (path)
|
|
terrainRough = (1 << terrNumRough), // rough terrain (shrub)
|
|
terrainStone = (1 << terrNumStone), // stone obstacle
|
|
terrainWood = (1 << terrNumWood), // wood obstacle
|
|
terrainHedge = (1 << terrNumHedge), // penetrable obstacle
|
|
terrainTree = (1 << terrNumTree), // tree obstacle
|
|
terrainWater = (1 << terrNumWater), // water (depth given by height)
|
|
terrainFall = (1 << terrNumFall), // does not support things
|
|
terrainRamp = (1 << terrNumRamp), // low friction slope
|
|
terrainStair = (1 << terrNumStair), // high friction slope
|
|
terrainLadder = (1 << terrNumLadder), // vertical climb
|
|
terrainObject = (1 << terrNumObject), // collision with other object
|
|
terrainActive = (1 << terrNumActive), // tile is sensitive to walking on
|
|
terrainSlash = (1 << terrNumSlash), // Slide Down Slope Left
|
|
terrainBash = (1 << terrNumBash), // Slide Down Slope Left
|
|
terrainIce = (1 << terrNumIce),
|
|
terrainCold = (1 << terrNumCold),
|
|
terrainHot = (1 << terrNumHot),
|
|
terrainFurniture = (1 << terrNumFurniture)
|
|
};
|
|
|
|
// A combination mask of all the terrain types which can have
|
|
// sloped surfaces. (Water is a negative sloped surface)
|
|
|
|
const int terrainSurface = terrainNormal
|
|
| terrainEasy
|
|
| terrainRough
|
|
| terrainWater
|
|
| terrainRamp
|
|
| terrainCold
|
|
| terrainStair;
|
|
|
|
const int terrainSolidSurface
|
|
= terrainNormal
|
|
| terrainEasy
|
|
| terrainRough
|
|
| terrainRamp
|
|
| terrainCold
|
|
| terrainStair;
|
|
|
|
// A combination mask of all terrain types which can have
|
|
// raised surfaces.
|
|
|
|
const int terrainRaised = terrainStone
|
|
| terrainWood
|
|
| terrainTree
|
|
| terrainHedge
|
|
| terrainFurniture;
|
|
|
|
const int terrainSupportingRaised = terrainStone
|
|
| terrainWood
|
|
| terrainFurniture;
|
|
|
|
const int terrainImpassable = terrainStone
|
|
| terrainWood
|
|
| terrainTree
|
|
| terrainHedge
|
|
| terrainFurniture;
|
|
|
|
const int terrainSlow = terrainRough
|
|
| terrainWater
|
|
| terrainLadder;
|
|
|
|
const int terrainAverage = terrainNormal
|
|
| terrainRamp
|
|
| terrainStair;
|
|
|
|
const int terrainInsubstantial = terrainFall
|
|
| terrainLadder
|
|
| terrainSlash
|
|
| terrainBash;
|
|
|
|
const int terrainTransparent = terrainSurface
|
|
| terrainInsubstantial;
|
|
|
|
|
|
/* ===================================================================== *
|
|
Describes an individual tile
|
|
* ===================================================================== */
|
|
|
|
struct TileInfo {
|
|
uint32 offset; // offset in tile list
|
|
TileAttrs attrs; // tile attributes
|
|
|
|
int32 combinedTerrainMask(void) {
|
|
return (1 << attrs.fgdTerrain) | (1 << attrs.bgdTerrain);
|
|
}
|
|
|
|
bool hasProperty(const TileProperty &tileProp) {
|
|
return tileProp.operator()(this);
|
|
}
|
|
|
|
static TileInfo *tileAddress(TileID id);
|
|
static TileInfo *tileAddress(TileID id, uint8 **imageData);
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
Describes a bank of tiles
|
|
* ===================================================================== */
|
|
|
|
class TileBank {
|
|
public:
|
|
uint32 _numTiles; // number of tiles in list
|
|
TileInfo *_tileArray; // variable-sized array
|
|
|
|
TileBank() {
|
|
_numTiles = 0;
|
|
_tileArray = nullptr;
|
|
}
|
|
|
|
TileBank(Common::SeekableReadStream *stream);
|
|
~TileBank();
|
|
|
|
TileInfo *tile(uint16 index) {
|
|
return &_tileArray[index];
|
|
}
|
|
};
|
|
|
|
|
|
/* ===================================================================== *
|
|
TileRef: This structure is used whenever a tile is positioned on a
|
|
map or TAG. It contains the tile, the tile height, and various flags.
|
|
* ===================================================================== */
|
|
|
|
struct TileRef {
|
|
TileID tile; // which tile
|
|
uint8 flags; // tile flags
|
|
uint8 tileHeight; // height of tile above platform
|
|
};
|
|
|
|
enum tileRefFlags {
|
|
trTileTAG = (1 << 0), // this tile part of a TAG
|
|
trTileHidden = (1 << 1), // tile hidden when covered
|
|
trTileFlipped = (1 << 2), // draw tile flipped horizontal
|
|
trTileSensitive = (1 << 3) // tile is triggerable (TAG only)
|
|
};
|
|
|
|
typedef TileRef *TileRefPtr, **TileRefHandle;
|
|
|
|
void drawMainDisplay(void);
|
|
|
|
/* ===================================================================== *
|
|
TileCycleData: This structure is used to define continously cycling
|
|
tiles such as waves on the ocean or a flickering torch.
|
|
* ===================================================================== */
|
|
|
|
class TileCycleData {
|
|
public:
|
|
int32 counter; // cycling counter
|
|
uint8 pad; // odd-byte pad
|
|
uint8 numStates, // number of animated states
|
|
currentState, // current state of animation
|
|
cycleSpeed; // speed of cycling (0=none)
|
|
|
|
TileID cycleList[16]; // array of tiles
|
|
|
|
void load(Common::SeekableReadStream *stream) {
|
|
counter = stream->readSint32LE();
|
|
pad = stream->readByte();
|
|
numStates = stream->readByte();
|
|
currentState = stream->readByte();
|
|
cycleSpeed = stream->readByte();
|
|
|
|
for (int i = 0; i < 16; ++i)
|
|
cycleList[i] = stream->readUint16LE();
|
|
}
|
|
};
|
|
|
|
typedef TileCycleData
|
|
*CyclePtr, // pointer to cycle data
|
|
* *CycleHandle; // handle to cycle data
|
|
|
|
const int maxCycleRanges = 128; // 128 should do for now...
|
|
|
|
/* ===================================================================== *
|
|
ActiveTileItem: This is the base class for all of the behavioral
|
|
objects which can be placed on a tilemap.
|
|
* ===================================================================== */
|
|
|
|
enum ActiveItemTypes {
|
|
activeTypeGroup = 0,
|
|
activeTypeInstance
|
|
};
|
|
|
|
// A pointer to the array of active item state arrays
|
|
extern byte **stateArray;
|
|
|
|
class ActiveItemList;
|
|
|
|
#include "common/pack-start.h"
|
|
|
|
struct ActiveItemData {
|
|
uint32 nextHashDummy; // next item in hash chain
|
|
uint16 scriptClassID; // associated script object
|
|
uint16 associationOffset; // offset into association table
|
|
uint8 numAssociations; // number of associated items
|
|
uint8 itemType; // item type code.
|
|
|
|
union {
|
|
struct {
|
|
uint16 grDataOffset; // offset to group data
|
|
uint8 numStates, // number of animated states
|
|
uSize, // dimensions of group
|
|
vSize,
|
|
animArea, // uSize * vSize
|
|
triggerWeight, // sensitivity
|
|
pad;
|
|
uint16 reserved0;
|
|
uint16 reserved1;
|
|
} group;
|
|
|
|
struct {
|
|
int16 groupID; // id of defining group
|
|
int16 u, v, h;
|
|
uint16 stateIndex; // for state-based anims.
|
|
uint16 scriptFlags;
|
|
uint16 targetU, // U-coord of target
|
|
targetV; // V-coord of target
|
|
uint8 targetZ, // Z-coord of target
|
|
worldNum; // Add 0xf000 to get world Object ID
|
|
} instance;
|
|
};
|
|
} PACKED_STRUCT;
|
|
|
|
#include "common/pack-end.h"
|
|
|
|
class ActiveItem {
|
|
public:
|
|
ActiveItem *_nextHash; // next item in hash chain
|
|
int _index;
|
|
ActiveItemList *_parent;
|
|
ActiveItemData _data;
|
|
|
|
enum {
|
|
activeItemLocked = (1 << 8), // The door is locked
|
|
activeItemOpen = (1 << 9), // The door is open (not used)
|
|
activeItemExclusive = (1 << 10) // Script semaphore
|
|
};
|
|
|
|
ActiveItem(ActiveItemList *parent, int ind, Common::SeekableReadStream *stream);
|
|
|
|
// Return the map number of this active item
|
|
int16 getMapNum(void);
|
|
|
|
// Return the address of an active item, given its ID
|
|
static ActiveItem *activeItemAddress(ActiveItemID id);
|
|
|
|
// Return this active items ID
|
|
ActiveItemID thisID(void);
|
|
|
|
// Return this active items ID
|
|
ActiveItemID thisID(int16 mapNum);
|
|
|
|
// Return a pointer to this TAI's group
|
|
ActiveItem *getGroup(void) {
|
|
assert(_data.itemType == activeTypeInstance);
|
|
return activeItemAddress(ActiveItemID(getMapNum(), _data.instance.groupID));
|
|
}
|
|
|
|
enum BuiltInBehaviorType {
|
|
builtInNone = 0, // TAG handled by SAGA
|
|
builtInLamp, // TAG has lamp behavior
|
|
builtInDoor, // TAG has door behavior
|
|
builtInTransporter // TAG has transporter behavior
|
|
};
|
|
|
|
// Return the state number of this active item instance
|
|
uint8 getInstanceState(int16 mapNum) {
|
|
return stateArray[mapNum][_data.instance.stateIndex];
|
|
}
|
|
|
|
// Set the state number of this active item instance
|
|
void setInstanceState(int16 mapNum, uint8 state) {
|
|
stateArray[mapNum][_data.instance.stateIndex] = state;
|
|
}
|
|
|
|
uint8 builtInBehavior(void) {
|
|
return (uint8)(_data.instance.scriptFlags >> 13);
|
|
}
|
|
|
|
// Access to the locked bit
|
|
bool isLocked(void) {
|
|
return (bool)(_data.instance.scriptFlags & activeItemLocked);
|
|
}
|
|
void setLocked(bool val) {
|
|
if (val)
|
|
_data.instance.scriptFlags |= activeItemLocked;
|
|
else
|
|
_data.instance.scriptFlags &= ~activeItemLocked;
|
|
}
|
|
|
|
// Access to the exclusion semaphore
|
|
bool isExclusive(void) {
|
|
return (bool)(_data.instance.scriptFlags & activeItemExclusive);
|
|
}
|
|
void setExclusive(bool val) {
|
|
if (val)
|
|
_data.instance.scriptFlags |= activeItemExclusive;
|
|
else
|
|
_data.instance.scriptFlags &= ~activeItemExclusive;
|
|
}
|
|
|
|
uint8 lockType(void) {
|
|
return (uint8)_data.instance.scriptFlags;
|
|
}
|
|
|
|
// ActiveItem instance methods
|
|
bool use(ObjectID enactor);
|
|
bool trigger(ObjectID enactor, ObjectID objID);
|
|
bool release(ObjectID enactor, ObjectID objID);
|
|
bool acceptLockToggle(ObjectID enactor, uint8 keyCode);
|
|
|
|
bool inRange(const TilePoint &loc, int16 range);
|
|
|
|
// ActiveItem group methods
|
|
bool use(ActiveItem *ins, ObjectID enactor);
|
|
bool trigger(ActiveItem *ins, ObjectID enactor, ObjectID objID);
|
|
bool release(ActiveItem *ins, ObjectID enactor, ObjectID objID);
|
|
bool acceptLockToggle(ActiveItem *ins, ObjectID enactor, uint8 keyCode);
|
|
|
|
bool inRange(ActiveItem *ins, const TilePoint &loc, int16 range) {
|
|
return loc.u >= ins->_data.instance.u - range
|
|
&& loc.v >= ins->_data.instance.v - range
|
|
&& loc.u < ins->_data.instance.u + _data.group.uSize + range
|
|
&& loc.v < ins->_data.instance.v + _data.group.vSize + range;
|
|
}
|
|
|
|
ObjectID getInstanceContext(void);
|
|
Location getInstanceLocation(void);
|
|
|
|
static void playTAGNoise(ActiveItem *ai, int16 tagNoiseID);
|
|
|
|
};
|
|
|
|
typedef ActiveItem *ActiveItemPtr,
|
|
*ActiveItemHandle;
|
|
|
|
struct WorldMapData;
|
|
|
|
class ActiveItemList {
|
|
public:
|
|
int _count;
|
|
ActiveItem **_items;
|
|
WorldMapData *_parent;
|
|
|
|
ActiveItemList(WorldMapData *parent, int count, Common::SeekableReadStream *stream);
|
|
~ActiveItemList();
|
|
};
|
|
|
|
#if 0
|
|
|
|
/* ===================================================================== *
|
|
TileHitZone: This object represents a large region which overlays the
|
|
tile map without affecting it's appearance. It does not contain any
|
|
tiles or animation information, it is a behavioral region only.
|
|
It can be much larger and more complex in shape than an activity group.
|
|
* ===================================================================== */
|
|
|
|
class TileHitZone : public ActiveItem {
|
|
public:
|
|
|
|
// REM: Allow discontiguous regions??
|
|
int16 numVertices;
|
|
XArray<Point16> vertexList;
|
|
|
|
int16 type(void) {
|
|
return activeTypeHitZone;
|
|
}
|
|
};
|
|
|
|
class ObjectClass : public ActiveItem {
|
|
public:
|
|
// A general type of object
|
|
|
|
int16 type(void) {
|
|
return activeTypeObjectType;
|
|
}
|
|
};
|
|
|
|
class ObjectInstance : public ActiveItem {
|
|
public:
|
|
TileGroupID classID; // ID of object class
|
|
|
|
// An instance of a specific object.
|
|
|
|
uint16 u, v, h; // where the instance lies
|
|
uint8 facing; // which direction it's facing
|
|
|
|
int16 type(void) {
|
|
return activeTypeObject;
|
|
}
|
|
};
|
|
#endif
|
|
|
|
|
|
/* ============================================================================ *
|
|
TileActivityTask class
|
|
* ============================================================================ */
|
|
|
|
// This class handles the built-in movement of active terrain items. It
|
|
// includes things like opening/closing doors, and toggling lamps.
|
|
//
|
|
// Since most things in the game aren't moving at a given point, the
|
|
// variables for simulating motion don't need to always be present.
|
|
|
|
class TileActivityTask {
|
|
friend class TileActivityTaskList;
|
|
friend class ActiveItem;
|
|
|
|
uint8 activityType; // open or close
|
|
uint8 targetState;
|
|
ActiveItem *tai; // the tile activity instance
|
|
ThreadID script; // script to wake up when task done
|
|
|
|
enum activityTypes {
|
|
activityTypeNone, // no activity
|
|
|
|
activityTypeOpen, // open door
|
|
activityTypeClose, // close door
|
|
|
|
activityTypeScript // scriptable activity
|
|
};
|
|
|
|
void remove(void); // tile activity task is finished.
|
|
|
|
public:
|
|
|
|
// Functions to create a new tile activity task.
|
|
static void openDoor(ActiveItem &activeInstance);
|
|
static void closeDoor(ActiveItem &activeInstance);
|
|
static void doScript(ActiveItem &activeInstance, uint8 finalState, ThreadID id);
|
|
|
|
static void updateActiveItems(void);
|
|
|
|
static void initTileActivityTasks(void);
|
|
|
|
static TileActivityTask *find(ActiveItem *tai);
|
|
static bool setWait(ActiveItem *tai, ThreadID script);
|
|
};
|
|
|
|
/* ============================================================================ *
|
|
TileActivityTaskList class
|
|
* ============================================================================ */
|
|
|
|
class TileActivityTaskList {
|
|
friend class TileActivityTask;
|
|
|
|
public:
|
|
Common::List<TileActivityTask *> _list;
|
|
|
|
// Constructor -- initial construction
|
|
TileActivityTaskList(void);
|
|
|
|
// Reconstruct the TileActivityTaskList from an archive buffer
|
|
TileActivityTaskList(void **buf);
|
|
|
|
TileActivityTaskList(Common::SeekableReadStream *stream);
|
|
|
|
// Return the number of bytes needed to archive this
|
|
// TileActivityTaskList
|
|
int32 archiveSize(void);
|
|
|
|
void read(Common::InSaveFile *in);
|
|
void write(Common::OutSaveFile *out);
|
|
|
|
// Cleanup this list
|
|
void cleanup(void);
|
|
|
|
// get new tile activity task
|
|
TileActivityTask *newTask(ActiveItem *activeInstance);
|
|
};
|
|
|
|
void moveActiveTerrain(int32 deltaTime);
|
|
|
|
/* ===================================================================== *
|
|
A structure to record special return values from tileSlopeHeight
|
|
* ===================================================================== */
|
|
|
|
struct StandingTileInfo {
|
|
TileInfo *surfaceTile;
|
|
ActiveItemPtr surfaceTAG;
|
|
TileRef surfaceRef;
|
|
int16 surfaceHeight;
|
|
};
|
|
|
|
/* ======================================================================= *
|
|
Platform struct
|
|
* ======================================================================= */
|
|
|
|
const int maxPlatforms = 8;
|
|
|
|
struct Platform {
|
|
uint16 height, // height above ground
|
|
highestPixel; // tallest tile upper extent
|
|
uint16 flags; // platform flags
|
|
TileRef tiles[kPlatformWidth][kPlatformWidth];
|
|
|
|
void load(Common::SeekableReadStream *stream) {
|
|
height = stream->readUint16LE();
|
|
highestPixel = stream->readUint16LE();
|
|
flags = stream->readUint16LE();
|
|
|
|
for (int j = 0; j < kPlatformWidth; ++j) {
|
|
for (int i = 0; i < kPlatformWidth; ++i) {
|
|
tiles[j][i].tile = stream->readUint16LE();
|
|
tiles[j][i].flags = stream->readByte();
|
|
tiles[j][i].tileHeight = stream->readByte();
|
|
}
|
|
}
|
|
}
|
|
|
|
TileRef &getTileRef(const TilePoint p) {
|
|
return tiles[p.u][p.v];
|
|
}
|
|
|
|
TileRef &getTileRef(int16 u, int16 v) {
|
|
return tiles[u][v];
|
|
}
|
|
|
|
// fetch the REAL tile terrain info
|
|
TileInfo *fetchTile(int16 mapNum,
|
|
const TilePoint &pt,
|
|
const TilePoint &origin,
|
|
int16 &height,
|
|
int16 &trFlags);
|
|
|
|
// Fetch the tile and the active item it came from...
|
|
TileInfo *fetchTAGInstance(
|
|
int16 mapNum,
|
|
const TilePoint &pt,
|
|
const TilePoint &origin,
|
|
StandingTileInfo &sti);
|
|
|
|
// fetch the REAL tile terrain info and image data
|
|
TileInfo *fetchTile(int16 mapNum,
|
|
const TilePoint &pt,
|
|
const TilePoint &origin,
|
|
uint8 **imageData,
|
|
int16 &height,
|
|
int16 &trFlags);
|
|
|
|
// Fetch the tile and image data and the active item it came from...
|
|
TileInfo *fetchTAGInstance(
|
|
int16 mapNum,
|
|
const TilePoint &pt,
|
|
const TilePoint &origin,
|
|
uint8 **imageData,
|
|
StandingTileInfo &sti);
|
|
|
|
uint16 roofRipID(void) {
|
|
return (uint16)(flags & 0x0FFF);
|
|
}
|
|
};
|
|
|
|
typedef Platform *PlatformPtr,
|
|
* *PlatformHandle;
|
|
|
|
enum platformFlags {
|
|
plCutaway = (1 << 0), // remove when player underneath
|
|
|
|
// Cutaway directions: When platform is cut away, also cut
|
|
// away any adjacent platforms in these directions.
|
|
plVisible = (1 << 15), // platform is visible
|
|
plModified = (1 << 14), // platform has been changed
|
|
plCutUPos = (1 << 13),
|
|
plCutUNeg = (1 << 13),
|
|
plCutVPos = (1 << 13),
|
|
plCutVNeg = (1 << 13)
|
|
};
|
|
|
|
#if OLDPLATFLAAGS
|
|
enum platformFlags {
|
|
plCutaway = (1 << 0), // remove when player underneath
|
|
|
|
// Cutaway directions: When platform is cut away, also cut
|
|
// away any adjacent platforms in these directions.
|
|
|
|
plCutUPos = (1 << 1),
|
|
plCutUNeg = (1 << 2),
|
|
plCutVPos = (1 << 3),
|
|
plCutVNeg = (1 << 4),
|
|
|
|
plVisible = (1 << 5), // platform is visible
|
|
plEnabled = (1 << 6) // enforce platform terrain.
|
|
};
|
|
#endif
|
|
|
|
/* ======================================================================= *
|
|
PlatformCacheEntry struct
|
|
* ======================================================================= */
|
|
|
|
struct PlatformCacheEntry {
|
|
uint16 platformNum, // original platform num
|
|
layerNum; // index of this plat in mt.
|
|
MetaTileID metaID; // pointer to parent metatile
|
|
Platform pl; // actual platform data
|
|
|
|
enum {
|
|
kPlatformCacheSize = 256
|
|
};
|
|
};
|
|
|
|
/* ======================================================================= *
|
|
RipTable struct
|
|
* ======================================================================= */
|
|
|
|
// An object roof ripping "z-buffer" type structure
|
|
|
|
typedef int16 RipTableID;
|
|
|
|
struct RipTable {
|
|
MetaTileID metaID;
|
|
uint16 ripID;
|
|
int16 zTable[kPlatformWidth][kPlatformWidth];
|
|
|
|
enum {
|
|
kRipTableSize = 25
|
|
};
|
|
|
|
// Constructor
|
|
RipTable(void) : metaID(NoMetaTile), ripID(0) {
|
|
for (int i = 0; i < kPlatformWidth; i++)
|
|
for (int j = 0; j < kPlatformWidth; j++)
|
|
zTable[i][j] = 0;
|
|
}
|
|
|
|
// Return a pointer to a rip table, given the rip table's ID
|
|
static RipTable *ripTableAddress(RipTableID id);
|
|
|
|
// Return the rip table's ID
|
|
RipTableID thisID(void);
|
|
};
|
|
|
|
typedef RipTable *RipTablePtr;
|
|
typedef RipTableID *RipTableIDPtr,
|
|
**RipTableIDHandle;
|
|
|
|
typedef uint16 metaTileNoise;
|
|
|
|
/* ======================================================================= *
|
|
MetaTile struct
|
|
* ======================================================================= */
|
|
|
|
// A "Metatile" is a larger tile made up of smaller tiles.
|
|
|
|
class MetaTileList;
|
|
|
|
class MetaTile {
|
|
public:
|
|
uint16 _highestPixel; // more drawing optimization
|
|
BankBits _banksNeeded; // which banks are needed
|
|
uint16 _stack[maxPlatforms]; // pointer to platforms
|
|
uint32 _properties; // more drawing optimization
|
|
int _index;
|
|
MetaTileList *_parent;
|
|
|
|
MetaTile(MetaTileList *parent, int ind, Common::SeekableReadStream *stream);
|
|
|
|
// Return a pointer to a meta tile given its ID
|
|
static MetaTile *metaTileAddress(MetaTileID id);
|
|
|
|
// Return this meta tile's ID
|
|
MetaTileID thisID(int16 mapNum);
|
|
|
|
// Return a pointer to the specified platform
|
|
Platform *fetchPlatform(int16 mapNum, int16 index);
|
|
|
|
// Return a pointer to this metatile's current object ripping
|
|
// table
|
|
RipTable *ripTable(int16 mapNum);
|
|
|
|
// Return a reference to this meta tile's rip table ID
|
|
RipTableID &ripTableID(int16 mapNum);
|
|
|
|
metaTileNoise HeavyMetaMusic(void);
|
|
|
|
bool hasProperty(
|
|
const MetaTileProperty &metaTileProp,
|
|
int16 mapNum,
|
|
const TilePoint &mCoords) {
|
|
return metaTileProp(this, mapNum, mCoords);
|
|
}
|
|
};
|
|
|
|
typedef MetaTile *MetaTilePtr,
|
|
* *MetaTileHandle;
|
|
|
|
class MetaTileList {
|
|
public:
|
|
int _count;
|
|
MetaTile **_tiles;
|
|
|
|
MetaTileList(int count, Common::SeekableReadStream *stream);
|
|
~MetaTileList();
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
MapHeader struct
|
|
* ===================================================================== */
|
|
|
|
struct MapHeader {
|
|
int16 size; // size of map
|
|
int16 edgeType; // edge type of map
|
|
uint16 *mapData; // start of map array
|
|
|
|
MapHeader(Common::SeekableReadStream *stream);
|
|
~MapHeader();
|
|
};
|
|
|
|
enum mapEdgeTypes {
|
|
edgeTypeBlack = 0,
|
|
edgeTypeFill0,
|
|
edgeTypeFill1,
|
|
edgeTypeRepeat,
|
|
edgeTypeWrap
|
|
};
|
|
|
|
typedef MapHeader *MapPtr,
|
|
* *MapHandle;
|
|
|
|
/* ===================================================================== *
|
|
WorldMapData struct
|
|
* ===================================================================== */
|
|
|
|
const uint16 metaTileVisited = (1 << 15);
|
|
|
|
struct WorldMapData {
|
|
ObjectID worldID; // The number of this map
|
|
|
|
MapPtr map; // Map data
|
|
MetaTileList *metaList; // MetaTile list
|
|
TileRefPtr activeItemData; // ActiveItem tileRefs
|
|
ActiveItemList *activeItemList; // ActiveItem list
|
|
uint16 *assocList; // Associations
|
|
RipTableIDPtr ripTableIDList; // MetaTile object ripping
|
|
|
|
ActiveItem *instHash[513]; // ActiveItem hash table
|
|
Common::HashMap<int16, ActiveItem*> itemHash;
|
|
|
|
int16 metaCount, // Number of MetaTiles
|
|
activeCount; // Number of ActiveItems
|
|
int16 mapSize; // Size of map in meta tiles
|
|
int32 mapHeight; // Height of map in Y
|
|
|
|
|
|
// Lookup metatile on map.
|
|
MetaTilePtr lookupMeta(TilePoint coords);
|
|
|
|
// Build active item instance hash table
|
|
void buildInstanceHash(void);
|
|
|
|
// Return a pointer to an active item instance based upon the
|
|
// group ID and the MetaTile's coordinates
|
|
ActiveItem *findHashedInstance(TilePoint &tp, int16 group);
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
MetaTileIterator class
|
|
* ===================================================================== */
|
|
|
|
class MetaTileIterator {
|
|
TilePoint mCoords;
|
|
TileRegion region;
|
|
|
|
int16 mapNum;
|
|
|
|
bool iterate(void);
|
|
|
|
public:
|
|
MetaTileIterator(int16 map, const TileRegion ®) : mapNum(map) {
|
|
region.min.u = reg.min.u >> kPlatShift;
|
|
region.max.u = (reg.max.u + kPlatMask) >> kPlatShift;
|
|
region.min.v = reg.min.v >> kPlatShift;
|
|
region.max.v = (reg.max.v + kPlatMask) >> kPlatShift;
|
|
region.min.z = region.max.z = 0;
|
|
}
|
|
|
|
MetaTile *first(TilePoint *loc = NULL);
|
|
MetaTile *next(TilePoint *loc = NULL);
|
|
|
|
int16 getMapNum(void) {
|
|
return mapNum;
|
|
}
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
TileIterator class
|
|
* ===================================================================== */
|
|
|
|
class TileIterator {
|
|
MetaTileIterator metaIter;
|
|
MetaTile *mt;
|
|
int16 platIndex;
|
|
Platform *platform;
|
|
TilePoint tCoords,
|
|
origin;
|
|
TileRegion region,
|
|
tCoordsReg;
|
|
|
|
bool iterate(void);
|
|
|
|
public:
|
|
TileIterator(int16 mapNum, const TileRegion ®) :
|
|
metaIter(mapNum, reg),
|
|
region(reg) {
|
|
mt = nullptr;
|
|
platIndex = 0;
|
|
platform = nullptr;
|
|
}
|
|
|
|
TileInfo *first(TilePoint *loc, StandingTileInfo *stiResult = NULL);
|
|
TileInfo *next(TilePoint *loc, StandingTileInfo *stiResult = NULL);
|
|
};
|
|
|
|
/* ===================================================================== *
|
|
Exports
|
|
* ===================================================================== */
|
|
|
|
extern StaticTilePoint viewCenter; // coordinates of view on map
|
|
|
|
// These two variables define which sectors overlap the view rect.
|
|
|
|
extern TilePoint minSector,
|
|
maxSector;
|
|
|
|
extern uint16 rippedRoofID;
|
|
|
|
/* ===================================================================== *
|
|
Prototypes
|
|
* ===================================================================== */
|
|
|
|
// Initialize map data
|
|
void initMaps(void);
|
|
|
|
// Cleanup map data
|
|
void cleanupMaps(void);
|
|
|
|
void setCurrentMap(int mapNum); // set which map is current
|
|
|
|
// Initialize the platform cache
|
|
void initPlatformCache(void);
|
|
|
|
// Initialize the tile activity task list
|
|
void initTileTasks(void);
|
|
|
|
void saveTileTasks(Common::OutSaveFile *out);
|
|
void loadTileTasks(Common::InSaveFile *in, int32 chunkSize);
|
|
|
|
// Cleanup the tile activity task list
|
|
void cleanupTileTasks(void);
|
|
|
|
TilePoint getClosestPointOnTAI(ActiveItem *TAI, GameObject *obj);
|
|
|
|
void initActiveItemStates(void);
|
|
void saveActiveItemStates(Common::OutSaveFile *out);
|
|
void loadActiveItemStates(Common::InSaveFile *in);
|
|
void cleanupActiveItemStates(void);
|
|
|
|
void initTileCyclingStates(void);
|
|
void saveTileCyclingStates(Common::OutSaveFile *out);
|
|
void loadTileCyclingStates(Common::InSaveFile *in);
|
|
void cleanupTileCyclingStates(void);
|
|
|
|
void initAutoMap(void);
|
|
void saveAutoMap(Common::OutSaveFile *out);
|
|
void loadAutoMap(Common::InSaveFile *in, int32 chunkSize);
|
|
inline void cleanupAutoMap(void) { /* nothing to do */ }
|
|
|
|
// Determine if a platform is ripped
|
|
inline bool platformRipped(Platform *pl) {
|
|
if (rippedRoofID != 0)
|
|
return pl->roofRipID() == rippedRoofID;
|
|
|
|
return false;
|
|
}
|
|
|
|
// Compute visible area in U/V coords
|
|
TilePoint XYToUV(const Point32 &pt);
|
|
void TileToScreenCoords(const TilePoint &tp, Point16 &p);
|
|
|
|
// Determine height of point on a tile based on four corner heights
|
|
int16 ptHeight(const TilePoint &tp, uint8 *cornerHeight);
|
|
|
|
|
|
/* --------------------------------------------------------------------- *
|
|
Prototypes for TERRAIN.CPP moved to terrain.h
|
|
* --------------------------------------------------------------------- */
|
|
|
|
|
|
// Determine which roof is above object
|
|
uint16 objRoofID(GameObject *obj);
|
|
uint16 objRoofID(GameObject *obj, int16 objMapNum, const TilePoint &objCoords);
|
|
|
|
// Determine if roof over an object is ripped
|
|
bool objRoofRipped(GameObject *obj);
|
|
|
|
// Determine if two objects are both under the same roof
|
|
bool underSameRoof(GameObject *obj1, GameObject *obj2);
|
|
|
|
// Determine the distance between a point and a line
|
|
uint16 lineDist(
|
|
const TilePoint &p1,
|
|
const TilePoint &p2,
|
|
const TilePoint &m);
|
|
|
|
/* ============================================================================ *
|
|
Misc prototypes
|
|
* ============================================================================ */
|
|
|
|
// Converts Local XY to UV coordinates
|
|
StaticTilePoint pickTilePos(Point32 pos, const TilePoint &protagPos);
|
|
StaticTilePoint pickTile(Point32 pos,
|
|
const TilePoint &protagPos,
|
|
StaticTilePoint *floor = NULL,
|
|
ActiveItemPtr *pickTAI = NULL);
|
|
|
|
// Function to select a nearby site
|
|
TilePoint selectNearbySite(
|
|
ObjectID worldID,
|
|
const TilePoint &startingCoords,
|
|
int32 minDist,
|
|
int32 maxDist,
|
|
bool offScreenOnly = false); // true if we want it off-screen
|
|
|
|
} // end of namespace Saga2
|
|
|
|
#endif
|