1 /* 2 * Copyright (C) 2011-2016 OpenDungeons Team 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef TILE_H 19 #define TILE_H 20 21 #include "entities/GameEntity.h" 22 23 #include <OgreVector3.h> 24 25 #include <string> 26 #include <vector> 27 #include <iosfwd> 28 #include <cstdint> 29 30 class Building; 31 class Creature; 32 class GameEntity; 33 class Player; 34 class Room; 35 class MapLight; 36 class GameMap; 37 class CreatureDefinition; 38 class Trap; 39 class TreasuryObject; 40 class ChickenEntity; 41 class CraftedTrap; 42 class BuildingObject; 43 class PersistentObject; 44 class ODPacket; 45 46 enum class RoomType; 47 enum class SelectionEntityWanted; 48 enum class TrapType; 49 50 //! Tile types a tile can be 51 enum class TileType 52 { 53 nullTileType = 0, 54 dirt = 1, 55 gold = 2, 56 rock = 3, 57 water = 4, 58 lava = 5, 59 gem = 6, 60 countTileType 61 }; 62 63 enum class TileSound 64 { 65 ClaimGround, 66 ClaimWall, 67 Digged, 68 BuildRoom, 69 BuildTrap 70 }; 71 72 ODPacket& operator<<(ODPacket& os, const TileType& type); 73 ODPacket& operator>>(ODPacket& is, TileType& type); 74 std::ostream& operator<<(std::ostream& os, const TileType& type); 75 std::istream& operator>>(std::istream& is, TileType& type); 76 77 78 //! Different representations a tile can have (ground or full) 79 enum class TileVisual 80 { 81 nullTileVisual = 0, 82 dirtGround, 83 dirtFull, 84 goldGround, 85 goldFull, 86 rockGround, 87 rockFull, 88 waterGround, 89 lavaGround, 90 claimedGround, 91 claimedFull, 92 gemGround, 93 gemFull, 94 countTileVisual 95 }; 96 97 ODPacket& operator<<(ODPacket& os, const TileVisual& type); 98 ODPacket& operator>>(ODPacket& is, TileVisual& type); 99 std::ostream& operator<<(std::ostream& os, const TileVisual& type); 100 std::istream& operator>>(std::istream& is, TileVisual& type); 101 102 enum class FloodFillType 103 { 104 ground = 0, 105 groundWater, 106 groundLava, 107 groundWaterLava, 108 nbValues 109 }; 110 111 /*! \brief Tile for listening for tile state events (like claiming or entity added/removed) 112 */ 113 class TileStateListener 114 { 115 public: 116 virtual void tileStateChanged(Tile& tile) = 0; 117 }; 118 119 120 /*! \brief The tile class contains information about tile type and contents and is the basic level bulding block. 121 * 122 * A Tile is the basic building block for the GameMap. It consists of a tile 123 * type (rock, dirt, gold, etc.) as well as a fullness which indicates how much 124 * the tile has been dug out. Additionally the tile contains lists of the 125 * entities located within it to aid in AI calculations. 126 */ 127 class Tile : public GameEntity 128 { 129 public: 130 Tile(GameMap* gameMap, int x = 0, int y = 0, TileType type = TileType::dirt, double fullness = 100.0); 131 132 virtual ~Tile(); 133 134 static const uint32_t NO_FLOODFILL; 135 static const std::string TILE_PREFIX; 136 static const std::string TILE_SCANF; 137 138 virtual GameEntityType getObjectType() const override; 139 doUpkeep()140 void doUpkeep() override 141 {} 142 getCoveredTiles()143 std::vector<Tile*> getCoveredTiles() override 144 { return std::vector<Tile*>(); } 145 getCoveredTile(int index)146 Tile* getCoveredTile(int index) override 147 { return nullptr; } 148 numCoveredTiles()149 uint32_t numCoveredTiles() const override 150 { return 0; } 151 getHP(Tile * tile)152 double getHP(Tile* tile) const override 153 { return 0.0; } 154 takeDamage(GameEntity * attacker,double absoluteDamage,double physicalDamage,double magicalDamage,double elementDamage,Tile * tileTakingDamage,bool ko)155 double takeDamage(GameEntity* attacker, double absoluteDamage, double physicalDamage, double magicalDamage, double elementDamage, 156 Tile *tileTakingDamage, bool ko) override 157 { return 0.0; } 158 addToGameMap()159 void addToGameMap() override 160 {} removeFromGameMap()161 void removeFromGameMap() override 162 {} 163 fireAddEntity(Seat * seat,bool async)164 void fireAddEntity(Seat* seat, bool async) override 165 {} 166 fireRemoveEntity(Seat * seat)167 void fireRemoveEntity(Seat* seat) override 168 {} 169 170 /*! \brief Set the type (rock, claimed, etc.) of the tile. 171 * 172 * In addition to setting the tile type this function also reloads the new mesh 173 * for the tile. 174 */ setType(TileType t)175 inline void setType(TileType t) 176 { mType = t; } 177 178 //! \brief Returns the tile type (rock, claimed, etc.). getType()179 inline TileType getType() const 180 { return mType; } 181 182 //! \brief Returns the tile type (rock, claimed, etc.). getTileVisual()183 inline TileVisual getTileVisual() const 184 { return mTileVisual; } 185 186 //! \brief Sets the tile type (rock, claimed, etc.). setTileVisual(TileVisual tileVisual)187 inline void setTileVisual(TileVisual tileVisual) 188 { mTileVisual = tileVisual; } 189 190 //! \brief A mutator to change how "filled in" the tile is. 191 //! Additionally this function refreshes floodfill if needed (if a tile becomes walkable) 192 void setFullness(double f); 193 194 //! \brief An accessor which returns the tile's fullness which should range from 0 to 100. getFullness()195 inline double getFullness() const 196 { return mFullness; } 197 198 //! \brief Tells whether a creature can see through a tile 199 bool permitsVision(); 200 getRefundPriceRoom()201 inline uint32_t getRefundPriceRoom() const 202 { return mRefundPriceRoom; } 203 getRefundPriceTrap()204 inline uint32_t getRefundPriceTrap() const 205 { return mRefundPriceTrap; } 206 207 208 /*! \brief This is a helper function to scroll through the list of available fullness levels. 209 * 210 * This function is used in the map editor when the user presses the button to 211 * select the next tile fullness level to be active in the user interface. The 212 * active fullness level is the one which is placed when the user clicks the 213 * mouse button. 214 */ 215 static int nextTileFullness(int f); 216 217 //! \brief This function puts a message in the renderQueue to change the mesh for this tile. 218 void refreshMesh(); 219 220 //! \brief Marks the tile as being selected through a mouse click or drag. 221 void setSelected(bool ss, const Player* pp); 222 223 //! \brief Returns whether or not the tile has been selected. getSelected()224 bool getSelected() const 225 { return mSelected; } 226 setLocalPlayerHasVision(bool localPlayerHasVision)227 inline void setLocalPlayerHasVision(bool localPlayerHasVision) 228 { mLocalPlayerHasVision = localPlayerHasVision; } 229 getLocalPlayerHasVision()230 inline bool getLocalPlayerHasVision() const 231 { return mLocalPlayerHasVision; } 232 233 //! \brief Set/unset the value of the mask depending on boolean value 234 void setTileCullingFlags(uint32_t mask, bool value); 235 236 //! \brief Set the tile digging mark for the given player. 237 void setMarkedForDigging(bool s, const Player* p); 238 239 //! \brief This accessor function returns whether or not the tile has been marked to be dug out by a given Player p. 240 bool getMarkedForDigging(const Player* p) const; 241 242 //! \brief This is a simple helper function which just calls setMarkedForDigging() for everyone in the game except 243 //! allied to exceptSeat. If exceptSeat is nullptr, it is called for every player 244 void setMarkedForDiggingForAllPlayersExcept(bool s, Seat* exceptSeat); 245 246 //! \brief Tells whether the tile is selected for digging by any player/AI. 247 bool isMarkedForDiggingByAnySeat(); 248 249 //! \brief Add/Remove a player to the vector of players who have marked this tile for digging. 250 void addPlayerMarkingTile(const Player *p); 251 void removePlayerMarkingTile(const Player *p); 252 253 //! \brief This function adds an entity to the list of entities in this tile. 254 bool addEntity(GameEntity *entity); 255 256 //! \brief This function removes an entity to the list of entities in this tile. 257 void removeEntity(GameEntity *entity); 258 259 //! \brief This function returns the count of the number of creatures in the tile. numEntitiesInTile()260 unsigned int numEntitiesInTile() const 261 { return mEntitiesInTile.size(); } 262 263 //! \brief This function returns the count of the number of creatures in the tile. getEntitiesInTile()264 const std::vector<GameEntity*>& getEntitiesInTile() const 265 { return mEntitiesInTile; } 266 267 void addNeighbor(Tile *n); 268 Tile* getNeighbor(unsigned index); getAllNeighbors()269 const std::vector<Tile*>& getAllNeighbors() const 270 { return mNeighbors; } 271 272 void claimForSeat(Seat* seat, double nDanceRate); 273 void claimTile(Seat* seat); 274 void unclaimTile(); 275 double digOut(double digRate); 276 getCoveringBuilding()277 inline Building* getCoveringBuilding() const 278 { return mCoveringBuilding; } 279 280 //! \brief Proxy that checks if there is a covering building and if it is a room. If yes, returns 281 //! a pointer to the covering room 282 Room* getCoveringRoom() const; 283 284 //! \brief Proxy that checks if there is a covering room and, if yes, that its 285 //! type is the expected one. This is for convenience because it is a pretty 286 //! common check 287 bool checkCoveringRoomType(RoomType type) const; 288 289 //! \brief Proxy that checks if there is a covering building and if it is a trap. If yes, returns 290 //! a pointer to the covering trap 291 Trap* getCoveringTrap() const; 292 293 //! \brief Proxy that checks if there is a covering trap and, if yes, that its 294 //! type is the expected one. This is for convenience because it is a pretty 295 //! common check 296 bool checkCoveringTrapType(TrapType type) const; 297 298 void setCoveringBuilding(Building* building); 299 300 //! \brief Add a tresaury object in this tile. There can be only one per tile so if there is already one, they are merged 301 bool addTreasuryObject(TreasuryObject* object); 302 303 //! \brief Tells whether the tile is diggable by dig-capable creatures. 304 //! \brief The player seat. 305 //! The function will check whether a tile is not already a reinforced wall owned by another team. 306 bool isDiggable(const Seat* seat) const; 307 308 //! \brief Tells whether the tile fullness is empty (ground tile) and can be claimed by the given seat. 309 bool isGroundClaimable(Seat* seat) const; 310 311 //! \brief Tells whether the tile is a wall (fullness > 1) and can be claimed for the given seat. 312 //! Reinforced walls by another team and hard rocks can't be claimed. 313 bool isWallClaimable(Seat* seat); 314 315 //! \brief Tells whether the tile is claimed for the given seat. 316 bool isClaimedForSeat(const Seat* seat) const; 317 318 //! \brief Tells whether the tile is claimed for the given seat. 319 bool isClaimed() const; 320 321 //! \brief Tells whether the given tile is a claimed wall for the given seat team. 322 //! Used to discover active spots for rooms. 323 bool isWallClaimedForSeat(Seat* seat); 324 325 //! \brief Tells whether a room can be built upon this tile. 326 bool isBuildableUpon(Seat* seat) const; 327 328 static std::string getFormat(); 329 330 //! \brief Loads the tile data from a level line. 331 static void loadFromLine(const std::string& line, Tile *t); 332 333 /*! \brief This is a helper function which just converts the tile type enum into a string. 334 * 335 * This function is used primarily in forming the mesh names to load from disk 336 * for the various tile types. The name returned by this function is 337 * concatenated with a fullnessMeshNumber to form the filename, e.g. 338 * Dirt104.mesh is a 4 sided dirt mesh with 100% fullness. 339 */ 340 static std::string tileTypeToString(TileType t); 341 342 static std::string tileVisualToString(TileVisual tileVisual); 343 static TileVisual tileVisualFromString(const std::string& strTileVisual); 344 getX()345 inline int getX() const 346 { return mX; } 347 getY()348 inline int getY() const 349 { return mY; } 350 getClaimedPercentage()351 inline double getClaimedPercentage() const 352 { return mClaimedPercentage; } 353 354 static std::string buildName(int x, int y); 355 static bool checkTileName(const std::string& tileName, int& x, int& y); 356 357 static std::string displayAsString(const Tile* tile); 358 359 //! \brief fills the given vector with the carryable entities on this tile 360 void fillWithCarryableEntities(Creature* carrier, std::vector<GameEntity*>& entities); 361 uint32_t countEntitiesOnTile(GameEntityType entityType) const; 362 363 //! \brief Returns true if the given entity is on the tile and false otherwise 364 bool isEntityOnTile(GameEntity* entity) const; 365 366 //! Fills the given vector with corresponding entities on this tile. 367 void fillWithEntities(std::vector<GameEntity*>& entities, SelectionEntityWanted entityWanted, Player* player); 368 369 //! \brief Computes the visible tiles and tags them to know which are visible 370 void computeVisibleTiles(); 371 void clearVision(); 372 void notifyVision(Seat* seat); 373 374 void setSeats(const std::vector<Seat*>& seats); 375 bool hasChangedForSeat(Seat* seat) const; 376 void changeNotifiedForSeat(Seat* seat); 377 378 void notifyEntitiesSeatsWithVision(); 379 getSeatsWithVision()380 const std::vector<Seat*>& getSeatsWithVision() 381 { return mSeatsWithVision; } 382 383 void resetFloodFill(); 384 385 static std::string toString(FloodFillType type); 386 387 bool isSameFloodFill(Seat* seat, FloodFillType type, Tile* tile) const; 388 389 //! Updates the floodfill from the given tile if floodfill is not already set. 390 //! returns true if the floodfill has been updated and false otherwise 391 bool updateFloodFillFromTile(Seat* seat, FloodFillType type, Tile* tile); 392 393 //! Sets the floodfill value corresponding at type to newValue 394 void replaceFloodFill(Seat* seat, FloodFillType type, uint32_t newValue); 395 396 void copyFloodFillToOtherSeats(Seat* seatToCopy); 397 398 uint32_t getFloodFillValue(Seat* seat, FloodFillType type) const; 399 400 void logFloodFill() const; 401 402 bool isFloodFillFilled(Seat* seat) const; 403 404 //! \brief Returns true if the given type can be set for the current tile 405 //! depending on its type/fullness 406 bool isFloodFillPossible(Seat* seat, FloodFillType type) const; 407 408 //! Refresh the tile visual according to the tile parameters (type, claimed, ...). 409 //! Used only on server side 410 void computeTileVisual(); 411 412 //! Function that allows to know if the tile is full or not. Works for both 413 //! server and client 414 bool isFullTile() const; 415 416 //! Sets the number of teams in this gamemap (after seat configuration). This number includes the rogue team. 417 void setTeamsNumber(uint32_t nbTeams); 418 419 //! \brief returns true if the mesh from the tileset should be displayed and false otherwise shouldDisplayTileMesh()420 inline bool shouldDisplayTileMesh() const 421 { return mDisplayTileMesh; } 422 423 //! \brief returns true if the mesh from the tileset should be colored and false otherwise 424 bool shouldColorTileMesh() const; 425 426 //! \brief returns true if the custom mesh (from a building, for example) should be colored and false otherwise shouldColorCustomMesh()427 inline bool shouldColorCustomMesh() const 428 { return mColorCustomMesh; } 429 getHasBridge()430 inline bool getHasBridge() const 431 { return mHasBridge; } 432 433 //! \brief returns true if there is a building on this tile and false otherwise. 434 //! client side function getIsBuilding()435 inline bool getIsBuilding() const 436 { return mIsRoom || mIsTrap; } getIsRoom()437 inline bool getIsRoom() const 438 { return mIsRoom; } getIsTrap()439 inline bool getIsTrap() const 440 { return mIsTrap; } 441 442 void fireTileSound(TileSound sound); 443 444 double getCreatureSpeedDefault(const Creature* creature) const; 445 446 //! \brief Allows to lock the tile for the workers claiming it. Returns true if the worker could be added 447 //! and false otherwise 448 //! Note that by nature, a tile cannot be claimed for wall and ground. Because of that, we can use the same 449 //! functions for both 450 bool canWorkerClaim(const Creature& worker); 451 bool addWorkerClaiming(const Creature& worker); 452 bool removeWorkerClaiming(const Creature& worker); 453 //! \brief Feels the tile vector with the available tiles the worker can 454 //! go to 455 void canWorkerDig(const Creature& worker, std::vector<Tile*>& tiles); 456 bool addWorkerDigging(const Creature& worker, Tile& tile); 457 bool removeWorkerDigging(const Creature& worker, Tile& tile); 458 459 static void exportToStream(Tile* tile, std::ostream& os); 460 461 virtual void exportToPacketForUpdate(ODPacket& os, const Seat* seat) const override; 462 virtual void updateFromPacket(ODPacket& is) override; 463 void exportToPacketForUpdate(ODPacket& os, const Seat* seat, bool hideSeatId) const; 464 465 bool addTileStateListener(TileStateListener& listener); 466 bool removeTileStateListener(TileStateListener& listener); 467 468 protected: exportHeadersToStream(std::ostream & os)469 virtual void exportHeadersToStream(std::ostream& os) const override 470 {} exportHeadersToPacket(ODPacket & os)471 virtual void exportHeadersToPacket(ODPacket& os) const override 472 {} 473 virtual void exportToStream(std::ostream& os) const override; importFromStream(std::istream & is)474 virtual bool importFromStream(std::istream& is) override 475 { return true; } exportToPacket(ODPacket & os,const Seat * seat)476 virtual void exportToPacket(ODPacket& os, const Seat* seat) const override 477 {} importFromPacket(ODPacket & is)478 virtual void importFromPacket(ODPacket& is) override 479 {} 480 481 virtual void createMeshLocal(); 482 virtual void destroyMeshLocal(); 483 private: 484 //! \brief The tile position 485 int mX, mY; 486 487 //! \brief The tile type: Dirt, Gold, ... 488 TileType mType; 489 490 //! \brief The tile visual: Claimed, Dirt, Gold, ... 491 //! On client side, we should rely on mTileVisual to know the tile type as claimed percentage 492 //! could not be up to date 493 TileVisual mTileVisual; 494 495 //! \brief Whether the tile is selected. 496 bool mSelected; 497 498 //! \brief The tile fullness (0.0 - 100.0). 499 //! At 0.0, it is a ground tile. Over it is a wall. 500 //! Used on server side only 501 double mFullness; 502 503 //! Used on client side to know how much gold can be retrieved if the room/trap 504 //! is sold. Note that it is needed because client are not aware of rooms/traps 505 uint32_t mRefundPriceRoom; 506 uint32_t mRefundPriceTrap; 507 508 std::vector<Tile*> mNeighbors; 509 std::vector<const Player*> mPlayersMarkingTile; 510 std::vector<std::pair<Seat*, bool>> mTileChangedForSeats; 511 std::vector<Seat*> mSeatsWithVision; 512 513 //! \brief List of the entities actually on this tile. Most of the creatures actions will rely on this list 514 std::vector<GameEntity*> mEntitiesInTile; 515 516 Building* mCoveringBuilding; 517 //! Floodfill values per seat and per floodfill type 518 std::vector<std::vector<uint32_t>> mFloodFillColor; 519 520 //! \brief The tile claiming. Used on server side only 521 double mClaimedPercentage; 522 523 //! \brief True if a building is on this tile. False otherwise. It is used on client side because the clients do not know about 524 //! buildings. However, it needs to know the tiles where a building is to display the room/trap costs. 525 bool mIsRoom; 526 bool mIsTrap; 527 528 bool mDisplayTileMesh; 529 530 bool mColorCustomMesh; 531 532 bool mHasBridge; 533 534 //! \brief Used on client side. true if the local player has vision, false otherwise. 535 bool mLocalPlayerHasVision; 536 537 uint32_t mTileCulling; 538 539 /*! \brief Set the fullness value for the tile. 540 * This only sets the fullness variable. This function is here to change the value 541 * before a map object has been set. setFullness is called once a map is assigned. 542 */ setFullnessValue(double f)543 inline void setFullnessValue(double f) 544 { mFullness = f; } 545 546 void setDirtyForAllSeats(); 547 548 //! \brief Vector with the number of workers digging the tile. The index corresponds 549 //! to the index in mNeighbors 550 std::vector<uint32_t> mNbWorkersDigging; 551 uint32_t mNbWorkersClaiming; 552 std::vector<TileStateListener*> mStateListeners; 553 554 void fireTileStateChanged(); 555 }; 556 557 #endif // TILE_H 558