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
Line 
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
14   co-programmer: Benjamin Grauer
15
16   2005-07-24: Benjamin Grauer: restructurate, so it can handle the new Weapons.
17*/
18
19#define DEBUG_SPECIAL_MODULE 4 //DEBUG_MODULE_WEAPON
20
21#include "weapon_manager.h"
22#include "weapon.h"
23#include "crosshair.h"
24
25#include "playable.h"
26
27#include "util/loading/load_param_xml.h"
28#include "util/loading/factory.h"
29
30#include "t_animation.h"
31
32
33ObjectListDefinition(WeaponManager);
34/**
35 * @brief this initializes the weaponManager for a given nnumber of weapon slots
36 * @param number of weapon slots of the model/ship <= 8 (limitied)
37 */
38WeaponManager::WeaponManager(WorldEntity* parent)
39{
40  this->init();
41  this->setParentEntity(parent);
42
43  assert (parent != NULL);
44}
45
46WeaponManager::WeaponManager(const TiXmlElement* root)
47{
48  this->init();
49  this->loadParams(root);
50}
51
52/**
53 * @brief Destroys a WeaponManager
54 */
55WeaponManager::~WeaponManager()
56{
57  // crosshair being a PNode it must not be deleted (this is because PNodes delete themselves.)
58  // rennerc: crosshair seems not to delete itselve
59  if (Crosshair::objectList().exists(this->crosshair))
60    delete this->crosshair;
61}
62
63/**
64 * @brief initializes the WeaponManager
65 */
66void WeaponManager::init()
67{
68  this->registerObject(this, WeaponManager::_objectList);
69
70  this->parentNode = NULL;
71  this->parentEntity = NULL;
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++)
78  {
79    this->currentSlotConfig[i].capability = WTYPE_ALL;
80    this->currentSlotConfig[i].currentWeapon = NULL;
81    this->currentSlotConfig[i].nextWeapon = NULL;
82
83    // NAMING
84    char* tmpName;
85    if (!this->getName().empty())
86    {
87      tmpName = new char[this->getName().size() + 10];
88      sprintf(tmpName, "%s_slot%d", this->getCName(), i);
89    }
90    else
91    {
92      tmpName = new char[30];
93      sprintf(tmpName, "WeaponMan_slot%d", i);
94    }
95    this->currentSlotConfig[i].position.setName(tmpName);
96    this->currentSlotConfig[i].position.deactivateNode();
97    delete[] tmpName;
98  }
99
100  for (int i = 0; i < WM_MAX_LOADED_WEAPONS; i++)
101    this->availiableWeapons[i] = NULL;
102
103
104  this->currentConfigID = 0;
105  this->slotCount = 2;
106  //this->weaponChange;
107
108  // CROSSHAIR INITIALISATION
109  this->crosshair = new Crosshair();
110  //this->crosshair->setRelCoor(1000,0,0);
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);
116}
117
118/**
119 * @brief loads the settings of the WeaponManager
120 * @param root the XML-element to load from
121 */
122void WeaponManager::loadParams(const TiXmlElement* root)
123{
124  BaseObject::loadParams(root);
125
126  LoadParam(root, "slot-count", this, WeaponManager, setSlotCount)
127  .describe("how many slots(cannons) the WeaponManager can handle");
128
129  LOAD_PARAM_START_CYCLE(root, element);
130  {
131    // CHECK IF THIS WORKS....
132    LoadParamXML_CYCLE(element, "weapons", this, WeaponManager, loadWeapons)
133    .describe("loads Weapons");
134  }
135  LOAD_PARAM_END_CYCLE(element);
136}
137
138/**
139 * @brief loads a Weapon onto the WeaponManager
140 * @param root the XML-element to load the Weapons from
141 */
142void WeaponManager::loadWeapons(const TiXmlElement* root)
143{
144  LOAD_PARAM_START_CYCLE(root, element);
145
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  }
153  LOAD_PARAM_END_CYCLE(element);
154}
155
156/**
157 * @brief sets the Parent of the WeaponManager.
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.
162 *
163 * The reason this function exists is that the WeaponManager is neither a WorldEntity nor
164 * a PNode.
165 */
166void WeaponManager::setParentEntity(WorldEntity* parent)
167{
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)
180  {
181    for (int i = 0; i < WM_MAX_SLOTS; i++)
182      this->parentNode->addChild(&this->currentSlotConfig[i].position);
183  }
184
185}
186
187
188/**
189 * @brief sets the number of Slots the WeaponManager has
190 * @param slotCount the number of slots
191 */
192void WeaponManager::setSlotCount(unsigned int slotCount)
193{
194  if (slotCount <= WM_MAX_SLOTS)
195    this->slotCount = slotCount;
196  else
197    this->slotCount = WM_MAX_SLOTS;
198}
199
200
201/**
202 * @brief sets the position of the Slot relative to the parent
203 * @param slot the slot to set-up
204 * @param position the position of the given slot
205 */
206void WeaponManager::setSlotPosition(int slot, const Vector& position, PNode* parent)
207{
208  if (slot < this->slotCount)
209  {
210    this->currentSlotConfig[slot].position.setRelCoor(position);
211
212    if (parent != NULL)
213      this->currentSlotConfig[slot].position.setParent(parent);
214  }
215}
216
217
218/**
219 * @brief sets the relative rotation of the slot to its parent
220 * @param slot the slot to set-up
221 * @param rotation the relative rotation of the given slot
222 */
223void WeaponManager::setSlotDirection(int slot, const Quaternion& rotation)
224{
225  if (slot < this->slotCount)
226    this->currentSlotConfig[slot].position.setRelDir(rotation);
227}
228
229
230/**
231 * @brief adds a weapon to the selected weaponconfiguration into the selected slot
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
235 *
236 * if you add explicitly a weapon at config:n, slot:m, the weapon placed at this location will be
237 * replaced by the weapon specified. if you use the WM_FREE_SLOT, the manager will look for a free
238 * slot in this weaponconfiguration. if there is non, the weapon won't be added and there will be
239 * a error message.
240 */
241bool WeaponManager::addWeapon(Weapon* weapon, int configID, int slotID)
242{
243  if ( weapon == NULL )
244    return false;
245
246  if (unlikely(configID >= WM_MAX_CONFIGS || slotID >= (int)this->slotCount))
247  {
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;
253  }
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  }
264
265  if (configID > 0 && slotID > 0 && this->configs[configID][slotID] != NULL)
266  {
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());
268    return false;
269  }
270
271  if (slotID <= -1) // WM_FREE_SLOT
272  {
273    slotID = this->getNextFreeSlot(configID, weapon->getCapability());
274    if( slotID < 0 || slotID >= this->slotCount)
275    {
276      PRINTF(1)("There is no free slot in this WeaponConfig to dock this weapon at! Aborting\n");
277      return false;
278    }
279  }
280
281  if (!(this->currentSlotConfig[slotID].capability & weapon->getCapability() & WTYPE_ALLKINDS) &&
282      this->currentSlotConfig[slotID].capability & weapon->getCapability() & WTYPE_ALLDIRS)
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);
286    return false;
287  }
288
289  //! @todo check if the weapon is already assigned to another config in another slot
290  if (this->configs[configID][slotID] != NULL)
291    return false;
292
293  this->configs[configID][slotID] = weapon;
294  weapon->setAmmoContainer(this->getAmmoContainer(weapon->getProjectileType()));
295  if(configID == this->currentConfigID)
296    this->currentSlotConfig[slotID].nextWeapon = weapon;
297  //if (this->parent != NULL)
298  {
299    this->parentNode->addChild(weapon);
300    if (this->parentEntity->isA(Playable::classID()))
301      dynamic_cast<Playable*>(this->parentEntity)->weaponConfigChanged();
302    weapon->setDefaultTarget(this->crosshair);
303  }
304  PRINTF(3)("Added a new Weapon (%s::%s) to the WeaponManager: config %i/ slot %i\n", weapon->getClassCName(), weapon->getCName(), configID, slotID);
305  return true;
306}
307
308/**
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 */
313float WeaponManager::increaseAmmunition(const ClassID& projectileType, float ammo)
314{
315  return this->getAmmoContainer(projectileType)->increaseEnergy(ammo);
316}
317
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);
326  return this->increaseAmmunition(weapon->getClassID(), ammo);
327
328}
329
330
331/**
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/**
345 * removes a Weapon from the WeaponManager
346 *
347 * !! The weapon must be inactive before you can delete it,    !!
348 * !! because it will still be deactivated (if it is selected) !!
349 */
350void WeaponManager::removeWeapon(Weapon* weapon, int configID)
351{
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  }
369}
370
371
372/**
373 * changes to the next weapon configuration
374 */
375void WeaponManager::nextWeaponConfig()
376{
377  ++this->currentConfigID;
378  if (this->currentConfigID >= WM_MAX_CONFIGS)
379    this->currentConfigID = 0;
380  this->changeWeaponConfig(this->currentConfigID);
381}
382
383/**
384 * changes to the previous configuration
385 */
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
394/**
395 * change to a desired configuration
396 * @param weaponConfig the configuration to jump to.
397 */
398void WeaponManager::changeWeaponConfig(int weaponConfig)
399{
400  this->currentConfigID = weaponConfig;
401  PRINTF(4)("Changing weapon configuration: to %i\n", this->currentConfigID);
402  for (int i = 0; i < WM_MAX_SLOTS; i++)
403    this->currentSlotConfig[i].nextWeapon = this->configs[currentConfigID][i];
404}
405
406
407/**
408 * triggers fire of all weapons in the current weaponconfig
409 */
410void WeaponManager::fire()
411{
412  Weapon* firingWeapon;
413  for(int i = 0; i < this->slotCount; i++)
414  {
415    firingWeapon = this->currentSlotConfig[i].currentWeapon;
416    if( firingWeapon != NULL) firingWeapon->requestAction(WA_SHOOT);
417  }
418  this->crosshair->setRotationSpeed(500);
419  this->crossHairSizeAnim->replay();
420}
421
422
423/**
424 * triggers tick of all weapons in the current weaponconfig
425 * @param second passed since last tick
426 */
427void WeaponManager::tick(float dt)
428{
429  Weapon* tickWeapon;
430
431  for(int i = 0; i < this->slotCount; i++)
432  {
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);*/
437
438    // current Weapon in Slot i
439    tickWeapon = this->currentSlotConfig[i].currentWeapon;
440    // On A change (current != next)
441    if (tickWeapon != this->currentSlotConfig[i].nextWeapon)
442    {
443      // if a Weapon is Active in slot i, deactivate it.
444      if (tickWeapon != NULL )
445      {
446        if (tickWeapon->isActive())
447        {
448          tickWeapon->requestAction(WA_DEACTIVATE);
449          continue;
450        }
451        else
452        {
453          tickWeapon->toList(OM_NULL);
454          this->currentSlotConfig[i].currentWeapon = NULL;
455        }
456      }
457
458      // switching to next Weapon
459      tickWeapon = this->currentSlotConfig[i].currentWeapon = this->currentSlotConfig[i].nextWeapon;
460      if (tickWeapon != NULL)
461      {
462           //        if (this->parent != NULL)
463          tickWeapon->toList(this->parentEntity->getOMListNumber());
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();
470      if (this->parentEntity != NULL && this->parentEntity->isA(Playable::classID()))
471        dynamic_cast<Playable*>(this->parentEntity)->weaponConfigChanged();
472    }
473    else if (unlikely(tickWeapon != NULL && tickWeapon->getCurrentState() == WS_DEACTIVATING))
474      this->currentSlotConfig[i].nextWeapon = NULL;
475  }
476}
477
478
479/**
480 * triggers draw of all weapons in the current weaponconfig
481 */
482void WeaponManager::draw() const
483{
484  assert(false || "must not be called");
485  Weapon* drawWeapon;
486  for (int i = 0; i < this->slotCount; i++)
487  {
488    drawWeapon = this->currentSlotConfig[i].currentWeapon;
489    if( drawWeapon != NULL && drawWeapon->isVisible())
490      drawWeapon->draw();
491  }
492}
493
494
495/**
496 * private gets the next free slot in a certain weaponconfig
497 * @param the selected weaponconfig -1 if none found
498 */
499int WeaponManager::getNextFreeSlot(int configID, long capability)
500{
501  if (configID == -1)
502  {
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;
510      }
511  }
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  }
522  return -1;
523}
524
525CountPointer<AmmoContainer>& WeaponManager::getAmmoContainer(const ClassID& projectileType)
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}
535
536CountPointer<AmmoContainer>& WeaponManager::getAmmoContainer(const Weapon* weapon)
537{
538  assert (weapon != NULL);
539  return (this->getAmmoContainer(weapon->getClassID()));
540}
541
542
543/**
544 * outputs some nice debug information about the WeaponManager
545 */
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)
557        PRINT(3)("Slot %d loaded a %s\n", j, this->configs[i][j]->getClassCName());
558    }
559  }
560}
Note: See TracBrowser for help on using the repository browser.