/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Fabian 'x3n' Landau * Co-authors: * Noe Pedrazzini * */ #include "ModularSpaceShip.h" #include #include "core/CoreIncludes.h" #include "core/config/ConfigValueIncludes.h" #include "core/Template.h" #include "core/XMLPort.h" #include "util/Math.h" #include "gametypes/Gametype.h" #include "core/command/ConsoleCommandIncludes.h" #include "items/ShipPart.h" #include "items/Engine.h" #include "worldentities/StaticEntity.h" #include #include namespace orxonox { SetConsoleCommand("ModularSpaceShip", "killshippart", &ModularSpaceShip::killShipPartStatic); RegisterClass(ModularSpaceShip); std::map* ModularSpaceShip::partMap_s = nullptr; ModularSpaceShip::ModularSpaceShip(Context* context) : SpaceShip(context) { RegisterObject(ModularSpaceShip); this->registerVariables(); ModularSpaceShip::partMap_s = &(this->partMap_); } ModularSpaceShip::~ModularSpaceShip() { if (this->isInitialized()) { while (!this->partList_.empty()) this->partList_[0]->destroy(); } } void ModularSpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(ModularSpaceShip, XMLPort, xmlelement, mode); XMLPortObject(ModularSpaceShip, ShipPart, "parts", addShipPart, getShipPart, xmlelement, mode); } void ModularSpaceShip::registerVariables() { return; } /** @brief Searches for ShipParts matching to StaticEntities. */ void ModularSpaceShip::updatePartAssignment() { // iterate through all attached objects for (unsigned int i=0; i < this->getAttachedObjects().size(); i++) { if (this->getAttachedObject(i) == nullptr) { break; } // iterate through all attached parts for(ShipPart* part : this->partList_) { // if the name of the part matches the name of the object, add the object to that parts entitylist (unless it was already done). if((part->getName() == this->getAttachedObject(i)->getName()) && !part->hasEntity(orxonox_cast(this->getAttachedObject(i)))) { // The Entity is added to the part's entityList_ part->addEntity(orxonox_cast(this->getAttachedObject(i))); // An entry in the partMap_ is created, assigning the part to the entity. this->addPartEntityAssignment((StaticEntity*)(this->getAttachedObject(i)), part); } } } } /** @brief Creates a new assignment for the given StaticEntity and ShipPart in the partMap_ @param entity A pointer to the StaticEntity @param part A pointer to the ShipPart. */ void ModularSpaceShip::addPartEntityAssignment(StaticEntity* entity, ShipPart* part) { if (!entity || !part) return; if (this->partMap_.find(entity) != this->partMap_.end()) { orxout(internal_warning) << "Assigning an Entity to multiple parts is not yet supported." << endl; return; } this->partMap_[entity] = part; } /** @brief Get the ShipPart an attached entity belongs to. @param entity The entity to be searched. @return Returns a pointer to the ShipPart the entity belongs to. */ ShipPart* ModularSpaceShip::getPartOfEntity(StaticEntity* entity) const { for (const auto& mapEntry : this->partMap_) { if (mapEntry.first == entity) return mapEntry.second; } return nullptr; } /** @brief If the damage occurred on an attached StaticEntity, the damage is given to the corresponding ShipPart to handle. */ void ModularSpaceShip::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs) { if (cs != nullptr && this->getPartOfEntity((StaticEntity*)(cs->getUserPointer())) != nullptr) this->getPartOfEntity((StaticEntity*)(cs->getUserPointer()))->handleHit(damage, healthdamage, shielddamage, originator); else SpaceShip::damage(damage, healthdamage, shielddamage, originator, cs); } /** @brief STATIC: Needed for consolecommand. Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]". @param name The name of the part to be killed. */ void ModularSpaceShip::killShipPartStatic(std::string name) { for (const auto& mapEntry : *ModularSpaceShip::partMap_s) { if (mapEntry.second->getName() == name) { mapEntry.second->death(); return; } } orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl; } /** @brief Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]". @param name The name of the part to be killed. */ void ModularSpaceShip::killShipPart(std::string name) { for (const auto& mapEntry : ModularSpaceShip::partMap_) { if (mapEntry.second->getName() == name) { mapEntry.second->death(); return; } } orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl; } /** @brief Add a ShipPart to the SpaceShip. @param engine A pointer to the ShipPart to be added. */ void ModularSpaceShip::addShipPart(ShipPart* part) { OrxAssert(part != nullptr, "The ShipPart cannot be nullptr."); this->partList_.push_back(part); part->setParent(this); this->updatePartAssignment(); } /** @brief Get the i-th ShipPart of the SpaceShip. @return Returns a pointer to the i-the ShipPart. nullptr if there is no ShipPart with that index. */ ShipPart* ModularSpaceShip::getShipPart(unsigned int index) { if(this->partList_.size() <= index) return nullptr; else return this->partList_[index]; } /** @brief Looks for an attached ShipPart with a certain name. @param name The name of the ShipPart to be returned. @return Pointer to the ShipPart with the given name, or nullptr if not found. */ ShipPart* ModularSpaceShip::getShipPartByName(std::string name) { for(ShipPart* part : this->partList_) { if(orxonox_cast(part)->getName() == name) { return orxonox_cast(part); } } orxout(internal_warning) << "Couldn't find ShipPart with name \"" << name << "\"." << endl; return nullptr; } /** @brief Check whether the SpaceShip has a particular Engine. @param search A pointer to the Engine to be checked. */ bool ModularSpaceShip::hasShipPart(ShipPart* search) const { for(ShipPart* part : this->partList_) { if(part == search) return true; } return false; } /** @brief Removes a ShipPart from the SpaceShip, destroying the corresponding StaticEntity @param part The ShipPart to be removed. */ void ModularSpaceShip::removeShipPart(ShipPart* part) { // Remove the part from the partList_ std::vector::iterator it = this->partList_.begin(); for(unsigned int i = 0; i < this->partList_.size(); i++) { if(this->partList_[i] == part) { this->partList_.erase(it); break; } it++; } // Remove the part-entity assignment and detach the Entity of this ShipPart for (std::map::iterator itt = this->partMap_.begin(); itt != this->partMap_.end(); ) { if (itt->second == part) { this->detach(itt->first); itt->first->destroy(); //itt->first->setActive(false); //itt->first->setVisible(false); //itt->first->setCollisionResponse(false); //itt->first->setCollisionType(None); //itt->first->deactivatePhysics(); this->partMap_.erase(itt++); } else { ++itt; } } } }