1 /* $Id: avatar.hpp,v 1.86.2.2 2006/01/20 11:33:52 chfreund Exp $ */
2 
3 #ifndef _AVATAR_HPP_
4 #define _AVATAR_HPP_
5 
6 /**********************************************************/
7 
8 #include <vector>
9 #include <iostream>
10 
11 #include  "global.hpp"
12 #include  "collidableobject.hpp"
13 #include  "spriteset.hpp"
14 #include  "player.hpp"
15 #include  "vector.hpp"
16 #include  "random.hpp"
17 #include  "map.hpp"
18 #include  "world.hpp"
19 #include  "particles.hpp"
20 #include  "flag.hpp"
21 #include  "messages.hpp"
22 #include  "bonuspack.hpp"
23 #include  "counter.hpp"
24 
25 #include  <SDL_mixer.h>
26 
27 /**********************************************************/
28 class HomingMissile;
29 class StationaryGun;
30 /**********************************************************
31  * Base class for all avatars.
32  **********************************************************/
33 
34 //! the basic object for all avatars
35 
36 /*! This is the base class for all avatars.
37  *  For more information about the Avatar \f$\leftrightarrow\f$
38  *  Player connection see the description of class Player.
39  */
40 class Avatar : public CollidableObject
41 {
42 	friend void    Player::attachAvatar( Avatar* const avatar );
43 	friend Avatar* Player::detachAvatar();
44 
45 	public:
46 
47 		//////////////////////////////////////////
48 		//! \name aiming angle, aiming speed, aiming, direction ...
49 
50 		//@{
51 		//! returns the aiming angle
getAimingAngle() const52 		real getAimingAngle() const { return m_aimingAngle; }
53 		//! returns the aiming speed
getAimingSpeed() const54 		real getAimingSpeed() const { return m_aimingSpeed; }
55 		//! returns the aiming vector
getAimingVector() const56 		Vector getAimingVector() const {
57 			return Vector( getAimingDX(), getAimingDY() ); }
58 		//! returns the x component of the aiming vector
getAimingDX() const59 		real getAimingDX() const {
60 			return   (isFacingRight() ? 1 : -1)
61 		           * SIN_REAL( m_aimingAngle*AIMING_ANGLE_TO_RAD ); }
62 		//! returns the y component of the aiming vector
getAimingDY() const63 		real getAimingDY() const {
64 			return -COS_REAL( m_aimingAngle*AIMING_ANGLE_TO_RAD ); }
65 		//! returns a randomly perturbated aiming vector
getRandomizedAimingVector(const real maxTremble) const66 		Vector getRandomizedAimingVector( const real maxTremble ) const {
67 			real tremble = 0.5 - m_worldPointer->getRandom().getNormedReal();
68 			tremble *= (M_PI/180.0);
69 			tremble *= maxTremble;
70 			return Vector(  (isFacingRight() ? 1 : -1)
71 			               * SIN_REAL( m_aimingAngle*AIMING_ANGLE_TO_RAD+tremble ),
72 			                -COS_REAL( m_aimingAngle*AIMING_ANGLE_TO_RAD+tremble ) );
73 		}
74 		//! comment missing
75 		Vector placeBesideCollRect( const int marginLeft   = 0,
76 		                            const int marginRight  = 0,
77 		                            const int marginTop    = 0,
78 		                            const int marginBottom = 0 );
79 
80 		//! sets the aiming angle
setAimingAngle(const real aimingAngle)81 		bool setAimingAngle( const real aimingAngle ) {
82 			if( aimingAngle > MAX_AIMING_ANGLE ) {
83 				m_aimingAngle = MAX_AIMING_ANGLE;
84 				updateSpriteSelection();
85 				return false;
86 			}
87 			else if( aimingAngle < 0.0 ) {
88 				m_aimingAngle = 0.0;
89 				updateSpriteSelection();
90 				return false;
91 			}
92 			else {
93 				m_aimingAngle = aimingAngle;
94 				updateSpriteSelection();
95 				return true;
96 			}
97 		}
98 
99 		//! sets turning of aiming
100 		void setAimingDirection( const int dir );
101 
102 		//! sets the direction (see enumeration type)
103 
104 		/*! Sets the new direction of the avatar. The passed direction
105 		 *  must be in the range of defined (enumeration constants in
106 		 *  this class) directions. If you add further directions, you
107 		 *  must also adapt the method updateSequenceIndex().
108 		 */
109 		void setDirection( const Uint32 direction );
110 
111 		//! returns the direction (enumeration type)
getDirection() const112 		Uint32 getDirection() const {
113 			return (isFacingRight() ? RIGHT : LEFT); }
114 		//@}
115 
116 		//////////////////////////////////////////
117 		//! \name information about the action state
118 
119 		//@{
isMovingLeft(void) const120 		bool isMovingLeft   ( void ) const { return m_state & m_stateMask & MOVING_LEFT;  }
isMovingRight(void) const121 		bool isMovingRight  ( void ) const { return m_state & m_stateMask & MOVING_RIGHT; }
isMovingAny(void) const122 		bool isMovingAny    ( void ) const { return m_state & m_stateMask & MOVING_ANY;   }
isJumping(void) const123 		bool isJumping      ( void ) const { return m_state & m_stateMask & JUMPING;      }
isDigging(void) const124 		bool isDigging      ( void ) const { return m_state & m_stateMask & DIGGING;      }
isShooting(void) const125 		bool isShooting     ( void ) const { return m_state & m_stateMask & SHOOTING;     }
isAimingUp(void) const126 		bool isAimingUp     ( void ) const { return m_state & m_stateMask & AIMING_UP;    }
isAimingDown(void) const127 		bool isAimingDown   ( void ) const { return m_state & m_stateMask & AIMING_DOWN;  }
isFacingRight(void) const128 		bool isFacingRight  ( void ) const { return m_state & m_stateMask & FACING_RIGHT; }
isSetRopeOn(void) const129 		bool isSetRopeOn    ( void ) const { return m_state & m_stateMask & ROPE_ON;      }
isSetRopeOff(void) const130 		bool isSetRopeOff   ( void ) const { return m_state & m_stateMask & ROPE_OFF;     }
isSetRopeIn(void) const131 		bool isSetRopeIn    ( void ) const { return m_state & m_stateMask & ROPE_IN;      }
isSetRopeOut(void) const132 		bool isSetRopeOut   ( void ) const { return m_state & m_stateMask & ROPE_OUT;     }
isSetRopeRel(void) const133 		bool isSetRopeRel   ( void ) const { return m_state & m_stateMask & ROPE_REL;     }
isInGunMode(void) const134 		bool isInGunMode    ( void ) const { return m_state & MODE_GUN; }
isInGMMode(void) const135 		bool isInGMMode     ( void ) const { return m_state & MODE_GM;  }
isInAnyMode(void) const136 		bool isInAnyMode    ( void ) const { return m_state & MODE_ANY; }
isInSkwoermZone(void) const137 		bool isInSkwoermZone( void ) const { return m_state & IN_SKWOERMZONE; }
setStateMask(const Uint32 mask)138 		void setStateMask( const Uint32 mask ) { m_stateMask = mask; }
139 
140 		//@}
141 
142 		//////////////////////////////////////////
143 		//! \name routines for special states
144 
145 		//@{
146 		//! the avatar takes a seat in the passed gun
147 		virtual void sitDownInGun( StationaryGun *const gun );
148 		//! the avatar leaves gun, it is currently sitting in
149 		virtual void leaveCurrentGun();
150 		//! the avatar takes the remote control
151 		virtual void takeRemoteControl();
152 		//! the avatar drops the remote control
153 		virtual void dropRemoteControl();
154 		//@}
155 
156 		//////////////////////////////////////////
157 		//! \name the avatar's health
158 
159 		//@{
160 		//! returns the avatar's maximal health value
getMaxHealth() const161 		Sint32 getMaxHealth() const { return m_maxHealth; }
162 		//! sets the maximal health value
setMaxHealth(const Sint32 H)163 		void setMaxHealth( const Sint32 H ) { m_maxHealth = H; }
164 		//! heals the avatar by \c addHealth points
heal(const Sint32 addHealth)165 		void heal( const Sint32 addHealth ) {
166 			if( (m_health += addHealth) > m_maxHealth ) {
167 				m_health = m_maxHealth;
168 			}
169 		}
170 		//@}
171 
172 		//////////////////////////////////////////
173 		//! \name fuel for the jet pack
174 
175 		//@{
176 		//! returns the current fuel
getFuel() const177 		real getFuel() const { return m_fuel.getTimeToLive(); }
178 		//! returns the tank size (maximal fuel)
getMaxFuel() const179 		real getMaxFuel() const { return m_maxFuel; }
180 		//! fills fuel in the tank
fillFuel(const real fuel)181 		void fillFuel( const real fuel ) {
182 			if( m_fuel.isElapsed() ) m_fuel.setTimeToLive( 0.0 );
183 			if( (m_fuel.getTimeToLive() + fuel) > m_maxFuel ) {
184 				m_fuel.setTimeToLive( m_maxFuel );
185 			}
186 			else {
187 				m_fuel.setTimeToLive( m_fuel.getTimeToLive() + fuel );
188 			}
189 		}
190 		//@}
191 
192 		//////////////////////////////////////////
193 		//! \name connected player object
194 
195 		//@{
196 		//! returns the pointer to the connected player object
197 
198 		/*! Returns the pointer to the Player object (also see description
199 		 *  of class Player), this avatar is attached to. Attaching and
200 		 *  detaching can and should be done only by the two friend
201 		 *  methods Player::attachAvatar and Player::detachAvatar.
202 		 */
getPlayer()203 		Player* getPlayer() { return m_Player; }
204 		//! the "const" version of getPlayer
getPlayer() const205 		const Player* getPlayer() const  { return m_Player; }
206 		//q}
207 
208 		//////////////////////////////////////////
209 		/*! \name functions concerning the graphic of the avatar
210 		 *  \brief Besides the implementation of the functions
211 		 *  Object::getColors() and Object::getNumColors class Avatar
212 		 *  must provide an interface to set and get the skin color and
213 		 *  the team color and the player color. This does not mean
214 		 *  that these three colors differ pairwise (for example see
215 		 *  class AvatarWorm). Als functions to set a color take an
216 		 *  additional bool flag, which specifies, whether the game
217 		 *  mode lets each player play alone or in a team. This is
218 		 *  important, for example, if in team modes a different area
219 		 *  of the avatar is used for the personal player color than
220 		 *  in single player modes.
221 		 *  <br>
222 		 *  <b>Important</b>: Note that, no matter how these colors
223 		 *  are organized, the implementations of Object::getColors()
224 		 *  still must return a pointer to an array containing
225 		 *  getNumColors() color values, exactly ordered like the
226 		 *  layers in the avatars graphic, whereby getNumColors() and
227 		 *  the number of layers must match!
228 		 */
229 
230 		//@{
231 		//! a virtual interface to set the player color
232 		virtual void setPlayerColor( const Uint32 color ) = 0;
233 		/*! \brief a virtual interface to set the skin color
234 		 *  NOTE: this function is a relict, and it is not clear, when
235 		 *  it should be used. Before you use it, please check, if not
236 		 *  setPlayerColor or setTeamColor is the function you want to
237 		 *  use.
238 		 */
239 		virtual void setSkinColor( const Uint32 color ) = 0;
240 		//! a virtual interface to set the team color
241 		virtual void setTeamColor( const Uint32 color ) = 0;
242 		//! a virtual interface to get the skin color
243 		virtual Uint32 getSkinColor() const = 0;
244 		//! a virtual interface to get the team color
245 		virtual Uint32 getTeamColor() const = 0;
246 		//! a virtual interface to get the player color
247 		virtual Uint32 getPlayerColor() const = 0;
248 		//@}
249 
250 		//! spawn the avatar at a randomly chosen position
251 		void spawnAvatar( void );
252 
253 		//////////////////////////////////////////
254 		//! \name functions concerning the avatar's movement
255 
256 		//@{
257 		//! digging in the dirt (P. Gabriel)
258 		void dig( void );
259 		//! ????
260 		void testGrounded( bool& groundedMid, bool& groundedFW,
261 		                   bool& groundedBW );
262 
testGrounded(void)263 		virtual bool testGrounded( void ) {
264 			bool groundedMid, groundedFW, groundedBW;
265 			testGrounded( groundedMid, groundedFW, groundedBW );
266 			if( isGrounded() )
267 				return groundedMid | groundedFW | groundedBW;
268 			else
269 				return groundedMid;
270 		}
271 
testPassableRel(const int dx,const int dy)272 		bool testPassableRel( const int dx, const int dy ) {
273 			return m_worldPointer->getMap()->testPassableSmoothing(
274 			                     ROUND( m_pos.x ) + dx, ROUND( m_pos.y ) + dy,
275 			                     Flags::OBSTACLE_EARTH | Flags::OBSTACLE_OBJECT );
276 		}
277 		//! ????
testLinePassableRel(const int dx1,const int dy1,const int dx2,const int dy2,int & pcx,int & pcy,int & cx,int & cy)278 		bool testLinePassableRel( const int dx1, const int dy1,
279 		                          const int dx2, const int dy2,
280 		                          int& pcx, int& pcy, int& cx, int& cy ) {
281 			return m_worldPointer->getMap()->testLinePassableSmoothing(
282 			                   ROUND( m_pos.x ) + dx1, ROUND( m_pos.y ) + dy1,
283 			                   ROUND( m_pos.x ) + dx2, ROUND( m_pos.y ) + dy2,
284 			                   pcx, pcy, cx, cy,
285 			                   Flags::OBSTACLE_EARTH | Flags::OBSTACLE_OBJECT );
286 		}
287 		//@}
288 
289 		//! applies damage to the avatar (reimplemented from CollidableObject)
290 
291 		/*! This method applies damage to the avatar, caused by the passed
292 		 *  passed particle. It is reimplemented here, for example because
293 		 *  of shield boni, which beware the avatar of damage, but not of
294 		 *  the particles recoil.
295 		 */
296 		virtual int applyDamage( const Particles::ParticleData& p );
297 
298 		//! applies damage to the avatar (reimplemented from CollidableObject)
299 		virtual int applyDamage( const int damage, Player* shooter );
300 
301 		//////////////////////////////////////////
302 		//! /name methods concerning boni
303 
304 		//@{
305 		//! pick up the passed bonus
306 
307 		/*! The collission rectangle of the passed bonus must not be set
308 		 *  at the moment, it is passed to this function. This function
309 		 *  will remove the bonus from the world, since it is consumed
310 		 *  and therefore also administrated by the avatar and therefore
311 		 *  not longer existent in the world. In addition to this the
312 		 *  bonus object might also be deleted by this function, depending
313 		 *  on the specific bonus type and possibly already present boni
314 		 *  in the avatar's bonus pack. <b>Do not use the bonus object after
315 		 *  this call any more</b>, since you do not know, whether it
316 		 *  still exists. But you also have not to care about it anyway,
317 		 *  because it is administrated by the avatars bonus pack from
318 		 *  now on!
319 		 */
320 		void pickUp( Bonus* bonus );
321 
322 		//! returns the bonus pack
getBonusPack()323 		BonusPack& getBonusPack() { return m_bonusPack; }
324 		//! returns the bonus pack
getBonusPack() const325 		const BonusPack& getBonusPack() const { return m_bonusPack; }
326 		//@}
327 
328 		//////////////////////////////////////////
329 		//! \name methods concerning special weapons
330 
331 		//@{
332 
333 		void getLockedByHomingMissile( HomingMissile *const missile,
334 		                               const real distanceSquare );
335 		//@}
336 
getWeaponPivotDY(void) const337 		Sint32 getWeaponPivotDY( void ) const { return m_weaponPivotDY; }
338 
setMessageSink(MessageSink * sink)339 		void setMessageSink( MessageSink* sink ) {
340 			m_messageSink = sink;
341 		}
342 
343 		std::vector<Object*> getVisibleObjects() const;
344 
345 		virtual void dump( std::ostream& out ) const;
346 
347 		//! facing direction possibilities
348 		enum { LEFT  = 0,
349 		       RIGHT = 1,
350 		       NUM_DIRECTIONS };
351 
352 		//! binary constants for avtar state
353 		enum { FACING_RIGHT   = LAST_OBJECT_STATE <<  1,
354 		       MOVING_LEFT    = LAST_OBJECT_STATE <<  2,
355 		       MOVING_RIGHT   = LAST_OBJECT_STATE <<  3,
356 		       MOVING_ANY     = MOVING_LEFT | MOVING_RIGHT,
357 		       JUMPING        = LAST_OBJECT_STATE <<  4,
358 		       DIGGING        = LAST_OBJECT_STATE <<  5,
359 		       SHOOTING       = LAST_OBJECT_STATE <<  6,
360 		       AIMING_UP      = LAST_OBJECT_STATE <<  7,
361 		       AIMING_DOWN    = LAST_OBJECT_STATE <<  8,
362 		       AIMING_ANY     = AIMING_UP | AIMING_DOWN,
363 		       ROPE_ON        = LAST_OBJECT_STATE <<  9,
364 		       ROPE_OFF       = LAST_OBJECT_STATE << 10,
365 		       ROPE_IN        = LAST_OBJECT_STATE << 11,
366 		       ROPE_OUT       = LAST_OBJECT_STATE << 12,
367 		       ROPE_REL       = LAST_OBJECT_STATE << 13,
368 		       ROPE_ANY       = ROPE_ON | ROPE_OFF | ROPE_IN | ROPE_OUT | ROPE_REL,
369 		       MODE_GUN       = LAST_OBJECT_STATE << 14,
370 		       MODE_GM        = LAST_OBJECT_STATE << 15,
371 		       MODE_ANY       = MODE_GUN | MODE_GM,
372 		       IN_SKWOERMZONE = LAST_OBJECT_STATE << 16
373 		     };
374 
375 		static const int   MAX_FUEL = 500;
376 
377 	protected:
378 
379 		//! Avatar should only be created in derived classes
380 		Avatar();
381 		virtual ~Avatar();
382 
383 		static const real INIT_AIMING_SPEED,
384 		                  AIMING_SPEED_INCREMENT,
385 		                  MAX_AIMING_SPEED,
386 		                  MAX_AIMING_ANGLE,
387 		                  AIMING_ANGLE_TO_RAD;
388 		static const real INIT_WALKING_SPEED,
389 		                  MAX_WALKING_SPEED,
390 		                  MAX_WALKING_SPEED_DIGGING;
391 
392 		Mix_Chunk* m_popupSample;
393 
394 
395 		//! implementation of pure virtual Object::update()
396 		virtual void update();
397 
398 		//! serialization
399 		virtual void serialize( Uint8*& bufferPointer ) const;
400 		//! deserialization
401 		virtual void deserialize( Uint8*& bufferPointer );
402 		//! size of the buffer, needed for (de)serialization
403 		virtual Uint32 getSerializeBufferSize() const;
404 
405 		//! maximal health value (current health derived from class Object)
406 		Sint32 m_maxHealth;
407 		//! current fuel for jet pack
408 		Counter m_fuel;
409 		//! maximal fuel
410 		real m_maxFuel;
411 		//! object ID of the gun, that the avatar is occupying at the moment
412 		Sint32 m_gunID;
413 
414 		real m_aimingAngle,   //!< aiming angle
415 		     m_aimingSpeed,   //!< aiming speed
416 		     m_walkingSpeed;  //!< aiming speed
417 
418 		Uint32 m_stateMask;   //!< masks away unwanted states, e.g., walking when in gun mode
419 
420 		//! bonus pack for keeping boni
421 		BonusPack m_bonusPack;
422 
423 		Sint32 m_weaponPivotDY;
424 
425 		//! pointer to the player object of this avatar
426 		Player *m_Player;
427 
428 		MessageSink  m_defaultMessageSink;
429 		MessageSink* m_messageSink;
430 };
431 
432 /**********************************************************/
433 
434 #endif // _AVATAR_HPP_
435