1 /************************************************************************
2  *                                                                      *
3  *  FreeSynd - a remake of the classic Bullfrog game "Syndicate".       *
4  *                                                                      *
5  *   Copyright (C) 2005  Stuart Binge  <skbinge@gmail.com>              *
6  *   Copyright (C) 2005  Joost Peters  <joostp@users.sourceforge.net>   *
7  *   Copyright (C) 2006  Trent Waddington <qg@biodome.org>              *
8  *   Copyright (C) 2006  Tarjei Knapstad <tarjei.knapstad@gmail.com>    *
9  *   Copyright (C) 2010  Bohdan Stelmakh <chamel@users.sourceforge.net> *
10  *   Copyright (C) 2013  Benoit Blancard <benblan@users.sourceforge.net>*
11  *                                                                      *
12  *    This program is free software;  you can redistribute it and / or  *
13  *  modify it  under the  terms of the  GNU General  Public License as  *
14  *  published by the Free Software Foundation; either version 2 of the  *
15  *  License, or (at your option) any later version.                     *
16  *                                                                      *
17  *    This program is  distributed in the hope that it will be useful,  *
18  *  but WITHOUT  ANY WARRANTY;  without even  the implied  warranty of  *
19  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  *
20  *  General Public License for more details.                            *
21  *                                                                      *
22  *    You can view the GNU  General Public License, online, at the GNU  *
23  *  project's  web  site;  see <http://www.gnu.org/licenses/gpl.html>.  *
24  *  The full text of the license is also included in the file COPYING.  *
25  *                                                                      *
26  ************************************************************************/
27 
28 #ifndef MAPOBJECT_H
29 #define MAPOBJECT_H
30 
31 #include <math.h>
32 #include <list>
33 #include "model/position.h"
34 #include "path.h"
35 #include "pathsurfaces.h"
36 
37 class Mission;
38 class WeaponInstance;
39 
40 /*!
41  * Map object class.
42  */
43 class MapObject {
44 public:
45     /*!
46      * Express the nature of a MapObject.
47      */
48     enum ObjectNature {
49         kNatureUndefined = 0,
50         kNaturePed = 1,
51         kNatureWeapon = 2,
52         kNatureStatic = 4,
53         kNatureVehicle = 8
54     };
55 
56 public:
57     MapObject(uint16 id, int m, ObjectNature nature);
~MapObject()58     virtual ~MapObject() {}
59 
60     //! Return the nature of the object
nature()61     ObjectNature nature() { return nature_; }
62     //! Return true the object has the same nature as the given one
is(ObjectNature aNature)63     bool is(ObjectNature aNature) const { return nature_ == aNature; }
64     //! For debug purpose
65     const char* natureName();
66 
67     //! Return the object's id
id()68     uint16 id() { return id_; }
69 
70     virtual void draw(int x, int y) = 0;
71     enum DamageType {
72         dmg_None = 0x0000,
73         dmg_Bullet = 0x0001,
74         dmg_Laser = 0x0002,
75         dmg_Burn = 0x0004,
76         dmg_Explosion = 0x0008,
77         dmg_Collision = 0x0010, // By car or door
78         dmg_Physical = (dmg_Bullet | dmg_Laser | dmg_Burn | dmg_Explosion | dmg_Collision),
79         dmg_Persuasion = 0x0020,
80         dmg_Heal = 0x0040,
81         dmg_Panic = 0x0080,
82         // dmg_Mental = (dmg_Persuasion | dmg_Panic), not used
83         dmg_All = 0xFFFF
84     };
85 
86     typedef enum {
87         ddmg_Invulnerable = dmg_None,
88         ddmg_Ped = dmg_All,
89         ddmg_PedPanicImmune = dmg_All ^ dmg_Panic,
90         ddmg_PedWithEnergyShield = dmg_Explosion | dmg_Collision | dmg_Heal | dmg_Panic,
91         ddmg_Vehicle = dmg_Bullet | dmg_Laser | dmg_Burn | dmg_Explosion,
92         ddmg_StaticTree = dmg_Laser | dmg_Burn | dmg_Explosion,
93         ddmg_StaticWindow = dmg_Bullet | dmg_Explosion,
94         ddmg_StaticGeneral = dmg_Laser | dmg_Explosion,
95         ddmg_WeaponBomb = dmg_Bullet | dmg_Laser | dmg_Explosion
96     } DefDamageType;
97 
position()98     const TilePoint & position()const { return pos_; }
99 
100     void setPosition(int tile_x, int tile_y, int tile_z, int off_x = 0,
101             int off_y = 0, int off_z = 0) {
102         pos_.tx = tile_x;
103         pos_.ty = tile_y;
104         pos_.tz = tile_z;
105         pos_.ox = off_x;
106         pos_.oy = off_y;
107         pos_.oz = off_z;
108     }
109 
setPosition(const TilePoint & pos)110     void setPosition(const TilePoint &pos) {
111         pos_.initFrom(pos);
112     }
113 
114     /*!
115      * Set the position of the object to be the given one.
116      * \param pos New object position
117      */
setPosition(const WorldPoint & pos)118     void setPosition(const WorldPoint &pos) {
119         setPosition(pos.x / 256, pos.y / 256, pos.z / 128, pos.x % 256,
120                     pos.y % 256, pos.z % 128 );
121     }
122 
tileX()123     int tileX() const { return pos_.tx; }
tileY()124     int tileY() const { return pos_.ty; }
tileZ()125     int tileZ() const { return pos_.tz; }
126 
setTileX(int x)127     void setTileX(int x) { pos_.tx = x; }
setTileY(int y)128     void setTileY(int y) { pos_.ty = y; }
setTileZ(int z)129     void setTileZ(int z) { pos_.tz = z; }
130 
offX()131     int offX() const { return pos_.ox; }
offY()132     int offY() const { return pos_.oy; }
offZ()133     int offZ() const { return pos_.oz; }
134 
135     void setOffX(int n);
136     void setOffY(int n);
137     void setOffZ(int n);
138 
sizeX()139     int sizeX() { return size_x_;}
sizeY()140     int sizeY() { return size_y_;}
sizeZ()141     int sizeZ() { return size_z_;}
142 
setSizeX(int size_x)143     void setSizeX(int size_x) { size_x_ = size_x;}
setSizeY(int size_y)144     void setSizeY(int size_y) { size_y_ = size_y;}
setSizeZ(int size_z)145     void setSizeZ(int size_z) { size_z_ = size_z;}
146 
map()147     virtual int map() { return map_; }
setMap(int new_map)148     void setMap(int new_map) { map_ = new_map; }
149 
150     /*!
151      *
152      */
samePosition(MapObject * other)153     bool samePosition(MapObject * other) {
154         return pos_.equals(other->position());
155     }
156 
157     /*!
158      * checks whether current position is on the same tile as
159      * posT.
160      * \param posT point to compare.
161      * \return true if tile is the same
162      */
sameTile(const TilePoint & posT)163     bool sameTile(const TilePoint &posT) {
164         return posT.tx == pos_.tx
165         && posT.ty == pos_.ty
166         && posT.tz == pos_.tz;
167     }
168 
169     /*!
170      * Return true if the distance between this object and the given object
171      * is less than the given distance.
172      * \param pObject The other object.
173      * \param distance
174      */
isCloseTo(MapObject * pObject,int distance)175     bool isCloseTo(MapObject *pObject, int distance) {
176         WorldPoint wp(pObject->position());
177         return isCloseTo(wp, distance);
178     }
179 
180     /*!
181      * Return true if the distance between this object and the given location
182      * is less than the given distance.
183      * \param loc The location.
184      * \param distance
185      */
isCloseTo(const WorldPoint & loc,int32 distance)186     bool isCloseTo(const WorldPoint &loc, int32 distance) {
187         int cx = pos_.tx * 256 + pos_.ox - (loc.x);
188         int cy = pos_.ty * 256 + pos_.oy - (loc.y);
189         int cz = pos_.tz * 128 + pos_.oz - (loc.z);
190 
191         return (cx * cx + cy * cy + cz * cz) < (distance * distance);
192     }
193 
distanceToPosition(const WorldPoint & pos)194     double distanceToPosition(const WorldPoint &pos) {
195         int cx = pos_.tx * 256 + pos_.ox - (pos.x);
196         int cy = pos_.ty * 256 + pos_.oy - (pos.y);
197         int cz = pos_.tz * 128 + pos_.oz - (pos.z);
198 
199         return sqrt((double) (cx * cx + cy * cy + cz * cz));
200     }
201 
distanceToPosSz(const WorldPoint & pos)202     double distanceToPosSz(const WorldPoint &pos) {
203         int cx = pos_.tx * 256 + pos_.ox - (pos.x);
204         int cy = pos_.ty * 256 + pos_.oy - (pos.y);
205         int cz = pos_.tz * 128 + pos_.oz + (size_z_ >> 1) - (pos.z);
206 
207         return sqrt((double) (cx * cx + cy * cy + cz * cz));
208     }
209 
210     virtual bool animate(int elapsed);
211 
setFramesPerSec(int framesPerSec)212     void setFramesPerSec(int framesPerSec)
213     {
214         frames_per_sec_ = framesPerSec;
215     }
getFramesPerSec()216     int getFramesPerSec() { return frames_per_sec_; }
217 
218     typedef struct{
219         // 0 - can go; 1 - wait; 2 - stop
220         char wayFree;
221         int tilex;
222         int tiley;
223         int tilez;
224         //! create range by x, should be 0 if not used
225         int xadj;
226         //! create range by y, should be 0 if not used
227         int yadj;
228         MapObject * pathBlocker;
229     }FreeWay;
230 
isPathBlocker()231     virtual bool isPathBlocker() {
232         return false;
233     }
234 
setFrame(int frame)235     void setFrame(int frame) { frame_ = frame;}
setFrameFromObject(MapObject * m)236     void setFrameFromObject(MapObject *m) {
237         frame_ = m->frame_;
238     }
239 
240     void setDirection(int dir);
241     void setDirection(int posx, int posy, int * dir = NULL);
242     //! Set this ped's direction so that he looks at the given object.
243     void setDirectionTowardObject(const MapObject &object);
244     //! Set this ped's direction so that he looks at the given position.
245     void setDirectionTowardPosition(const WorldPoint &pos);
246 
direction()247     int direction() { return dir_;}
248     int getDirection(int snum = 8);
249 
setTimeShowAnim(int t)250     void setTimeShowAnim(int t) {
251         frame_ = 0;
252         time_show_anim_ = t;
253         time_showing_anim_ = 0;
254     }
leftTimeShowAnim(int t)255     bool leftTimeShowAnim(int t) {
256         if (time_show_anim_ == -1)
257             return true;
258         time_showing_anim_ += t;
259         return time_show_anim_ > time_showing_anim_;
260     }
261 
262     bool isBlocker(WorldPoint * pStartPt, WorldPoint * pEndPt,
263                double * inc_xyz);
264 
setStateMasks(unsigned int state)265     void setStateMasks(unsigned int state) {
266         state_ = state;
267     }
stateMasks()268     unsigned int stateMasks() { return state_; }
269 
270     void offzOnStairs(uint8 twd);
271 
272 protected:
273     //! the nature of this object
274     ObjectNature nature_;
275     //! Id of the object. Id is unique within a nature
276     uint16 id_;
277     /*!
278      * Tile based coordinates.
279      */
280     TilePoint pos_;
281     //! these are not true sizes, but halfs of full size by respective coord
282     int size_x_, size_y_, size_z_;
283     //! if equal -1 object is not on map and should not be drawn
284     int map_;
285     //! animation frame changing
286     int frame_;
287     /*!
288      * Time left, if frame needs to be drawn every 'n' milliseconds
289      * elapsed time % 'n' = time left
290      */
291     int elapsed_carry_;
292     //! how often this frame should be drawn per seccond
293     int frames_per_sec_;
294     //! objects direction
295     int dir_;
296     //! looped animations, time to show them is set here, if = -1 show forever
297     int time_show_anim_;
298     //! looped animations, playing time
299     int time_showing_anim_;
300     /*! animation to draw can, change this varible should provide check
301      * whether first frame was drawn successfully, only if successful
302      * MapObject::animate should be called
303      */
304     bool is_frame_drawn_;
305     uint32 state_;
306 
307     void addOffs(int &x, int &y);
308 };
309 
310 /*!
311  * SFXObject map object class.
312  */
313 class SFXObject : public MapObject {
314 public:
315     /*!
316      * Type of SfxObject.
317      */
318     enum SfxTypeEnum {
319         sfxt_Unknown = 0,
320         sfxt_BulletHit = 1,
321         sfxt_FlamerFire = 2,
322         sfxt_Smoke = 3,
323         sfxt_Fire_LongSmoke = 4,
324         sfxt_ExplosionFire = 5,
325         sfxt_ExplosionBall = 6,
326         sfxt_LargeFire = 7,
327         sfxt_SelArrow = 8,
328         sfxt_AgentFirst = 9,
329         sfxt_AgentSecond = 10,
330         sfxt_AgentThird = 11,
331         sfxt_AgentFourth = 12
332     };
333 
334     SFXObject(int m, SfxTypeEnum type, int t_show = 0, bool managed = false);
~SFXObject()335     virtual ~SFXObject() {}
336 
sfxLifeOver()337     bool sfxLifeOver() { return sfx_life_over_; }
338     //! Return true if object is managed by another object
isManaged()339     bool isManaged() { return managed_; }
340     //! Set whether animation should loop or not
setLoopAnimation(bool flag)341     void setLoopAnimation(bool flag) { loopAnimation_ = flag; }
342     //! Reset animation
343     void reset();
344 
345     void draw(int x, int y);
346     bool animate(int elapsed);
347     void correctZ();
setDrawAllFrames(bool daf)348     void setDrawAllFrames(bool daf) {
349         if (daf != draw_all_frames_) {
350             draw_all_frames_ = daf;
351             frame_ = 0;
352         }
353     }
354 protected:
355     static uint16 sfxIdCnt;
356     /*! The type of SfxObject.*/
357     SfxTypeEnum type_;
358     int anim_;
359     bool sfx_life_over_;
360     // to draw all frames or first frame only
361     bool draw_all_frames_;
362     //! Tells if the animation should restart automatically after ending
363     bool loopAnimation_;
364     int elapsed_left_;
365     //! True means the life of the object is managed by something else than gameplaymenu
366     bool managed_;
367 };
368 
369 /*!
370  * Shootable map object class.
371  */
372 class ShootableMapObject : public MapObject {
373 public:
374     /*!
375      * This structure holds informations on the damage inflicted to a ShootableMapObject.
376      */
377     struct DamageInflictType {
378         //! The type of damage
379         DamageType dtype;
380         //! Range of damage
381         double range;
382         //! The value of the damage
383         int dvalue;
384         //! direction damage comes from, should be angle 256 degree based
385         int ddir;
386         //! Location of aimed point
387         WorldPoint aimedLocW;
388         //! Location of origin of shot
389         WorldPoint originLocW;
390         //! The object that inflicted the damage
391         ShootableMapObject * d_owner;
392         //! The weapon that generated this damage
393         WeaponInstance *pWeapon;
394     };
395 
396 public:
397     ShootableMapObject(uint16 id, int m, ObjectNature nature);
~ShootableMapObject()398     virtual ~ShootableMapObject() {}
399 
health()400     int health() { return health_; }
401 
402     // NOTE: objects that are not used or have negative health from start
403     // shoud have -1; objects destroyed during gameplay 0
setHealth(int n)404     void setHealth(int n) {
405         if (n > 255)
406             n = 255;
407 
408         if (n < -1)
409             n = -1;
410 
411         health_ = n;
412     }
413 
startHealth()414     int startHealth() { return start_health_; }
415 
setStartHealth(int n)416     void setStartHealth(int n) {
417         if (n > 255)
418             n = 255;
419 
420         if (n < -1)
421             n = -1;
422 
423         start_health_ = n;
424     }
425 
426     /*!
427      * Add a certain amount to health.
428      * \return true if health reached max
429      * \param amount how much to increase health
430      */
increaseHealth(int amount)431     bool increaseHealth(int amount) {
432         health_ += amount;
433         if (health_ > start_health_) {
434             health_ = start_health_;
435         }
436 
437         return health_ == start_health_;
438     }
439 
440     /*!
441      * Remove a certain amount of health.
442      */
decreaseHealth(int amount)443     void decreaseHealth(int amount) {
444         health_ -= amount;
445         if (health_ <= 0) {
446             health_ = 0;
447         }
448     }
449     /*!
450      * Reset current ped's health to starting health.
451      */
resetHealth()452     void resetHealth() {
453         health_ = start_health_;
454     }
455 
456     /*!
457      * Method called when object is hit by a weapon shot.
458      * By default do nothing. Subclasses must implement
459      * to react to a shot.
460      * \param d Damage description
461      */
handleHit(DamageInflictType & d)462     virtual void handleHit(DamageInflictType &d) {}
463 
isAlive()464     bool isAlive() { return health_ > 0; }
isDead()465     bool isDead() { return health_ <= 0; }
466 
467   protected:
468     int health_, start_health_;
469 };
470 
471 /*!
472  * Shootable movable map object class.
473  */
474 class ShootableMovableMapObject : public ShootableMapObject {
475 public:
476     ShootableMovableMapObject(uint16 id, int m, ObjectNature nature);
~ShootableMovableMapObject()477     virtual ~ShootableMovableMapObject() {}
478 
setSpeed(int new_speed)479     void setSpeed(int new_speed) {
480         speed_ = new_speed;
481     }
482 
speed()483     int speed() {
484         return speed_;
485     }
setBaseSpeed(int bs)486     void setBaseSpeed(int bs) {
487         base_speed_ = bs;
488     }
489     /*!
490      * Clear path to destination and sets speed to 0.
491      */
clearDestination()492     void clearDestination() {
493         dest_path_.clear();
494         speed_ = 0;
495     }
496 
497     //! Set the destination to reach at given speed
498     virtual bool setDestination(Mission *m, const TilePoint &locT, int newSpeed = -1) = 0;
499 
500     //! Return true if the ped is moving
isMoving()501     bool isMoving() { return speed_ != 0 || !dest_path_.empty();}
502     //! Returns true if object currently has a destination point (ie it's arrived)
hasDestination()503     bool hasDestination() { return !dest_path_.empty(); }
504 
505     FreeWay hold_on_;
506 
507 protected:
508     int speed_, base_speed_;
509     //! on reaching this distance object should stop
510     int dist_to_pos_;
511     std::list<TilePoint> dest_path_;
512 
513     bool updatePlacement(int nOffX, int nOffY);
514 
515     virtual bool walkable(int x, int y, int z) = 0;
516 };
517 
518 /*!
519  * Static map object class.
520  */
521 class Static : public ShootableMapObject {
522 public:
523     /*! Const for orientation 1 of Static.*/
524     static const int kStaticOrientation1;
525     /*! Const for orientation 2 of Static.*/
526     static const int kStaticOrientation2;
527 
528     enum StaticType {
529         // NOTE: should be the same name as Class
530         smt_None = 0,
531         smt_Advertisement,
532         smt_Semaphore,
533         smt_Door,
534         smt_LargeDoor,
535         smt_Tree,
536         smt_Window,
537         smt_AnimatedWindow,
538         smt_NeonSign
539     };
540 
541     enum stateDoors {
542         sttdoor_Closed = 0,
543         sttdoor_Closing,
544         sttdoor_Open,
545         sttdoor_Opening
546     };
547 
548     enum stateTrees {
549         stttree_Healthy = 0,
550         stttree_Burning,
551         stttree_Damaged
552     };
553 
554     //semaphore, 4 animations + damaged
555     enum stateSemaphores {
556         sttsem_Stt0 = 0,
557         sttsem_Stt1,
558         sttsem_Stt2,
559         sttsem_Stt3,
560         sttsem_Damaged
561     };
562 
563     enum stateWindows {
564         sttwnd_Closed = 0,
565         sttwnd_Open,
566         sttwnd_Breaking,
567         sttwnd_Damaged
568     };
569 
570     enum stateAnimatedWindows {
571         sttawnd_LightOff = 0,
572         sttawnd_LightSwitching,
573         sttawnd_PedAppears,
574         sttawnd_ShowPed,
575         sttawnd_PedDisappears,
576         sttawnd_LightOn
577     };
578 public:
579     static Static *loadInstance(uint8 *data, uint16 id, int m);
~Static()580     virtual ~Static() {}
581 
582     //! Return the type of statics
type()583     StaticType type() { return type_; }
584     //! Set the sub type of statics
setOrientation(int anOrientation)585     void setOrientation(int anOrientation) { orientation_ = anOrientation; }
586     //! Return the type of statics
orientation()587     int orientation() { return orientation_; }
588 
589     //! Return true if static should not be included in the search for blockers
isExcludedFromBlockers()590     bool isExcludedFromBlockers() { return excludedFromBlockers_; }
591     //! Set whether to include static in search for blockers
setExcludedFromBlockers(bool exclude)592     void setExcludedFromBlockers(bool exclude) { excludedFromBlockers_ = exclude; }
593 
animate(int elapsed,Mission * obj)594     virtual bool animate(int elapsed, Mission *obj) {
595         return MapObject::animate(elapsed);
596     }
597 
598 protected:
Static(uint16 anId,int m,StaticType aType)599     Static(uint16 anId, int m, StaticType aType) :
600             ShootableMapObject(anId, m, MapObject::kNatureStatic) {
601         type_ = aType;
602         orientation_ = kStaticOrientation1;
603         excludedFromBlockers_ = false;
604     }
605 
606 protected:
607     /*! Type of statics.*/
608     StaticType type_;
609     /*! Some statics can be displayed in 1 of 2 orientations : SW or SE.*/
610     int orientation_;
611     /*! This flag is used to exclude this object from the list of statics
612      * that can block a shoot.
613      */
614      bool excludedFromBlockers_;
615 };
616 
617 /*!
618  * Door map object class.
619  */
620 class Door : public Static {
621 public:
622     Door(uint16 id, int m, int anim, int closingAnim, int openAnim, int openingAnim);
~Door()623     virtual ~Door() {}
624 
625     void draw(int x, int y);
626     bool animate(int elapsed, Mission *obj);
627     bool isPathBlocker();
628 
629 protected:
630     int anim_, closing_anim_, open_anim_, opening_anim_;
631 };
632 
633 /*!
634  * LargeDoor map object class.
635  */
636 class LargeDoor : public Static {
637 public:
638     LargeDoor(uint16 id, int m, int anim, int closingAnim, int openingAnim);
~LargeDoor()639     virtual ~LargeDoor() {}
640 
641     void draw(int x, int y);
642     bool animate(int elapsed, Mission *obj);
643     bool isPathBlocker();
644 
645 protected:
646     int anim_, closing_anim_, opening_anim_;
647 };
648 /*!
649  * Tree map object class.
650  */
651 class Tree : public Static {
652 public:
653     Tree(uint16 id, int m, int anim, int burningAnim, int damagedAnim);
~Tree()654     virtual ~Tree() {}
655 
656     void draw(int x, int y);
657     bool animate(int elapsed, Mission *obj);
658     void handleHit(DamageInflictType &d);
659 
660 protected:
661     int anim_, burning_anim_, damaged_anim_;
662 };
663 
664 /*!
665  * Window map object class.
666  */
667 class WindowObj : public Static {
668 public:
669     WindowObj(uint16 id, int m, int anim, int openAnim, int breakingAnim,
670               int damagedAnim);
~WindowObj()671     virtual ~WindowObj() {}
672 
673     bool animate(int elapsed, Mission *obj);
674     void draw(int x, int y);
675     void handleHit(DamageInflictType &d);
676 
677 protected:
678     int anim_, open_anim_, breaking_anim_, damaged_anim_;
679 };
680 
681 /*!
682  * EtcObj map object class.
683  */
684 class EtcObj : public Static {
685 public:
686     EtcObj(uint16 id, int m, int anim, int burningAnim, int damagedAnim, StaticType type = smt_None);
~EtcObj()687     virtual ~EtcObj() {}
688 
689     void draw(int x, int y);
690 
691 protected:
692     int anim_, burning_anim_, damaged_anim_;
693 };
694 
695 /*!
696  * NeonSign map object class.
697  */
698 class NeonSign : public Static {
699 public:
700     NeonSign(uint16 id, int m, int anim);
~NeonSign()701     virtual ~NeonSign() {}
702 
703     void draw(int x, int y);
704 
705 protected:
706     int anim_;
707 };
708 
709 /*!
710  * Semaphore map object class.
711  * That thing that bounces on crossroad.
712  */
713 class Semaphore : public Static {
714 public:
715     Semaphore(uint16 id, int m, int anim, int damagedAnim);
~Semaphore()716     virtual ~Semaphore() {}
717 
718     bool animate(int elapsed, Mission *obj);
719     void draw(int x, int y);
720 
721     void handleHit(DamageInflictType &d);
722 
723 protected:
724     int anim_, damaged_anim_;
725     /*! used to make animation of movement up/down,
726      * when damaged, stores time not consumed for movement down
727      */
728     int elapsed_left_smaller_;
729     /*! animation color rotation,
730      * when damaged, stores target Z distance to fall
731      */
732     int elapsed_left_bigger_;
733     //! switch for moving up or down
734     int up_down_;
735 };
736 
737 /*!
738  * AnimatedWindow map object class.
739  */
740 class AnimWindow : public Static {
741 public:
742     AnimWindow(uint16 id, int m, int anim);
~AnimWindow()743     virtual ~AnimWindow() {}
744 
745     bool animate(int elapsed, Mission *obj);
746     void draw(int x, int y);
747 
748 protected:
749     int anim_;
750 };
751 
752 #endif
753