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
RevLine 
[2072]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:
[8706]25 *      Simon Miescher
[2072]26 *
27 */
28
29#include "Pawn.h"
30
[3280]31#include <algorithm>
32
[3196]33#include "core/CoreIncludes.h"
[2896]34#include "core/GameMode.h"
[2072]35#include "core/XMLPort.h"
[3196]36#include "network/NetworkFunction.h"
37
[5735]38#include "infos/PlayerInfo.h"
[6417]39#include "controllers/Controller.h"
[5735]40#include "gametypes/Gametype.h"
[5737]41#include "graphics/ParticleSpawner.h"
[5735]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"
[2072]48
49namespace orxonox
50{
51    CreateFactory(Pawn);
52
[7163]53    Pawn::Pawn(BaseObject* creator)
54        : ControllableEntity(creator)
55        , RadarViewable(creator, static_cast<WorldEntity*>(this))
[2072]56    {
57        RegisterObject(Pawn);
58
[2662]59        this->bAlive_ = true;
[3053]60        this->bReload_ = false;
[2072]61
62        this->health_ = 0;
63        this->maxHealth_ = 0;
64        this->initialHealth_ = 0;
[8706]65
[7163]66        this->shieldHealth_ = 0;
[8706]67        this->initialShieldHealth_ = 0;
68        this->maxShieldHealth_ = 100; //otherwise shield might increase to float_max
[7163]69        this->shieldAbsorption_ = 0.5;
[2072]70
[8706]71        this->reloadRate_ = 0;
72        this->reloadWaitTime_ = 1.0f;
73        this->reloadWaitCountdown_ = 0;
74
[2072]75        this->lastHitOriginator_ = 0;
76
[9099]77        // set damage multiplier to default value 1, meaning nominal damage
78        this->damageMultiplier_ = 1;
79
[2662]80        this->spawnparticleduration_ = 3.0f;
[2098]81
[6417]82        this->aimPosition_ = Vector3::ZERO;
83
[2896]84        if (GameMode::isMaster())
[2662]85        {
86            this->weaponSystem_ = new WeaponSystem(this);
[3053]87            this->weaponSystem_->setPawn(this);
[2662]88        }
89        else
90            this->weaponSystem_ = 0;
91
92        this->setRadarObjectColour(ColourValue::Red);
93        this->setRadarObjectShape(RadarViewable::Dot);
94
[2072]95        this->registerVariables();
[3089]96
97        this->isHumanShip_ = this->hasLocalController();
[8891]98
[8329]99        this->setSyncMode(ObjectDirection::Bidirectional); // needed to synchronise e.g. aimposition
[2072]100    }
101
102    Pawn::~Pawn()
103    {
[2662]104        if (this->isInitialized())
105        {
106            if (this->weaponSystem_)
[5929]107                this->weaponSystem_->destroy();
[2662]108        }
[2072]109    }
110
111    void Pawn::XMLPort(Element& xmlelement, XMLPort::Mode mode)
112    {
113        SUPER(Pawn, XMLPort, xmlelement, mode);
114
[2662]115        XMLPortParam(Pawn, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
[2072]116        XMLPortParam(Pawn, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
117        XMLPortParam(Pawn, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
[7163]118
119        XMLPortParam(Pawn, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode).defaultValues(0);
[8706]120        XMLPortParam(Pawn, "initialshieldhealth", setInitialShieldHealth, getInitialShieldHealth, xmlelement, mode).defaultValues(0);
121        XMLPortParam(Pawn, "maxshieldhealth", setMaxShieldHealth, getMaxShieldHealth, xmlelement, mode).defaultValues(100);
[7163]122        XMLPortParam(Pawn, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode).defaultValues(0);
123
[2662]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
[3053]128        XMLPortObject(Pawn, WeaponSlot, "weaponslots", addWeaponSlot, getWeaponSlot, xmlelement, mode);
129        XMLPortObject(Pawn, WeaponSet, "weaponsets", addWeaponSet, getWeaponSet, xmlelement, mode);
[6417]130        XMLPortObject(Pawn, WeaponPack, "weapons", addWeaponPackXML, getWeaponPack, xmlelement, mode);
[8706]131
132        XMLPortParam(Pawn, "reloadrate", setReloadRate, getReloadRate, xmlelement, mode).defaultValues(0);
133        XMLPortParam(Pawn, "reloadwaittime", setReloadWaitTime, getReloadWaitTime, xmlelement, mode).defaultValues(1.0f);
[9016]134   
135        XMLPortParam ( RadarViewable, "RVName", setRVName, getRVName, xmlelement, mode );
[2072]136    }
137
138    void Pawn::registerVariables()
139    {
[7163]140        registerVariable(this->bAlive_,           VariableDirection::ToClient);
141        registerVariable(this->health_,           VariableDirection::ToClient);
[8706]142        registerVariable(this->maxHealth_,        VariableDirection::ToClient);
[7163]143        registerVariable(this->shieldHealth_,     VariableDirection::ToClient);
[8706]144        registerVariable(this->maxShieldHealth_,  VariableDirection::ToClient);
[7163]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
[2072]148    }
149
150    void Pawn::tick(float dt)
151    {
[2809]152        SUPER(Pawn, tick, dt);
[2072]153
[3053]154        this->bReload_ = false;
[2662]155
[8706]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
[3084]167        if (GameMode::isMaster())
[8706]168        {
[3087]169            if (this->health_ <= 0 && bAlive_)
[6864]170            {
[8706]171                this->fireEvent(); // Event to notify anyone who wants to know about the death.
[3087]172                this->death();
[6864]173            }
[8706]174        }
[2072]175    }
176
[7889]177    void Pawn::preDestroy()
178    {
179        // yay, multiple inheritance!
180        this->ControllableEntity::preDestroy();
181        this->PickupCarrier::preDestroy();
182    }
183
[2826]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
[8706]200
[2072]201    void Pawn::setHealth(float health)
202    {
[8706]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
[2072]204    }
205
[8706]206    void Pawn::setShieldHealth(float shieldHealth)
[2072]207    {
[8706]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    {
[9099]233        // apply multiplier
[9118]234        Pawn *test = dynamic_cast<Pawn *>(originator);
235        if( test != NULL )
[9155]236        { orxout() << "Test " << damage << endl;
[9118]237          damage *= originator->getDamageMultiplier();
[9155]238        }
[9099]239
240        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
[2826]241        {
[8706]242            if (shielddamage >= this->getShieldHealth())
[7163]243            {
244                this->setShieldHealth(0);
[8706]245                this->setHealth(this->health_ - (healthdamage + damage));
[7163]246            }
[8706]247            else
248            {
249                this->setShieldHealth(this->shieldHealth_ - shielddamage);
[7163]250
[8706]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);
[7163]255
[8706]256                // set remaining damage to health
257                this->setHealth(this->health_ - (damage - shielddamage) - healthdamage);
[7163]258            }
259
[2826]260            this->lastHitOriginator_ = originator;
261        }
[2072]262    }
263
[8706]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)
[2072]270    {
[6417]271        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
[2826]272        {
[8706]273            this->damage(damage, healthdamage, shielddamage, originator);
[2826]274            this->setVelocity(this->getVelocity() + force);
275        }
[2072]276    }
277
[8706]278
279    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage, float shielddamage)
[6417]280    {
281        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
282        {
[8706]283            this->damage(damage, healthdamage, shielddamage, originator);
[6417]284
285            if ( this->getController() )
[8706]286                this->getController()->hit(originator, contactpoint, damage); // changed to damage, why shielddamage?
[6417]287        }
288    }
289
[8706]290
[2072]291    void Pawn::kill()
292    {
293        this->damage(this->health_);
294        this->death();
295    }
296
[2662]297    void Pawn::spawneffect()
[2072]298    {
299        // play spawn effect
[6417]300        if (!this->spawnparticlesource_.empty())
[2662]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        }
[2072]309    }
310
311    void Pawn::death()
312    {
[3033]313        this->setHealth(1);
[2826]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;
[2662]318
[2826]319            this->setDestroyWhenPlayerLeft(false);
[2662]320
[2826]321            if (this->getGametype())
322                this->getGametype()->pawnKilled(this, this->lastHitOriginator_);
[2662]323
[3038]324            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
325                this->getPlayer()->stopControl();
[2072]326
[2896]327            if (GameMode::isMaster())
[3087]328            {
329//                this->deathEffect();
330                this->goWithStyle();
331            }
[2826]332        }
[2662]333    }
[3087]334    void Pawn::goWithStyle()
335    {
336        this->bAlive_ = false;
337        this->setDestroyWhenPlayerLeft(false);
[2072]338
[3087]339        BigExplosion* chunk = new BigExplosion(this->getCreator());
340        chunk->setPosition(this->getPosition());
341
342    }
[2662]343    void Pawn::deatheffect()
344    {
[2072]345        // play death effect
[2662]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        }
[2072]375    }
376
[6417]377    void Pawn::fired(unsigned int firemode)
[2098]378    {
[6417]379        if (this->weaponSystem_)
380            this->weaponSystem_->fire(firemode);
[2098]381    }
382
[3053]383    void Pawn::reload()
384    {
385        this->bReload_ = true;
386    }
387
[2072]388    void Pawn::postSpawn()
389    {
390        this->setHealth(this->initialHealth_);
[2896]391        if (GameMode::isMaster())
[2662]392            this->spawneffect();
[2072]393    }
[2662]394
[2893]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    */
[3053]400    void Pawn::addWeaponSlot(WeaponSlot * wSlot)
[2662]401    {
402        this->attach(wSlot);
403        if (this->weaponSystem_)
[3053]404            this->weaponSystem_->addWeaponSlot(wSlot);
[2662]405    }
406
407    WeaponSlot * Pawn::getWeaponSlot(unsigned int index) const
408    {
409        if (this->weaponSystem_)
[3053]410            return this->weaponSystem_->getWeaponSlot(index);
[2662]411        else
412            return 0;
413    }
414
[3053]415    void Pawn::addWeaponSet(WeaponSet * wSet)
[2662]416    {
417        if (this->weaponSystem_)
[3053]418            this->weaponSystem_->addWeaponSet(wSet);
[2662]419    }
420
[3053]421    WeaponSet * Pawn::getWeaponSet(unsigned int index) const
[2662]422    {
423        if (this->weaponSystem_)
[3053]424            return this->weaponSystem_->getWeaponSet(index);
[2662]425        else
426            return 0;
427    }
428
[3053]429    void Pawn::addWeaponPack(WeaponPack * wPack)
[2662]430    {
431        if (this->weaponSystem_)
[7163]432        {
[3053]433            this->weaponSystem_->addWeaponPack(wPack);
[7163]434            this->addedWeaponPack(wPack);
435        }
[2662]436    }
437
[6417]438    void Pawn::addWeaponPackXML(WeaponPack * wPack)
439    {
440        if (this->weaponSystem_)
[7163]441        {
[6417]442            if (!this->weaponSystem_->addWeaponPack(wPack))
443                wPack->destroy();
[7163]444            else
445                this->addedWeaponPack(wPack);
446        }
[6417]447    }
448
[3053]449    WeaponPack * Pawn::getWeaponPack(unsigned int index) const
[2662]450    {
451        if (this->weaponSystem_)
[3053]452            return this->weaponSystem_->getWeaponPack(index);
[2662]453        else
454            return 0;
455    }
456
[3089]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    }
[8891]464
465    void Pawn::changedActivity(void)
466    {
467        SUPER(Pawn, changedActivity);
468
[9016]469        this->setRadarVisibility(this->isVisible());
[8891]470    }
471
472    void Pawn::changedVisibility(void)
473    {
474        SUPER(Pawn, changedVisibility);
475        //this->setVisible(this->isVisible());
476        this->setRadarVisibility(this->isVisible());
477    }
478
[2072]479}
Note: See TracBrowser for help on using the repository browser.