Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/orxonox/weaponsystem/WeaponMode.cc @ 10904

Last change on this file since 10904 was 10362, checked in by landauf, 10 years ago

use static identifier initializer to store the inheritance definition of abstract classes. this prevents that identifiers are used (via Class(Name)) before they are properly initialized.

  • Property svn:eol-style set to native
File size: 10.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Martin Polak
24 *      Fabian 'x3n' Landau
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "WeaponMode.h"
31
32#include "core/CoreIncludes.h"
33#include "core/XMLPort.h"
34#include "controllers/Controller.h"
35#include "worldentities/pawns/Pawn.h"
36
37#include "Munition.h"
38#include "Weapon.h"
39#include "WeaponPack.h"
40#include "WeaponSystem.h"
41#include "WeaponSlot.h"
42
43#include "sound/WorldSound.h"
44
45namespace orxonox
46{
47    RegisterAbstractClass(WeaponMode).inheritsFrom<BaseObject>();
48
49    WeaponMode::WeaponMode(Context* context) : BaseObject(context)
50    {
51        RegisterObject(WeaponMode);
52
53        this->weapon_ = 0;
54        this->mode_ = WeaponSystem::WEAPON_MODE_UNASSIGNED;
55
56        this->munition_ = 0;
57        this->initialMunition_ = 0;
58        this->initialMagazines_ = 0;
59        this->munitionPerShot_ = 1;
60
61        this->reloadTime_ = 0.25;
62        this->bReloading_ = false;
63        this->bAutoReload_ = true;
64        this->bParallelReload_ = true;
65
66        this->reloadTimer_.setTimer(0.0f, false, createExecutor(createFunctor(&WeaponMode::reloaded, this)));
67        this->reloadTimer_.stopTimer();
68
69        this->damage_ = 0;
70        this->healthdamage_ = 0;
71        this->shielddamage_ = 0;
72
73        this->muzzleOffset_ = Vector3::ZERO;
74        this->muzzlePosition_ = Vector3::ZERO;
75        this->muzzleOrientation_ = Quaternion::IDENTITY;
76
77        if( GameMode::isMaster() )
78        {
79            this->defSndWpnFire_ = new WorldSound(this->getContext());
80            this->defSndWpnFire_->setLooping(false);
81            this->defSndWpnFire_->setVolume(0.8f);
82            this->bSoundAttached_ = false;
83        }
84        else
85            this->defSndWpnFire_ = 0;
86    }
87
88    WeaponMode::~WeaponMode()
89    {
90        if (this->isInitialized())
91        {
92            if (this->defSndWpnFire_)
93                this->defSndWpnFire_->destroy();
94        }
95    }
96
97    void WeaponMode::XMLPort(Element& xmlelement, XMLPort::Mode mode)
98    {
99        SUPER(WeaponMode, XMLPort, xmlelement, mode);
100
101        XMLPortParam(WeaponMode, "mode",             setMode,             getMode,             xmlelement, mode);
102
103        XMLPortParam(WeaponMode, "munitiontype",     setMunitionName,     getMunitionName,     xmlelement, mode);
104        XMLPortParam(WeaponMode, "initialmunition",  setInitialMunition,  getInitialMunition,  xmlelement, mode);
105        XMLPortParam(WeaponMode, "initialmagazines", setInitialMagazines, getInitialMagazines, xmlelement, mode);
106        XMLPortParam(WeaponMode, "munitionpershot",  setMunitionPerShot,  getMunitionPerShot,  xmlelement, mode);
107
108        XMLPortParam(WeaponMode, "reloadtime",       setReloadTime,       getReloadTime,       xmlelement, mode);
109        XMLPortParam(WeaponMode, "autoreload",       setAutoReload,       getAutoReload,       xmlelement, mode).description("If true, the weapon reloads the magazine automatically");
110        XMLPortParam(WeaponMode, "parallelreload",   setParallelReload,   getParallelReload,   xmlelement, mode).description("If true, the weapon reloads in parallel to the magazine reloading");
111
112        XMLPortParam(WeaponMode, "damage",           setDamage,           getDamage,           xmlelement, mode);
113        XMLPortParam(WeaponMode, "healthdamage",     setHealthDamage,     getHealthDamage,     xmlelement, mode);
114        XMLPortParam(WeaponMode, "shielddamage",     setShieldDamage,     getShieldDamage,     xmlelement, mode);
115        XMLPortParam(WeaponMode, "muzzleoffset",     setMuzzleOffset,     getMuzzleOffset,     xmlelement, mode);
116    }
117
118    bool WeaponMode::fire(float* reloadTime)
119    {
120        (*reloadTime) = this->reloadTime_;
121        if( !this->bSoundAttached_ && GameMode::isMaster() )
122        {
123            assert(this->getWeapon());
124            this->getWeapon()->attach(this->defSndWpnFire_);
125            this->bSoundAttached_ = true;
126        }
127
128        if (!this->bReloading_ && this->munition_ && this->munition_->takeMunition(this->munitionPerShot_, this))
129        {
130            float reloadtime = this->reloadTime_;
131
132            if (this->bAutoReload_ && this->munition_->needReload(this))
133            {
134                if (this->munition_->reload(this))
135                {
136                    if (this->bParallelReload_)
137                        reloadtime = std::max(this->reloadTime_, this->munition_->getReloadTime());
138                    else
139                        reloadtime = this->reloadTime_ + this->munition_->getReloadTime();
140                }
141            }
142
143            this->bReloading_ = true;
144            this->reloadTimer_.setInterval(reloadtime);
145            this->reloadTimer_.startTimer();
146
147            if( this->defSndWpnFire_ && !(this->defSndWpnFire_->isPlaying()))
148            {
149                this->defSndWpnFire_->play();
150            }
151
152            this->fire();
153
154            return true;
155        }
156        else
157        {
158            return false;
159        }
160    }
161
162    bool WeaponMode::reload()
163    {
164        if (this->munition_ && this->munition_->reload(this))
165        {
166            if (!this->bParallelReload_)
167            {
168                this->bReloading_ = true;
169                this->reloadTimer_.setInterval(this->reloadTime_ + this->munition_->getReloadTime());
170                this->reloadTimer_.startTimer();
171            }
172
173            return true;
174        }
175
176        return false;
177    }
178
179    void WeaponMode::setMunitionType(Identifier* identifier)
180    {
181        this->munitionname_ = identifier->getName();
182        this->munitiontype_ = identifier;
183        this->updateMunition();
184    }
185
186    void WeaponMode::setMunitionName(const std::string& munitionname)
187    {
188        this->munitionname_ = munitionname;
189        Identifier* identifier = ClassByString(this->munitionname_);
190        if (identifier)
191            this->munitiontype_ = identifier;
192        else
193            orxout(internal_warning) << "No munition class defined in WeaponMode " << this->getName() << endl;
194        this->updateMunition();
195    }
196
197    void WeaponMode::updateMunition()
198    {
199        if (this->munitiontype_ && this->weapon_ && this->weapon_->getWeaponPack() && this->weapon_->getWeaponPack()->getWeaponSystem())
200        {
201            this->munition_ = this->weapon_->getWeaponPack()->getWeaponSystem()->getMunition(&this->munitiontype_);
202
203            if (this->munition_)
204            {
205                // Add the initial magazines
206                this->munition_->addMagazines(this->initialMagazines_);
207
208                // Maybe we have to reload (if this munition is used the first time or if there weren't any magazines available before)
209                if (this->munition_->needReload(this))
210                    this->munition_->reload(this, false);
211
212                // Add the initial munition
213                if (this->initialMunition_ > 0 && this->munition_->getNumMunitionInCurrentMagazine(this) == this->munition_->getMaxMunitionPerMagazine())
214                {
215                    // The current magazine is still full, so let's just add another magazine to
216                    // the stack and reduce the current magazine to the given amount of munition
217
218                    unsigned int initialmunition = this->initialMunition_;
219                    if (initialmunition > this->munition_->getMaxMunitionPerMagazine())
220                        initialmunition = this->munition_->getMaxMunitionPerMagazine();
221
222                    this->munition_->takeMunition(this->munition_->getMaxMunitionPerMagazine() - initialmunition, this);
223                    this->munition_->addMagazines(1);
224                }
225                else
226                {
227                    // The current magazine isn't full, add the munition directly
228
229                    this->munition_->addMunition(this->initialMunition_);
230                }
231            }
232        }
233        else
234            this->munition_ = 0;
235    }
236
237    void WeaponMode::reloaded()
238    {
239        if( this->defSndWpnFire_ && this->defSndWpnFire_->isPlaying())
240        {
241            this->defSndWpnFire_->stop();
242        }
243        this->bReloading_ = false;
244    }
245
246    void WeaponMode::computeMuzzleParameters(const Vector3& target)
247    {
248        if (this->weapon_)
249        {
250            this->muzzlePosition_ = this->weapon_->getWorldPosition() + this->weapon_->getWorldOrientation() * this->muzzleOffset_;
251
252            Vector3 muzzleDirection;
253            muzzleDirection = target - this->muzzlePosition_;
254            this->muzzleOrientation_ = (this->weapon_->getWorldOrientation() * WorldEntity::FRONT).getRotationTo(muzzleDirection) * this->weapon_->getWorldOrientation();
255        }
256        else
257        {
258            this->muzzlePosition_ = this->muzzleOffset_;
259            this->muzzleOrientation_ = Quaternion::IDENTITY;
260        }
261    }
262
263    Vector3 WeaponMode::getMuzzleDirection() const
264    {
265        if (this->weapon_)
266            return (this->getMuzzleOrientation() * WorldEntity::FRONT);
267        else
268            return WorldEntity::FRONT;
269    }
270
271    void WeaponMode::setDefaultSound(const std::string& soundPath)
272    {
273        if( this->defSndWpnFire_ )
274            this->defSndWpnFire_->setSource(soundPath);
275    }
276
277    const std::string& WeaponMode::getDefaultSound()
278    {
279        if( this->defSndWpnFire_ )
280            return this->defSndWpnFire_->getSource();
281        else
282            return BLANKSTRING;
283    }
284
285    void WeaponMode::setDefaultSoundWithVolume(const std::string& soundPath, const float soundVolume){
286        if (this->defSndWpnFire_) {
287            this->defSndWpnFire_->setSource(soundPath);
288            this->defSndWpnFire_->setVolume(soundVolume);
289        }
290    }
291
292}
Note: See TracBrowser for help on using the repository browser.