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