1 /* $Id: weapon.hpp,v 1.16 2005/10/20 19:46:52 chfreund Exp $ */ 2 3 #ifndef _WEAPON_HPP_ 4 #define _WEAPON_HPP_ 5 6 #include "constants.hpp" 7 #include "serializable.hpp" 8 #include "serialize.hpp" 9 #include "audio.hpp" 10 #include "counter.hpp" 11 12 class World; 13 class Avatar; 14 class StationaryGun; 15 16 /*! 17 This class provides the basic functionality for a vanilla weapon. There are 18 four pure virtual methods which have to be overloaded: 19 - Weapon::reallyShoot 20 21 These methods do not have to take care of the weapon counters like remaining 22 ammo, reloading, ... This is done in other base classes. 23 24 To create a new weapon it is best to start from an already existing weapon 25 like WeaponShotgun or WeaponGrenade and alter its behavior. There are two 26 requirements for all new Weapon class contructors: 27 28 - \a rechargeNow must be called 29 - \a m_shotSample must be initialized as is the following example: 30 \code 31 m_shotSample = Audio::getInstance()->loadSound( "sound/weapons/shotgun/shotgun.wav" ); 32 \endcode 33 */ 34 35 class Weapon : public Serializable { 36 protected: 37 Weapon(); 38 39 //! the weapon ID, defined in constants.hpp 40 Sint32 m_ID; 41 //! The maximum amount of ammo. 42 Uint32 m_maximumAmmo; 43 //! The required number of frames for preparing the next shot. 44 real m_reloadTime; 45 //! The required number of frames for recharging a completely empty weapon. 46 Uint32 m_chargeTime; 47 48 //! The remaining number of frames until the empty weapon is recharged. 49 Uint32 m_chargeTimer; 50 //! The remaining number of frames until the weapon can fire the next shot. 51 Counter m_reloadTimer; 52 //! flags for special states 53 Uint32 m_flags; 54 //! The remaining amount of ammo. 55 Uint32 m_ammo; 56 //! This sample is played after a successful shot. 57 Mix_Chunk* m_shotSample; 58 59 //! enumeration constants for member m_flags 60 enum { NO_FLAG = 0, 61 RELOAD_LOCKED = 1<<0, 62 RECHARGE_LOCKED = 1<<2, 63 SHOT_LOCKED = 1<<3 }; 64 65 public: 66 67 //! \name IDs and nomenclature of weapons 68 //@{ 69 //! returns the weapon's ID getID() const70 Sint32 getID() const { return m_ID; } 71 //! returns the weapon's ID string getIDString() const72 const char* getIDString() const { 73 DBG(3) ASSERT( INVALID_WEAPON < getID() && getID() < NUMBER_OF_WEAPON_IDs, 74 "Weapon::getIDString: %d is not a valid weapon ID " 75 "from range [0,%d]\n", getID(), NUMBER_OF_WEAPON_IDs-1 ); 76 return getIDString(getID()); } 77 //! static method, that maps a weapon ID (constants.hpp) to its string getIDString(const Sint32 id)78 static const char* getIDString( const Sint32 id ) { 79 ASSERT( INVALID_WEAPON < id && id < NUMBER_OF_WEAPON_IDs, 80 "Weapon::getIDString(%d): %d is not a valid weapon ID in " 81 "range [0,%d]\n", id, id, NUMBER_OF_WEAPON_IDs ); 82 return WeaponIDString[id]; 83 } 84 //@} 85 86 //! \name special weapon controls 87 //@{ 88 //! returns true, if reloading is locked reloadIsLocked() const89 bool reloadIsLocked() const { return m_flags & RELOAD_LOCKED; } 90 //! locks the reloading of the weapon lockReload()91 void lockReload() { m_flags |= RELOAD_LOCKED; } 92 //! unlocks the reloading of the weapon unlockReload()93 void unlockReload() { m_flags &= ~RELOAD_LOCKED; } 94 //! returns true, if recharging is locked rechargeIsLocked() const95 bool rechargeIsLocked() const { return m_flags & RECHARGE_LOCKED; } 96 //! locks the recharging of the weapon lockRecharge()97 void lockRecharge() { m_flags |= RECHARGE_LOCKED; } 98 //! unlocks the recharging of the weapon unlockRecharge()99 void unlockRecharge() { m_flags &= ~RECHARGE_LOCKED; } 100 //! returns true, if shooting is locked shotIsLocked() const101 bool shotIsLocked() const { return m_flags & SHOT_LOCKED; } 102 //! locks shooting the weapon lockShot()103 void lockShot() { m_flags |= SHOT_LOCKED; } 104 //! unlocks shooting the weapon unlockShot()105 void unlockShot() { m_flags &= ~SHOT_LOCKED; } 106 //@} 107 getMaximumAmmo(void) const108 Uint32 getMaximumAmmo( void ) const { return m_maximumAmmo; } getReloadTime(void) const109 real getReloadTime ( void ) const { return m_reloadTime; } getChargeTime(void) const110 Uint32 getChargeTime ( void ) const { return m_chargeTime; } 111 setMaximumAmmo(const Uint32 maximumAmmo)112 void setMaximumAmmo( const Uint32 maximumAmmo ) { m_maximumAmmo = maximumAmmo; rechargeNow(); } setReloadTime(const real reloadTime)113 void setReloadTime ( const real reloadTime ) { m_reloadTime = reloadTime; rechargeNow(); } setChargeTime(const Uint32 chargeTime)114 void setChargeTime ( const Uint32 chargeTime ) { m_chargeTime = chargeTime; rechargeNow(); } 115 116 //! This method should check whether a shot is possible. If shooting is 117 //! possible, place particles and/or other weapon objects. 118 //! \note Checking or decreasing the ammo, charge or reload counters is 119 //! not necessary. 120 //! \return Return \c true if the weapon could be fired successfully. 121 //! Otherwise \c false. 122 virtual bool reallyShoot( World* world, Avatar* avatar, 123 const StationaryGun* gun = NULL ) const = 0; 124 125 //! All basic things for handling the weapon counters are handled here. 126 //! If shooting is possible according to these counters, Weapon::reallyShoot 127 //! will be called and the shot sample will be played. 128 virtual void shoot( World* world, Avatar* avatar, 129 const StationaryGun* gun = NULL ); 130 131 //! Takes care of the weapon counters. doTimestep(const real dt)132 virtual void doTimestep( const real dt ) { 133 if ( !rechargeIsLocked() && m_chargeTimer > 0 && --m_chargeTimer == 0 ) { 134 m_ammo = m_maximumAmmo; 135 } 136 137 if ( !reloadIsLocked() && !m_reloadTimer.isElapsed() ) { 138 m_reloadTimer.countDown( dt ); 139 } 140 } 141 142 /*! \brief \return \c true if weapon is recharging; \c false 143 * otherwise. \b Note that recharging can be locked nevertheless. 144 */ isCharging() const145 virtual bool isCharging() const { return m_chargeTimer > 0; } 146 147 /*! \brief \return \c true if weapon is reloading; \c false 148 * otherwise. \b Note that reloading can be locked nevertheless 149 */ isReloading() const150 virtual bool isReloading() const { return !m_reloadTimer.isElapsed(); } 151 152 //! \return The current amount of ammo. getCurrentAmmo() const153 virtual Uint32 getCurrentAmmo() const { return m_ammo; } 154 155 //! \return The current charging state between 0 (not charged) and 100 156 //! (completely charged). getChargingPercentage() const157 virtual Uint32 getChargingPercentage() const {; 158 return 100 - ( 100 * m_chargeTimer ) / m_chargeTime; 159 } 160 161 /*! \brief Sets all weapon counters to a completely charged weapon, 162 * even \b circumventing a locked recharging. Recharging is 163 * unlocked after this call. 164 */ rechargeNow()165 virtual void rechargeNow() { 166 m_ammo = m_maximumAmmo; 167 m_reloadTimer = m_chargeTimer = 0; 168 unlockRecharge(); 169 } 170 getSerializeBufferSize() const171 virtual Uint32 getSerializeBufferSize() const { 172 return 5 * Serialize<Uint32>::sizeOf() 173 + Serialize<real>::sizeOf() 174 + m_reloadTimer.getSerializeBufferSize(); 175 } 176 177 //! static factory method for weapons 178 static Weapon* newWeapon( const Sint32 ID ); 179 serialize(Uint8 * & bufferPointer) const180 virtual void serialize( Uint8*& bufferPointer ) const { 181 Serialize<Uint32>::serialize( m_ammo , bufferPointer ); 182 m_reloadTimer.serialize( bufferPointer ); 183 Serialize<Uint32>::serialize( m_chargeTimer, bufferPointer ); 184 Serialize<Uint32>::serialize( m_maximumAmmo, bufferPointer ); 185 Serialize<real>::serialize( m_reloadTime , bufferPointer ); 186 Serialize<Uint32>::serialize( m_flags , bufferPointer ); 187 Serialize<Uint32>::serialize( m_chargeTime , bufferPointer ); 188 } 189 deserialize(Uint8 * & bufferPointer)190 virtual void deserialize( Uint8*& bufferPointer ) { 191 Serialize<Uint32>::deserialize( bufferPointer, m_ammo ); 192 m_reloadTimer.deserialize( bufferPointer ); 193 Serialize<Uint32>::deserialize( bufferPointer, m_chargeTimer ); 194 Serialize<Uint32>::deserialize( bufferPointer, m_maximumAmmo ); 195 Serialize<real>::deserialize( bufferPointer, m_reloadTime ); 196 Serialize<Uint32>::deserialize( bufferPointer, m_flags ); 197 Serialize<Uint32>::deserialize( bufferPointer, m_chargeTime ); 198 } 199 200 }; 201 202 #endif // _WEAPON_HPP_ 203