Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/world_entities/weapons/weapon_manager.cc @ 9727

Last change on this file since 9727 was 9727, checked in by bensch, 18 years ago

orxonox/new_class_id: new Executor construct, that is much more typesafe, faster, and easier to extend…

Also changed the LoadParam process, and adapted ScriptEngine calls

Then at the end, some missing headers appeared, and appended them to all the cc-files again.

File size: 15.9 KB
RevLine 
[4826]1
2/*
3   orxonox - the future of 3D-vertical-scrollers
4
5   Copyright (C) 2004 orx
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11
12### File Specific
13   main-programmer: Patrick Boenzli
[4832]14   co-programmer: Benjamin Grauer
[4951]15
16   2005-07-24: Benjamin Grauer: restructurate, so it can handle the new Weapons.
[4826]17*/
18
[7350]19#define DEBUG_SPECIAL_MODULE 4 //DEBUG_MODULE_WEAPON
[4826]20
21#include "weapon_manager.h"
22#include "weapon.h"
[4834]23#include "crosshair.h"
[4828]24
[6561]25#include "playable.h"
26
[9727]27#include "util/loading/load_param_xml.h"
[7193]28#include "util/loading/factory.h"
[6055]29
[4837]30#include "t_animation.h"
[4826]31
32
[9715]33ObjectListDefinition(WeaponManager);
[4826]34/**
[6054]35 * @brief this initializes the weaponManager for a given nnumber of weapon slots
[4826]36 * @param number of weapon slots of the model/ship <= 8 (limitied)
37 */
[6142]38WeaponManager::WeaponManager(WorldEntity* parent)
[4826]39{
[4833]40  this->init();
[8844]41  this->setParentEntity(parent);
42
43  assert (parent != NULL);
[4826]44}
45
[4949]46WeaponManager::WeaponManager(const TiXmlElement* root)
47{
48  this->init();
49  this->loadParams(root);
50}
[4826]51
[4833]52/**
[6054]53 * @brief Destroys a WeaponManager
[4833]54 */
[4826]55WeaponManager::~WeaponManager()
56{
[4834]57  // crosshair being a PNode it must not be deleted (this is because PNodes delete themselves.)
[8147]58  // rennerc: crosshair seems not to delete itselve
[9705]59  if (Crosshair::objectList().exists(this->crosshair))
[8315]60    delete this->crosshair;
[4826]61}
62
[4834]63/**
[6054]64 * @brief initializes the WeaponManager
[4834]65 */
[4833]66void WeaponManager::init()
67{
[9705]68  this->registerObject(this, WeaponManager::_objectList);
[4826]69
[8844]70  this->parentNode = NULL;
71  this->parentEntity = NULL;
[4951]72
73  for (int i = 0; i < WM_MAX_CONFIGS; i++)
74    for (int j = 0; j < WM_MAX_SLOTS; j++)
75      this->configs[i][j] = NULL;
76
77  for (int i = 0; i < WM_MAX_SLOTS; i++)
[4833]78  {
[4959]79    this->currentSlotConfig[i].capability = WTYPE_ALL;
[4951]80    this->currentSlotConfig[i].currentWeapon = NULL;
81    this->currentSlotConfig[i].nextWeapon = NULL;
[4992]82
83    // NAMING
84    char* tmpName;
[9406]85    if (!this->getName().empty())
[4992]86    {
[9406]87      tmpName = new char[this->getName().size() + 10];
88      sprintf(tmpName, "%s_slot%d", this->getCName(), i);
[4992]89    }
90    else
91    {
92      tmpName = new char[30];
93      sprintf(tmpName, "WeaponMan_slot%d", i);
94    }
95    this->currentSlotConfig[i].position.setName(tmpName);
[6056]96    this->currentSlotConfig[i].position.deactivateNode();
[5208]97    delete[] tmpName;
[4833]98  }
[4895]99
[4951]100  for (int i = 0; i < WM_MAX_LOADED_WEAPONS; i++)
101    this->availiableWeapons[i] = NULL;
[4895]102
103
[4951]104  this->currentConfigID = 0;
105  this->slotCount = 2;
[8315]106  //this->weaponChange;
[4895]107
[4951]108  // CROSSHAIR INITIALISATION
[4834]109  this->crosshair = new Crosshair();
[6807]110  //this->crosshair->setRelCoor(1000,0,0);
[4837]111  this->crossHairSizeAnim = new tAnimation<Crosshair>(this->crosshair, &Crosshair::setSize);
112  this->crossHairSizeAnim->setInfinity(ANIM_INF_REWIND);
113  this->crossHairSizeAnim->addKeyFrame(50, .1, ANIM_LINEAR);
114  this->crossHairSizeAnim->addKeyFrame(100, .05, ANIM_LINEAR);
115  this->crossHairSizeAnim->addKeyFrame(50, .01, ANIM_LINEAR);
[4834]116}
[4833]117
[4834]118/**
[7350]119 * @brief loads the settings of the WeaponManager
[4834]120 * @param root the XML-element to load from
121 */
122void WeaponManager::loadParams(const TiXmlElement* root)
123{
[6512]124  BaseObject::loadParams(root);
[4972]125
[5671]126  LoadParam(root, "slot-count", this, WeaponManager, setSlotCount)
[6736]127  .describe("how many slots(cannons) the WeaponManager can handle");
[4834]128
[5644]129  LOAD_PARAM_START_CYCLE(root, element);
[5654]130  {
131    // CHECK IF THIS WORKS....
132    LoadParamXML_CYCLE(element, "weapons", this, WeaponManager, loadWeapons)
[6736]133    .describe("loads Weapons");
[5654]134  }
[5644]135  LOAD_PARAM_END_CYCLE(element);
[4833]136}
137
[4826]138/**
[7350]139 * @brief loads a Weapon onto the WeaponManager
[4834]140 * @param root the XML-element to load the Weapons from
141 */
142void WeaponManager::loadWeapons(const TiXmlElement* root)
143{
[5644]144  LOAD_PARAM_START_CYCLE(root, element);
[4834]145
[8315]146  BaseObject* object = Factory::fabricate(element);
147  if (object != NULL)
148  {
149    Weapon* newWeapon = dynamic_cast<Weapon*>(object);
150    if (newWeapon == NULL)
151      delete object;
152  }
[5644]153  LOAD_PARAM_END_CYCLE(element);
[4834]154}
155
[4992]156/**
[7350]157 * @brief sets the Parent of the WeaponManager.
[4992]158 * @param parent the parent of the WeaponManager
159 *
160 * this is used, to identify to which ship/man/whatever this WeaponManager is connected.
161 * also all the Slots will be subconnected to this parent.
[5435]162 *
163 * The reason this function exists is that the WeaponManager is neither a WorldEntity nor
164 * a PNode.
[4992]165 */
[8844]166void WeaponManager::setParentEntity(WorldEntity* parent)
[4953]167{
[8844]168  this->parentEntity = parent;
169  if (this->parentNode == NULL)
170    this->setParentNode(parent);
171}
172
173
174void WeaponManager::setParentNode(PNode* parent)
175{
176  this->parentNode = parent;
177  assert(parent != NULL);
178
179  if (this->parentNode != NULL)
[4953]180  {
181    for (int i = 0; i < WM_MAX_SLOTS; i++)
[8844]182      this->parentNode->addChild(&this->currentSlotConfig[i].position);
[4953]183  }
[8844]184
[4953]185}
186
[8844]187
[4834]188/**
[7350]189 * @brief sets the number of Slots the WeaponManager has
[4926]190 * @param slotCount the number of slots
[4834]191 */
[4951]192void WeaponManager::setSlotCount(unsigned int slotCount)
[4834]193{
[4951]194  if (slotCount <= WM_MAX_SLOTS)
195    this->slotCount = slotCount;
196  else
197    this->slotCount = WM_MAX_SLOTS;
[4834]198}
199
[4972]200
201/**
[7350]202 * @brief sets the position of the Slot relative to the parent
[4972]203 * @param slot the slot to set-up
204 * @param position the position of the given slot
205 */
[6803]206void WeaponManager::setSlotPosition(int slot, const Vector& position, PNode* parent)
[4953]207{
208  if (slot < this->slotCount)
[6803]209  {
[4953]210    this->currentSlotConfig[slot].position.setRelCoor(position);
[6803]211
212    if (parent != NULL)
213      this->currentSlotConfig[slot].position.setParent(parent);
214  }
[4953]215}
216
[4972]217
218/**
[7350]219 * @brief sets the relative rotation of the slot to its parent
[4972]220 * @param slot the slot to set-up
221 * @param rotation the relative rotation of the given slot
222 */
[4969]223void WeaponManager::setSlotDirection(int slot, const Quaternion& rotation)
224{
225  if (slot < this->slotCount)
226    this->currentSlotConfig[slot].position.setRelDir(rotation);
227}
228
229
[4834]230/**
[7350]231 * @brief adds a weapon to the selected weaponconfiguration into the selected slot
[4972]232 * @param weapon the weapon to add
233 * @param configID an identifier for the slot: number between 0..7 if not specified: slotID=next free slot
234 * @param slotID an identifier for the weapon configuration, number between 0..3
[4832]235 *
236 * if you add explicitly a weapon at config:n, slot:m, the weapon placed at this location will be
[4906]237 * replaced by the weapon specified. if you use the WM_FREE_SLOT, the manager will look for a free
[4832]238 * slot in this weaponconfiguration. if there is non, the weapon won't be added and there will be
239 * a error message.
[4826]240 */
[6561]241bool WeaponManager::addWeapon(Weapon* weapon, int configID, int slotID)
[4826]242{
[6753]243  if ( weapon == NULL )
[6737]244    return false;
[6679]245
[4951]246  if (unlikely(configID >= WM_MAX_CONFIGS || slotID >= (int)this->slotCount))
[4826]247  {
[6679]248    PRINTF(2)("Slot %d of config %d is not availiabe (max: %d) searching for suitable slot\n", slotID, configID, this->slotCount);
249    if (configID >= WM_MAX_CONFIGS)
250      configID = -1;
251    if (slotID >= (int)this->slotCount)
252      slotID = -1;
[4951]253  }
[6679]254  // if no ConfigID is supplied set to Current Config.
255  if (configID <= -1)
256    configID = this->currentConfigID;
257  //
258  if (configID > -1 && slotID == -1)
259  {
260    slotID = this->getNextFreeSlot(configID, weapon->getCapability());
261    if (slotID == -1)
262      configID = -1;
263  }
[4951]264
[6676]265  if (configID > 0 && slotID > 0 && this->configs[configID][slotID] != NULL)
266  {
[9406]267    PRINTF(3)("Weapon-slot %d/%d of %s already poulated, remove weapon (%s::%s) first\n", configID, slotID, this->getCName(), weapon->getClassCName(), weapon->getCName());
[6676]268    return false;
269  }
[4951]270
[6676]271  if (slotID <= -1) // WM_FREE_SLOT
[4951]272  {
[5441]273    slotID = this->getNextFreeSlot(configID, weapon->getCapability());
[4951]274    if( slotID < 0 || slotID >= this->slotCount)
[4826]275    {
[5441]276      PRINTF(1)("There is no free slot in this WeaponConfig to dock this weapon at! Aborting\n");
[6561]277      return false;
[4826]278    }
279  }
[4953]280
[5441]281  if (!(this->currentSlotConfig[slotID].capability & weapon->getCapability() & WTYPE_ALLKINDS) &&
[6736]282      this->currentSlotConfig[slotID].capability & weapon->getCapability() & WTYPE_ALLDIRS)
[5441]283  {
284    PRINTF(2)("Unable to add Weapon with wrong capatibility to Slot %d (W:%d M:%d)\n",
285              slotID, weapon->getCapability(), this->currentSlotConfig[slotID].capability);
[6561]286    return false;
[5441]287  }
288
[4953]289  //! @todo check if the weapon is already assigned to another config in another slot
[6714]290  if (this->configs[configID][slotID] != NULL)
291    return false;
[6676]292
[4951]293  this->configs[configID][slotID] = weapon;
[6669]294  weapon->setAmmoContainer(this->getAmmoContainer(weapon->getProjectileType()));
[6736]295  if(configID == this->currentConfigID)
296    this->currentSlotConfig[slotID].nextWeapon = weapon;
[8844]297  //if (this->parent != NULL)
[6142]298  {
[8844]299    this->parentNode->addChild(weapon);
[9705]300    if (this->parentEntity->isA(Playable::classID()))
[8844]301      dynamic_cast<Playable*>(this->parentEntity)->weaponConfigChanged();
[6920]302    weapon->setDefaultTarget(this->crosshair);
[6142]303  }
[9406]304  PRINTF(3)("Added a new Weapon (%s::%s) to the WeaponManager: config %i/ slot %i\n", weapon->getClassCName(), weapon->getCName(), configID, slotID);
[6561]305  return true;
[4826]306}
307
[4834]308/**
[6931]309 * @brief increases the Energy of the WeaponContainer of type (projectileType)
310 * @param projectileType the type of weapon to increase Energy from
311 * @param ammo the ammo to increase
312 */
[9715]313float WeaponManager::increaseAmmunition(const ClassID& projectileType, float ammo)
[6931]314{
315  return this->getAmmoContainer(projectileType)->increaseEnergy(ammo);
316}
317
[6972]318/**
319 * @brief does the same as the funtion inclreaseAmmunition, added four your convenience
320 * @param weapon, the Weapon to read the ammo-info about.
321 * @param ammo how much ammo to add.
322 */
323float WeaponManager::inclreaseAmmunition(const Weapon* weapon, float ammo)
324{
325  assert (weapon != NULL);
[9705]326  return this->increaseAmmunition(weapon->getClassID(), ammo);
[6931]327
[6972]328}
[6931]329
[6972]330
[6931]331/**
[4954]332 * sets the capabilities of a Slot
333 * @param slot the slot to set the capability
334 * @param slotCapability the capability @see WM_SlotCapability
335 */
336void WeaponManager::setSlotCapability(int slot, long slotCapability)
337{
338  if (slot > slotCount)
339    return;
340  this->currentSlotConfig[slot].capability = slotCapability;
341}
342
343
344/**
[4834]345 * removes a Weapon from the WeaponManager
[4954]346 *
347 * !! The weapon must be inactive before you can delete it,    !!
348 * !! because it will still be deactivated (if it is selected) !!
[4834]349 */
[4826]350void WeaponManager::removeWeapon(Weapon* weapon, int configID)
351{
[4954]352  if (weapon == NULL)
353    return;
354  if (configID < 0)
355  {
356    for (int j = 0; j < WM_MAX_SLOTS; j++)
357    {
358      for (int i = 0; i < WM_MAX_CONFIGS; i++)
359      {
360        if (this->configs[i][j] == weapon)
361          this->configs[i][j] = NULL;
362      }
363      if (this->currentSlotConfig[j].currentWeapon == weapon)
364      {
365        this->currentSlotConfig[j].nextWeapon = NULL;
366      }
367    }
368  }
[4826]369}
370
371
372/**
[4832]373 * changes to the next weapon configuration
[4826]374 */
[4954]375void WeaponManager::nextWeaponConfig()
[4826]376{
[4951]377  ++this->currentConfigID;
378  if (this->currentConfigID >= WM_MAX_CONFIGS)
379    this->currentConfigID = 0;
[4952]380  this->changeWeaponConfig(this->currentConfigID);
381}
[4826]382
[4953]383/**
384 * changes to the previous configuration
385 */
[4952]386void WeaponManager::previousWeaponConfig()
387{
388  --this->currentConfigID;
389  if (this->currentConfigID < 0)
390    this->currentConfigID = WM_MAX_CONFIGS -1;
391  this->changeWeaponConfig(this->currentConfigID);
392}
393
[4953]394/**
395 * change to a desired configuration
396 * @param weaponConfig the configuration to jump to.
397 */
[4952]398void WeaponManager::changeWeaponConfig(int weaponConfig)
399{
400  this->currentConfigID = weaponConfig;
401  PRINTF(4)("Changing weapon configuration: to %i\n", this->currentConfigID);
[4951]402  for (int i = 0; i < WM_MAX_SLOTS; i++)
403    this->currentSlotConfig[i].nextWeapon = this->configs[currentConfigID][i];
[4826]404}
405
406
407/**
[4832]408 * triggers fire of all weapons in the current weaponconfig
[4826]409 */
[4832]410void WeaponManager::fire()
[4826]411{
412  Weapon* firingWeapon;
[4951]413  for(int i = 0; i < this->slotCount; i++)
[4826]414  {
[4951]415    firingWeapon = this->currentSlotConfig[i].currentWeapon;
[4885]416    if( firingWeapon != NULL) firingWeapon->requestAction(WA_SHOOT);
[4826]417  }
[4837]418  this->crosshair->setRotationSpeed(500);
419  this->crossHairSizeAnim->replay();
[4826]420}
421
422
423/**
[4832]424 * triggers tick of all weapons in the current weaponconfig
425 * @param second passed since last tick
[4826]426 */
[4833]427void WeaponManager::tick(float dt)
[4826]428{
[4951]429  Weapon* tickWeapon;
430
431  for(int i = 0; i < this->slotCount; i++)
[4826]432  {
[6736]433/*
434    NICE LITTLE DEBUG FUNCTION
435       if (this->currentSlotConfig[i].currentWeapon != NULL || this->currentSlotConfig[i].nextWeapon != NULL)
436      printf("%p %p\n", this->currentSlotConfig[i].currentWeapon, this->currentSlotConfig[i].nextWeapon);*/
[4951]437
[6736]438    // current Weapon in Slot i
[4951]439    tickWeapon = this->currentSlotConfig[i].currentWeapon;
[6736]440    // On A change (current != next)
441    if (tickWeapon != this->currentSlotConfig[i].nextWeapon)
[4951]442    {
[6736]443      // if a Weapon is Active in slot i, deactivate it.
444      if (tickWeapon != NULL )
[4951]445      {
[6736]446        if (tickWeapon->isActive())
[4953]447        {
[6736]448          tickWeapon->requestAction(WA_DEACTIVATE);
449          continue;
[4953]450        }
[6055]451        else
[6736]452        {
453          tickWeapon->toList(OM_NULL);
454          this->currentSlotConfig[i].currentWeapon = NULL;
455        }
[4951]456      }
[6736]457
458      // switching to next Weapon
459      tickWeapon = this->currentSlotConfig[i].currentWeapon = this->currentSlotConfig[i].nextWeapon;
460      if (tickWeapon != NULL)
461      {
[8844]462           //        if (this->parent != NULL)
463          tickWeapon->toList(this->parentEntity->getOMListNumber());
[6736]464        tickWeapon->requestAction(WA_ACTIVATE);
465        this->currentSlotConfig[i].position.activateNode();
466        tickWeapon->setParent(&this->currentSlotConfig[i].position);
467      }
468      else
469        this->currentSlotConfig[i].position.deactivateNode();
[9705]470      if (this->parentEntity != NULL && this->parentEntity->isA(Playable::classID()))
[8844]471        dynamic_cast<Playable*>(this->parentEntity)->weaponConfigChanged();
[4951]472    }
[6918]473    else if (unlikely(tickWeapon != NULL && tickWeapon->getCurrentState() == WS_DEACTIVATING))
474      this->currentSlotConfig[i].nextWeapon = NULL;
[4826]475  }
476}
477
478
479/**
[4832]480 * triggers draw of all weapons in the current weaponconfig
[4826]481 */
[4951]482void WeaponManager::draw() const
[4826]483{
[8315]484  assert(false || "must not be called");
[4951]485  Weapon* drawWeapon;
486  for (int i = 0; i < this->slotCount; i++)
[4826]487  {
[4951]488    drawWeapon = this->currentSlotConfig[i].currentWeapon;
489    if( drawWeapon != NULL && drawWeapon->isVisible())
490      drawWeapon->draw();
[4826]491  }
492}
493
494
495/**
[4832]496 * private gets the next free slot in a certain weaponconfig
[6669]497 * @param the selected weaponconfig -1 if none found
[4826]498 */
[5440]499int WeaponManager::getNextFreeSlot(int configID, long capability)
[4826]500{
[6676]501  if (configID == -1)
[4826]502  {
[6676]503    for (configID = 0; configID < WM_MAX_CONFIGS; configID++)
504      for( int i = 0; i < this->slotCount; ++i)
505      {
506        if( this->configs[configID][i] == NULL &&
507            (this->currentSlotConfig[i].capability & capability & WTYPE_ALLKINDS) &&
508            (this->currentSlotConfig[i].capability & capability & WTYPE_ALLDIRS))
509          return i;
[6736]510      }
[4826]511  }
[6676]512  else
513  {
514    for( int i = 0; i < this->slotCount; ++i)
515    {
516      if( this->configs[configID][i] == NULL &&
517          (this->currentSlotConfig[i].capability & capability & WTYPE_ALLKINDS) &&
518          (this->currentSlotConfig[i].capability & capability & WTYPE_ALLDIRS))
519        return i;
520    }
521  }
[4826]522  return -1;
523}
524
[9715]525CountPointer<AmmoContainer>& WeaponManager::getAmmoContainer(const ClassID& projectileType)
[6669]526{
527  for (unsigned int i = 0; i < this->ammo.size(); i++)
528  {
529    if (this->ammo[i]->getProjectileType() == projectileType)
530      return this->ammo[i];
531  }
532  this->ammo.push_back(CountPointer<AmmoContainer>(new AmmoContainer(projectileType)));
533  return this->ammo.back();
534}
[4951]535
[6972]536CountPointer<AmmoContainer>& WeaponManager::getAmmoContainer(const Weapon* weapon)
537{
538  assert (weapon != NULL);
[9705]539  return (this->getAmmoContainer(weapon->getClassID()));
[6972]540}
[4951]541
[6972]542
[4953]543/**
544 * outputs some nice debug information about the WeaponManager
545 */
[4951]546void WeaponManager::debug() const
547{
548  PRINT(3)("WeaponManager Debug Information\n");
549  PRINT(3)("-------------------------------\n");
550  PRINT(3)("current Config is %d\n", this->currentConfigID);
551  for (int i = 0; i < WM_MAX_CONFIGS; i++)
552  {
553    PRINT(3)("Listing Weapons in Configuration %d\n", i);
554    for (int j = 0; j < WM_MAX_SLOTS; j++)
555    {
556      if (this->configs[i][j] != NULL)
[9406]557        PRINT(3)("Slot %d loaded a %s\n", j, this->configs[i][j]->getClassCName());
[4951]558    }
559  }
560}
Note: See TracBrowser for help on using the repository browser.