/* * 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: * Martin Polak * Co-authors: * ... * */ #include "WeaponSystem.h" #include "core/CoreIncludes.h" #include "core/class/SubclassIdentifier.h" #include "worldentities/pawns/Pawn.h" #include "WeaponSlot.h" #include "WeaponPack.h" #include "WeaponSet.h" #include "Weapon.h" #include "Munition.h" /* WeaponSystem * * www.orxonox.net/wiki/WeaponSystem */ namespace orxonox { RegisterClass(WeaponSystem); WeaponSystem::WeaponSystem(Context* context) : BaseObject(context) { RegisterObject(WeaponSystem); this->pawn_ = nullptr; } WeaponSystem::~WeaponSystem() { if (this->isInitialized()) { if (this->pawn_) this->pawn_->setWeaponSystem(nullptr); while (!this->weaponSets_.empty()) this->weaponSets_.begin()->second->destroy(); while (!this->weaponPacks_.empty()) (*this->weaponPacks_.begin())->destroy(); while (!this->weaponSlots_.empty()) (*this->weaponSlots_.begin())->destroy(); while (!this->munitions_.empty()) { this->munitions_.begin()->second->destroy(); this->munitions_.erase(this->munitions_.begin()); } } } void WeaponSystem::addWeaponSlot(WeaponSlot * wSlot) { if (!wSlot) return; this->weaponSlots_.push_back(wSlot); wSlot->setWeaponSystem(this); } void WeaponSystem::removeWeaponSlot(WeaponSlot * wSlot) { if (!wSlot) return; if (wSlot->getWeapon()) this->removeWeaponPack(wSlot->getWeapon()->getWeaponPack()); for (std::vector::iterator it = this->weaponSlots_.begin(); it != this->weaponSlots_.end(); ++it) { if ((*it) == wSlot) { this->weaponSlots_.erase(it); break; } } } WeaponSlot * WeaponSystem::getWeaponSlot(unsigned int index) const { unsigned int i = 0; for (WeaponSlot* weaponSlot : this->weaponSlots_) { ++i; if (i > index) return weaponSlot; } return nullptr; } bool WeaponSystem::addWeaponSet(WeaponSet * wSet) { if (wSet) return this->addWeaponSet(wSet, wSet->getDesiredFiremode()); else return false; } bool WeaponSystem::addWeaponSet(WeaponSet * wSet, unsigned int firemode) { if (!wSet || firemode >= WeaponSystem::MAX_FIRE_MODES) return false; std::map::const_iterator it = this->weaponSets_.find(firemode); if (it == this->weaponSets_.end()) { this->weaponSets_[firemode] = wSet; wSet->setWeaponSystem(this); return true; } return false; } void WeaponSystem::removeWeaponSet(WeaponSet * wSet) { for (std::map::iterator it = this->weaponSets_.begin(); it != this->weaponSets_.end(); ) { if (it->second == wSet) this->weaponSets_.erase(it++); else ++it; } } WeaponSet * WeaponSystem::getWeaponSet(unsigned int index) const { unsigned int i = 0; for (const auto& mapEntry : this->weaponSets_) { ++i; if (i > index) return mapEntry.second; } return nullptr; } bool WeaponSystem::canAddWeaponPack(WeaponPack * wPack) { if (!wPack) return false; unsigned int freeSlots = 0; for (WeaponSlot* weaponSlot : this->weaponSlots_) { if (!weaponSlot->isOccupied()) ++freeSlots; } return (freeSlots >= wPack->getNumWeapons()); } bool WeaponSystem::addWeaponPack(WeaponPack * wPack) { if (!this->canAddWeaponPack(wPack)) return false; // Attach all weapons to the first free slots (and to the Pawn) unsigned int i = 0; for (WeaponSlot* weaponSlot : this->weaponSlots_) { if (!weaponSlot->isOccupied() && i < wPack->getNumWeapons()) { Weapon* weapon = wPack->getWeapon(i); weaponSlot->attachWeapon(weapon); this->getPawn()->attach(weapon); ++i; } } // Assign the desired weaponmode to the firemodes for (const auto& mapEntry : this->weaponSets_) { unsigned int weaponmode = wPack->getDesiredWeaponmode(mapEntry.first); if (weaponmode != WeaponSystem::WEAPON_MODE_UNASSIGNED) mapEntry.second->setWeaponmodeLink(wPack, weaponmode); } this->weaponPacks_.push_back(wPack); wPack->setWeaponSystem(this); return true; } void WeaponSystem::removeWeaponPack(WeaponPack * wPack) { // Remove all weapons from their WeaponSlot unsigned int i = 0; Weapon* weapon = nullptr; while ((weapon = wPack->getWeapon(i++))) if (weapon->getWeaponSlot()) weapon->getWeaponSlot()->removeWeapon(); // Remove all added links from the WeaponSets for (const auto& mapEntry : this->weaponSets_) mapEntry.second->removeWeaponmodeLink(wPack); // Remove the WeaponPack from the WeaponSystem std::vector::iterator it2 = std::find(this->weaponPacks_.begin(),this->weaponPacks_.end(), wPack); assert(it2 !=this->weaponPacks_.end()); this->weaponPacks_.erase(it2); } WeaponPack * WeaponSystem::getWeaponPack(unsigned int index) const { unsigned int i = 0; for (WeaponPack* weaponPack : this->weaponPacks_) { ++i; if (i > index) return weaponPack; } return nullptr; } bool WeaponSystem::swapWeaponSlots(WeaponSlot * wSlot1, WeaponSlot * wSlot2) { if (!wSlot1 || !wSlot2) return false; Weapon* weapon1 = wSlot1->getWeapon(); Weapon* weapon2 = wSlot2->getWeapon(); wSlot1->attachWeapon(weapon2); wSlot2->attachWeapon(weapon1); return true; // In the future, certain weapons might not fit to some slots. Swapping would then be // impossible and the returnvalue would be false. } void WeaponSystem::changeWeaponmode(WeaponPack * wPack, WeaponSet * wSet, unsigned int weaponmode) { if (!wPack || !wSet) return; // Check if the WeaponPack belongs to this WeaponSystem std::vector::iterator it1 = std::find( this->weaponPacks_.begin(), this->weaponPacks_.end(), wPack ); if (it1 == this->weaponPacks_.end()) return; // Check if the WeaponSet belongs to this WeaponSystem bool foundWeaponSet = false; for (const auto& mapEntry : this->weaponSets_) { if (mapEntry.second == wSet) { foundWeaponSet = true; break; } } if (!foundWeaponSet) return; // Finally set the link between firemode and weaponmode wSet->setWeaponmodeLink(wPack, weaponmode); } /** @brief Fires the @ref orxonox::WeaponSet with the specified firemode. */ void WeaponSystem::fire(unsigned int firemode) { std::map::iterator it = this->weaponSets_.find(firemode); if (it != this->weaponSets_.end() && it->second) it->second->fire(); } void WeaponSystem::reload() { for (const auto& mapEntry : this->weaponSets_) mapEntry.second->reload(); } Munition * WeaponSystem::getMunition(SubclassIdentifier * identifier) { if (!identifier || !identifier->getIdentifier()) return nullptr; std::map::iterator it = this->munitions_.find(identifier->getIdentifier()); if (it != this->munitions_.end()) { return it->second; } else { return nullptr; } } void WeaponSystem::addMunition(Munition* munition) { if (munition == nullptr) { return; } SubclassIdentifier identifier = munition->getIdentifier(); if (identifier) { this->munitions_[identifier] = munition; updateMunition(); } else { orxout(internal_warning) << "Adding munition failed. identifier == nullptr " << endl; } } void WeaponSystem::updateMunition() { for (WeaponPack* weaponPack : this->weaponPacks_) { weaponPack->updateMunition(); } } }