Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/modularships/src/orxonox/worldentities/pawns/ModularSpaceShip.cc @ 10058

Last change on this file since 10058 was 10058, checked in by noep, 10 years ago

Expanded functionality of PartDestructionEvents, fixed cursor not showing when flying a ModularSpaceShip

File size: 12.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 *      Noe Pedrazzini
26 *
27 */
28
29#include "ModularSpaceShip.h"
30
31#include <BulletDynamics/Dynamics/btRigidBody.h>
32
33#include "core/CoreIncludes.h"
34#include "core/config/ConfigValueIncludes.h"
35#include "core/Template.h"
36#include "core/XMLPort.h"
37#include "util/Math.h"
38#include "gametypes/Gametype.h"
39#include "core/command/ConsoleCommand.h"
40
41#include "items/ShipPart.h"
42#include "items/Engine.h"
43#include "worldentities/StaticEntity.h"
44#include "collisionshapes/WorldEntityCollisionShape.h"
45#include <BulletCollision/CollisionShapes/btCollisionShape.h>
46#include <BulletCollision/CollisionShapes/btCompoundShape.h>
47
48
49
50namespace orxonox
51{
52    SetConsoleCommand("ModularSpaceShip", "killshippart", &ModularSpaceShip::killShipPart);
53
54    RegisterClass(ModularSpaceShip);
55
56    std::map<StaticEntity*, ShipPart*>* ModularSpaceShip::partMap_s = 0;
57
58    ModularSpaceShip::ModularSpaceShip(Context* context) : SpaceShip(context)
59    {
60        RegisterObject(ModularSpaceShip);
61
62        this->registerVariables();
63
64        ModularSpaceShip::partMap_s = &(this->partMap_);
65
66    }
67
68    ModularSpaceShip::~ModularSpaceShip()
69    {
70        if (this->isInitialized())
71        {
72
73        }
74    }
75
76    void ModularSpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
77    {
78        SUPER(ModularSpaceShip, XMLPort, xmlelement, mode);
79        XMLPortObject(ModularSpaceShip, ShipPart, "parts", addShipPart, getShipPart, xmlelement, mode);
80    }
81
82    void ModularSpaceShip::registerVariables()
83    {
84        return;
85    }
86
87    /**
88    @brief
89        Searches for ShipParts matching to StaticEntities.
90    */
91    void ModularSpaceShip::updatePartAssignment()
92    {
93        // iterate through all attached objects
94        for (unsigned int i=0; i < (unsigned int)(this->getNumAttachedObj()); i++)
95        {
96            if (this->getAttachedObject(i) == NULL)
97            {
98                break;
99            }
100            // iterate through all attached parts
101            for(unsigned int j = 0; j < this->partList_.size(); j++)
102            {
103                // if the name of the part matches the name of the object, add the object to that parts entitylist (unless it was already done).
104                if((this->partList_[j]->getName() == this->getAttachedObject(i)->getName()) && !this->partList_[j]->hasEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i))))
105                {
106                    // The Entity is added to the part's entityList_
107                    this->partList_[j]->addEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i)));
108                    // An entry in the partMap_ is created, assigning the part to the entity.
109                    this->addPartEntityAssignment((StaticEntity*)(this->getAttachedObject(i)), this->partList_[j]);
110                    orxout() << "A matching part-entity-pair with name " << this->partList_[j]->getName() << " was found!" << endl;
111                    this->partList_[j]->printEntities(); // FIXME: (noep) remove debug
112                }
113            }
114        }
115
116        orxout() << "List of all assignments:" << endl;
117        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = this->partMap_.begin(); it != this->partMap_.end(); ++it)
118                {
119                    orxout() << "Entity: " << it->first << "   Part: " << it->second << endl;
120                }
121    }
122
123    void ModularSpaceShip::attach(WorldEntity* object)
124    {
125        SpaceShip::attach(object);
126        this->updatePartAssignment();
127    }
128
129    /**
130    @brief
131        Creates a new assignment for the given StaticEntity and ShipPart in the partMap_
132    @param entity
133        A pointer to the StaticEntity
134    @param part
135        A pointer to the ShipPart.
136    */
137    void ModularSpaceShip::addPartEntityAssignment(StaticEntity* entity, ShipPart* part)
138    {
139        if (!entity || !part)
140            return;
141
142        if (this->partMap_.find(entity) != this->partMap_.end())
143                {
144                    orxout(internal_warning) << "Assigning an Entity to multiple parts is not yet supported." << endl;
145                    return;
146                }
147
148        this->partMap_[entity] = part;
149
150        orxout() << "New entity-part assignment created!" << endl;
151    }
152
153
154    /**
155    @brief
156        Get the ShipPart an attached entity belongs to.
157    @param entity
158        The entity to be searched.
159    @return
160        Returns a pointer to the ShipPart the entity belongs to.
161    */
162    ShipPart* ModularSpaceShip::getPartOfEntity(StaticEntity* entity) const
163    {
164        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = this->partMap_.begin(); it != this->partMap_.end(); ++it)
165        {
166            if (it->first == entity)
167                return it->second;
168        }
169        return NULL;
170    }
171
172    /**
173    @brief
174        If the damage occurred on an attached StaticEntity, the damage is given to the corresponding ShipPart to handle.
175    */
176    void ModularSpaceShip::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
177    {
178        if (this->getPartOfEntity((StaticEntity*)(cs->getUserPointer())) != NULL)
179            this->getPartOfEntity((StaticEntity*)(cs->getUserPointer()))->handleHit(damage, healthdamage, shielddamage, originator);
180        else
181            SpaceShip::damage(damage, healthdamage, shielddamage, originator, cs);
182    }
183
184    /**
185    @brief
186        Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
187    @param name
188        The name of the part to be killed.
189    */
190    void ModularSpaceShip::killShipPart(std::string name)
191    {
192        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = ModularSpaceShip::partMap_s->begin(); it != ModularSpaceShip::partMap_s->end(); ++it)
193        {
194            if (it->second->getName() == name)
195            {
196                it->second->death();
197                return;
198            }
199        }
200        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
201    }
202
203    /**
204    @brief
205        Add a ShipPart to the SpaceShip.
206    @param engine
207        A pointer to the ShipPart to be added.
208    */
209    void ModularSpaceShip::addShipPart(ShipPart* part)
210    {
211        OrxAssert(part != NULL, "The ShipPart cannot be NULL.");
212        this->partList_.push_back(part);
213        part->setParent(this);
214        this->updatePartAssignment();
215    }
216
217    /**
218    @brief
219        Get the i-th ShipPart of the SpaceShip.
220    @return
221        Returns a pointer to the i-the ShipPart. NULL if there is no ShipPart with that index.
222    */
223    ShipPart* ModularSpaceShip::getShipPart(unsigned int index)
224    {
225        if(this->partList_.size() <= index)
226            return NULL;
227        else
228            return this->partList_[index];
229    }
230
231    /**
232    @brief
233        Looks for an attached ShipPart with a certain name.
234    @param name
235        The name of the ShipPart to be returned.
236    @return
237        Pointer to the ShipPart with the given name, or NULL if not found.
238    */
239    ShipPart* ModularSpaceShip::getShipPartByName(std::string name)
240    {
241        for(std::vector<ShipPart*>::iterator it = this->partList_.begin(); it != this->partList_.end(); ++it)
242        {
243            if(orxonox_cast<ShipPart*>(*it)->getName() == name)
244            {
245                return orxonox_cast<ShipPart*>(*it);
246            }
247        }
248        orxout(internal_warning) << "Couldn't find ShipPart with name \"" << name << "\"." << endl;
249        return NULL;
250    }
251
252    /**
253    @brief
254        Check whether the SpaceShip has a particular Engine.
255    @param engine
256        A pointer to the Engine to be checked.
257    */
258    bool ModularSpaceShip::hasShipPart(ShipPart* part) const
259    {
260        for(unsigned int i = 0; i < this->partList_.size(); i++)
261        {
262            if(this->partList_[i] == part)
263                return true;
264        }
265        return false;
266    }
267
268
269    /**
270    @brief
271        Removes a ShipPart from the SpaceShip, destroying the corresponding StaticEntity
272    @param part
273        The ShipPart to be removed.
274    */
275    void ModularSpaceShip::removeShipPart(ShipPart* part)
276    {
277        // Remove the part from the partList_
278        std::vector<ShipPart*>::iterator it = this->partList_.begin();
279        for(unsigned int i = 0; i < this->partList_.size(); i++)
280        {
281            if(this->partList_[i] == part)
282            {
283                this->partList_.erase(it);
284                break;
285            }
286            it++;
287        }
288        // Remove the part-entity assignment and detach the Entity of this ShipPart
289        for (std::map<StaticEntity*, ShipPart*>::iterator itt = this->partMap_.begin(); itt != this->partMap_.end(); )
290        {
291            if (itt->second == part)
292            {
293                this->detach(itt->first);
294                itt->first->destroy();
295                //itt->first->setActive(false);
296                //itt->first->setVisible(false);
297                //itt->first->setCollisionResponse(false);
298                //itt->first->setCollisionType(None);
299                //itt->first->deactivatePhysics();
300                this->partMap_.erase(itt++);
301            } else {
302                ++itt;
303            }
304        }
305    }
306
307    /**
308    @brief
309        Looks for an attached Engine with a certain name.
310    @param name
311        The name of the engine to be returned.
312    @return
313        Pointer to the engine with the given name, or NULL if not found.
314    */
315    Engine* ModularSpaceShip::getEngineByName(std::string name)
316    {
317        for(std::vector<Engine*>::iterator it = this->engineList_.begin(); it != this->engineList_.end(); ++it)
318        {
319            if(orxonox_cast<Engine*>(*it)->getName() == name)
320            {
321                return orxonox_cast<Engine*>(*it);
322            }
323        }
324        orxout(internal_warning) << "Couldn't find Engine with name \"" << name << "\"." << endl;
325        return NULL;
326    }
327
328    /**
329    @brief
330        Detaches a child WorldEntity from this instance.
331    */
332    void ModularSpaceShip::detach(WorldEntity* object)
333    {
334        std::set<WorldEntity*>::iterator it = this->children_.find(object);
335        if (it == this->children_.end())
336        {
337            orxout(internal_warning) << "Cannot detach an object that is not a child." << endl;
338            return;
339        }
340
341        // collision shapes
342
343        //this->printBtChildShapes((btCompoundShape*)(this->getWorldEntityCollisionShape()->getCollisionShape()), 2, 0);
344        this->detachCollisionShape(object->collisionShape_);  // after succeeding, causes a crash in the collision handling
345        //this->printBtChildShapes((btCompoundShape*)(this->getWorldEntityCollisionShape()->getCollisionShape()), 2, 0);
346
347        // mass
348        if (object->getMass() > 0.0f)
349        {
350            this->childrenMass_ -= object->getMass();
351            recalculateMassProps();
352        }
353
354        this->detachNode(object->node_);
355        this->children_.erase(it);        // this causes a crash when unloading the level. Or not?
356
357        object->notifyDetached();
358    }
359}
Note: See TracBrowser for help on using the repository browser.