Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/weapons/weapon.cc @ 10498

Last change on this file since 10498 was 10443, checked in by patrick, 18 years ago

weapon now added to the main model

File size: 22.8 KB
RevLine 
[3573]1
[4597]2/*
[3573]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
[4826]12### File Specific
[3573]13   main-programmer: Patrick Boenzli
[4832]14   co-programmer: Benjamin Grauer
[4885]15
16   2005-07-15: Benjamin Grauer: restructurating the entire Class
[3573]17*/
18
[4885]19#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WEAPON
20
[4828]21#include "weapon.h"
22
[9869]23#include "loading/fast_factory.h"
[6434]24#include "world_entities/projectiles/projectile.h"
[4834]25
[7350]26#include "util/loading/factory.h"
[7193]27#include "util/loading/load_param.h"
[4828]28#include "state.h"
[4885]29#include "animation3d.h"
[3573]30
[5930]31#include "sound_source.h"
32#include "sound_buffer.h"
[9869]33#include "resource_sound_buffer.h"
[5930]34
[10368]35#include "elements/glgui_energywidgetvertical.h"
[6438]36
[9869]37ObjectListDefinition(Weapon);
[7350]38
[4892]39////////////////////
40// INITAILISATION //
41// SETTING VALUES //
42////////////////////
[3870]43/**
[4885]44 * standard constructor
45 *
46 * creates a new weapon
[3575]47*/
[5750]48Weapon::Weapon ()
[3620]49{
[4885]50  this->init();
[3620]51}
[3573]52
[3575]53/**
[4885]54 * standard deconstructor
[3575]55*/
[4597]56Weapon::~Weapon ()
[3573]57{
[4885]58  for (int i = 0; i < WS_STATE_COUNT; i++)
[9869]59    if (this->animation[i] && Animation::objectList().exists(animation[i]))  //!< @todo this should check animation3D
[4885]60      delete this->animation[i];
[4959]61
[9869]62  if (OrxSound::SoundSource::objectList().exists(this->soundSource))
[4959]63    delete this->soundSource;
[4885]64}
[4597]65
[4885]66/**
[7350]67 * @brief creates a new Weapon of type weaponID and returns it.
68 * @param weaponID the WeaponID type to create.
69 * @returns the newly created Weapon.
70 */
[9869]71Weapon* Weapon::createWeapon(const ClassID& weaponID)
[7350]72{
73  BaseObject* createdObject = Factory::fabricate(weaponID);
74  if (createdObject != NULL)
75  {
[9869]76    if (createdObject->isA(Weapon::staticClassID()))
[7350]77      return dynamic_cast<Weapon*>(createdObject);
78    else
79    {
80      delete createdObject;
81      return NULL;
82    }
83  }
[8316]84  return NULL;
[7350]85}
86
[9869]87Weapon* Weapon::createWeapon(const std::string& weaponName)
88{
89  BaseObject* createdObject = Factory::fabricate(weaponName);
90  if (createdObject != NULL)
91  {
92    if (createdObject->isA(Weapon::staticClassID()))
93      return dynamic_cast<Weapon*>(createdObject);
94    else
95    {
96      delete createdObject;
97      return NULL;
98    }
99  }
100  return NULL;
101}
102
103
[7350]104/**
[4885]105 * initializes the Weapon with ALL default values
[5498]106 *
107 * This Sets the default values of the Weapon
[4885]108 */
109void Weapon::init()
110{
[9869]111  this->registerObject(this, Weapon::_objectList);
[5498]112  this->currentState     = WS_INACTIVE;            //< Normaly the Weapon is Inactive
113  this->requestedAction  = WA_NONE;                //< No action is requested by default
114  this->stateDuration    = 0.0;                    //< All the States have zero duration
115  for (int i = 0; i < WS_STATE_COUNT; i++)         //< Every State has:
[6438]116  {
117    this->times[i] = 0.0;                        //< An infinitesimal duration
118    this->animation[i] = NULL;                   //< No animation
119  }
[3888]120
[10368]121  this->soundSource = new OrxSound::SoundSource(this);       //< Every Weapon has exacty one SoundSource
[4885]122
[10368]123  this->barrels = 1;
124  this->segs = 1;
125
[10443]126  this->preferedSide = -1;
127  this->preferedSlot = -1;
128
[10368]129  this->shootAnim = new Animation3D**[this->getBarrels()];
130  for (int i = 0; i < this->getBarrels(); i++)
131    this->shootAnim[i] = new Animation3D* [this->getSegs()];
132
133  this->emissionPoint = new PNode*[this->barrels];
134  for(int i = 0; i < this->barrels; i++){
135    this->emissionPoint[i] = new PNode;
136    this->emissionPoint[i]->setParent(this);             //< One EmissionPoint, that is a PNode connected to the weapon. You can set this to the exitting point of the Projectiles
137    this->emissionPoint[i]->setName("EmissionPoint");
138    this->emissionPoint[i]->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
139  }
140
[6920]141  this->defaultTarget = NULL;                      //< Nothing is Targeted by default.
[6756]142
[9869]143  this->projectile = NullClass::staticClassID();         //< No Projectile Class is Connected to this weapon
[5498]144  this->projectileFactory = NULL;                  //< No Factory generating Projectiles is selected.
[4885]145
[5498]146  this->hideInactive = true;                       //< The Weapon will be hidden if it is inactive (by default)
[4906]147
[5498]148  this->minCharge = 1.0;                           //< The minimum charge the Weapon can hold is 1 unit.
149  this->maxCharge = 1.0;                           //< The maximum charge is also one unit.
[4927]150
[6671]151  this->energy = 10;                               //< The secondary Buffer (before we have to reload)
[5498]152  this->energyMax = 10.0;                          //< How much energy can be carried
153  this->capability = WTYPE_ALL;                    //< The Weapon has all capabilities @see W_Capability.
[6438]154
155  this->energyWidget = NULL;
[6695]156
157  // set this object to be synchronized over network
158  //this->setSynchronized(true);
[3573]159}
160
[5498]161/**
[10368]162 * needed, if there are more than one barrel or segments
163 */
[10443]164void Weapon::init2()
[10368]165{
166  if (this->barrels == 1 && this->segs == 1)
167    return;
168
169  delete this->emissionPoint[0];
170  delete this->emissionPoint;
171  delete this->shootAnim[0];
172  delete this->shootAnim;
173
174  this->shootAnim = new Animation3D**[this->barrels];
175  this->emissionPoint = new PNode*[this->barrels];
176  for(int i = 0; i < this->barrels; i++){
177    this->emissionPoint[i] = new PNode;
178    this->emissionPoint[i]->setParent(this);             //< One EmissionPoint, that is a PNode connected to the weapon. You can set this to the exitting point of the Projectiles
179    this->emissionPoint[i]->setName("EmissionPoint");
180    this->emissionPoint[i]->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
181    this->shootAnim[i] = new Animation3D* [this->segs];
182  }
183}
184
185/**
186 * deconstructor for init2
187 */
188void Weapon::deconstr()
189{
190  for(int i = 0; i < this->barrels; i++) {
191    delete this->emissionPoint[i];
192    for (int j = 0; j < this->segs; j++)
193      delete this->shootAnim[i][j];
194    delete this->shootAnim[i];
195  }
196
197  delete this->emissionPoint;
198  delete this->shootAnim;
199}
200
201/**
[5498]202 * loads the Parameters of a Weapon
203 * @param root the XML-Element to load the Weapons settings from
204 */
[4972]205void Weapon::loadParams(const TiXmlElement* root)
206{
[6512]207  WorldEntity::loadParams(root);
[4972]208
[7102]209  LoadParam(root, "projectile", this, Weapon, setProjectileTypeC)
[6438]210  .describe("Sets the name of the Projectile to load onto the Entity");
[10443]211
212  LoadParam(root, "energy", this, Weapon, setEnergyMax)
213  .describe("number of shoots/ energy whatever");
214
215  LoadParam(root, "slot", this, Weapon, setPreferedSlot)
216  .describe("slot this weapon will be added");
[10368]217/*
[5671]218  LoadParam(root, "emission-point", this, Weapon, setEmissionPoint)
[10368]219  .describe("Sets the Point of emission of this weapon (1: EmmsionVector; 2: EmissionPoint)");*/
[4972]220
[5671]221  LoadParam(root, "state-duration", this, Weapon, setStateDuration)
[6438]222  .describe("Sets the duration of a given state (1: state-Name; 2: duration in seconds)");
[4972]223
[5671]224  LoadParam(root, "action-sound", this, Weapon, setActionSound)
[6438]225  .describe("Sets a given sound to an action (1: action-Name; 2: name of the sound (relative to the Data-Path))");
[4972]226}
227
[6728]228
[4947]229/**
230 * sets the Projectile to use for this weapon.
231 * @param projectile The ID of the Projectile to use
[4950]232 * @returns true, if it was sucessfull, false on error
[4947]233 *
[5498]234 * be aware, that this function does not create Factories, as this is job of Projecitle/Bullet-classes.
235 * What it does, is telling the Weapon what Projectiles it can Emit.
[4947]236 */
[9869]237void Weapon::setProjectileType(const ClassID& projectile)
[4947]238{
239  this->projectile = projectile;
240  this->projectileFactory = FastFactory::searchFastFactory(projectile);
241  if (this->projectileFactory == NULL)
[4979]242  {
243    PRINTF(1)("unable to find FastFactory for the Projectile.\n");
[4972]244    return;
[4979]245  }
[4948]246  else
247  {
248    // grabbing Parameters from the Projectile to have them at hand here.
249    Projectile* pj = dynamic_cast<Projectile*>(this->projectileFactory->resurrect());
[6431]250    this->minCharge = pj->getMinEnergy();
[6700]251    this->maxCharge = pj->getHealthMax();
[4948]252    this->chargeable = pj->isChageable();
[4979]253    this->projectileFactory->kill(pj);
[4948]254  }
[4979]255}
[3573]256
[6728]257
[4891]258/**
[4950]259 * @see bool Weapon::setProjectile(ClassID projectile)
260 * @param projectile the Name of the Projectile.
261 */
[7221]262void Weapon::setProjectileTypeC(const std::string& projectile)
[4950]263{
264  FastFactory* tmpFac = FastFactory::searchFastFactory(projectile);
265  if (tmpFac != NULL)
266  {
[5356]267    this->setProjectileType(tmpFac->getStoredID());
[4950]268  }
[4972]269  else
270  {
[9406]271    PRINTF(1)("Projectile %s does not exist for weapon %s\n", projectile.c_str(), this->getCName());
[4972]272  }
[4950]273}
274
[6728]275
[4950]276/**
[5356]277 * prepares Projectiles of the Weapon
[5498]278 * @param count how many Projectiles to create (they will be stored in the ProjectileFactory)
[5356]279 */
280void Weapon::prepareProjectiles(unsigned int count)
281{
[5357]282  if (likely(this->projectileFactory != NULL))
[5356]283    projectileFactory->prepare(count);
284  else
[9406]285    PRINTF(2)("unable to create %d projectile for Weapon %s::%s\n", count, this->getClassCName(), this->getCName());
[5356]286}
287
[6728]288
[5356]289/**
290 * resurects and returns a Projectile
[5498]291 * @returns a Projectile on success, NULL on error
292 *
293 * errors: 1. (ProjectileFastFactory not Found)
294 *         2. No more Projectiles availiable.
[5356]295 */
296Projectile* Weapon::getProjectile()
297{
[5357]298  if (likely (this->projectileFactory != NULL))
[6142]299  {
300    Projectile* pj = dynamic_cast<Projectile*>(this->projectileFactory->resurrect());
301    pj->toList((OM_LIST)(this->getOMListNumber()+1));
302    return pj;
303  }
[5356]304  else
305  {
[9406]306    PRINTF(2)("No projectile defined for Weapon %s(%s) can't return any\n", this->getCName(), this->getClassCName());
[5356]307    return NULL;
308  }
309}
310
311
312/**
[4892]313 * sets the emissionPoint's relative position from the Weapon
314 * @param point the Point relative to the mass-point of the Weapon
315 */
[10368]316void Weapon::setEmissionPoint(const Vector& point, int barrel)
317{
318  this->emissionPoint[barrel]->setRelCoor(point);
319}
320
[4892]321void Weapon::setEmissionPoint(const Vector& point)
322{
[10368]323  this->emissionPoint[0]->setRelCoor(point);
[4892]324}
325
326/**
[4891]327 * assigns a Sound-file to an action
328 * @param action the action the sound should be assigned too
329 * @param soundFile the soundFile's relative position to the data-directory (will be looked for by the ResourceManager)
330 */
[7221]331void Weapon::setActionSound(WeaponAction action, const std::string& soundFile)
[4885]332{
333  if (action >= WA_ACTION_COUNT)
334    return;
[4930]335
[7221]336  else if (!soundFile.empty())
[4885]337  {
[9869]338    this->soundBuffers[action] = OrxSound::ResourceSoundBuffer(soundFile);
339    if (this->soundBuffers[action].loaded())
[4885]340    {
[7221]341      PRINTF(4)("Loaded sound %s to action %s.\n", soundFile.c_str(), actionToChar(action));
[4885]342    }
343    else
344    {
[7221]345      PRINTF(2)("Failed to load sound %s to %s.\n.", soundFile.c_str(), actionToChar(action));
[4885]346    }
347  }
348  else
[9869]349    this->soundBuffers[action] = OrxSound::SoundBuffer();
[4885]350}
351
[6728]352
[4893]353/**
[4895]354 * creates/returns an Animation3D for a certain State.
355 * @param state what State should the Animation be created/returned for
356 * @param node the node this Animation should apply to. (NULL is fine if the animation was already created)
357 * @returns The created animation.Animation(), NULL on error (or if the animation does not yet exist).
[4893]358 *
359 * This function does only generate the Animation Object, and if set it will
360 * automatically be executed, when a certain State is reached.
361 * What this does not do, is set keyframes, you have to operate on the returned animation.
362 */
[4895]363Animation3D* Weapon::getAnimation(WeaponState state, PNode* node)
[4893]364{
[4895]365  if (state >= WS_STATE_COUNT) // if the state is not known
[4893]366    return NULL;
367
[4895]368  if (unlikely(this->animation[state] == NULL)) // if the animation does not exist yet create it.
[4893]369  {
[4895]370    if (likely(node != NULL))
371      return this->animation[state] = new Animation3D(node);
372    else
373    {
374      PRINTF(2)("Node not defined for the Creation of the 3D-animation of state %s\n", stateToChar(state));
375      return NULL;
376    }
[4893]377  }
[4895]378  else
379    return this->animation[state];
[4893]380}
381
[10368]382Animation3D* Weapon::getAnimation(int barrel, int seg, PNode* node)
383{
384  if (barrel >= this->getBarrels() || seg >= this->getSegs()) // if the state is not known
385    return NULL;
386
387  if (unlikely(this->shootAnim[barrel][seg] == NULL)) // if the animation does not exist yet create it.
388  {
389    if (likely(node != NULL))
390      return this->shootAnim[barrel][seg] = new Animation3D(node);
391    else
392    {
393//       PRINTF(2)("Node not defined for the Creation of the 3D-animation of state %s\n", stateToChar(state));
394      return NULL;
395    }
396  }
397  else
398    return this->shootAnim[barrel][seg];
399}
400
[7779]401OrxGui::GLGuiWidget* Weapon::getEnergyWidget()
[6438]402{
[10368]403  if ( this->energyWidget == NULL)
[6438]404  {
[10368]405    this->energyWidget = new OrxGui::GLGuiEnergyWidgetVertical();
406    //this->energyWidget->setDisplayedName(this->getClassCName());
[6438]407    this->energyWidget->setSize2D( 20, 100);
408    this->energyWidget->setMaximum(this->getEnergyMax());
409    this->energyWidget->setValue(this->getEnergy());
410  }
411  return this->energyWidget;
412}
413
414void Weapon::updateWidgets()
415{
416  if (this->energyWidget != NULL)
417  {
418    this->energyWidget->setMaximum(this->energyMax);
419    this->energyWidget->setValue(this->energy);
420  }
421}
422
[4892]423/////////////////
424//  EXECUTION  //
425// GAME ACTION //
426/////////////////
[4597]427/**
[4885]428 * request an action that should be executed,
429 * @param action the next action to take
430 *
431 * This function must be called instead of the actions (like fire/reload...)
432 * to make all the checks needed to have a usefull WeaponSystem.
433 */
434void Weapon::requestAction(WeaponAction action)
435{
[4906]436  if (likely(this->isActive()))
[4885]437  {
[10368]438    /** Disabled for releaseFire() from WM*/
[4906]439    if (this->requestedAction != WA_NONE)
440      return;
[5041]441    PRINTF(5)("next action will be %s in %f seconds\n", actionToChar(action), this->stateDuration);
[4885]442    this->requestedAction = action;
443  }
[4906]444  //else
445  else if (unlikely(action == WA_ACTIVATE))
446  {
447    this->currentState = WS_ACTIVATING;
[4926]448    this->requestedAction = WA_ACTIVATE;
[4906]449  }
[4885]450}
[3577]451
[6728]452
[4890]453/**
454 * adds energy to the Weapon
455 * @param energyToAdd The amount of energy
456 * @returns the amount of energy we did not pick up, because the weapon is already full
457 */
458float Weapon::increaseEnergy(float energyToAdd)
459{
460  float maxAddEnergy = this->energyMax - this->energy;
461
462  if (maxAddEnergy >= energyToAdd)
463  {
464    this->energy += energyToAdd;
[10368]465    this->updateWidgets();
[4890]466    return 0.0;
467  }
468  else
469  {
470    this->energy += maxAddEnergy;
[10368]471    this->updateWidgets();
[4890]472    return energyToAdd - maxAddEnergy;
473  }
[10443]474
[4890]475}
476
[6728]477
[5498]478////////////////////////////////////////////////////////////
479// WEAPON INTERNALS                                       //
480// These are functions, that no other Weapon should over- //
481// write. No class has direct Access to them, as it is    //
482// quite a complicated process, handling a Weapon from    //
483// the outside                                            //
484////////////////////////////////////////////////////////////
[4891]485/**
486 * executes an action, and with it starts a new State.
487 * @return true, if it worked, false otherwise
488 *
489 * This function checks, wheter the possibility of executing an action is valid,
490 * and does all the necessary stuff, to execute them. If an action does not succeed,
491 * it tries to go around it. (ex. shoot->noAmo->reload()->wait until shoot comes again)
492 */
[4885]493bool Weapon::execute()
[3583]494{
[7729]495#if DEBUG_LEVEL > 4
[4885]496  PRINTF(4)("trying to execute action %s\n", actionToChar(this->requestedAction));
497  this->debug();
[4906]498#endif
[4885]499
[4926]500  WeaponAction action = this->requestedAction;
501  this->requestedAction = WA_NONE;
502
503  switch (action)
[4885]504  {
[7350]505    case WA_SHOOT:
[9869]506    return this->fireW();
507    break;
[7350]508    case WA_CHARGE:
[9869]509    return this->chargeW();
510    break;
[7350]511    case WA_RELOAD:
[9869]512    return this->reloadW();
513    break;
[7350]514    case WA_DEACTIVATE:
[9869]515    return this->deactivateW();
516    break;
[7350]517    case WA_ACTIVATE:
[9869]518    return this->activateW();
519    break;
[8316]520    default:
[10368]521    PRINTF(5)("Action %s Not Implemented yet \n", Weapon::actionToChar(action));
[9869]522    return false;
[4885]523  }
[3583]524}
[3577]525
[4597]526/**
[4894]527 * checks and activates the Weapon.
528 * @return true on success.
[4892]529 */
530bool Weapon::activateW()
[3583]531{
[6438]532  //  if (this->currentState == WS_INACTIVE)
[4892]533  {
[6433]534    // play Sound
[9869]535    if (likely(this->soundBuffers[WA_ACTIVATE].loaded()))
[4892]536      this->soundSource->play(this->soundBuffers[WA_ACTIVATE]);
[6444]537    this->updateWidgets();
[6438]538    // activate
[9406]539    PRINTF(4)("Activating the Weapon %s\n", this->getCName());
[4892]540    this->activate();
[4895]541    // setting up for next action
[4926]542    this->enterState(WS_ACTIVATING);
[4892]543  }
[8316]544  return true;
[3583]545}
[3577]546
[4597]547/**
[4894]548 * checks and deactivates the Weapon
549 * @return true on success.
[4892]550 */
551bool Weapon::deactivateW()
[3583]552{
[6438]553  //  if (this->currentState != WS_INACTIVE)
[4892]554  {
[9406]555    PRINTF(4)("Deactivating the Weapon %s\n", this->getCName());
[6438]556    // play Sound
[9869]557    if (this->soundBuffers[WA_DEACTIVATE].loaded())
[4892]558      this->soundSource->play(this->soundBuffers[WA_DEACTIVATE]);
[4926]559    // deactivate
[4892]560    this->deactivate();
[4926]561    this->enterState(WS_DEACTIVATING);
[4892]562  }
[8316]563
564  return true;
[3583]565}
[3577]566
[4892]567/**
[4894]568 * checks and charges the Weapon
569 * @return true on success.
[4892]570 */
571bool Weapon::chargeW()
[4885]572{
[6671]573  if ( this->currentState != WS_INACTIVE && this->energy >= this->minCharge)
[4892]574  {
[6438]575    // playing Sound
[9869]576    if (this->soundBuffers[WA_CHARGE].loaded())
[4892]577      this->soundSource->play(this->soundBuffers[WA_CHARGE]);
[4893]578
[6438]579    // charge
[4892]580    this->charge();
[6438]581    // setting up for the next state
[4926]582    this->enterState(WS_CHARGING);
[4892]583  }
584  else // deactivate the Weapon if we do not have enough energy
585  {
586    this->requestAction(WA_RELOAD);
587  }
[8316]588  return true;
[4885]589}
[3573]590
[4892]591/**
[4894]592 * checks and fires the Weapon
593 * @return true on success.
[4892]594 */
595bool Weapon::fireW()
[3575]596{
[10368]597//   printf("fireW Weapon\n");
[6438]598  //if (likely(this->currentState != WS_INACTIVE))
[6671]599  if (this->minCharge <= this->energy)
[4892]600  {
[6438]601    // playing Sound
[9869]602    if (this->soundBuffers[WA_SHOOT].loaded())
[4892]603      this->soundSource->play(this->soundBuffers[WA_SHOOT]);
[6438]604    // fire
[6671]605    this->energy -= this->minCharge;
[4892]606    this->fire();
[6438]607    // setting up for the next state
[4926]608    this->enterState(WS_SHOOTING);
[10368]609    this->updateWidgets();
[4892]610  }
611  else  // reload if we still have the charge
612  {
613    this->requestAction(WA_RELOAD);
[4930]614    this->execute();
[4892]615  }
[8316]616  return true;
[4892]617}
618
619/**
[4894]620 * checks and Reloads the Weapon
621 * @return true on success.
[4892]622 */
623bool Weapon::reloadW()
624{
[9406]625  PRINTF(4)("Reloading Weapon %s\n", this->getCName());
[9869]626  if (!this->ammoContainer.isNull() &&
[7350]627      unlikely(this->energy + this->ammoContainer->getStoredEnergy() < this->minCharge))
[4885]628  {
[10368]629    //this->requestAction(WA_DEACTIVATE);
[4930]630    this->execute();
[4892]631    return false;
[4885]632  }
[3573]633
634
[9869]635  if (this->soundBuffers[WA_RELOAD].loaded())
[4892]636    this->soundSource->play(this->soundBuffers[WA_RELOAD]);
637
[9869]638  if (!this->ammoContainer.isNull())
[6671]639    this->ammoContainer->fillWeapon(this);
[4885]640  else
641  {
[6671]642    this->energy = this->energyMax;
[4885]643  }
[6444]644  this->updateWidgets();
[4892]645  this->reload();
[4926]646  this->enterState(WS_RELOADING);
[8316]647
648  return true;
[4926]649}
[3575]650
[4926]651/**
652 * enters the requested State, plays back animations updates the timing.
653 * @param state the state to enter.
654 */
655inline void Weapon::enterState(WeaponState state)
656{
[5041]657  PRINTF(4)("ENTERING STATE %s\n", stateToChar(state));
[4926]658  // playing animation if availiable
659  if (likely(this->animation[state] != NULL))
660    this->animation[state]->replay();
661
[6728]662  this->stateDuration += this->times[state];
[4926]663  this->currentState = state;
[3575]664}
665
[4927]666///////////////////
667//  WORLD-ENTITY //
668// FUNCTIONALITY //
669///////////////////
[3575]670/**
[4885]671 * tick signal for time dependent/driven stuff
[3575]672*/
[6736]673bool Weapon::tickW(float dt)
[4885]674{
[4934]675  //printf("%s ", stateToChar(this->currentState));
[4910]676
[4885]677  // setting up the timing properties
678  this->stateDuration -= dt;
[3575]679
[4949]680  if (this->stateDuration <= 0.0)
[4885]681  {
[4949]682    if (unlikely (this->currentState == WS_DEACTIVATING))
[4885]683    {
[4949]684      this->currentState = WS_INACTIVE;
[6736]685      return false;
[4949]686    }
687    else
688      this->currentState = WS_IDLE;
[4906]689
[4949]690    if (this->requestedAction != WA_NONE)
691    {
692      this->stateDuration = -dt;
693      this->execute();
[4885]694    }
695  }
[6736]696  return true;
[4885]697}
698
[3575]699
700
701
[4885]702//////////////////////
703// HELPER FUNCTIONS //
704//////////////////////
[3576]705/**
[4891]706 * checks wether all the Weapons functions are valid, and if it is possible to go to action with it.
[5498]707 * @todo IMPLEMENT the Weapons Check
[4891]708 */
709bool Weapon::check() const
710{
711  bool retVal = true;
712
[6438]713  //  if (this->projectile == NULL)
[4891]714  {
[5041]715    PRINTF(1)("There was no projectile assigned to the Weapon.\n");
[4891]716    retVal = false;
717  }
718
719
720
721
722  return retVal;
723}
724
725/**
[4885]726 * some nice debugging information about this Weapon
727 */
728void Weapon::debug() const
729{
[9406]730  PRINT(0)("Weapon-Debug %s, state: %s (duration: %fs), nextAction: %s\n", this->getCName(), Weapon::stateToChar(this->currentState), this->stateDuration, Weapon::actionToChar(requestedAction));
[6671]731  PRINT(0)("Energy: max: %f; current: %f; chargeMin: %f, chargeMax %f\n",
732           this->energyMax, this->energy, this->minCharge, this->maxCharge);
[4967]733
734
[4885]735}
[3575]736
[5498]737////////////////////////////////////////////////////////
738// static Definitions (transormators for readability) //
739////////////////////////////////////////////////////////
[4885]740/**
741 * Converts a String into an Action.
742 * @param action the String input holding the Action.
743 * @return The Action if known, WA_NONE otherwise.
744 */
[7221]745WeaponAction Weapon::charToAction(const std::string& action)
[4885]746{
[7221]747  if (action == "none")
[4885]748    return WA_NONE;
[7221]749  else if (action == "shoot")
[4885]750    return WA_SHOOT;
[7221]751  else if (action == "charge")
[4885]752    return WA_CHARGE;
[7221]753  else if (action == "reload")
[4885]754    return WA_RELOAD;
[7221]755  else if (action == "acitvate")
[4885]756    return WA_ACTIVATE;
[7221]757  else if (action == "deactivate")
[4885]758    return WA_DEACTIVATE;
[7221]759  else if (action == "special1")
[4885]760    return WA_SPECIAL1;
761  else
[6438]762  {
[7221]763    PRINTF(2)("action %s could not be identified.\n", action.c_str());
[6438]764    return WA_NONE;
765  }
[4885]766}
[3575]767
768/**
[4885]769 * converts an action into a String
770 * @param action the action to convert
771 * @return a String matching the name of the action
772 */
773const char* Weapon::actionToChar(WeaponAction action)
774{
775  switch (action)
776  {
[7350]777    case WA_SHOOT:
[9869]778    return "shoot";
779    break;
[7350]780    case WA_CHARGE:
[9869]781    return "charge";
782    break;
[7350]783    case WA_RELOAD:
[9869]784    return "reload";
785    break;
[7350]786    case WA_ACTIVATE:
[9869]787    return "activate";
788    break;
[7350]789    case WA_DEACTIVATE:
[9869]790    return "deactivate";
791    break;
[7350]792    case WA_SPECIAL1:
[9869]793    return "special1";
794    break;
[7350]795    default:
[9869]796    return "none";
797    break;
[4885]798  }
799}
[3577]800
801/**
[4885]802 * Converts a String into a State.
803 * @param state the String input holding the State.
804 * @return The State if known, WS_NONE otherwise.
805 */
[7221]806WeaponState Weapon::charToState(const std::string& state)
[4885]807{
[7221]808  if (state == "none")
[4885]809    return WS_NONE;
[7221]810  else if (state == "shooting")
[4885]811    return WS_SHOOTING;
[7221]812  else if (state == "charging")
[4885]813    return WS_CHARGING;
[7221]814  else if (state == "reloading")
[4885]815    return WS_RELOADING;
[7221]816  else if (state == "activating")
[4885]817    return WS_ACTIVATING;
[7221]818  else if (state == "deactivating")
[4885]819    return WS_DEACTIVATING;
[7221]820  else if (state == "inactive")
[4885]821    return WS_INACTIVE;
[7221]822  else if (state == "idle")
[4885]823    return WS_IDLE;
824  else
[6438]825  {
[7221]826    PRINTF(2)("state %s could not be identified.\n", state.c_str());
[6438]827    return WS_NONE;
828  }
[4885]829}
[3583]830
831/**
[4885]832 * converts a State into a String
833 * @param state the state to convert
834 * @return a String matching the name of the state
835 */
836const char* Weapon::stateToChar(WeaponState state)
837{
838  switch (state)
839  {
[7350]840    case WS_SHOOTING:
[9869]841    return "shooting";
842    break;
[7350]843    case WS_CHARGING:
[9869]844    return "charging";
845    break;
[7350]846    case WS_RELOADING:
[9869]847    return "reloading";
848    break;
[7350]849    case WS_ACTIVATING:
[9869]850    return "activating";
851    break;
[7350]852    case WS_DEACTIVATING:
[9869]853    return "deactivating";
854    break;
[7350]855    case WS_IDLE:
[9869]856    return "idle";
857    break;
[7350]858    case WS_INACTIVE:
[9869]859    return "inactive";
860    break;
[7350]861    default:
[9869]862    return "none";
863    break;
[4885]864  }
865}
Note: See TracBrowser for help on using the repository browser.