1 /***************************************************************************
2                   map.h  -  Manages and renders the level map
3                              -------------------
4     begin                : Sat May 3 2003
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7 ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef MAP_H
19 #define MAP_H
20 #pragma once
21 
22 #include "render.h"
23 #include <vector>
24 #include <set>
25 #include <sstream>
26 #include "location.h"
27 
28 class CFrustum;
29 class RenderedProjectile;
30 class Location;
31 class EffectLocation;
32 class Shape;
33 class RenderedCreature;
34 class RenderedItem;
35 class RenderedProjectile;
36 class GLShape;
37 class Shapes;
38 class MapAdapter;
39 class Location;
40 class Effect;
41 class DisplayInfo;
42 class MapRenderHelper;
43 
44 enum {
45 	GROUND_LAYER = 0,
46 	ROAD_LAYER,
47 
48 	MAX_OUTDOOR_LAYER
49 };
50 
51 /// It's a trap!
52 class Trap {
53 public:
54 	SDL_Rect r;
55 	int type;
56 	bool discovered;
57 	bool enabled;
58 	std::vector<CVector2*> hull;
59 };
60 
61 /// A 3D point with texture coordinates and color.
62 class CVectorTex {
63 public:
64 	float x, y, z, u, v, r, g, b, a;
65 	Texture tex;
66 };
67 
68 
69 /// General map settings.
70 
71 class MapSettings {
72 
73 public:
MapSettings()74 	MapSettings() {
75 	}
76 
~MapSettings()77 	virtual ~MapSettings() {
78 	}
79 
80 	virtual bool isLightMapEnabled() = 0;
81 	virtual bool isGridShowing() = 0;
82 	virtual bool isPlayerEnabled() = 0;
83 	virtual bool isItemPosEnabled() = 0;
84 	virtual float getMinZoomIn() = 0;
85 	virtual float getMaxZoomOut() = 0;
86 	virtual float getMaxYRot() = 0;
87 };
88 
89 /// General map settings (ingame).
90 
91 class GameMapSettings : public MapSettings {
92 
93 public:
94 	GameMapSettings();
95 	virtual ~GameMapSettings();
96 
97 	bool isLightMapEnabled();
98 	bool isGridShowing();
99 	bool isPlayerEnabled();
100 	bool isItemPosEnabled();
101 	float getMinZoomIn();
102 	float getMaxZoomOut();
103 	float getMaxYRot();
104 };
105 
106 /// General map settings for the map editor.
107 
108 class EditorMapSettings : public MapSettings {
109 
110 public:
111 	EditorMapSettings();
112 	virtual ~EditorMapSettings();
113 
114 	bool isLightMapEnabled();
115 	bool isGridShowing();
116 	bool isPlayerEnabled();
117 	bool isItemPosEnabled();
118 	float getMinZoomIn();
119 	float getMaxZoomOut();
120 	float getMaxYRot();
121 };
122 
123 /// Stores the state and contents of a level map location for later drawing.
124 
125 struct DrawLater {
126 	float xpos, ypos, zpos;
127 	Shape *shape;
128 	RenderedCreature *creature;
129 	RenderedItem *item;
130 	EffectLocation *effect;
131 	GLuint name;
132 	Location *pos;
133 	bool inFront;
134 	int x, y;
135 };
136 
137 #define SWAP(src, dst) { int _t; _t = src; src = dst; dst = _t; }
138 #define POS_CACHE_WIDTH    5
139 #define POS_CACHE_DEPTH    5
140 #define POS_CACHE_HEIGHT   10
141 #define MAX_POS_CACHE (POS_CACHE_WIDTH * POS_CACHE_DEPTH * POS_CACHE_HEIGHT)
142 
143 class Map;
144 
145 /// Utilities for cleaning up on level maps, and managing memory use.
146 
147 class MapMemoryManager {
148 private:
149 	std::vector<Location*> unused;
150 	std::vector<EffectLocation*> unusedEffect;
151 	int maxSize;
152 	int accessCount;
153 	int usedCount, usedEffectCount;
154 public:
155 	/**
156 	    Maxsize of 0 means unlimited size cache.
157 	*/
158 	MapMemoryManager( int maxSize = 0 );
159 	~MapMemoryManager();
160 	Location *newLocation();
161 	void deleteLocation( Location *pos );
162 	EffectLocation *newEffectLocation( Map *map, Preferences *preferences, Shapes *shapes, int width, int height );
163 	void deleteEffectLocation( EffectLocation *pos );
164 private:
165 	void printStatus();
166 };
167 
168 
169 /// A nice, fluffy rug.
170 
171 struct Rug {
172 	Texture texture;
173 	bool isHorizontal;
174 	float angle;
175 };
176 
177 // how many water points per 1 floor tile
178 #define WATER_TILE_X 8
179 #define WATER_TILE_Y 8
180 
181 /**
182  *@author Gabor Torok
183  */
184 
185 /// This huge class contains a level map.
186 
187 class Map {
188 private:
189 	MapAdapter *adapter;
190 	Preferences *preferences;
191 	Shapes *shapes;
192 	static MapMemoryManager mapMemoryManager;
193 	bool mapChanged;
194 	bool resortShapes;
195 	float zoom;
196 	bool zoomIn, zoomOut;
197 	Sint16 x;
198 	Sint16 y;
199 	int viewX, viewY, viewWidth, viewHeight;
200 	float mapx, mapy;
201 	Location *pos[MAP_WIDTH][MAP_DEPTH][MAP_VIEW_HEIGHT];
202 	Location *itemPos[MAP_WIDTH][MAP_DEPTH];
203 	EffectLocation *effect[MAP_WIDTH][MAP_DEPTH][MAP_VIEW_HEIGHT];
204 	Location *posCache[MAX_POS_CACHE];
205 	signed int nbPosCache;
206 	Rug rugPos[MAP_CHUNKS_X][MAP_CHUNKS_Y];
207 	Shape *floorPositions[MAP_WIDTH][MAP_DEPTH];
208 
209 	/// An indoor water tile.
210 	struct WaterTile {
211 		float z[WATER_TILE_X][WATER_TILE_Y];
212 		float step[WATER_TILE_X][WATER_TILE_Y];
213 		Uint32 lastTime[WATER_TILE_X][WATER_TILE_Y];
214 	};
215 
216 	std::map<Uint32, WaterTile*> water;
217 	bool debugGridFlag;
218 	bool drawGridFlag;
219 	float xrot, yrot, zrot;
220 	float xpos, ypos, zpos;
221 	float xRotating, yRotating, zRotating;
222 	float fShadowMatrix[16];
223 	//bool alwaysCenter;
224 	static const int X_CENTER_TOLERANCE = 8;
225 	static const int Y_CENTER_TOLERANCE = 8;
226 
227 	bool lightMapChanged;
228 	int lightMap[MAP_CHUNKS_X][MAP_CHUNKS_Y];
229 	bool groundVisible;
230 
231 	// FIXME: either make this value adjustable or find a faster way to blast it onscreen?
232 	static const int SHADE_SIZE = 20;
233 
234 	bool useShadow;
235 	// squish on z and shear x,y
236 	static const float shadowTransformMatrix[16];
237 
238 	bool colorAlreadySet;
239 	Location *selectedDropTarget;
240 
241 	int accessMap[MAP_CHUNKS_X][MAP_CHUNKS_Y];
242 	std::map<Uint32, bool> locked;
243 	std::map<Uint32, Uint32> doorToKey;
244 	std::map<Uint32, Uint32> keyToDoor;
245 
246 	int LIGHTMAP_ENABLED;
247 	int lastOutlinedX, lastOutlinedY, lastOutlinedZ;
248 
249 	MapRenderHelper *helper;
250 
251 	static int dir_index[];
252 
253 	/// Unused.
254 	void drawGrid( SDL_Surface *surface );
255 	/// Unused.
256 	void debugGrid( SDL_Surface *surface );
257 
258 	int mapViewWidth, mapViewDepth;
259 	enum { DEBUG_SIZE = 200 };
260 	char mapDebugStr[ DEBUG_SIZE ];
261 
262 	char name[80];
263 	bool edited; // is this a non-random (edited) map?
264 	bool hasWater;
265 
266 	MapSettings *settings;
267 
268 	bool mouseMoveScreen;
269 	Uint16 move;
270 	bool mouseRot, mouseZoom;
271 	int mouseRotDir;
272 
273 	Uint16 cursorMapX, cursorMapY, cursorMapZ, cursorFlatMapX, cursorFlatMapY;
274 	Uint16 cursorChunkX, cursorChunkY;
275 
276 	int floorTexWidth, floorTexHeight;
277 	Texture floorTex;
278 
279 	RenderedCreature *mapCenterCreature;
280 	std::map<int, bool> secretDoors;
281 
282 	bool quakesEnabled;
283 
284 	bool heightMapEnabled;
285 	OutdoorTexture outdoorTex[MAP_TILES_X][MAP_TILES_Y][MAX_OUTDOOR_LAYER];
286 	float ground[MAP_WIDTH][MAP_DEPTH];
287 	Texture groundTex[MAP_WIDTH][MAP_DEPTH];
288 	bool refreshGroundPos;
289 	int debugHeightPosXX[4], debugHeightPosYY[4];
290 	CVectorTex groundPos[MAP_WIDTH][MAP_DEPTH];
291 	Texture outdoorShadow;
292 	Texture outdoorShadowTree;
293 	Texture waterTexture;
294 	Location *hackBlockingPos;
295 
296 	std::map<Uint32, Uint8> trapPos;
297 	std::vector<Trap> trapList;
298 	std::set<Uint8> trapSet;
299 	int selectedTrapIndex;
300 	bool isRoofShowing, isCurrentlyUnderRoof;
301 	Uint32 roofAlphaUpdate;
302 	float roofAlpha;
303 	bool gridEnabled;
304 
305 	int weather;
306 
307 	std::set<Location*> gates, teleporters;
308 	std::map<RenderedCreature*, DrawLater*> creatureMap, creatureEffectMap;
309 
310 public:
311 	bool useFrustum;
312 	static bool debugMd2Shapes;
313 
314 	int cursorWidth, cursorDepth, cursorHeight, cursorZ;
315 	int startx, starty;
316 	int mapGridX, mapGridY;
317 
318 	Map( MapAdapter *adapter, Preferences *preferences, Shapes *shapes );
319 	~Map();
320 
setGridEnabled(bool b)321 	inline void setGridEnabled( bool b ) {
322 		this->gridEnabled = b;
323 	}
isGridEnabled()324 	inline bool isGridEnabled() {
325 		return this->gridEnabled;
326 	}
327 
328 	/// Levels can have occasional quakes.
setQuakesEnabled(bool b)329 	inline void setQuakesEnabled( bool b ) {
330 		quakesEnabled = b;
331 	}
areQuakesEnabled()332 	inline bool areQuakesEnabled() {
333 		return quakesEnabled;
334 	}
335 	void quake();
336 
337 	void setRoofShowing( bool b );
338 	/// Unused.
getRoofShowing()339 	inline bool getRoofShowing() {
340 		return isRoofShowing;
341 	}
342 
343 	/// Are we under a roof (inside a house)?
getCurrentlyUnderRoof()344 	inline bool getCurrentlyUnderRoof() {
345 		return isCurrentlyUnderRoof;
346 	}
347 
348 	/// Which weather will the map have?
setWeather(int i)349 	inline void setWeather( int i ) {
350 		weather = i;
351 	}
352 	/// The current weather conditions.
getWeather()353 	inline int getWeather() {
354 		return weather;
355 	}
356 	int generateWeather();
357 
358 	void addSecretDoor( int x, int y );
359 	void removeSecretDoor( int x, int y );
360 	bool isSecretDoor( Location *pos );
361 	bool isSecretDoor( int x, int y );
362 	bool isSecretDoorDetected( Location *pos );
363 	bool isSecretDoorDetected( int x, int y );
364 	void setSecretDoorDetected( Location *pos );
365 	void setSecretDoorDetected( int x, int y );
366 
367 	/// The creature on which the main view should be centered.
setMapCenterCreature(RenderedCreature * c)368 	inline void setMapCenterCreature( RenderedCreature *c ) {
369 		mapCenterCreature = c;
370 	}
371 	/// The creature on which the main view should be centered.
getMapCenterCreature()372 	inline RenderedCreature *getMapCenterCreature() {
373 		return mapCenterCreature;
374 	}
375 
376 	void setMapRenderHelper( MapRenderHelper *helper );
getMapRenderHelper()377 	inline MapRenderHelper *getMapRenderHelper() {
378 		return helper;
379 	}
380 
getAdapter()381 	inline MapAdapter *getAdapter() {
382 		return adapter;
383 	}
384 
385 	/// Gets the game's user-set preferences.
getPreferences()386 	inline Preferences *getPreferences() {
387 		return preferences;
388 	}
389 
getHelper()390 	inline MapRenderHelper *getHelper() {
391 		return helper;
392 	}
393 
getShapes()394 	inline Shapes *getShapes() {
395 		return shapes;
396 	}
397 
getSettings()398 	inline MapSettings *getSettings() {
399 		return settings;
400 	}
401 
402 	/// Returns the frustum (the viewing area).
getFrustum()403 	inline CFrustum *getFrustum() {
404 		return frustum;
405 	}
406 
407 	/// Which floor texture will we use (indoors)?
setFloor(int tw,int th,Texture texture)408 	inline void setFloor( int tw, int th, Texture texture ) {
409 		floorTexWidth = tw; floorTexHeight = th; floorTex = texture;
410 	}
411 
412 	/// Is this an edited (instead of randomly generated) map?
isEdited()413 	inline bool isEdited() {
414 		return edited;
415 	}
getName()416 	inline char *getName() {
417 		return name;
418 	}
419 
420 
421 	void saveMap( const std::string& name, std::string& result, bool absolutePath = false, int referenceType = REF_TYPE_NAME );
422 	bool loadMap( const std::string& name, std::string& result, StatusReport *report = NULL,
423 	              int level = 1, int depth = 0,
424 	              bool changingStory = false, bool fromRandom = false,
425 	              bool goingUp = false, bool goingDown = false,
426 	              std::vector< RenderedItem* > *items = NULL,
427 	              std::vector< RenderedCreature* > *creatures = NULL,
428 	              bool absolutePath = false,
429 	              char *templateMapName = NULL );
430 	void loadMapLocation( const std::string& name, std::string& result, int *gridX, int *gridY, int depth = 0 );
431 	void initForCave( char *themeName = NULL );
432 
433 	/// Returns the mouse cursor's map position.
getCursorMapX()434 	inline Uint16 getCursorMapX() {
435 		return cursorMapX;
436 	}
getCursorMapY()437 	inline Uint16 getCursorMapY() {
438 		return cursorMapY;
439 	}
getCursorMapZ()440 	inline Uint16 getCursorMapZ() {
441 		return cursorMapZ;
442 	}
443 
444 	/// Returns the mouse cursor's map position (using flat map math).
getCursorFlatMapX()445 	inline Uint16 getCursorFlatMapX() {
446 		return cursorFlatMapX;
447 	}
getCursorFlatMapY()448 	inline Uint16 getCursorFlatMapY() {
449 		return cursorFlatMapY;
450 	}
451 
getCursorChunkX()452 	inline Uint16 getCursorChunkX() {
453 		return cursorChunkX;
454 	}
getCursorChunkY()455 	inline Uint16 getCursorChunkY() {
456 		return cursorChunkY;
457 	}
458 
459 	void handleEvent( SDL_Event *event );
460 
461 	void reset();
462 
463 	/// Stops moving the view.
resetMove()464 	inline void resetMove() {
465 		move = 0;
466 	}
467 
468 	/// Do we currently rotate the view?
isMouseRotating()469 	inline bool isMouseRotating() {
470 		return mouseRot;
471 	}
472 	/// Do we currently zoom the view?
isMouseZooming()473 	inline bool isMouseZooming() {
474 		return mouseZoom;
475 	}
476 	/// Do we currently scroll the view?
isMapMoving()477 	inline bool isMapMoving() {
478 		return move != 0;
479 	}
480 
setMapSettings(MapSettings * settings)481 	inline void setMapSettings( MapSettings *settings ) {
482 		this->settings = settings;
483 	}
getMapSettings()484 	inline MapSettings *getMapSettings() {
485 		return settings;
486 	}
487 
488 	/// Is this a flooded level (indoors only)?
getHasWater()489 	inline bool getHasWater() {
490 		return hasWater;
491 	}
492 	/// Make this a "flooded" level (indoors).
setHasWater(bool b)493 	inline void setHasWater( bool b ) {
494 		hasWater = b;
495 	}
496 
497 	int debugX, debugY, debugZ;
498 
499 	int toggleLightMap();
500 
501 	bool floorOnly;
502 
503 	/// A location where an item is to be dropped by the player.
setSelectedDropTarget(Location * loc)504 	inline void setSelectedDropTarget( Location *loc ) {
505 		selectedDropTarget = loc;
506 	}
507 	/// A location where an item is to be dropped by the player.
getSelectedDropTarget()508 	inline Location *getSelectedDropTarget() {
509 		return selectedDropTarget;
510 	}
511 
setZoomIn(bool b)512 	inline void setZoomIn( bool b ) {
513 		zoomIn = b;
514 	}
setZoomOut(bool b)515 	inline void setZoomOut( bool b ) {
516 		zoomOut = b;
517 	}
518 	/// Current camera zoom.
getZoom()519 	inline float getZoom() {
520 		return zoom;
521 	}
522 	float getZoomPercent();
523 
524 	/// Camera rotation.
setXRot(float b)525 	inline void setXRot( float b ) {
526 		xRotating = b;
527 	}
setYRot(float b)528 	inline void setYRot( float b ) {
529 		yRotating = b;
530 	}
setZRot(float b)531 	inline void setZRot( float b ) {
532 		zRotating = b;
533 	}
534 
getXRot()535 	inline float getXRot() {
536 		return xrot;
537 	}
getYRot()538 	inline float getYRot() {
539 		return yrot;
540 	}
getZRot()541 	inline float getZRot() {
542 		return zrot;
543 	}
544 
545 	/// Move the camera one tile east.
addXPos(float f)546 	inline void addXPos( float f ) {
547 		xpos += f;
548 	}
549 	/// Move the camera one tile south.
addYPos(float f)550 	inline void addYPos( float f ) {
551 		ypos += f;
552 	}
553 	/// Make the camera point at a higher z pos.
addZPos(float f)554 	inline void addZPos( float f ) {
555 		zpos += f;
556 	}
557 
558 	/// X position of tile the view is centered on.
getXPos()559 	inline float getXPos() {
560 		return xpos;
561 	}
562 	/// Y position of tile the view is centered on.
getYPos()563 	inline float getYPos() {
564 		return ypos;
565 	}
566 	/// Z position of tile the view is centered on.
getZPos()567 	inline float getZPos() {
568 		return zpos;
569 	}
570 
571 	// camera control
572 	void setPos( float x, float y, float z );
573 	/// Sets the camera rotation.
setRot(float x,float y,float z)574 	inline void setRot( float x, float y, float z ) {
575 		xrot = x; yrot = y; zrot = z;
576 	}
setZoom(float zoom)577 	inline void setZoom( float zoom ) {
578 		this->zoom = zoom;
579 	}
580 
581 	bool isLocationVisible( int x, int y );
582 
583 	bool isLocationInLight( int x, int y, Shape *shape );
584 
585 	void draw();
586 	void preDraw();
587 	void postDraw();
588 
589 	/// Unused.
590 	void drawBorder();
591 
592 	/// The map top left x coordinate
getX()593 	inline int getX() {
594 		return x;
595 	}
596 
597 	/// The map top left y coordinate
getY()598 	inline int getY() {
599 		return y;
600 	}
601 
getMapX()602 	inline float getMapX() {
603 		return mapx;
604 	}
getMapY()605 	inline float getMapY() {
606 		return mapy;
607 	}
608 
setXY(int x,int y)609 	inline void setXY( int x, int y ) {
610 		this->x = x; this->y = y;
611 	}
612 
613 	void center( Sint16 x, Sint16 y, bool force = false );
614 
615 	void stopEffect( Sint16 x, Sint16 y, Sint16 z );
616 	void startEffect( Sint16 x, Sint16 y, Sint16 z,
617 	                  int effect_type, GLuint duration = Constants::DAMAGE_DURATION,
618 	                  int width = 1, int height = 1,
619 	                  GLuint delay = 0, bool forever = false,
620 	                  DisplayInfo *di = NULL );
621 
622 	void setPosition( Sint16 x, Sint16 y, Sint16 z, Shape *shape, DisplayInfo *di = NULL );
623 	Shape *removePosition( Sint16 x, Sint16 y, Sint16 z );
624 	Shape *removeLocation( Sint16 x, Sint16 y, Sint16 z );
625 
626 	bool hasOutdoorTexture( int x, int y, int width, int height );
627 
628 	void setOutdoorTexture( int x, int y, float offsetX, float offsetY,
629 	                        int ref, float angle, bool horizFlip,
630 	                        bool vertFlip, int z );
631 	void removeOutdoorTexture( int x, int y, float width, float height, int z );
632 
633 	Shape *removeItemPosition( Sint16 x, Sint16 y );
634 
635 	void setItem( Sint16 x, Sint16 y, Sint16 z, RenderedItem *item );
636 	RenderedItem *removeItem( Sint16 x, Sint16 y, Sint16 z );
637 
638 	void setCreature( Sint16 x, Sint16 y, Sint16 z, RenderedCreature *creature );
639 	RenderedCreature *removeCreature( Sint16 x, Sint16 y, Sint16 z );
640 
641 	Location *moveCreature( Sint16 x, Sint16 y, Sint16 z, Uint16 dir,
642 	                        RenderedCreature *newCreature );
643 	Location *moveCreature( Sint16 x, Sint16 y, Sint16 z,
644 	                        Sint16 nx, Sint16 ny, Sint16 nz,
645 	                        RenderedCreature *newCreature );
646 
647 	void setFloorPosition( Sint16 x, Sint16 y, Shape *shape );
648 	Shape *removeFloorPosition( Sint16 x, Sint16 y );
649 
650 	void setRugPosition( Sint16 x, Sint16 y, Rug *rug );
651 	void removeRugPosition( Sint16 x, Sint16 y );
hasRugAtPosition(Sint16 x,Sint16 y)652 	inline bool hasRugAtPosition( Sint16 x, Sint16 y ) {
653 		return rugPos[x][y].texture.isSpecified();
654 	}
655 
656 	Location *isBlocked( Sint16 x, Sint16 y, Sint16 z,
657 	                     Sint16 shapex, Sint16 shapey, Sint16 shapez,
658 	                     Shape *shape,
659 	                     int *newz = NULL,
660 	                     bool useItemPos = false );
661 
662 	Location *getPosition( Sint16 x, Sint16 y, Sint16 z );
663 	/// Returns a position struct for the specified map tile.
getLocation(Sint16 x,Sint16 y,Sint16 z)664 	inline Location *getLocation( Sint16 x, Sint16 y, Sint16 z ) {
665 		return pos[x][y][z];
666 	}
667 	/// Returns an item position struct for the x,y map tile.
getItemLocation(Sint16 x,Sint16 y)668 	inline Location *getItemLocation( Sint16 x, Sint16 y ) {
669 		return itemPos[x][y];
670 	}
671 	/// Gets the shape that is on the floor at x,y.
getFloorPosition(Sint16 x,Sint16 y)672 	inline Shape *getFloorPosition( Sint16 x, Sint16 y ) {
673 		if ( x < 0 || x >= MAP_WIDTH || y < 0 || y >= MAP_DEPTH ) return NULL; else return floorPositions[x][y];
674 	}
675 
676 	//void showInfoAtMapPos(Uint16 mapx, Uint16 mapy, Uint16 mapz, char *message);
677 	/// Unused.
678 	void showCreatureInfo( RenderedCreature *creature, bool player, bool selected, bool groupMode );
679 
680 	void initMapView( bool ignoreRot = false );
681 
682 	void moveMap( int dir );
683 
684 	bool isWallBetweenShapes( int x1, int y1, int z1,
685 	                          Shape *shape1,
686 	                          int x2, int y2, int z2,
687 	                          Shape *shape2 );
688 
689 	Shape *isWallBetween( int x1, int y1, int z1,
690 	                      int x2, int y2, int z2 );
691 
692 	bool shapeFits( Shape *shape, int x, int y, int z );
693 
694 	bool shapeFitsOutdoors( GLShape *shape, int x, int y, int z );
695 
696 	Location *getBlockingLocation( Shape *shape, int x, int y, int z );
697 
698 	Location *getDropLocation( Shape *shape, int x, int y, int z );
699 
700 	/// Forces an update of the light map (indoor visibility map).
updateLightMap()701 	inline void updateLightMap() {
702 		lightMapChanged = resortShapes = true;
703 	}
704 
705 	void refresh();
706 
707 	/// Force to resort the shapes so transparency will work.
refreshTransparency()708 	inline void refreshTransparency() {
709 		resortShapes = true;
710 	}
711 
712 	void setViewArea( int x, int y, int w, int h );
713 	/// Width of the 3D view (usually equal to screen width)
getViewWidth()714 	inline int getViewWidth() {
715 		return viewWidth;
716 	}
717 	/// Height of the 3D view (usually equal to screen height)
getViewHeight()718 	inline int getViewHeight() {
719 		return viewHeight;
720 	}
721 
722 	void dropItemsAbove( int x, int y, int z, RenderedItem *item );
723 
724 	int getCreaturesInArea( int x, int y, int radius, RenderedCreature *targets[] );
725 
726 	bool isOnScreen( Uint16 mapx, Uint16 mapy, Uint16 mapz );
727 	void doDrawShape( DrawLater *later, int effect = 0 );
728 	void doDrawShape( float xpos2, float ypos2, float zpos2,
729 	                  Shape *shape, int effect = 0, DrawLater *later = NULL );
730 	void findOccludedSides( DrawLater *later, bool *sides );
731 
732 	bool isDoor( int x, int y );
733 	bool isDoor( Shape *shape );
734 	bool isDoorType( Shape *shape, bool includeCorner = true );
735 
736 	// ====================================================================
737 	// Locked doors/chests code
738 	void setLocked( int doorX, int doorY, int doorZ, bool value );
739 	/// Unlocks the door at x,y,z.
removeLocked(int doorX,int doorY,int doorZ)740 	inline void removeLocked( int doorX, int doorY, int doorZ ) {
741 		Uint32 door = createTripletKey( doorX, doorY, doorZ );
742 		locked.erase( door );
743 		if ( doorToKey.find( door ) != doorToKey.end() ) {
744 			Uint32 key = doorToKey[door];
745 			doorToKey.erase( key );
746 			keyToDoor.erase( door );
747 		}
748 	}
749 
750 	/// Clear the locked objects (doors and levers).
clearLocked()751 	inline void clearLocked() {
752 		if ( !locked.empty() ) locked.clear();
753 		if ( !doorToKey.empty() ) doorToKey.clear();
754 		if ( !keyToDoor.empty() ) keyToDoor.clear();
755 	}
756 
757 	/// Is the door at x,y,z locked?
isLocked(int doorX,int doorY,int doorZ)758 	inline bool isLocked( int doorX, int doorY, int doorZ ) {
759 		Uint32 door = createTripletKey( doorX, doorY, doorZ );
760 		return ( locked.find( door ) != locked.end() ? locked[door] : false );
761 	}
762 
763 	/// Gets the position of the door that is connected to the lever at x,y,z.
getDoorLocation(int keyX,int keyY,int keyZ,int * doorX,int * doorY,int * doorZ)764 	inline void getDoorLocation( int keyX, int keyY, int keyZ,
765 	                             int *doorX, int *doorY, int *doorZ ) {
766 		Uint32 key = createTripletKey( keyX, keyY, keyZ );
767 		if ( keyToDoor.find( key ) != keyToDoor.end() ) {
768 			decodeTripletKey( keyToDoor[key], doorX, doorY, doorZ );
769 		} else {
770 			*doorX = *doorY = *doorZ = -1;
771 		}
772 	}
773 
774 	/// Gets the position of the lever that is connected to the door at x,y,z.
getKeyLocation(int doorX,int doorY,int doorZ,int * keyX,int * keyY,int * keyZ)775 	inline void getKeyLocation( int doorX, int doorY, int doorZ,
776 	                            int *keyX, int *keyY, int *keyZ ) {
777 		Uint32 key = createTripletKey( doorX, doorY, doorZ );
778 		if ( doorToKey.find( key ) != doorToKey.end() ) {
779 			decodeTripletKey( doorToKey[ key ], keyX, keyY, keyZ );
780 		} else {
781 			*keyX = *keyY = *keyZ = -1;
782 		}
783 	}
784 
785 	/// Moves a door and tries to keep it connected to its unlock lever.
updateDoorLocation(int oldDoorX,int oldDoorY,int oldDoorZ,int newDoorX,int newDoorY,int newDoorZ)786 	inline void updateDoorLocation( int oldDoorX, int oldDoorY, int oldDoorZ,
787 	                                int newDoorX, int newDoorY, int newDoorZ ) {
788 		//cerr << "**********************" << endl;
789 		Uint32 oldDoor = createTripletKey( oldDoorX, oldDoorY, oldDoorZ );
790 		Uint32 newDoor = createTripletKey( newDoorX, newDoorY, newDoorZ );
791 		//cerr << "oldDoor=" << oldDoor << " pos: " << oldDoorX << "," << oldDoorY << "," << oldDoorZ << endl;
792 		//cerr << "newDoor=" << newDoor << " pos: " << newDoorX << "," << newDoorY << "," << newDoorZ << endl;
793 		if ( locked.find( oldDoor ) != locked.end() ) {
794 			//cerr << "\tfound locked." << endl;
795 			locked[newDoor] = locked[oldDoor];
796 			locked.erase( oldDoor );
797 		}
798 		if ( doorToKey.find( oldDoor ) != doorToKey.end() ) {
799 			//cerr << "\tfound door<->key." << endl;
800 			Uint32 key = doorToKey[oldDoor];
801 			int keyX, keyY, keyZ;
802 			decodeTripletKey( key, &keyX, &keyY, &keyZ );
803 			//cerr << "\tkey=" << key << " pos: " << keyX << "," << keyY << "," << keyZ << endl;
804 			doorToKey[newDoor] = key;
805 			doorToKey.erase( oldDoor );
806 			keyToDoor[key] = newDoor;
807 		}
808 		//cerr << "**********************" << endl;
809 	}
810 
811 	/// Creates a door/unlock lever pair.
setKeyLocation(int doorX,int doorY,int doorZ,int keyX,int keyY,int keyZ)812 	void setKeyLocation( int doorX, int doorY, int doorZ,
813 	                     int keyX, int keyY, int keyZ ) {
814 		Uint32 door = createTripletKey( doorX, doorY, doorZ );
815 		Uint32 key = createTripletKey( keyX, keyY, keyZ );
816 		doorToKey[door] = key;
817 		keyToDoor[key] = door;
818 	}
819 	// ====================================================================
820 
821 	// access map methods for locked doors/chests
822 	void configureAccessMap( int fromX, int fromY );
823 	bool isPositionAccessible( int atX, int atY );
824 
825 	void getMapXYAtScreenXY( Uint16 x, Uint16 y, Uint16 *mapx, Uint16 *mapy );
826 	void getScreenXYAtMapXY( Uint16 mapx, Uint16 mapy, Uint16 *screenx, Uint16 *screeny );
827 	int getPanningFromMapXY( Uint16 mapx, Uint16 mapy );
828 
829 	/// Sets the ground height at x,y (outdoors).
setGroundHeight(int x,int y,float h)830 	inline void setGroundHeight( int x, int y, float h ) {
831 		this->ground[x][y] = h; refreshGroundPos = true;
832 	}
833 	/// Gets the ground height at x,y.
getGroundHeight(int x,int y)834 	inline float getGroundHeight( int x, int y ) {
835 		return this->ground[x][y];
836 	}
837 	/// Does this map have an uneven floor (e.g. is it outdoors)?
setHeightMapEnabled(bool b)838 	inline void setHeightMapEnabled( bool b ) {
839 		this->heightMapEnabled = b;
840 	}
841 	/// Does this map have an uneven floor (e.g is it outdoors)?
isHeightMapEnabled()842 	inline bool isHeightMapEnabled() {
843 		return this->heightMapEnabled;
844 	}
845 	/// Do we need to setup the ground textures?
setRefreshGroundPos(bool b)846 	inline void setRefreshGroundPos( bool b ) {
847 		this->refreshGroundPos = b;
848 	}
849 	/// Do we need to setup the ground textures?
isRefreshGroundPos()850 	inline bool isRefreshGroundPos() {
851 		return this->refreshGroundPos;
852 	}
853 	/// Sets the ground texture at x,y (outdoors).
setGroundTex(int x,int y,Texture tex)854 	inline void setGroundTex( int x, int y, Texture tex ) {
855 		this->groundTex[x][y] = tex;
856 	}
857 	/// Returns the ground texture of tile x,y.
getGroundTex(int x,int y)858 	inline Texture getGroundTex( int x, int y ) {
859 		return this->groundTex[x][y];
860 	}
861 
862 	float findMaxHeightPos( float x, float y, float z, bool findMax = false );
863 
864 	void drawGroundTex( Texture tex, float tx, float ty, float tw, float th, float angle = 0 );
865 
866 	void drawOutdoorTex( Texture tex, float tx, float ty, float tw, float th, float angle = 0 );
867 
868 	void debugGround( int sx, int sy, int ex, int ey );
869 
870 	void initOutdoorsGroundTexture();
871 
872 	// Traps
873 	int addTrap( int x, int y, int w, int h );
874 	void removeTrap( int trap );
875 	int getTrapAtLoc( int x, int y );
876 	Trap *getTrapLoc( int trap );
877 	/// Returns an array of trap indices.
getTrapsShown()878 	inline std::set<Uint8> *getTrapsShown() {
879 		return &trapSet;
880 	}
881 	/// The currently selected trap (mouse cursor is over it).
getSelectedTrapIndex()882 	inline int getSelectedTrapIndex() {
883 		return selectedTrapIndex;
884 	}
885 
886 	bool canFit( int x, int y, Shape *shape );
887 	bool isEmpty( int x, int y );
888 
889 	bool inMapEditor();
890 	bool coversDoor( Shape *shape, int x, int y );
891 
getGates()892 	inline std::set<Location*> *getGates() {
893 		return &gates;
894 	}
getTeleporters()895 	inline std::set<Location*> *getTeleporters() {
896 		return &teleporters;
897 	}
898 
899 protected:
900 	void drawIndoors();
901 	void drawOutdoors();
902 	void drawEffects();
903 	void drawRoofs();
904 	bool checkLightMap( int chunkX, int chunkY );
905 	void applyGrassEdges( int x, int y, bool w, bool e, bool s, bool n );
906 	Texture getThemeTex( int ref );
907 	void addHighVariation( int ref, int z );
908 	bool isRockTexture( int x, int y );
909 	bool isLakebedTexture( int x, int y );
910 	bool isAllHigh( int x, int y, int w, int h );
911 	void clearTraps();
912 	void drawTraps();
913 
914 	void createGroundMap();
915 	void addLight( CVectorTex *pt, CVectorTex *a, CVectorTex *b );
916 
917 	void renderFloor();
918 	void drawFlatFloor();
919 	bool drawHeightMapFloor();
920 	void drawWaterLevel();
921 
922 	void willDrawGrid();
923 
924 	void setPositionInner( Sint16 x, Sint16 y, Sint16 z,
925 	                       Shape *shape,
926 	                       RenderedItem *item,
927 	                       RenderedCreature *creature );
928 
929 	/// Set which direction to move the map in.
930 
931 	/// @param n is a bitfield.
932 	/// See constants for direction values.
setMove(Uint16 n)933 	inline void setMove( Uint16 n ) {
934 		move |= n;
935 	};
936 
937 	/// Stop moving the map in the given direction(s).
938 
939 	/// @param n is a bitfield.
940 	/// See constants for directions values.
removeMove(Uint16 n)941 	inline void removeMove( Uint16 n ) {
942 		move &= ( 0xffff - n );
943 	}
944 
945 	/// Creates a unique key from a x,y,z map position.
946 
947 	/// This assumes that MAP_WIDTH >= MAP_HEIGHT
948 	/// and that MAP_WIDTH^3 < 2^32.
createTripletKey(int x,int y,int z)949 	inline Uint32 createTripletKey( int x, int y, int z ) {
950 		Uint32 key =
951 		  ( ( Uint32 )x * ( Uint32 )MAP_WIDTH * ( Uint32 )MAP_WIDTH ) +
952 		  ( ( Uint32 )y * ( Uint32 )MAP_WIDTH ) +
953 		  ( ( Uint32 )z );
954 		//cerr << "DEBUG: createTripletKey, x=" << x << " y=" << y << " z=" << z << " key=" << key << endl;
955 		return key;
956 	}
957 
958 	/// Decodes a triplet key to a x,y,z map position.
decodeTripletKey(Uint32 key,int * x,int * y,int * z)959 	inline void decodeTripletKey( Uint32 key, int *x, int *y, int *z ) {
960 		*x = static_cast<int>( key / ( ( Uint32 )MAP_WIDTH * ( Uint32 )MAP_WIDTH ) );
961 		*y = static_cast<int>( ( key % ( ( Uint32 )MAP_WIDTH * ( Uint32 )MAP_WIDTH ) ) / ( Uint32 )MAP_WIDTH );
962 		*z = static_cast<int>( ( key % ( ( Uint32 )MAP_WIDTH * ( Uint32 )MAP_WIDTH ) ) % ( Uint32 )MAP_WIDTH );
963 		//cerr << "DEBUG: decodeTripletKey, key=" << key << " x=" << (*x) << " y=" << (*y) << " z=" << (*z) << endl;
964 	}
965 
966 	/// Creates a unique key from a map position.
createPairKey(int x,int y)967 	inline Uint32 createPairKey( int x, int y ) {
968 		Uint32 key =
969 		  ( ( Uint32 )x * ( Uint32 )MAP_WIDTH ) +
970 		  ( ( Uint32 )y );
971 		return key;
972 	}
973 
974 	/// Decodes a pair key to a map position.
decodePairKey(Uint32 key,int * x,int * y)975 	inline void decodePairKey( Uint32 key, int *x, int *y ) {
976 		*x = static_cast<int>( key / ( ( Uint32 )MAP_WIDTH ) );
977 		*y = static_cast<int>( key % ( ( Uint32 )MAP_WIDTH ) );
978 	}
979 
980 	CFrustum *frustum;
981 
982 	/// A chunk (of several tiles).
983 	struct ChunkInfo {
984 		float x, y;
985 		int cx, cy;
986 	};
987 
988 	ChunkInfo chunks[100];
989 	int chunkCount;
990 	DrawLater later[100], stencil[1000], other[1000], damage[1000], roof[1000];
991 	int laterCount, stencilCount, otherCount, damageCount, roofCount;
992 	std::map<Uint32, EffectLocation*> currentEffectsMap;
993 
994 	void setupShapes( bool forGround, bool forWater, int *csx = NULL, int *cex = NULL, int *csy = NULL, int *cey = NULL );
995 	void setupPosition( int posX, int posY, int posZ,
996 	                    float xpos2, float ypos2, float zpos2,
997 	                    Shape *shape, RenderedItem *item, RenderedCreature *creature,
998 	                    EffectLocation *effect, bool itemPos = false );
999 	void setupLocation( Location *location, Uint16 drawSide, int chunkStartX, int chunkStartY, int chunkOffsetX, int chunkOffsetY );
1000 	void drawRug( Rug *rug, float xpos2, float ypos2, int xchunk, int ychunk );
1001 	void drawGroundPosition( int posX, int posY,
1002 	                         float xpos2, float ypos2,
1003 	                         Shape *shape );
1004 	void drawWaterPosition( int posX, int posY,
1005 	                        float xpos2, float ypos2,
1006 	                        Shape *shape );
1007 	Shape *isWall( int x, int y, int z );
1008 
1009 	void configureLightMap();
1010 	void traceLight( int chunkX, int chunkY, int lightMap[MAP_CHUNKS_X][MAP_CHUNKS_Y], bool onlyLockedDoors );
1011 	bool isLocationBlocked( int x, int y, int z, bool onlyLockedDoors );
1012 
1013 	void drawProjectiles();
1014 
1015 	void drawCube( float x, float y, float z, float r );
1016 
1017 	void removeEffect( Sint16 x, Sint16 y, Sint16 z );
1018 	void removeAllEffects();
1019 
1020 	void moveCreaturePos( Sint16 nx, Sint16 ny, Sint16 nz,
1021 	                      Sint16 ox, Sint16 oy, Sint16 oz,
1022 	                      RenderedCreature *creature );
1023 
1024 	void calculateChunkInfo( int *chunkOffsetX, int *chunkOffsetY,
1025 	                         int *chunkStartX, int *chunkStartY,
1026 	                         int *chunkEndX, int *chunkEndY );
1027 	void getChunk( int mapX, int mapY, int *chunkX, int *chunkY );
1028 	void calculateLocationInfo( Location *location,
1029 	                            int chunkStartX, int chunkStartY,
1030 	                            int chunkOffsetX, int chunkOffsetY,
1031 	                            Uint16 drawSide,
1032 	                            int *posX, int *posY, int *posZ,
1033 	                            float *xpos, float *ypos, float *zpos,
1034 	                            int *chunkX, int *chunkY,
1035 	                            bool *lightEdge );
1036 	bool checkUnderRoof();
1037 
1038 	/// Unused.
1039 	void drawWater();
1040 
1041 	void removeCurrentEffects();
1042 
1043 	void sortShapes( DrawLater *playerDrawLater,
1044 	                 DrawLater *shapes,
1045 	                 int shapeCount );
1046 
1047 	void getMapXYAtScreenXY( Uint16 *mapx, Uint16 *mapy );
1048 	void getMapXYZAtScreenXY( Uint16 *mapx, Uint16 *mapy, Uint16 *mapz, Location **pos );
1049 
1050 	bool isShapeInFront( GLdouble playerWinY, GLdouble objX, GLdouble objY, std::map< std::string, bool > *cache, GLdouble *mm, GLdouble *pm, GLint *vp );
1051 
1052 	DECLARE_NOISY_OPENGL_SUPPORT();
1053 };
1054 
1055 #endif
1056