Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.cc @ 10961

Last change on this file since 10961 was 10961, checked in by maxima, 10 years ago

Merged presentation and fabiens branch. Had to modify hoverHUD and invaderHUD, because the text of the healthbar wasn't correctly displayed and the weapon settings of the hovership.

  • Property svn:eol-style set to native
File size: 11.0 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        hudImageString_ = "WSHUD_WM_Unknown";
78
79        if( GameMode::isMaster() )
80        {
81            this->defSndWpnFire_ = new WorldSound(this->getContext());
82            this->defSndWpnFire_->setLooping(false);
83            this->defSndWpnFire_->setVolume(0.8f);
84            this->bSoundAttached_ = false;
85        }
86        else
87            this->defSndWpnFire_ = 0;
88    }
89
90    WeaponMode::~WeaponMode()
91    {
92        if (this->isInitialized())
93        {
94            if (this->defSndWpnFire_)
95                this->defSndWpnFire_->destroy();
96        }
97    }
98
99    void WeaponMode::XMLPort(Element& xmlelement, XMLPort::Mode mode)
100    {
101        SUPER(WeaponMode, XMLPort, xmlelement, mode);
102
103        XMLPortParam(WeaponMode, "mode",             setMode,             getMode,             xmlelement, mode);
104
105        XMLPortParam(WeaponMode, "munitiontype",     setMunitionName,     getMunitionName,     xmlelement, mode);
106        XMLPortParam(WeaponMode, "initialmunition",  setInitialMunition,  getInitialMunition,  xmlelement, mode);
107        XMLPortParam(WeaponMode, "initialmagazines", setInitialMagazines, getInitialMagazines, xmlelement, mode);
108        XMLPortParam(WeaponMode, "munitionpershot",  setMunitionPerShot,  getMunitionPerShot,  xmlelement, mode);
109
110        XMLPortParam(WeaponMode, "reloadtime",       setReloadTime,       getReloadTime,       xmlelement, mode);
111        XMLPortParam(WeaponMode, "autoreload",       setAutoReload,       getAutoReload,       xmlelement, mode).description("If true, the weapon reloads the magazine automatically");
112        XMLPortParam(WeaponMode, "parallelreload",   setParallelReload,   getParallelReload,   xmlelement, mode).description("If true, the weapon reloads in parallel to the magazine reloading");
113
114        XMLPortParam(WeaponMode, "damage",           setDamage,           getDamage,           xmlelement, mode);
115        XMLPortParam(WeaponMode, "healthdamage",     setHealthDamage,     getHealthDamage,     xmlelement, mode);
116        XMLPortParam(WeaponMode, "shielddamage",     setShieldDamage,     getShieldDamage,     xmlelement, mode);
117        XMLPortParam(WeaponMode, "muzzleoffset",     setMuzzleOffset,     getMuzzleOffset,     xmlelement, mode);
118    }
119
120    bool WeaponMode::fire(float* reloadTime)
121    {
122        (*reloadTime) = this->reloadTime_;
123        if( !this->bSoundAttached_ && GameMode::isMaster() )
124        {
125            assert(this->getWeapon());
126            this->getWeapon()->attach(this->defSndWpnFire_);
127            this->bSoundAttached_ = true;
128        }
129       
130        // Fireing is only possible if this weapon mode is not reloading and there is enough munition
131        if (!this->bReloading_ && this->munition_ && this->munition_->takeMunition(this->munitionPerShot_, this))
132        {
133            float tempReloadtime = this->reloadTime_;
134
135            if (this->bAutoReload_ && this->munition_->needReload(this))
136            {
137                if (this->munition_->reload(this))
138                {
139                    // If true, the weapon reloads in parallel to the magazine reloading
140                    if (this->bParallelReload_)
141                    {
142                        // The time needed to reload is the maximum of the reload time of the weapon mode and the magazine.
143                        tempReloadtime = std::max(this->reloadTime_, this->munition_->getReloadTime());
144                    }                       
145                    else
146                    {
147                        // The time needed to reload is the sum of the reload time of the weapon mode and the magazine.
148                        tempReloadtime = this->reloadTime_ + this->munition_->getReloadTime();
149                    }                       
150                }
151            }
152
153            // Mark this weapon mode as reloading and start the reload timer
154            this->bReloading_ = true;
155            this->reloadTimer_.setInterval(tempReloadtime);
156            this->reloadTimer_.startTimer();
157
158            if( this->defSndWpnFire_ && !(this->defSndWpnFire_->isPlaying()))
159            {
160                this->defSndWpnFire_->play();
161            }
162
163            this->fire();
164
165            return true;
166        }
167        else
168        {
169            return false;
170        }
171    }
172
173    bool WeaponMode::reload()
174    {
175        if (this->munition_ && this->munition_->reload(this))
176        {
177            if (!this->bParallelReload_)
178            {
179                this->bReloading_ = true;
180                this->reloadTimer_.setInterval(this->reloadTime_ + this->munition_->getReloadTime());
181                this->reloadTimer_.startTimer();
182            }
183
184            return true;
185        }
186
187        return false;
188    }
189
190    void WeaponMode::setMunitionType(Identifier* identifier)
191    {
192        this->munitionname_ = identifier->getName();
193        this->munitiontype_ = identifier;
194        this->updateMunition();
195    }
196
197    void WeaponMode::setMunitionName(const std::string& munitionname)
198    {
199        this->munitionname_ = munitionname;
200        Identifier* identifier = ClassByString(this->munitionname_);
201        if (identifier)
202            this->munitiontype_ = identifier;
203        else
204            orxout(internal_warning) << "No munition class defined in WeaponMode " << this->getName() << endl;
205        this->updateMunition();
206    }
207
208    void WeaponMode::updateMunition()
209    {
210        if (this->munitiontype_ && this->weapon_ && this->weapon_->getWeaponPack() && this->weapon_->getWeaponPack()->getWeaponSystem())
211        {
212            this->munition_ = this->weapon_->getWeaponPack()->getWeaponSystem()->getMunition(&this->munitiontype_);
213
214            if (this->munition_)
215            {
216                // Add the initial magazines
217                this->munition_->addMagazines(this->initialMagazines_);
218
219                // Maybe we have to reload (if this munition is used the first time or if there weren't any magazines available before)
220                if (this->munition_->needReload(this))
221                    this->munition_->reload(this, false);
222
223                // Add the initial munition
224                if (this->initialMunition_ > 0 && this->munition_->getNumMunitionInCurrentMagazine(this) == this->munition_->getMaxMunitionPerMagazine())
225                {
226                    // The current magazine is still full, so let's just add another magazine to
227                    // the stack and reduce the current magazine to the given amount of munition
228
229                    unsigned int initialmunition = this->initialMunition_;
230                    if (initialmunition > this->munition_->getMaxMunitionPerMagazine())
231                        initialmunition = this->munition_->getMaxMunitionPerMagazine();
232
233                    this->munition_->takeMunition(this->munition_->getMaxMunitionPerMagazine() - initialmunition, this);
234                    this->munition_->addMagazines(1);
235                }
236                else
237                {
238                    // The current magazine isn't full, add the munition directly
239
240                    this->munition_->addMunition(this->initialMunition_);
241                }
242            }
243        }
244        else
245        {
246            this->munition_ = NULL;
247        }
248    }
249
250    void WeaponMode::reloaded()
251    {
252        if( this->defSndWpnFire_ && this->defSndWpnFire_->isPlaying())
253        {
254            this->defSndWpnFire_->stop();
255        }
256        this->bReloading_ = false;
257    }
258
259    void WeaponMode::computeMuzzleParameters(const Vector3& target)
260    {
261        if (this->weapon_)
262        {
263            this->muzzlePosition_ = this->weapon_->getWorldPosition() + this->weapon_->getWorldOrientation() * this->muzzleOffset_;
264
265            Vector3 muzzleDirection;
266            muzzleDirection = target - this->muzzlePosition_;
267            this->muzzleOrientation_ = (this->weapon_->getWorldOrientation() * WorldEntity::FRONT).getRotationTo(muzzleDirection) * this->weapon_->getWorldOrientation();
268        }
269        else
270        {
271            this->muzzlePosition_ = this->muzzleOffset_;
272            this->muzzleOrientation_ = Quaternion::IDENTITY;
273        }
274    }
275
276    Vector3 WeaponMode::getMuzzleDirection() const
277    {
278        if (this->weapon_)
279            return (this->getMuzzleOrientation() * WorldEntity::FRONT);
280        else
281            return WorldEntity::FRONT;
282    }
283
284    void WeaponMode::setDefaultSound(const std::string& soundPath)
285    {
286        if( this->defSndWpnFire_ )
287            this->defSndWpnFire_->setSource(soundPath);
288    }
289
290    const std::string& WeaponMode::getDefaultSound()
291    {
292        if( this->defSndWpnFire_ )
293            return this->defSndWpnFire_->getSource();
294        else
295            return BLANKSTRING;
296    }
297
298    void WeaponMode::setDefaultSoundWithVolume(const std::string& soundPath, const float soundVolume)
299    {
300        if (this->defSndWpnFire_)
301        {
302            this->defSndWpnFire_->setSource(soundPath);
303            this->defSndWpnFire_->setVolume(soundVolume);
304        }
305    }
306
307}
Note: See TracBrowser for help on using the repository browser.