Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/playability/src/world_entities/weapons/weapon.cc @ 10229

Last change on this file since 10229 was 10229, checked in by nicolasc, 17 years ago

spikeball still not working, doing a manual hack

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