Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Removed all segfaults (or at least those we found…)

File size: 12.3 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::killShipPartStatic);
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                }
111            }
112        }
113    }
114
115    void ModularSpaceShip::attach(WorldEntity* object)
116    {
117        SpaceShip::attach(object);
118        this->updatePartAssignment();
119    }
120
121    /**
122    @brief
123        Creates a new assignment for the given StaticEntity and ShipPart in the partMap_
124    @param entity
125        A pointer to the StaticEntity
126    @param part
127        A pointer to the ShipPart.
128    */
129    void ModularSpaceShip::addPartEntityAssignment(StaticEntity* entity, ShipPart* part)
130    {
131        if (!entity || !part)
132            return;
133
134        if (this->partMap_.find(entity) != this->partMap_.end())
135                {
136                    orxout(internal_warning) << "Assigning an Entity to multiple parts is not yet supported." << endl;
137                    return;
138                }
139
140        this->partMap_[entity] = part;
141    }
142
143
144    /**
145    @brief
146        Get the ShipPart an attached entity belongs to.
147    @param entity
148        The entity to be searched.
149    @return
150        Returns a pointer to the ShipPart the entity belongs to.
151    */
152    ShipPart* ModularSpaceShip::getPartOfEntity(StaticEntity* entity) const
153    {
154        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = this->partMap_.begin(); it != this->partMap_.end(); ++it)
155        {
156            if (it->first == entity)
157                return it->second;
158        }
159        return NULL;
160    }
161
162    /**
163    @brief
164        If the damage occurred on an attached StaticEntity, the damage is given to the corresponding ShipPart to handle.
165    */
166    void ModularSpaceShip::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
167    {
168        if (this->getPartOfEntity((StaticEntity*)(cs->getUserPointer())) != NULL)
169            this->getPartOfEntity((StaticEntity*)(cs->getUserPointer()))->handleHit(damage, healthdamage, shielddamage, originator);
170        else
171            SpaceShip::damage(damage, healthdamage, shielddamage, originator, cs);
172    }
173
174    /**
175    @brief
176        STATIC: Needed for consolecommand. Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
177    @param name
178        The name of the part to be killed.
179    */
180    void ModularSpaceShip::killShipPartStatic(std::string name)
181    {
182        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = ModularSpaceShip::partMap_s->begin(); it != ModularSpaceShip::partMap_s->end(); ++it)
183        {
184            if (it->second->getName() == name)
185            {
186                it->second->setAlive(false);
187                return;
188            }
189        }
190        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
191    }
192
193    /**
194    @brief
195        Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
196    @param name
197        The name of the part to be killed.
198    */
199    void ModularSpaceShip::killShipPart(std::string name)
200    {
201        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = ModularSpaceShip::partMap_.begin(); it != ModularSpaceShip::partMap_.end(); ++it)
202        {
203            if (it->second->getName() == name)
204            {
205                it->second->setAlive(false);
206                return;
207            }
208        }
209        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
210    }
211
212    /**
213    @brief
214        Add a ShipPart to the SpaceShip.
215    @param engine
216        A pointer to the ShipPart to be added.
217    */
218    void ModularSpaceShip::addShipPart(ShipPart* part)
219    {
220        OrxAssert(part != NULL, "The ShipPart cannot be NULL.");
221        this->partList_.push_back(part);
222        part->setParent(this);
223        this->updatePartAssignment();
224    }
225
226    /**
227    @brief
228        Get the i-th ShipPart of the SpaceShip.
229    @return
230        Returns a pointer to the i-the ShipPart. NULL if there is no ShipPart with that index.
231    */
232    ShipPart* ModularSpaceShip::getShipPart(unsigned int index)
233    {
234        if(this->partList_.size() <= index)
235            return NULL;
236        else
237            return this->partList_[index];
238    }
239
240    /**
241    @brief
242        Looks for an attached ShipPart with a certain name.
243    @param name
244        The name of the ShipPart to be returned.
245    @return
246        Pointer to the ShipPart with the given name, or NULL if not found.
247    */
248    ShipPart* ModularSpaceShip::getShipPartByName(std::string name)
249    {
250        for(std::vector<ShipPart*>::iterator it = this->partList_.begin(); it != this->partList_.end(); ++it)
251        {
252            if(orxonox_cast<ShipPart*>(*it)->getName() == name)
253            {
254                return orxonox_cast<ShipPart*>(*it);
255            }
256        }
257        orxout(internal_warning) << "Couldn't find ShipPart with name \"" << name << "\"." << endl;
258        return NULL;
259    }
260
261    /**
262    @brief
263        Check whether the SpaceShip has a particular Engine.
264    @param engine
265        A pointer to the Engine to be checked.
266    */
267    bool ModularSpaceShip::hasShipPart(ShipPart* part) const
268    {
269        for(unsigned int i = 0; i < this->partList_.size(); i++)
270        {
271            if(this->partList_[i] == part)
272                return true;
273        }
274        return false;
275    }
276
277
278    /**
279    @brief
280        Removes a ShipPart from the SpaceShip, destroying the corresponding StaticEntity
281    @param part
282        The ShipPart to be removed.
283    */
284    void ModularSpaceShip::removeShipPart(ShipPart* part)
285    {
286        // Remove the part from the partList_
287        std::vector<ShipPart*>::iterator it = this->partList_.begin();
288        for(unsigned int i = 0; i < this->partList_.size(); i++)
289        {
290            if(this->partList_[i] == part)
291            {
292                this->partList_.erase(it);
293                break;
294            }
295            it++;
296        }
297        // Remove the part-entity assignment and detach the Entity of this ShipPart
298        for (std::map<StaticEntity*, ShipPart*>::iterator itt = this->partMap_.begin(); itt != this->partMap_.end(); )
299        {
300            if (itt->second == part)
301            {
302                this->detach(itt->first);
303                itt->first->destroy();
304                //itt->first->setActive(false);
305                //itt->first->setVisible(false);
306                //itt->first->setCollisionResponse(false);
307                //itt->first->setCollisionType(None);
308                //itt->first->deactivatePhysics();
309                this->partMap_.erase(itt++);
310            } else {
311                ++itt;
312            }
313        }
314    }
315
316    /**
317    @brief
318        Looks for an attached Engine with a certain name.
319    @param name
320        The name of the engine to be returned.
321    @return
322        Pointer to the engine with the given name, or NULL if not found.
323    */
324    Engine* ModularSpaceShip::getEngineByName(std::string name)
325    {
326        for(std::vector<Engine*>::iterator it = this->engineList_.begin(); it != this->engineList_.end(); ++it)
327        {
328            if(orxonox_cast<Engine*>(*it)->getName() == name)
329            {
330                return orxonox_cast<Engine*>(*it);
331            }
332        }
333        orxout(internal_warning) << "Couldn't find Engine with name \"" << name << "\"." << endl;
334        return NULL;
335    }
336
337    /**
338    @brief
339        Detaches a child WorldEntity from this instance.
340    */
341    void ModularSpaceShip::detach(WorldEntity* object)
342    {
343        std::set<WorldEntity*>::iterator it = this->children_.find(object);
344        if (it == this->children_.end())
345        {
346            orxout(internal_warning) << "Cannot detach an object that is not a child." << endl;
347            return;
348        }
349
350        // collision shapes
351
352        //this->printBtChildShapes((btCompoundShape*)(this->getWorldEntityCollisionShape()->getCollisionShape()), 2, 0);
353        this->detachCollisionShape(object->collisionShape_);  // after succeeding, causes a crash in the collision handling
354        //this->printBtChildShapes((btCompoundShape*)(this->getWorldEntityCollisionShape()->getCollisionShape()), 2, 0);
355
356        // mass
357        if (object->getMass() > 0.0f)
358        {
359            this->childrenMass_ -= object->getMass();
360            recalculateMassProps();
361        }
362
363        this->detachNode(object->node_);
364        this->children_.erase(it);        // this causes a crash when unloading the level. Or not?
365
366        object->notifyDetached();
367    }
368}
Note: See TracBrowser for help on using the repository browser.