Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/orxonox/worldentities/pawns/Pawn.cc @ 7212

Last change on this file since 7212 was 7162, checked in by dafrick, 15 years ago

Significant structural changes to the pickup module. Lots of bugs found and fixed.
Introduced a new class CollectiblePickup (which is now the only kind a PickupCollection can consist of) to solve some issues cleanly.
MetaPickup received additional functionality. It can now also be set to either destroy all the pickups of a PickupCarrier or destroy the PickupCarrier itself. (This was done mainly for testing purposes)
I've done some extensive testing on the pickups, so they should really work now.

  • Property svn:eol-style set to native
File size: 12.4 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
71        this->lastHitOriginator_ = 0;
72
73        this->spawnparticleduration_ = 3.0f;
74
75        this->aimPosition_ = Vector3::ZERO;
76
77        if (GameMode::isMaster())
78        {
79            this->weaponSystem_ = new WeaponSystem(this);
80            this->weaponSystem_->setPawn(this);
81        }
82        else
83            this->weaponSystem_ = 0;
84
85        this->setRadarObjectColour(ColourValue::Red);
86        this->setRadarObjectShape(RadarViewable::Dot);
87
88        this->registerVariables();
89
90        this->isHumanShip_ = this->hasLocalController();
91    }
92
93    Pawn::~Pawn()
94    {
95        if (this->isInitialized())
96        {
97            if (this->weaponSystem_)
98                this->weaponSystem_->destroy();
99        }
100    }
101
102    void Pawn::XMLPort(Element& xmlelement, XMLPort::Mode mode)
103    {
104        SUPER(Pawn, XMLPort, xmlelement, mode);
105
106        XMLPortParam(Pawn, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
107        XMLPortParam(Pawn, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
108        XMLPortParam(Pawn, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
109
110        XMLPortParam(Pawn, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode).defaultValues(0);
111        XMLPortParam(Pawn, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode).defaultValues(0);
112
113        XMLPortParam(Pawn, "spawnparticlesource", setSpawnParticleSource, getSpawnParticleSource, xmlelement, mode);
114        XMLPortParam(Pawn, "spawnparticleduration", setSpawnParticleDuration, getSpawnParticleDuration, xmlelement, mode).defaultValues(3.0f);
115        XMLPortParam(Pawn, "explosionchunks", setExplosionChunks, getExplosionChunks, xmlelement, mode).defaultValues(7);
116
117        XMLPortObject(Pawn, WeaponSlot, "weaponslots", addWeaponSlot, getWeaponSlot, xmlelement, mode);
118        XMLPortObject(Pawn, WeaponSet, "weaponsets", addWeaponSet, getWeaponSet, xmlelement, mode);
119        XMLPortObject(Pawn, WeaponPack, "weapons", addWeaponPackXML, getWeaponPack, xmlelement, mode);
120    }
121
122    void Pawn::registerVariables()
123    {
124        registerVariable(this->bAlive_,           VariableDirection::ToClient);
125        registerVariable(this->health_,           VariableDirection::ToClient);
126        registerVariable(this->initialHealth_,    VariableDirection::ToClient);
127        registerVariable(this->shieldHealth_,     VariableDirection::ToClient);
128        registerVariable(this->shieldAbsorption_, VariableDirection::ToClient);
129        registerVariable(this->bReload_,          VariableDirection::ToServer);
130        registerVariable(this->aimPosition_,      VariableDirection::ToServer);  // For the moment this variable gets only transfered to the server
131    }
132
133    void Pawn::tick(float dt)
134    {
135        SUPER(Pawn, tick, dt);
136
137        this->bReload_ = false;
138
139        if (GameMode::isMaster())
140            if (this->health_ <= 0 && bAlive_)
141            {
142                this->fireEvent(); // Event to notify anyone who want's to know about the death.
143                this->death();
144            }
145    }
146
147    void Pawn::setPlayer(PlayerInfo* player)
148    {
149        ControllableEntity::setPlayer(player);
150
151        if (this->getGametype())
152            this->getGametype()->playerStartsControllingPawn(player, this);
153    }
154
155    void Pawn::removePlayer()
156    {
157        if (this->getGametype())
158            this->getGametype()->playerStopsControllingPawn(this->getPlayer(), this);
159
160        ControllableEntity::removePlayer();
161    }
162
163    void Pawn::setHealth(float health)
164    {
165        this->health_ = std::min(health, this->maxHealth_);
166    }
167
168    void Pawn::damage(float damage, Pawn* originator)
169    {
170        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
171        {
172            //share the dealt damage to the shield and the Pawn.
173            float shielddamage = damage*this->shieldAbsorption_;
174            float healthdamage = damage*(1-this->shieldAbsorption_);
175
176            // In case the shield can not take all the shield damage.
177            if (shielddamage > this->getShieldHealth())
178            {
179                healthdamage += shielddamage-this->getShieldHealth();
180                this->setShieldHealth(0);
181            }
182
183            this->setHealth(this->health_ - healthdamage);
184
185            if (this->getShieldHealth() > 0)
186            {
187                this->setShieldHealth(this->shieldHealth_ - shielddamage);
188            }
189
190            this->lastHitOriginator_ = originator;
191
192            // play damage effect
193        }
194    }
195
196    void Pawn::hit(Pawn* originator, const Vector3& force, float damage)
197    {
198        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
199        {
200            this->damage(damage, originator);
201            this->setVelocity(this->getVelocity() + force);
202
203            // play hit effect
204        }
205    }
206
207    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
208    {
209        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
210        {
211            this->damage(damage, originator);
212
213            if ( this->getController() )
214                this->getController()->hit(originator, contactpoint, damage);
215
216            // play hit effect
217        }
218    }
219
220    void Pawn::kill()
221    {
222        this->damage(this->health_);
223        this->death();
224    }
225
226    void Pawn::spawneffect()
227    {
228        // play spawn effect
229        if (!this->spawnparticlesource_.empty())
230        {
231            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
232            effect->setPosition(this->getPosition());
233            effect->setOrientation(this->getOrientation());
234            effect->setDestroyAfterLife(true);
235            effect->setSource(this->spawnparticlesource_);
236            effect->setLifetime(this->spawnparticleduration_);
237        }
238    }
239
240    void Pawn::death()
241    {
242        this->setHealth(1);
243        if (this->getGametype() && this->getGametype()->allowPawnDeath(this, this->lastHitOriginator_))
244        {
245            // Set bAlive_ to false and wait for PawnManager to do the destruction
246            this->bAlive_ = false;
247
248            this->setDestroyWhenPlayerLeft(false);
249
250            this->dropItems();
251
252            if (this->getGametype())
253                this->getGametype()->pawnKilled(this, this->lastHitOriginator_);
254
255            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
256                this->getPlayer()->stopControl();
257
258            if (GameMode::isMaster())
259            {
260//                this->deathEffect();
261                this->goWithStyle();
262            }
263        }
264    }
265    void Pawn::goWithStyle()
266    {
267        this->bAlive_ = false;
268        this->setDestroyWhenPlayerLeft(false);
269
270        BigExplosion* chunk = new BigExplosion(this->getCreator());
271        chunk->setPosition(this->getPosition());
272
273    }
274    void Pawn::deatheffect()
275    {
276        // play death effect
277        {
278            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
279            effect->setPosition(this->getPosition());
280            effect->setOrientation(this->getOrientation());
281            effect->setDestroyAfterLife(true);
282            effect->setSource("Orxonox/explosion2b");
283            effect->setLifetime(4.0f);
284        }
285        {
286            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
287            effect->setPosition(this->getPosition());
288            effect->setOrientation(this->getOrientation());
289            effect->setDestroyAfterLife(true);
290            effect->setSource("Orxonox/smoke6");
291            effect->setLifetime(4.0f);
292        }
293        {
294            ParticleSpawner* effect = new ParticleSpawner(this->getCreator());
295            effect->setPosition(this->getPosition());
296            effect->setOrientation(this->getOrientation());
297            effect->setDestroyAfterLife(true);
298            effect->setSource("Orxonox/sparks");
299            effect->setLifetime(4.0f);
300        }
301        for (unsigned int i = 0; i < this->numexplosionchunks_; ++i)
302        {
303            ExplosionChunk* chunk = new ExplosionChunk(this->getCreator());
304            chunk->setPosition(this->getPosition());
305        }
306    }
307
308    void Pawn::fired(unsigned int firemode)
309    {
310        if (this->weaponSystem_)
311            this->weaponSystem_->fire(firemode);
312    }
313
314    void Pawn::reload()
315    {
316        this->bReload_ = true;
317    }
318
319    void Pawn::postSpawn()
320    {
321        this->setHealth(this->initialHealth_);
322        if (GameMode::isMaster())
323            this->spawneffect();
324    }
325
326    /* WeaponSystem:
327    *   functions load Slot, Set, Pack from XML and make sure all parent-pointers are set.
328    *   with setWeaponPack you can not just load a Pack from XML but if a Pack already exists anywhere, you can attach it.
329    *       --> e.g. Pickup-Items
330    */
331    void Pawn::addWeaponSlot(WeaponSlot * wSlot)
332    {
333        this->attach(wSlot);
334        if (this->weaponSystem_)
335            this->weaponSystem_->addWeaponSlot(wSlot);
336    }
337
338    WeaponSlot * Pawn::getWeaponSlot(unsigned int index) const
339    {
340        if (this->weaponSystem_)
341            return this->weaponSystem_->getWeaponSlot(index);
342        else
343            return 0;
344    }
345
346    void Pawn::addWeaponSet(WeaponSet * wSet)
347    {
348        if (this->weaponSystem_)
349            this->weaponSystem_->addWeaponSet(wSet);
350    }
351
352    WeaponSet * Pawn::getWeaponSet(unsigned int index) const
353    {
354        if (this->weaponSystem_)
355            return this->weaponSystem_->getWeaponSet(index);
356        else
357            return 0;
358    }
359
360    void Pawn::addWeaponPack(WeaponPack * wPack)
361    {
362        if (this->weaponSystem_)
363        {
364            this->weaponSystem_->addWeaponPack(wPack);
365            this->addedWeaponPack(wPack);
366        }
367    }
368
369    void Pawn::addWeaponPackXML(WeaponPack * wPack)
370    {
371        if (this->weaponSystem_)
372        {
373            if (!this->weaponSystem_->addWeaponPack(wPack))
374                wPack->destroy();
375            else
376                this->addedWeaponPack(wPack);
377        }
378    }
379
380    WeaponPack * Pawn::getWeaponPack(unsigned int index) const
381    {
382        if (this->weaponSystem_)
383            return this->weaponSystem_->getWeaponPack(index);
384        else
385            return 0;
386    }
387
388    //Tell the Map (RadarViewable), if this is a playership
389    void Pawn::startLocalHumanControl()
390    {
391//        SUPER(ControllableEntity, changedPlayer());
392        ControllableEntity::startLocalHumanControl();
393        this->isHumanShip_ = true;
394    }
395}
Note: See TracBrowser for help on using the repository browser.