Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pickup2012/src/orxonox/worldentities/pawns/Pawn.cc @ 9155

Last change on this file since 9155 was 9155, checked in by lkevin, 12 years ago

Changed pickup icon and xml for possible varieties of the pickup in the future.

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