/* 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: */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WEAPON #include "weapon.h" #include "stdincl.h" #include "world_entity.h" #include "vector.h" #include "model.h" #include "projectile.h" #include "list.h" #include "world.h" using namespace std; /** \brief 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) { 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->nrOfSlots = nrOfSlots; this->currConfID = W_CONFIG0; } 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; } } /** \brief 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); } void WeaponManager::removeWeapon(Weapon* weapon, int configID) { /* empty */ } /** \brief 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->deactivate(); printf("deactivating %i,%i\n", j,lastConfID); } if( w2 != NULL) { w2->activate(); printf("activating %i,%i\n", j, this->currConfID); } } } } /** \brief 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->fire(); } } /** \brief triggers tick of all weapons in the current weaponconfig \param second passed since last tick */ void WeaponManager::tick(float sec) { Weapon* w; for(int i = 0; i < W_MAX_SLOTS; ++i) { w = this->configs[this->currConfID].slots[i]; if( w != NULL) w->tick(sec); } } /** \brief 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(); } } /** \brief 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; } /** \brief standard constructor creates a new weapon */ Weapon::Weapon (PNode* parent, const Vector& coordinate, const Quaternion& direction) : WorldEntity() { parent->addChild(this, PNODE_ALL); this->setRelCoor(coordinate); this->setRelDir(direction); WorldInterface* wi = WorldInterface::getInstance(); this->worldEntities = wi->getEntityList(); this->objectComponent1 = NULL; this->objectComponent2 = NULL; this->objectComponent3 = NULL; this->animation1 = NULL; this->animation2 = NULL; this->animation3 = NULL; } /** \brief standard deconstructor */ Weapon::~Weapon () { // model will be deleted from WorldEntity-destructor //this->worldEntities = NULL; /* dont delete objectComponentsX here, they will be killed when the pnodes are cleaned out */ /* all animations are deleted via the animation player*/ } /** \brief enables the weapon a weapon can be enabled/disabled because of various reasons. if a weapon is been enabled, it can interact in a world. elswhere it wont react to any action. */ void Weapon::enable() { this->enabled = true; } /** \brief disables the weapon a weapon can be enabled/disabled because of various reasons. if a weapon is been enabled, it can interact in a world. elswhere it wont react to any action. */ void Weapon::disable() { this->enabled = false; } /** \brief checks if the weapon is enabled \returns true if enabled a weapon can be ebabled/disabled because of various reasons. if a weapon is been enabled, it can interact in a world. elswhere it wont react to any action. */ bool Weapon::isEnabled() { return this->enabled; } /** \brief sets a new projectile to the weapon \param new projectile for this weapon weapon an projectile are independent, so you can combine them as you want */ void Weapon::setProjectile(Projectile* projectile) { this->projectile = projectile; } /** \brief sets a new projectile to the weapon \returns the current projectile of this weapon weapon an projectile are independent, so you can combine them as you want */ Projectile* Weapon::getProjectile() { return this->projectile; } /** \brief this activates the weapon This is needed, since there can be more than one weapon on a ship. the activation can be connected with an animation. for example the weapon is been armed out. */ void Weapon::activate() {} /** \brief this deactivates the weapon This is needed, since there can be more than one weapon on a ship. the activation can be connected with an animation. for example the weapon is been armed out. */ void Weapon::deactivate() {} /** \brief asks if the current weapon is active \returns true if it the weapon is active */ bool Weapon::isActive() {} /** \brief is called, when the weapon gets hit (=collide with something) \param from which entity it is been hit \param where it is been hit this may not be used, since it would make the game relay complicated when one can destroy the weapons of enemies or vice versa. */ void Weapon::hit (WorldEntity* entity, Vector* position) {} /** \brief is called, when the weapon is destroyed this is in conjunction with the hit function, so when a weapon is able to get hit, it can also be destoryed. */ void Weapon::destroy () {} /** \brief tick signal for time dependent/driven stuff */ void Weapon::tick (float time) {} /** \brief is called, when there is no fire button pressed */ void Weapon::weaponIdle() {} /** \brief this will draw the weapon */ void Weapon::draw () {}