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