Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gameimmersion/src/orxonox/worldentities/pawns/Pawn.cc @ 8492

Last change on this file since 8492 was 8492, checked in by simonmie, 13 years ago

New Shield effect added (from tibork), first working BasicProjectile class, changes in weapon classes to fit new BasicProjectile system, some spam messages in Pawn.cc removed

  • Property svn:eol-style set to native
File size: 17.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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
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 "PawnManager.h"
39#include "infos/PlayerInfo.h"
40#include "controllers/Controller.h"
41#include "gametypes/Gametype.h"
42#include "graphics/ParticleSpawner.h"
43#include "worldentities/ExplosionChunk.h"
44#include "worldentities/BigExplosion.h"
45#include "weaponsystem/WeaponSystem.h"
46#include "weaponsystem/WeaponSlot.h"
47#include "weaponsystem/WeaponPack.h"
48#include "weaponsystem/WeaponSet.h"
49
50
51namespace orxonox
52{
53    CreateFactory(Pawn);
54
55    Pawn::Pawn(BaseObject* creator)
56        : ControllableEntity(creator)
57        , RadarViewable(creator, static_cast<WorldEntity*>(this))
58    {
59        RegisterObject(Pawn);
60
61        PawnManager::touch();
62        this->bAlive_ = true;
63        this->bReload_ = false;
64
65        this->health_ = 0;
66        this->maxHealth_ = 0;
67        this->initialHealth_ = 0;
68        this->shieldHealth_ = 0;
69        this->shieldAbsorption_ = 0.5;
70////////////////////////me
71        this->reloadRate_ = 0;
72        this->reloadWaitTime_ = 1.0f;
73        this->reloadWaitCountdown_ = 0;
74
75        this->maxShieldHealth_ = 0;
76////////////////////////end me
77
78        this->lastHitOriginator_ = 0;
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
100    Pawn::~Pawn()
101    {
102        if (this->isInitialized())
103        {
104            if (this->weaponSystem_)
105                this->weaponSystem_->destroy();
106        }
107    }
108
109    void Pawn::XMLPort(Element& xmlelement, XMLPort::Mode mode)
110    {
111        SUPER(Pawn, XMLPort, xmlelement, mode);
112
113        XMLPortParam(Pawn, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
114        XMLPortParam(Pawn, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
115        XMLPortParam(Pawn, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
116
117        XMLPortParam(Pawn, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode).defaultValues(0);
118        XMLPortParam(Pawn, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode).defaultValues(0);
119
120        XMLPortParam(Pawn, "spawnparticlesource", setSpawnParticleSource, getSpawnParticleSource, xmlelement, mode);
121        XMLPortParam(Pawn, "spawnparticleduration", setSpawnParticleDuration, getSpawnParticleDuration, xmlelement, mode).defaultValues(3.0f);
122        XMLPortParam(Pawn, "explosionchunks", setExplosionChunks, getExplosionChunks, xmlelement, mode).defaultValues(7);
123
124        XMLPortObject(Pawn, WeaponSlot, "weaponslots", addWeaponSlot, getWeaponSlot, xmlelement, mode);
125        XMLPortObject(Pawn, WeaponSet, "weaponsets", addWeaponSet, getWeaponSet, xmlelement, mode);
126        XMLPortObject(Pawn, WeaponPack, "weapons", addWeaponPackXML, getWeaponPack, xmlelement, mode);
127
128/////// me
129        XMLPortParam(Pawn, "reloadrate", setReloadRate, getReloadRate, xmlelement, mode).defaultValues(0);
130        XMLPortParam(Pawn, "reloadwaittime", setReloadWaitTime, getReloadWaitTime, xmlelement, mode).defaultValues(1.0f);
131
132        XMLPortParam(Pawn, "maxshieldhealth", setMaxShieldHealth, getMaxShieldHealth, xmlelement, mode).defaultValues(100);
133        XMLPortParam(Pawn, "initialshieldhealth", setInitialShieldHealth, getInitialShieldHealth, xmlelement, mode).defaultValues(0);
134
135/////// end me
136        //TODO: DEFINES fuer defaultwerte (hier und weiter oben dieselben)
137    }
138
139    void Pawn::registerVariables()
140    {
141        registerVariable(this->bAlive_,           VariableDirection::ToClient);
142        registerVariable(this->health_,           VariableDirection::ToClient);
143        registerVariable(this->initialHealth_,    VariableDirection::ToClient);
144        registerVariable(this->shieldHealth_,     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////////me
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////////end me
168        if (GameMode::isMaster())
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    void Pawn::preDestroy()
177    {
178        // yay, multiple inheritance!
179        this->ControllableEntity::preDestroy();
180        this->PickupCarrier::preDestroy();
181    }
182
183    void Pawn::setPlayer(PlayerInfo* player)
184    {
185        ControllableEntity::setPlayer(player);
186
187        if (this->getGametype())
188            this->getGametype()->playerStartsControllingPawn(player, this);
189    }
190
191    void Pawn::removePlayer()
192    {
193        if (this->getGametype())
194            this->getGametype()->playerStopsControllingPawn(this->getPlayer(), this);
195
196        ControllableEntity::removePlayer();
197    }
198
199//////////////////me
200    void Pawn::setReloadRate(float reloadrate)
201    {
202        this->reloadRate_ = reloadrate;
203        //COUT(2) << "RELOAD RATE SET TO " << this->reloadRate_ << endl;
204    }
205
206    void Pawn::setReloadWaitTime(float reloadwaittime)
207    {
208        this->reloadWaitTime_ = reloadwaittime;
209        //COUT(2) << "RELOAD WAIT TIME SET TO " << this->reloadWaitTime_ << endl;
210    }
211
212    void Pawn::decreaseReloadCountdownTime(float dt)
213    {
214        this->reloadWaitCountdown_ -= dt;
215    }
216
217    void Pawn::setMaxShieldHealth(float maxshieldhealth)
218    {
219        this->maxShieldHealth_ = maxshieldhealth;
220    }
221
222    void Pawn::setShieldHealth(float shieldHealth)
223    {
224        this->shieldHealth_ = std::min(shieldHealth, this->maxShieldHealth_);
225    }
226
227///////////////end me
228
229    void Pawn::setHealth(float health)
230    {
231        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
232    }
233
234//////////////////me edit
235    void Pawn::damage(float damage, Pawn* originator)
236    {
237        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
238        {
239            //share the dealt damage to the shield and the Pawn.
240            float shielddamage = damage*this->shieldAbsorption_;
241            float healthdamage = damage*(1-this->shieldAbsorption_);
242
243            // In case the shield can not take all the shield damage.
244            if (shielddamage > this->getShieldHealth())
245            {
246                healthdamage += shielddamage-this->getShieldHealth();
247                this->setShieldHealth(0);
248                COUT(3) << "### SHIELD KAPUTT ###" << endl;
249            }
250
251            else { COUT(3) << "## SHIELD : " << this->getShieldHealth() << endl; }
252
253            this->setHealth(this->health_ - healthdamage);
254
255            if (this->getShieldHealth() > 0)
256            {
257                this->setShieldHealth(this->shieldHealth_ - shielddamage);
258            }
259
260            this->lastHitOriginator_ = originator;
261
262            // play damage effect
263        }
264    }
265////////////////////end edit
266
267
268/////////////////////me override
269    void Pawn::damage(float damage, float healthdamage, float shielddamage, Pawn* originator)
270    {
271        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
272        {
273            if (shielddamage >= this->getShieldHealth())
274            {
275                this->setShieldHealth(0);
276                this->setHealth(this->health_ - (healthdamage + damage));
277            }
278            else
279            {
280                this->setShieldHealth(this->shieldHealth_ - shielddamage);
281
282                // remove remaining shieldAbsorpton-Part of damage from shield
283                shielddamage = damage * this->shieldAbsorption_;
284                shielddamage = std::min(this->getShieldHealth(),shielddamage);
285                this->setShieldHealth(this->shieldHealth_ - shielddamage);
286
287                // set remaining damage to health
288                this->setHealth(this->health_ - (damage - shielddamage) - healthdamage);
289            }
290
291            this->lastHitOriginator_ = originator;
292
293            // play damage effect
294        }
295        //COUT(3) << "neue damage-Funktion wurde aufgerufen // " << "Shield:" << this->getShieldHealth() << endl;
296    }
297
298/////////////end me
299
300
301/* HIT-Funktionen
302        Die hit-Funktionen muessen auch in src/orxonox/controllers/Controller.h angepasst werden!
303
304*/
305
306
307    void Pawn::hit(Pawn* originator, const Vector3& force, float damage)
308    {
309        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
310        {
311            this->damage(damage, originator);
312            this->setVelocity(this->getVelocity() + force);
313
314            // play hit effect
315        }
316    }
317
318/////////////me override
319    void Pawn::hit(Pawn* originator, const Vector3& force, float damage, float healthdamage, float shielddamage)
320    {
321        COUT(3) << "neue hit-Funktion wurde aufgerufen // " << std::flush;
322        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
323        {
324            this->damage(damage, healthdamage, shielddamage, originator);
325            this->setVelocity(this->getVelocity() + force);
326
327            // play hit effect
328        }
329    }
330/////////////end me
331
332    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
333    {
334        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
335        {
336            this->damage(damage, originator);
337
338            if ( this->getController() )
339                this->getController()->hit(originator, contactpoint, damage);
340
341            // play hit effect
342        }
343    }
344
345/////////////me override
346    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage, float shielddamage)
347    {
348//        COUT(3) << "neue hit2-Funktion wurde aufgerufen // shielddamage: " << shielddamage << std::flush;
349        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
350        {
351            this->damage(damage, healthdamage, shielddamage, originator);
352
353            if ( this->getController() )
354                this->getController()->hit(originator, contactpoint, shielddamage);
355
356            // play hit effect
357        }
358    }
359/////////////end me
360
361    void Pawn::kill()
362    {
363        this->damage(this->health_);
364        this->death();
365    }
366
367    void Pawn::spawneffect()
368    {
369        // play spawn effect
370        if (!this->spawnparticlesource_.empty())
371        {
372            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
373            effect->setPosition(this->getPosition());
374            effect->setOrientation(this->getOrientation());
375            effect->setDestroyAfterLife(true);
376            effect->setSource(this->spawnparticlesource_);
377            effect->setLifetime(this->spawnparticleduration_);
378        }
379    }
380
381    void Pawn::death()
382    {
383        this->setHealth(1);
384        if (this->getGametype() && this->getGametype()->allowPawnDeath(this, this->lastHitOriginator_))
385        {
386            // Set bAlive_ to false and wait for PawnManager to do the destruction
387            this->bAlive_ = false;
388
389            this->setDestroyWhenPlayerLeft(false);
390
391            if (this->getGametype())
392                this->getGametype()->pawnKilled(this, this->lastHitOriginator_);
393
394            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
395                this->getPlayer()->stopControl();
396
397            if (GameMode::isMaster())
398            {
399//                this->deathEffect();
400                this->goWithStyle();
401            }
402        }
403    }
404    void Pawn::goWithStyle()
405    {
406        this->bAlive_ = false;
407        this->setDestroyWhenPlayerLeft(false);
408
409        BigExplosion* chunk = new BigExplosion(this->getCreator());
410        chunk->setPosition(this->getPosition());
411
412    }
413    void Pawn::deatheffect()
414    {
415        // play death effect
416        {
417            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
418            effect->setPosition(this->getPosition());
419            effect->setOrientation(this->getOrientation());
420            effect->setDestroyAfterLife(true);
421            effect->setSource("Orxonox/explosion2b");
422            effect->setLifetime(4.0f);
423        }
424        {
425            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
426            effect->setPosition(this->getPosition());
427            effect->setOrientation(this->getOrientation());
428            effect->setDestroyAfterLife(true);
429            effect->setSource("Orxonox/smoke6");
430            effect->setLifetime(4.0f);
431        }
432        {
433            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
434            effect->setPosition(this->getPosition());
435            effect->setOrientation(this->getOrientation());
436            effect->setDestroyAfterLife(true);
437            effect->setSource("Orxonox/sparks");
438            effect->setLifetime(4.0f);
439        }
440        for (unsigned int i = 0; i < this->numexplosionchunks_; ++i)
441        {
442            ExplosionChunk* chunk = new ExplosionChunk(this->getCreator());
443            chunk->setPosition(this->getPosition());
444        }
445    }
446
447    void Pawn::fired(unsigned int firemode)
448    {
449        if (this->weaponSystem_)
450            this->weaponSystem_->fire(firemode);
451    }
452
453    void Pawn::reload()
454    {
455        this->bReload_ = true;
456    }
457
458    void Pawn::postSpawn()
459    {
460        this->setHealth(this->initialHealth_);
461        if (GameMode::isMaster())
462            this->spawneffect();
463    }
464
465    /* WeaponSystem:
466    *   functions load Slot, Set, Pack from XML and make sure all parent-pointers are set.
467    *   with setWeaponPack you can not just load a Pack from XML but if a Pack already exists anywhere, you can attach it.
468    *       --> e.g. Pickup-Items
469    */
470    void Pawn::addWeaponSlot(WeaponSlot * wSlot)
471    {
472        this->attach(wSlot);
473        if (this->weaponSystem_)
474            this->weaponSystem_->addWeaponSlot(wSlot);
475    }
476
477    WeaponSlot * Pawn::getWeaponSlot(unsigned int index) const
478    {
479        if (this->weaponSystem_)
480            return this->weaponSystem_->getWeaponSlot(index);
481        else
482            return 0;
483    }
484
485    void Pawn::addWeaponSet(WeaponSet * wSet)
486    {
487        if (this->weaponSystem_)
488            this->weaponSystem_->addWeaponSet(wSet);
489    }
490
491    WeaponSet * Pawn::getWeaponSet(unsigned int index) const
492    {
493        if (this->weaponSystem_)
494            return this->weaponSystem_->getWeaponSet(index);
495        else
496            return 0;
497    }
498
499    void Pawn::addWeaponPack(WeaponPack * wPack)
500    {
501        if (this->weaponSystem_)
502        {
503            this->weaponSystem_->addWeaponPack(wPack);
504            this->addedWeaponPack(wPack);
505        }
506    }
507
508    void Pawn::addWeaponPackXML(WeaponPack * wPack)
509    {
510        if (this->weaponSystem_)
511        {
512            if (!this->weaponSystem_->addWeaponPack(wPack))
513                wPack->destroy();
514            else
515                this->addedWeaponPack(wPack);
516        }
517    }
518
519    WeaponPack * Pawn::getWeaponPack(unsigned int index) const
520    {
521        if (this->weaponSystem_)
522            return this->weaponSystem_->getWeaponPack(index);
523        else
524            return 0;
525    }
526
527    //Tell the Map (RadarViewable), if this is a playership
528    void Pawn::startLocalHumanControl()
529    {
530//        SUPER(ControllableEntity, changedPlayer());
531        ControllableEntity::startLocalHumanControl();
532        this->isHumanShip_ = true;
533    }
534}
Note: See TracBrowser for help on using the repository browser.