/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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, or (at your option) any later version. ### File Specific main-programmer: Patrick Boenzli co-programmer: Benjamin Grauer */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WEAPON #include "weapon_manager.h" #include "weapon.h" #include "crosshair.h" #include "load_param.h" #include "factory.h" #include "vector.h" #include "list.h" #include "t_animation.h" using namespace std; /** * this initializes the weaponManager for a given nnumber of weapon slots * @param number of weapon slots of the model/ship <= 8 (limitied) */ WeaponManager::WeaponManager(int nrOfSlots) { this->init(); this->nrOfSlots = nrOfSlots; } /** * Destroys a WeaponManager */ WeaponManager::~WeaponManager() { /* i dont have to delete the weapons itself, because they are worldentities and therefore in the entities list of the world. world will clean them up for me */ for(int i = 0; i < W_MAX_CONFIGS; ++i) { this->configs[i].bUsed = false; for(int j = 0; j < W_MAX_SLOTS; ++j) this->configs[i].slots[j] = NULL; } // crosshair being a PNode it must not be deleted (this is because PNodes delete themselves.) //delete this->crosshair; } /** * initializes the WeaponManager */ void WeaponManager::init() { this->setClassID(CL_WEAPON_MANAGER, "WeaponManager"); for(int i = 0; i < W_MAX_CONFIGS; ++i) { this->configs[i].bUsed = false; for(int j = 0; j < W_MAX_SLOTS; ++j) this->configs[i].slots[j] = NULL; } this->currConfID = W_CONFIG0; this->crosshair = new Crosshair(); this->crossHairSizeAnim = new tAnimation(this->crosshair, &Crosshair::setSize); this->crossHairSizeAnim->setInfinity(ANIM_INF_REWIND); this->crossHairSizeAnim->addKeyFrame(50, .1, ANIM_LINEAR); this->crossHairSizeAnim->addKeyFrame(100, .05, ANIM_LINEAR); this->crossHairSizeAnim->addKeyFrame(50, .01, ANIM_LINEAR); } /** * loads the settings of the WeaponManager * @param root the XML-element to load from */ void WeaponManager::loadParams(const TiXmlElement* root) { static_cast(this)->loadParams(root); LoadParam(root, "slot-count", this, &WeaponManager::setSlotCount) .describe("how many slots(cannons) the WeaponManager can handle"); LOAD_PARAM_START_CYCLE; LoadParam(root, "Weapons", this, &WeaponManager::loadWeapons) .describe("loads Weapons"); // LoadParam(root, "Weapon", this, &WeaponManager::addWeapon); LOAD_PARAM_END_CYCLE; } /** * loads a Weapon onto the WeaponManager * @param root the XML-element to load the Weapons from */ void WeaponManager::loadWeapons(const TiXmlElement* root) { LOAD_PARAM_START_CYCLE; Weapon* newWeapon = dynamic_cast(Factory::getFirst()->fabricate(element)); LOAD_PARAM_END_CYCLE; } /** * sets the number of Slots the WeaponManager has * @param nrOfSlots the number of slots */ void WeaponManager::setSlotCount(int nrOfSlots) { this->nrOfSlots = nrOfSlots; } /** * adds a weapon to the selected weaponconfiguration into the selected slot * @param the weapon to add * @param an identifier for the slot: number between 0..7 if not specified: slotID=next free slot * @param an identifier for the weapon configuration, number between 0..3 * * if you add explicitly a weapon at config:n, slot:m, the weapon placed at this location will be * replaced by the weapon specified. if you use the W_FREE_SLOT, the manager will look for a free * slot in this weaponconfiguration. if there is non, the weapon won't be added and there will be * a error message. */ void WeaponManager::addWeapon(Weapon* weapon, int configID, int slotID) { if( slotID == W_FREE_SLOT) { int freeSlot = this->getNextFreeSlot( configID); if( freeSlot < 0 || freeSlot >= this->nrOfSlots) { PRINTF(0)("There is no free slot in this WeaponConfig to dock this weapon at! Aborting\n"); return; } PRINTF(3)("Added new Weapon to Config:%i/Slot:%i\n", configID, freeSlot); this->configs[configID].bUsed = true; this->configs[configID].slots[freeSlot] = weapon; return; } this->configs[configID].bUsed = true; this->configs[configID].slots[slotID] = weapon; PRINTF(3)("Added a new Weapon to the WeaponManager: config %i/ slot %i\n", configID, slotID); } /** * removes a Weapon from the WeaponManager */ void WeaponManager::removeWeapon(Weapon* weapon, int configID) { /* empty */ } /** * changes to the next weapon configuration * * if there are multiple weapon configurations defined by the manager, use this to switch between them * this function will deactivate the weapons first, change the config and reactivate them later */ void WeaponManager::nextWeaponConf() { PRINTF(4)("Changing weapon configuration: from %i to next\n", this->currConfID); int i, lastConfID; lastConfID = this->currConfID; for(i = this->currConfID + 1; i < W_MAX_CONFIGS && !this->configs[i].bUsed; ++i); if( i == W_MAX_CONFIGS) this->currConfID = W_CONFIG0; else this->currConfID = i; Weapon *w1, *w2; for(int j = 0; j < W_MAX_SLOTS; ++j) { w1 = this->configs[lastConfID].slots[j]; w2 = this->configs[this->currConfID].slots[j]; if( w1 == w2) { printf("no need for change\n"); } else { if( w1 != NULL ) { w1->requestAction(WA_DEACTIVATE); printf("deactivating %i,%i\n", j,lastConfID); } if( w2 != NULL) { w2->requestAction(WA_ACTIVATE); printf("activating %i,%i\n", j, this->currConfID); } } } } /** * triggers fire of all weapons in the current weaponconfig */ void WeaponManager::fire() { Weapon* firingWeapon; for(int i = 0; i < W_MAX_SLOTS; ++i) { firingWeapon = this->configs[this->currConfID].slots[i]; if( firingWeapon != NULL) firingWeapon->requestAction(WA_SHOOT); } this->crosshair->setRotationSpeed(500); this->crossHairSizeAnim->replay(); } /** * triggers tick of all weapons in the current weaponconfig * @param second passed since last tick */ void WeaponManager::tick(float dt) { Weapon* w; for(int i = 0; i < W_MAX_SLOTS; ++i) { w = this->configs[this->currConfID].slots[i]; if( w != NULL) w->tick(dt); } crosshair->setRotationSpeed(5); } /** * triggers draw of all weapons in the current weaponconfig */ void WeaponManager::draw() { Weapon* w; for(int i = 0; i < W_MAX_SLOTS; ++i) { w = this->configs[this->currConfID].slots[i]; if( w != NULL) w->draw(); } } /** * private gets the next free slot in a certain weaponconfig * @param the selected weaponconfig */ int WeaponManager::getNextFreeSlot(int configID) { for( int i = 0; i < W_MAX_SLOTS; ++i) { if( this->configs[configID].slots[i] == NULL) return i; } return -1; }