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 PLAYER_H
19 #define PLAYER_H
20 
21 #include <OgrePrerequisites.h>
22 
23 #include <string>
24 #include <vector>
25 #include <cstdint>
26 
27 class Creature;
28 class GameMap;
29 class GameEntity;
30 class ODPacket;
31 class Skill;
32 class Seat;
33 class Tile;
34 
35 enum class CreatureActionType;
36 enum class SpellType;
37 
38 enum class PlayerEventType
39 {
40     nullType,
41     fight
42 };
43 
44 ODPacket& operator<<(ODPacket& os, const PlayerEventType& type);
45 ODPacket& operator>>(ODPacket& is, PlayerEventType& type);
46 
47 //! Class that represents the events where the player can zoom
48 class PlayerEvent
49 {
50 public:
PlayerEvent()51     PlayerEvent() :
52         mType(PlayerEventType::nullType),
53         mTile(nullptr),
54         mTimeRemain(0.0)
55     {
56     }
57 
PlayerEvent(PlayerEventType type,Tile * tile,Ogre::Real timeRemain)58     PlayerEvent(PlayerEventType type, Tile* tile, Ogre::Real timeRemain) :
59         mType(type),
60         mTile(tile),
61         mTimeRemain(timeRemain)
62     {
63     }
64 
getType()65     inline PlayerEventType getType() const
66     { return mType; }
67 
getTile()68     inline Tile* getTile() const
69     { return mTile; }
70 
getTimeRemain()71     inline float getTimeRemain() const
72     { return mTimeRemain; }
73 
setTimeRemain(float timeRemain)74     inline void setTimeRemain(float timeRemain)
75     { mTimeRemain = timeRemain; }
76 
77     static PlayerEvent* getPlayerEventFromPacket(GameMap* gameMap, ODPacket& is);
78     static void exportPlayerEventToPacket(PlayerEvent* event, GameMap* gameMap, ODPacket& is);
79 
80 protected:
81     void exportToPacket(GameMap* gameMap, ODPacket& os);
82     void importFromPacket(GameMap* gameMap, ODPacket& is);
83 
84 private:
85     PlayerEventType mType;
86     Tile* mTile;
87     float mTimeRemain;
88 };
89 
90 class PlayerSpellData
91 {
92 public:
PlayerSpellData(uint32_t cooldownNbTurnPending,float cooldownTimePendingTurn)93     PlayerSpellData(uint32_t cooldownNbTurnPending, float cooldownTimePendingTurn) :
94         mCooldownNbTurnPending(cooldownNbTurnPending),
95         mCooldownTimePendingTurn(cooldownTimePendingTurn)
96     {}
97 
98     uint32_t mCooldownNbTurnPending;
99     float mCooldownTimePendingTurn;
100 };
101 
102 /*! \brief The player class contains information about a human, or computer, player in the game.
103  *
104  * When a new player joins a game being hosted on a server the server will
105  * allocate a new Player structure and fill it in with the appropriate values.
106  * Its relevant information will then be sent to the other players in the game
107  * so they are aware of its presence.
108  */
109 class Player
110 {
111     friend class Seat;
112 public:
113     enum class Direction
114     {
115         left = -1,
116         right = 1
117     };
118 
119     Player(GameMap* gameMap, int32_t id);
120 
getId()121     inline int32_t getId() const
122     { return mId; }
123 
getNick()124     const std::string& getNick() const
125     { return mNickname; }
126 
getSeat()127     Seat* getSeat()
128     { return mSeat; }
129 
getSeat()130     const Seat* getSeat() const
131     { return mSeat; }
132 
setNick(const std::string & nick)133     void setNick (const std::string& nick)
134     { mNickname = nick; }
135 
136     //! \brief A simple accessor function to return the number of creatures
137     //! this player is holding in his/her hand that belongs to seat seat.
138     //! If seat is nullptr, then returns the total number of creatures
139     unsigned int numCreaturesInHand(const Seat* seat = nullptr) const;
140     unsigned int numObjectsInHand() const;
141 
142     /*! \brief Check to see if it is the user or another player picking up the creature and act accordingly.
143      *
144      * This function takes care of all of the operations required for a player to
145      * pick up an object (creature, treasury, ...).  If the player is the user we need to move the creature
146      * oncreen to the "hand" as well as add the creature to the list of creatures
147      * in our own hand, this is done by setting moveToHand to true.  If move to
148      * hand is false we just hide the creature (and stop its AI, etc.), rather than
149      * making it follow the cursor.
150      */
151     void pickUpEntity(GameEntity *entity);
152 
153     //! \brief Check to see the first object in hand can be dropped on Tile t and do so if possible.
154     bool isDropHandPossible(Tile *t, unsigned int index = 0);
155 
156     //! \brief Drops the creature on tile t. Returns the dropped creature
157     void dropHand(Tile *t, unsigned int index = 0);
158 
159     void rotateHand(Direction d);
160 
161     //! \brief Clears all creatures that a player might have in his hand
162     void clearObjectsInHand();
163 
164     //! \brief Clears all creatures that a player might have in his hand
165     void notifyNoMoreDungeonTemple();
166 
getIsHuman()167     inline bool getIsHuman() const
168     { return mIsHuman; }
169 
setIsHuman(bool isHuman)170     inline void setIsHuman(bool isHuman)
171     { mIsHuman = isHuman; }
172 
getObjectsInHand()173     inline const std::vector<GameEntity*>& getObjectsInHand()
174     { return mObjectsInHand; }
175 
getHasLost()176     inline bool getHasLost() const
177     { return mHasLost; }
178 
179     //! \brief Notify the player is fighting
180     //! Should be called on the server game map for human players only. tile represents
181     //! the place where the fight is happening and player is the Player actually fighting
182     void notifyTeamFighting(Player* player, Tile* tile);
183 
184     //! \brief Notify the player that they are not skill anything
185     //! Should be called on the server game map for human players only
186     void notifyNoSkillInQueue();
187 
188     //! \brief Notify the player that he has no worker
189     void notifyNoWorker();
190 
191     //! \brief Notify the player that no treasury tiles are available for gold storage
192     //! Should be called on the server game map for human players only
193     void notifyNoTreasuryAvailable();
194 
195     //! \brief Notify the player that a creature cannot find a bed
196     void notifyCreatureCannotFindBed(Creature& creature);
197 
198     //! \brief Notify the player that a creature cannot find a bed
199     void notifyCreatureCannotFindFood(Creature& creature);
200 
201     void fireEvents();
202 
203     //! \brief Called on client side to update the current list of events. Note that
204     //! the time remaining of PlayerEvent class is not relevant on client side
205     void updateEvents(const std::vector<PlayerEvent*>& events);
206 
207     //! \brief Get the next event. After index. If index > events size, the first one is
208     //! sent. When the function returns, index is set to the index of the returned event
209     //! and it returns the PlayerEvent if any (nullptr is none).
210     //! Note that on client side, PlayerEvent::mTimeRemain is not relevant
211     const PlayerEvent* getNextEvent(uint32_t& index) const;
212 
213     //! \brief Marks the tiles for digging and send the refresh event to concerned player if human
214     void markTilesForDigging(bool marked, const std::vector<Tile*>& tiles, bool asyncMsg);
215 
216     //! \brief Gets the spell cooldown in turns for the given spell
217     uint32_t getSpellCooldownTurns(SpellType spellType) const;
218 
219     //! \brief Gets the spell cooldown as a smooth value 0 being no cooldown and 1
220     //! max cooldown for the given spell
221     float getSpellCooldownSmooth(SpellType spellType) const;
222     float getSpellCooldownSmoothTime(SpellType spellType) const;
223 
224     void setSpellCooldownTurns(SpellType spellType, uint32_t cooldown);
225 
226     //! \brief Called each turn, it should handle Player upkeep on server side
227     void upkeepPlayer(double timeSinceLastUpkeep);
228 
229     //! \brief Decreases cooldown for all spells. Used on both server and client sides
230     void decreaseSpellCooldowns();
231 
232     //! \brief Called each time a frame is displayed. Called on client side
233     void frameStarted(float timeSinceLastFrame);
234 
235     //! \brief Called when a worker picks up a new action
236     void notifyWorkerAction(Creature& worker, CreatureActionType actionType);
237     void notifyWorkerStopsAction(Creature& worker, CreatureActionType actionType);
238 
239     //! \brief Returns how many workers are doing the given action
240     uint32_t getNbWorkersDoing(CreatureActionType actionType) const;
241 
242     //! \brief Returns a list of the actions the worker should do based on what the other workers
243     //! of this seat are doing. The worker should try the actions on the given order
244     std::vector<CreatureActionType> getWorkerPreferredActions(Creature& worker) const;
245 
246 private:
247     //! \brief Player ID is only used during seat configuration phase
248     //! During the game, one should use the seat ID to identify a player because
249     //! every AI player has an id = 0.
250     //! ID is unique only for human players
251     int32_t mId;
252 
253     GameMap* mGameMap;
254     Seat *mSeat;
255 
256     //! \brief The nickname used in chat, etc.
257     std::string mNickname;
258 
259     //! \brief The creature the player has got in hand.
260     std::vector<GameEntity*> mObjectsInHand;
261 
262     //! True: player is human. False: player is a computer/inactive.
263     bool mIsHuman;
264 
265     //! \brief This counter tells for how much time is left before considering
266     //! the player should be notified again that he has not queued a skill.
267     float mNoSkillInQueueTime;
268 
269     //! \brief This counter tells for how much time is left before considering
270     //! the player should be notified again that he has no worker.
271     float mNoWorkerTime;
272 
273     //! \brief This counter tells for how much time is left before considering
274     //! the player should be notified again that he has no free space to store gold.
275     float mNoTreasuryAvailableTime;
276 
277     //! \brief This counter tells how much time is left before considering
278     //! the player should be notified again that a creature cannot find place in a dormitory.
279     float mCreatureCannotFindBed;
280 
281     //! \brief This counter tells how much time is left before considering
282     //! the player should be notified again that a creature cannot find place in a hatchery.
283     float mCreatureCannotFindFood;
284 
285     bool mHasLost;
286 
287     //! \brief List of tiles there is an event on. Used on client and server
288     std::vector<PlayerEvent*> mEvents;
289 
290     //! \brief Cooldown for every spells. Used on client and server.
291     //! the first value is the cooldown in turn. The second is the smooth time (set to
292     //! 1 turn duration at each refresh)
293     //! Note that the second value is used on client side only
294     std::vector<PlayerSpellData> mSpellsCooldown;
295 
296     //! \brief Used to know what the workers are doing. That will help to change
297     //! probability to choose the action to do
298     std::vector<uint32_t> mWorkersActions;
299 
300     //! \brief A simple mutator function to put the given entity into the player's hand,
301     //! note this should NOT be called directly for creatures on the map,
302     //! for that you should use the correct function like pickUpEntity() instead.
303     void addEntityToHand(GameEntity *entity);
304 };
305 
306 #endif // PLAYER_H
307