Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/worldentities/pawns/Pawn.cc @ 9306

Last change on this file since 9306 was 9257, checked in by landauf, 13 years ago

renamed RVName to radarname
cast to RadarViewable instead of SpaceShip to set the name (in PlayerInfo)

  • Property svn:eol-style set to native
File size: 15.1 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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Simon Miescher
26 *
27 */
28
29#include "Pawn.h"
30
31#include <algorithm>
32
33#include "core/CoreIncludes.h"
34#include "core/GameMode.h"
35#include "core/XMLPort.h"
36#include "network/NetworkFunction.h"
37
38#include "infos/PlayerInfo.h"
39#include "controllers/Controller.h"
40#include "gametypes/Gametype.h"
41#include "graphics/ParticleSpawner.h"
42#include "worldentities/ExplosionChunk.h"
43#include "worldentities/BigExplosion.h"
44#include "weaponsystem/WeaponSystem.h"
45#include "weaponsystem/WeaponSlot.h"
46#include "weaponsystem/WeaponPack.h"
47#include "weaponsystem/WeaponSet.h"
48
49namespace orxonox
50{
51    CreateFactory(Pawn);
52
53    Pawn::Pawn(BaseObject* creator)
54        : ControllableEntity(creator)
55        , RadarViewable(creator, static_cast<WorldEntity*>(this))
56    {
57        RegisterObject(Pawn);
58
59        this->bAlive_ = true;
60        this->bReload_ = false;
61
62        this->health_ = 0;
63        this->maxHealth_ = 0;
64        this->initialHealth_ = 0;
65
66        this->shieldHealth_ = 0;
67        this->initialShieldHealth_ = 0;
68        this->maxShieldHealth_ = 100; //otherwise shield might increase to float_max
69        this->shieldAbsorption_ = 0.5;
70
71        this->reloadRate_ = 0;
72        this->reloadWaitTime_ = 1.0f;
73        this->reloadWaitCountdown_ = 0;
74
75        this->lastHitOriginator_ = 0;
76
77        this->spawnparticleduration_ = 3.0f;
78
79        this->aimPosition_ = Vector3::ZERO;
80
81        if (GameMode::isMaster())
82        {
83            this->weaponSystem_ = new WeaponSystem(this);
84            this->weaponSystem_->setPawn(this);
85        }
86        else
87            this->weaponSystem_ = 0;
88
89        this->setRadarObjectColour(ColourValue::Red);
90        this->setRadarObjectShape(RadarViewable::Dot);
91
92        this->registerVariables();
93
94        this->isHumanShip_ = this->hasLocalController();
95
96        this->setSyncMode(ObjectDirection::Bidirectional); // needed to synchronise e.g. aimposition
97    }
98
99    Pawn::~Pawn()
100    {
101        if (this->isInitialized())
102        {
103            if (this->weaponSystem_)
104                this->weaponSystem_->destroy();
105        }
106    }
107
108    void Pawn::XMLPort(Element& xmlelement, XMLPort::Mode mode)
109    {
110        SUPER(Pawn, XMLPort, xmlelement, mode);
111
112        XMLPortParam(Pawn, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
113        XMLPortParam(Pawn, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
114        XMLPortParam(Pawn, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
115
116        XMLPortParam(Pawn, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode).defaultValues(0);
117        XMLPortParam(Pawn, "initialshieldhealth", setInitialShieldHealth, getInitialShieldHealth, xmlelement, mode).defaultValues(0);
118        XMLPortParam(Pawn, "maxshieldhealth", setMaxShieldHealth, getMaxShieldHealth, xmlelement, mode).defaultValues(100);
119        XMLPortParam(Pawn, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode).defaultValues(0);
120
121        XMLPortParam(Pawn, "spawnparticlesource", setSpawnParticleSource, getSpawnParticleSource, xmlelement, mode);
122        XMLPortParam(Pawn, "spawnparticleduration", setSpawnParticleDuration, getSpawnParticleDuration, xmlelement, mode).defaultValues(3.0f);
123        XMLPortParam(Pawn, "explosionchunks", setExplosionChunks, getExplosionChunks, xmlelement, mode).defaultValues(7);
124
125        XMLPortObject(Pawn, WeaponSlot, "weaponslots", addWeaponSlot, getWeaponSlot, xmlelement, mode);
126        XMLPortObject(Pawn, WeaponSet, "weaponsets", addWeaponSet, getWeaponSet, xmlelement, mode);
127        XMLPortObject(Pawn, WeaponPack, "weapons", addWeaponPackXML, getWeaponPack, xmlelement, mode);
128
129        XMLPortParam(Pawn, "reloadrate", setReloadRate, getReloadRate, xmlelement, mode).defaultValues(0);
130        XMLPortParam(Pawn, "reloadwaittime", setReloadWaitTime, getReloadWaitTime, xmlelement, mode).defaultValues(1.0f);
131
132        XMLPortParam ( RadarViewable, "radarname", setRadarName, getRadarName, xmlelement, mode );
133    }
134
135    void Pawn::registerVariables()
136    {
137        registerVariable(this->bAlive_,           VariableDirection::ToClient);
138        registerVariable(this->health_,           VariableDirection::ToClient);
139        registerVariable(this->maxHealth_,        VariableDirection::ToClient);
140        registerVariable(this->shieldHealth_,     VariableDirection::ToClient);
141        registerVariable(this->maxShieldHealth_,  VariableDirection::ToClient);
142        registerVariable(this->shieldAbsorption_, VariableDirection::ToClient);
143        registerVariable(this->bReload_,          VariableDirection::ToServer);
144        registerVariable(this->aimPosition_,      VariableDirection::ToServer);  // For the moment this variable gets only transfered to the server
145    }
146
147    void Pawn::tick(float dt)
148    {
149        SUPER(Pawn, tick, dt);
150
151        this->bReload_ = false;
152
153        // TODO: use the existing timer functions instead
154        if(this->reloadWaitCountdown_ > 0)
155        {
156            this->decreaseReloadCountdownTime(dt);
157        }
158        else
159        {
160            this->addShieldHealth(this->getReloadRate() * dt);
161            this->resetReloadCountdown();
162        }
163
164        if (GameMode::isMaster())
165        {
166            if (this->health_ <= 0 && bAlive_)
167            {
168                this->fireEvent(); // Event to notify anyone who wants to know about the death.
169                this->death();
170            }
171        }
172    }
173
174    void Pawn::preDestroy()
175    {
176        // yay, multiple inheritance!
177        this->ControllableEntity::preDestroy();
178        this->PickupCarrier::preDestroy();
179    }
180
181    void Pawn::setPlayer(PlayerInfo* player)
182    {
183        ControllableEntity::setPlayer(player);
184
185        if (this->getGametype())
186            this->getGametype()->playerStartsControllingPawn(player, this);
187    }
188
189    void Pawn::removePlayer()
190    {
191        if (this->getGametype())
192            this->getGametype()->playerStopsControllingPawn(this->getPlayer(), this);
193
194        ControllableEntity::removePlayer();
195    }
196
197
198    void Pawn::setHealth(float health)
199    {
200        this->health_ = std::min(health, this->maxHealth_); //Health can't be set to a value bigger than maxHealth, otherwise it will be reduced at first hit
201    }
202
203    void Pawn::setShieldHealth(float shieldHealth)
204    {
205        this->shieldHealth_ = std::min(shieldHealth, this->maxShieldHealth_);
206    }
207
208    void Pawn::setMaxShieldHealth(float maxshieldhealth)
209    {
210        this->maxShieldHealth_ = maxshieldhealth;
211    }
212
213    void Pawn::setReloadRate(float reloadrate)
214    {
215        this->reloadRate_ = reloadrate;
216    }
217
218    void Pawn::setReloadWaitTime(float reloadwaittime)
219    {
220        this->reloadWaitTime_ = reloadwaittime;
221    }
222
223    void Pawn::decreaseReloadCountdownTime(float dt)
224    {
225        this->reloadWaitCountdown_ -= dt;
226    }
227
228    void Pawn::damage(float damage, float healthdamage, float shielddamage, Pawn* originator)
229    {
230        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
231        {
232            if (shielddamage >= this->getShieldHealth())
233            {
234                this->setShieldHealth(0);
235                this->setHealth(this->health_ - (healthdamage + damage));
236            }
237            else
238            {
239                this->setShieldHealth(this->shieldHealth_ - shielddamage);
240
241                // remove remaining shieldAbsorpton-Part of damage from shield
242                shielddamage = damage * this->shieldAbsorption_;
243                shielddamage = std::min(this->getShieldHealth(),shielddamage);
244                this->setShieldHealth(this->shieldHealth_ - shielddamage);
245
246                // set remaining damage to health
247                this->setHealth(this->health_ - (damage - shielddamage) - healthdamage);
248            }
249
250            this->lastHitOriginator_ = originator;
251        }
252    }
253
254// TODO: Still valid?
255/* HIT-Funktionen
256    Die hit-Funktionen muessen auch in src/orxonox/controllers/Controller.h angepasst werden! (Visuelle Effekte)
257
258*/
259    void Pawn::hit(Pawn* originator, const Vector3& force, float damage, float healthdamage, float shielddamage)
260    {
261        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
262        {
263            this->damage(damage, healthdamage, shielddamage, originator);
264            this->setVelocity(this->getVelocity() + force);
265        }
266    }
267
268
269    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage, float shielddamage)
270    {
271        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
272        {
273            this->damage(damage, healthdamage, shielddamage, originator);
274
275            if ( this->getController() )
276                this->getController()->hit(originator, contactpoint, damage); // changed to damage, why shielddamage?
277        }
278    }
279
280
281    void Pawn::kill()
282    {
283        this->damage(this->health_);
284        this->death();
285    }
286
287    void Pawn::spawneffect()
288    {
289        // play spawn effect
290        if (!this->spawnparticlesource_.empty())
291        {
292            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
293            effect->setPosition(this->getPosition());
294            effect->setOrientation(this->getOrientation());
295            effect->setDestroyAfterLife(true);
296            effect->setSource(this->spawnparticlesource_);
297            effect->setLifetime(this->spawnparticleduration_);
298        }
299    }
300
301    void Pawn::death()
302    {
303        this->setHealth(1);
304        if (this->getGametype() && this->getGametype()->allowPawnDeath(this, this->lastHitOriginator_))
305        {
306            // Set bAlive_ to false and wait for PawnManager to do the destruction
307            this->bAlive_ = false;
308
309            this->setDestroyWhenPlayerLeft(false);
310
311            if (this->getGametype())
312                this->getGametype()->pawnKilled(this, this->lastHitOriginator_);
313
314            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
315                this->getPlayer()->stopControl();
316
317            if (GameMode::isMaster())
318            {
319//                this->deathEffect();
320                this->goWithStyle();
321            }
322        }
323    }
324    void Pawn::goWithStyle()
325    {
326        this->bAlive_ = false;
327        this->setDestroyWhenPlayerLeft(false);
328
329        BigExplosion* chunk = new BigExplosion(this->getCreator());
330        chunk->setPosition(this->getPosition());
331
332    }
333    void Pawn::deatheffect()
334    {
335        // play death effect
336        {
337            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
338            effect->setPosition(this->getPosition());
339            effect->setOrientation(this->getOrientation());
340            effect->setDestroyAfterLife(true);
341            effect->setSource("Orxonox/explosion2b");
342            effect->setLifetime(4.0f);
343        }
344        {
345            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
346            effect->setPosition(this->getPosition());
347            effect->setOrientation(this->getOrientation());
348            effect->setDestroyAfterLife(true);
349            effect->setSource("Orxonox/smoke6");
350            effect->setLifetime(4.0f);
351        }
352        {
353            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
354            effect->setPosition(this->getPosition());
355            effect->setOrientation(this->getOrientation());
356            effect->setDestroyAfterLife(true);
357            effect->setSource("Orxonox/sparks");
358            effect->setLifetime(4.0f);
359        }
360        for (unsigned int i = 0; i < this->numexplosionchunks_; ++i)
361        {
362            ExplosionChunk* chunk = new ExplosionChunk(this->getCreator());
363            chunk->setPosition(this->getPosition());
364        }
365    }
366
367    void Pawn::fired(unsigned int firemode)
368    {
369        if (this->weaponSystem_)
370            this->weaponSystem_->fire(firemode);
371    }
372
373    void Pawn::reload()
374    {
375        this->bReload_ = true;
376    }
377
378    void Pawn::postSpawn()
379    {
380        this->setHealth(this->initialHealth_);
381        if (GameMode::isMaster())
382            this->spawneffect();
383    }
384
385    /* WeaponSystem:
386    *   functions load Slot, Set, Pack from XML and make sure all parent-pointers are set.
387    *   with setWeaponPack you can not just load a Pack from XML but if a Pack already exists anywhere, you can attach it.
388    *       --> e.g. Pickup-Items
389    */
390    void Pawn::addWeaponSlot(WeaponSlot * wSlot)
391    {
392        this->attach(wSlot);
393        if (this->weaponSystem_)
394            this->weaponSystem_->addWeaponSlot(wSlot);
395    }
396
397    WeaponSlot * Pawn::getWeaponSlot(unsigned int index) const
398    {
399        if (this->weaponSystem_)
400            return this->weaponSystem_->getWeaponSlot(index);
401        else
402            return 0;
403    }
404
405    void Pawn::addWeaponSet(WeaponSet * wSet)
406    {
407        if (this->weaponSystem_)
408            this->weaponSystem_->addWeaponSet(wSet);
409    }
410
411    WeaponSet * Pawn::getWeaponSet(unsigned int index) const
412    {
413        if (this->weaponSystem_)
414            return this->weaponSystem_->getWeaponSet(index);
415        else
416            return 0;
417    }
418
419    void Pawn::addWeaponPack(WeaponPack * wPack)
420    {
421        if (this->weaponSystem_)
422        {
423            this->weaponSystem_->addWeaponPack(wPack);
424            this->addedWeaponPack(wPack);
425        }
426    }
427
428    void Pawn::addWeaponPackXML(WeaponPack * wPack)
429    {
430        if (this->weaponSystem_)
431        {
432            if (!this->weaponSystem_->addWeaponPack(wPack))
433                wPack->destroy();
434            else
435                this->addedWeaponPack(wPack);
436        }
437    }
438
439    WeaponPack * Pawn::getWeaponPack(unsigned int index) const
440    {
441        if (this->weaponSystem_)
442            return this->weaponSystem_->getWeaponPack(index);
443        else
444            return 0;
445    }
446
447    //Tell the Map (RadarViewable), if this is a playership
448    void Pawn::startLocalHumanControl()
449    {
450//        SUPER(ControllableEntity, changedPlayer());
451        ControllableEntity::startLocalHumanControl();
452        this->isHumanShip_ = true;
453    }
454
455    void Pawn::changedVisibility(void)
456    {
457        SUPER(Pawn, changedVisibility);
458
459        // enable proper radarviewability when the visibility is changed
460        this->RadarViewable::settingsChanged();
461    }
462
463}
Note: See TracBrowser for help on using the repository browser.