1 /*
2 ** gamemap.h
3 **
4 **---------------------------------------------------------------------------
5 ** Copyright 2011 Braden Obrzut
6 ** All rights reserved.
7 **
8 ** Redistribution and use in source and binary forms, with or without
9 ** modification, are permitted provided that the following conditions
10 ** are met:
11 **
12 ** 1. Redistributions of source code must retain the above copyright
13 **    notice, this list of conditions and the following disclaimer.
14 ** 2. Redistributions in binary form must reproduce the above copyright
15 **    notice, this list of conditions and the following disclaimer in the
16 **    documentation and/or other materials provided with the distribution.
17 ** 3. The name of the author may not be used to endorse or promote products
18 **    derived from this software without specific prior written permission.
19 **
20 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 **---------------------------------------------------------------------------
31 **
32 **
33 */
34 
35 #ifndef __GAMEMAP_H__
36 #define __GAMEMAP_H__
37 
38 #include "tarray.h"
39 #include "zstring.h"
40 #include "textures/textures.h"
41 #include "dobject.h"
42 
43 class Thinker;
44 class UWMFParser;
45 
46 enum
47 {
48 	SLIDE_Normal,
49 	SLIDE_Split,
50 	SLIDE_Invert
51 };
52 
53 enum
54 {
55 	AM_Visible = 0x1,
56 	AM_DontOverlay = 0x2
57 };
58 
59 class GameMap
60 {
61 	public:
62 		struct Header
63 		{
64 			FString			name;
65 			unsigned int	width;
66 			unsigned int	height;
67 			unsigned int	tileSize;
68 		};
69 		struct Thing
70 		{
ThingThing71 			Thing() : x(0), y(0), z(0), angle(0), type(0), ambush(false),
72 				patrol(false)
73 			{
74 				skill[0] = skill[1] = skill[2] = skill[3] = false;
75 			}
76 
77 			fixed			x, y, z;
78 			unsigned short	angle;
79 			unsigned int	type;
80 			bool			ambush;
81 			bool			patrol;
82 			bool			skill[4];
83 		};
84 		struct Trigger
85 		{
TriggerTrigger86 			Trigger() : x(0), y(0), z(0), active(true), action(0),
87 				playerUse(false), playerCross(false), monsterUse(false),
88 				isSecret(false), repeatable(false)
89 			{
90 				activate[0] = activate[1] = activate[2] = activate[3] = true;
91 				arg[0] = arg[1] = arg[2] = arg[3] = arg[4] = 0;
92 			}
93 
94 			unsigned int	x, y, z;
95 			// Stores if the trigger hasn't been used yet.
96 			// Note that this is set to false on for repeatable actions as well so that secrets are only accounted for once.
97 			bool			active;
98 
99 			enum Side { East, North, West, South };
100 			unsigned int	action;
101 			bool			activate[4];
102 			int				arg[5];
103 
104 			bool			playerUse;
105 			bool			playerCross;
106 			bool			monsterUse;
107 			bool			isSecret;
108 			bool			repeatable;
109 		};
110 		struct Tile
111 		{
TileTile112 			Tile() : offsetVertical(false), offsetHorizontal(false),
113 				mapped(0), dontOverlay(false)
114 			{
115 				overhead.SetInvalid();
116 				sideSolid[0] = sideSolid[1] = sideSolid[2] = sideSolid[3] = true;
117 			}
118 
119 			enum Side { East, North, West, South };
120 			FTextureID		texture[4];
121 			FTextureID		overhead;
122 			bool			sideSolid[4];
123 			bool			offsetVertical;
124 			bool			offsetHorizontal;
125 			FName			soundSequence;
126 
127 			unsigned int	mapped; // filter level for always visible
128 			bool			dontOverlay;
129 		};
130 		struct Sector
131 		{
132 			enum Flat { Floor, Ceiling };
133 			FTextureID	texture[2];
134 		};
135 		struct Zone
136 		{
137 			unsigned short	index;
138 		};
139 		struct Plane
140 		{
141 			const GameMap	*gm;
142 
143 			unsigned int	depth;
144 			struct Map
145 			{
MapPlane::Map146 				Map() : tile(NULL), sector(NULL), zone(NULL), visible(false),
147 					amFlags(0), thinker(NULL), slideStyle(0),
148 					pushDirection(Tile::East), pushAmount(0),
149 					pushReceptor(NULL), tag(0), nexttag(NULL)
150 				{
151 					slideAmount[0] = slideAmount[1] = slideAmount[2] = slideAmount[3] = 0;
152 					sideSolid[0] = sideSolid[1] = sideSolid[2] = sideSolid[3] = true;
153 				}
154 
155 				unsigned int	GetX() const;
156 				unsigned int	GetY() const;
157 				Map				*GetAdjacent(Tile::Side dir, bool opposite=false) const;
158 				void			SetTile(const Tile *tile);
159 
160 				const Plane		*plane;
161 
162 				const Tile		*tile;
163 				const Sector	*sector;
164 				const Zone		*zone;
165 
166 				// So that the textures can change.
167 				FTextureID		texture[4];
168 
169 				bool			visible;
170 				unsigned int	amFlags;
171 				TObjPtr<Thinker> thinker;
172 				unsigned int	slideAmount[4];
173 				unsigned int	slideStyle;
174 				bool			sideSolid[4];
175 				TArray<Trigger>	triggers;
176 				Tile::Side		pushDirection;
177 				unsigned int	pushAmount;
178 				Map				*pushReceptor;
179 
180 				unsigned int	tag;
181 				Plane::Map		*nexttag;
182 			}*	map;
183 		};
184 
185 		GameMap(const FString &map);
186 		~GameMap();
187 
188 		bool			ActivateTrigger(Trigger &trig, Trigger::Side direction, AActor *activator);
189 		void			ClearVisibility();
GetHeader()190 		const Header	&GetHeader() const { return header; }
191 		void			GetHitlist(BYTE* hitlist) const;
GetMarketLumpNum()192 		int				GetMarketLumpNum() const { return markerLump; }
GetSpot(unsigned int x,unsigned int y,unsigned int z)193 		Plane::Map		*GetSpot(unsigned int x, unsigned int y, unsigned int z) const { return &GetPlane(z).map[y*header.width+x]; }
194 		Plane::Map		*GetSpotByTag(unsigned int tag, Plane::Map *start) const;
GetZone(unsigned int index)195 		const Zone		&GetZone(unsigned int index) { return zonePalette[index]; }
IsValid()196 		bool			IsValid() const { return valid; }
IsValidTileCoordinate(unsigned int x,unsigned int y,unsigned int z)197 		bool			IsValidTileCoordinate(unsigned int x, unsigned int y, unsigned int z) const { return x < header.width && y < header.height && z < NumPlanes(); }
198 		void			LoadMap(bool loadingSave);
NumPlanes()199 		unsigned int	NumPlanes() const { return planes.Size(); }
GetPlane(unsigned int index)200 		const Plane		&GetPlane(unsigned int index) const { return planes[index]; }
201 		void			SpawnThings() const;
202 
203 		// Sound functions
204 		bool			CheckLink(const Zone *zone1, const Zone *zone2, bool recurse);
205 		void			LinkZones(const Zone *zone1, const Zone *zone2, bool open);
206 
207 		// Save lookups
208 		const Tile		*GetTile(unsigned int index) const;
209 		unsigned int	GetTileIndex(const Tile *tile) const;
210 		const Sector	*GetSector(unsigned int index) const;
211 		unsigned int	GetSectorIndex(const Sector *sector) const;
212 
213 		static bool		CheckMapExists(const FString &map);
214 
215 		void PropagateMark();
216 
217 		TMap<unsigned int, Plane::Map *> elevatorPosition;
218 	private:
219 		friend class UWMFParser;
220 		friend FArchive &operator<< (FArchive &, GameMap *&);
221 
222 		Plane	&NewPlane();
223 		Trigger	&NewTrigger(unsigned int x, unsigned int y, unsigned int z);
224 		void	ReadPlanesData();
225 		void	ReadUWMFData();
226 		void	SetSpotTag(Plane::Map *spot, unsigned int tag);
227 		void	SetupLinks();
228 		void	ScanTiles();
229 		bool	TraverseLink(const Zone *src, const Zone *dest);
230 		void	UnloadLinks();
231 
232 		FString	map;
233 
234 		bool	valid;
235 		bool	isWad;
236 		bool	isUWMF;
237 		int		markerLump;
238 		int		numLumps;
239 
240 		class FResourceFile	*file;
241 		class FileReader	*lumps[1];
242 
243 		// Actual map data
244 		Header			header;
245 		TArray<Tile>	tilePalette;
246 		TArray<Sector>	sectorPalette;
247 		TArray<Zone>	zonePalette;
248 		TArray<Thing>	things;
249 		TArray<Plane>	planes;
250 		TMap<unsigned int, Plane::Map *> tagMap;
251 
252 		// Sound travel links.  zoneTraversed is temporary array for recursive
253 		// traversals.  zoneLinks is the table of links (counts the number of
254 		// links that are opened).
255 		bool*				zoneTraversed;
256 		unsigned short**	zoneLinks;
257 };
258 
259 typedef GameMap::Plane::Map *	MapSpot;
260 
261 // The following are mainly for easy access to enums
262 typedef GameMap::Plane			MapPlane;
263 typedef GameMap::Sector			MapSector;
264 typedef GameMap::Thing			MapThing;
265 typedef GameMap::Tile			MapTile;
266 typedef GameMap::Trigger		MapTrigger;
267 typedef GameMap::Zone			MapZone;
268 
269 #include "farchive.h"
270 FArchive &operator<< (FArchive &arc, GameMap *&gm);
271 FArchive &operator<< (FArchive &arc, MapSpot &spot);
272 FArchive &operator<< (FArchive &arc, const MapSector *&tile);
273 FArchive &operator<< (FArchive &arc, const MapTile *&tile);
274 FArchive &operator<< (FArchive &arc, const MapZone *&zone);
275 FArchive &operator<< (FArchive &arc, MapTrigger &trigger);
276 
277 #endif
278