1 /*
2  *  This file is part of Dune Legacy.
3  *
4  *  Dune Legacy 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 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Dune Legacy 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 Dune Legacy.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef UNITBASE_H
19 #define UNITBASE_H
20 
21 #include <ObjectBase.h>
22 
23 #include <House.h>
24 
25 #include <list>
26 
27 // forward declarations
28 class Tile;
29 
30 class UnitBase : public ObjectBase
31 {
32 public:
33     explicit UnitBase(House* newOwner);
34     explicit UnitBase(InputStream& stream);
35     void init();
36     virtual ~UnitBase();
37 
38     virtual void save(OutputStream& stream) const;
39 
40     void blitToScreen();
41 
42     virtual ObjectInterface* getInterfaceContainer();
43 
44     virtual void checkPos() = 0;
45     virtual void deploy(const Coord& newLocation);
46 
47     virtual void destroy();
48     void deviate(House* newOwner);
49 
50     virtual void drawSelectionBox();
51     virtual void drawOtherPlayerSelectionBox();
52 
53     /**
54         This method is called when an unit is ordered by a right click
55         \param  xPos    the x position on the map
56         \param  yPos    the y position on the map
57     */
58     virtual void handleActionClick(int xPos, int yPos);
59 
60     /**
61         This method is called when an unit is ordered to attack
62         \param  xPos    the x position on the map
63         \param  yPos    the y position on the map
64     */
65     virtual void handleAttackClick(int xPos, int yPos);
66 
67     /**
68         This method is called when an unit is ordered to move
69         \param  xPos    the x position on the map
70         \param  yPos    the y position on the map
71     */
72     virtual void handleMoveClick(int xPos, int yPos);
73 
74 
75     /**
76         This method is called when an unit is ordered to be in a new attack mode
77         \param  newAttackMode   the new attack mode the unit is put in.
78     */
79     virtual void handleSetAttackModeClick(ATTACKMODE newAttackMode);
80 
81 
82     /**
83         This method is called when an unit is ordered to request a carryall drop
84         \param  xPos    the x position on the map
85         \param  yPos    the y position on the map
86     */
87     virtual void handleRequestCarryallDropClick(int xPos, int yPos);
88 
89     /**
90         This method is called when an unit should move to (xPos,yPos)
91         \param  xPos    the x position on the map
92         \param  yPos    the y position on the map
93         \param  bForced true, if the unit should ignore everything else
94     */
95     virtual void doMove2Pos(int xPos, int yPos, bool bForced);
96 
97     /**
98         This method is called when an unit should move to coord
99         \param  coord   the position on the map
100         \param  bForced true, if the unit should ignore everything else
101     */
102     virtual void doMove2Pos(const Coord& coord, bool bForced);
103 
104     /**
105         This method is called when an unit should move to another unit/structure
106         \param  TargetObjectID  the ID of the other unit/structure
107     */
108     virtual void doMove2Object(Uint32 TargetObjectID);
109 
110     /**
111         This method is called when an unit should move to another unit/structure
112         \param  pTargetObject   the other unit/structure
113     */
114     virtual void doMove2Object(const ObjectBase* pTargetObject);
115 
116     /**
117         This method is called when an unit should attack a position
118         \param  xPos    the x position on the map
119         \param  yPos    the y position on the map
120         \param  bForced true, if the unit should ignore everything else
121     */
122     virtual void doAttackPos(int xPos, int yPos, bool bForced);
123 
124     /**
125         This method is called when an unit should attack to another unit/structure
126         \param  pTargetObject   the target unit/structure
127         \param  bForced true, if the unit should ignore everything else
128     */
129     virtual void doAttackObject(const ObjectBase* pTargetObject, bool bForced);
130 
131     /**
132         This method is called when an unit should attack to another unit/structure
133         \param  TargetObjectID  the ID of the other unit/structure
134         \param  bForced true, if the unit should ignore everything else
135     */
136     virtual void doAttackObject(Uint32 TargetObjectID, bool bForced);
137 
138     /**
139         This method is called when an unit should change it's current attack mode
140         \param  newAttackMode   the new attack mode
141     */
142     void doSetAttackMode(ATTACKMODE newAttackMode);
143 
144     virtual void handleDamage(int damage, Uint32 damagerID, House* damagerOwner);
145 
doRepair()146     virtual void doRepair() { };
147 
148     /**
149         Is this object in a range we are guarding. If yes we shall react.
150         \param  object  the object to check
151     */
152     bool isInGuardRange(const ObjectBase* object) const;
153 
154     /**
155         Is this object in a range we want to attack. If no, we should stop following it.
156         \param  object  the object to check
157     */
158     bool isInAttackRange(const ObjectBase* object) const;
159 
160     /**
161         Is this object in a range we can attack.
162         \param  object  the object to check
163     */
164     bool isInWeaponRange(const ObjectBase* object) const;
165 
166     void setAngle(int newAngle);
167 
168     virtual void setTarget(const ObjectBase* newTarget);
169 
170     void setGettingRepaired();
171 
setGuardPoint(const Coord & newGuardPoint)172     inline void setGuardPoint(const Coord& newGuardPoint) { setGuardPoint(newGuardPoint.x, newGuardPoint.y); }
173 
174     void setGuardPoint(int newX, int newY);
175 
176     void setLocation(int xPos, int yPos);
177 
setLocation(const Coord & location)178     inline void setLocation(const Coord& location) { setLocation(location.x, location.y); }
179 
setDestination(int newX,int newY)180     inline void setDestination(int newX, int newY) {
181         if((destination.x != newX) || (destination.y != newY)) {
182             ObjectBase::setDestination(newX, newY);
183             clearPath();
184         }
185     }
186 
setDestination(const Coord & location)187     inline void setDestination(const Coord& location) { setDestination(location.x, location.y); }
188 
189     virtual void setPickedUp(UnitBase* newCarrier);
190 
191     /**
192         Updates this unit.
193         \return true if this unit still exists, false if it was destroyed
194     */
195     virtual bool update();
196 
197     virtual bool canPass(int xPos, int yPos) const;
198 
hasBumpyMovementOnRock()199     virtual bool hasBumpyMovementOnRock() const { return false; }
200 
201     /**
202         Returns how fast a unit can move over the specified terrain type.
203         \param  terrainType the type to consider
204         \return Returns a speed factor. Higher values mean slower.
205     */
getTerrainDifficulty(TERRAINTYPE terrainType)206     virtual FixPoint getTerrainDifficulty(TERRAINTYPE terrainType) const { return 1; }
207 
208     virtual int getCurrentAttackAngle() const;
209 
210     virtual FixPoint getMaxSpeed() const;
211 
clearPath()212     inline void clearPath() {
213         pathList.clear();
214         nextSpotFound = false;
215         recalculatePathTimer = 0;
216         nextSpotAngle = INVALID;
217         noCloserPointCount = 0;
218     }
219 
isTracked()220     inline bool isTracked() const { return tracked; }
221 
isTurreted()222     inline bool isTurreted() const { return turreted; }
223 
isMoving()224     inline bool isMoving() const { return moving; }
225 
wasDeviated()226     inline bool wasDeviated() const { return (owner->getHouseID() != originalHouseID); }
227 
getAngle()228     inline int getAngle() const { return drawnAngle; }
229 
getAttackMode()230     inline ATTACKMODE getAttackMode() const { return attackMode; }
231 
getGuardPoint()232     inline const Coord& getGuardPoint() const { return guardPoint; }
233 
234     virtual void playAttackSound();
235 
236 protected:
237 
238     virtual void attack();
239 
240     virtual void releaseTarget();
241     virtual void engageTarget();
242     virtual void move();
243 
244     virtual void bumpyMovementOnRock(FixPoint fromDistanceX, FixPoint fromDistanceY, FixPoint toDistanceX, FixPoint toDistanceY);
245 
246     virtual void navigate();
247 
248     /**
249         When the unit is currently idling this method is called about every 5 seconds.
250     */
251     virtual void idleAction();
252 
253     virtual void setSpeeds();
254 
255     virtual void targeting();
256 
257     virtual void turn();
258     void turnLeft();
259     void turnRight();
260 
261     void quitDeviation();
262 
263     bool SearchPathWithAStar();
264 
265     void drawSmoke(int x, int y);
266 
267     // constant for all units of the same type
268     bool     tracked;                ///< Does this unit have tracks?
269     bool     turreted;               ///< Does this unit have a turret?
270     int      numWeapons;             ///< How many weapons do we have?
271     int      bulletType;             ///< Type of bullet to shot with
272 
273     // unit state/properties
274     Coord    guardPoint;             ///< The guard point where to return to after the micro-AI hunted some nearby enemy unit
275     Coord    attackPos;              ///< The position to attack
276     bool     goingToRepairYard;      ///< Are we currently going to a repair yard?
277     bool     pickedUp;               ///< Were we picked up by a carryall?
278     bool     bFollow;                ///< Do we currently follow some other unit (specified by target)?
279 
280 
281     bool     moving;                 ///< Are we currently moving?
282     bool     turning;                ///< Are we currently turning?
283     bool     justStoppedMoving;      ///< Do we have just stopped moving?
284     FixPoint xSpeed;                 ///< Speed in x direction
285     FixPoint ySpeed;                 ///< Speed in y direction
286     FixPoint bumpyOffsetX;           ///< The bumpy offset in x direction which is already included in realX
287     FixPoint bumpyOffsetY;           ///< The bumpy offset in y direction which is already included in realY
288 
289     FixPoint targetDistance;         ///< Distance to the destination
290     Sint8    targetAngle;            ///< Angle to the destination
291 
292     // path finding
293     Uint8    noCloserPointCount;     ///< How often have we tried to dinf a path?
294     bool     nextSpotFound;          ///< Is the next spot to move to already found?
295     Sint8    nextSpotAngle;          ///< The angle to get to the next spot
296     Sint32   recalculatePathTimer;   ///< This timer is for recalculating the best path after x ticks
297     Coord    nextSpot;               ///< The next spot to move to
298     std::list<Coord> pathList;       ///< The path to the destination found so far
299 
300     Sint32  findTargetTimer;         ///< When to look for the next target?
301     Sint32  primaryWeaponTimer;      ///< When can the primary weapon shot again?
302     Sint32  secondaryWeaponTimer;    ///< When can the secondary weapon shot again?
303 
304     // deviation
305     Sint32          deviationTimer;  ///< When to revert back to the original owner?
306 
307     // drawing information
308     int drawnFrame;                  ///< Which row in the picture should be drawn
309 };
310 
311 #endif //UNITBASE_H
312