Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4895 was 4895, checked in by bensch, 19 years ago

orxonox/trunk: messed things up a bit, try fixing

File size: 14.0 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-15: Benjamin Grauer: restructurating the entire Class
17*/
18
19#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WEAPON
20
21#include "weapon.h"
22
23#include "projectile.h"
24
25#include "class_list.h"
26#include "load_param.h"
27#include "vector.h"
28#include "list.h"
29#include "state.h"
30#include "animation3d.h"
31#include "sound_engine.h"
32
33////////////////////
34// INITAILISATION //
35// SETTING VALUES //
36////////////////////
37/**
38 * standard constructor
39 *
40 * creates a new weapon
41*/
42Weapon::Weapon (PNode* parent, const Vector& coordinate, const Quaternion& direction)
43{
44  this->init();
45  parent->addChild(this, PNODE_ALL);
46  this->setRelCoor(coordinate);
47  this->setRelDir(direction);
48}
49
50/**
51 * standard deconstructor
52*/
53Weapon::~Weapon ()
54{
55  for (int i = 0; i < WS_STATE_COUNT; i++)
56    if (this->animation[i] && ClassList::exists(animation[i], CL_ANIMATION))  //!< @todo this should check animation3D
57      delete this->animation[i];
58  for (int i = 0; i < WA_ACTION_COUNT; i++)
59    if (this->soundBuffers[i])
60      ResourceManager::getInstance()->unload(this->soundBuffers[i]);
61}
62
63/**
64 * initializes the Weapon with ALL default values
65 */
66void Weapon::init()
67{
68  this->currentState     = WS_INACTIVE;
69  this->requestedAction  = WA_NONE;
70  this->stateDuration    = 0.0;
71  for (int i = 0; i < WS_STATE_COUNT; i++)
72    {
73      this->times[i] = 0.0;
74      this->animation[i] = NULL;
75    }
76  for (int i = 0; i < WA_ACTION_COUNT; i++)
77    this->soundBuffers[i] = NULL;
78
79  this->requestedAction = WA_NONE;
80  this->soundSource = new SoundSource(this);
81  this->emissionPoint.setParent(this);
82
83  this->active = true;
84  this->projectile = NULL;
85
86  this->minCharge = 1.0;
87  this->maxCharge = 1.0;
88  this->energyLoaded = .0;
89  this->energyLoadedMax = 10.0;
90  this->energy = .0;
91  this->energyMax = 100.0;
92}
93
94
95/**
96 * sets the emissionPoint's relative position from the Weapon
97 * @param point the Point relative to the mass-point of the Weapon
98 */
99void Weapon::setEmissionPoint(const Vector& point)
100{
101  this->emissionPoint.setRelCoor(point);
102}
103
104/**
105 * assigns a Sound-file to an action
106 * @param action the action the sound should be assigned too
107 * @param soundFile the soundFile's relative position to the data-directory (will be looked for by the ResourceManager)
108 */
109void Weapon::setActionSound(WeaponAction action, const char* soundFile)
110{
111  if (action >= WA_ACTION_COUNT)
112    return;
113  else if (soundFile != NULL)
114  {
115    this->soundBuffers[action] = (SoundBuffer*)ResourceManager::getInstance()->load(soundFile, WAV);
116    if (this->soundBuffers[action] != NULL)
117    {
118      PRINTF(4)("Loaded sound %s to action %s\n", soundFile, actionToChar(action));
119    }
120    else
121    {
122      PRINTF(4)("failed to load sound %s to %s\n", soundFile, actionToChar(action));
123    }
124  }
125  else
126    this->soundBuffers[action] = NULL;
127}
128
129
130/**
131 * creates/returns an Animation3D for a certain State.
132 * @param state what State should the Animation be created/returned for
133 * @param node the node this Animation should apply to. (NULL is fine if the animation was already created)
134 * @returns The created animation.Animation(), NULL on error (or if the animation does not yet exist).
135 *
136 * This function does only generate the Animation Object, and if set it will
137 * automatically be executed, when a certain State is reached.
138 * What this does not do, is set keyframes, you have to operate on the returned animation.
139 */
140Animation3D* Weapon::getAnimation(WeaponState state, PNode* node)
141{
142  if (state >= WS_STATE_COUNT) // if the state is not known
143    return NULL;
144
145  if (unlikely(this->animation[state] == NULL)) // if the animation does not exist yet create it.
146  {
147    if (likely(node != NULL))
148      return this->animation[state] = new Animation3D(node);
149    else
150    {
151      PRINTF(2)("Node not defined for the Creation of the 3D-animation of state %s\n", stateToChar(state));
152      return NULL;
153    }
154  }
155  else
156    return this->animation[state];
157}
158
159
160/////////////////
161//  EXECUTION  //
162// GAME ACTION //
163/////////////////
164/**
165 * request an action that should be executed,
166 * @param action the next action to take
167 *
168 * This function must be called instead of the actions (like fire/reload...)
169 * to make all the checks needed to have a usefull WeaponSystem.
170 */
171void Weapon::requestAction(WeaponAction action)
172{
173  if (this->requestedAction != WA_NONE)
174    return;
175  else
176  {
177    printf("next action will be %s in %f seconds\n", actionToChar(action), this->stateDuration);
178    this->requestedAction = action;
179  }
180}
181
182
183/**
184 * adds energy to the Weapon
185 * @param energyToAdd The amount of energy
186 * @returns the amount of energy we did not pick up, because the weapon is already full
187 */
188float Weapon::increaseEnergy(float energyToAdd)
189{
190  float maxAddEnergy = this->energyMax - this->energy;
191
192  if (maxAddEnergy >= energyToAdd)
193  {
194    this->energy += energyToAdd;
195    return 0.0;
196  }
197  else
198  {
199    this->energy += maxAddEnergy;
200    return energyToAdd - maxAddEnergy;
201  }
202}
203
204//////////////////////
205// WEAPON INTERNALS //
206//////////////////////
207/**
208 * executes an action, and with it starts a new State.
209 * @return true, if it worked, false otherwise
210 *
211 * This function checks, wheter the possibility of executing an action is valid,
212 * and does all the necessary stuff, to execute them. If an action does not succeed,
213 * it tries to go around it. (ex. shoot->noAmo->reload()->wait until shoot comes again)
214 */
215bool Weapon::execute()
216{
217
218  PRINTF(4)("trying to execute action %s\n", actionToChar(this->requestedAction));
219  this->debug();
220
221  switch (this->requestedAction)
222  {
223    case WA_SHOOT:
224      return this->fireW();
225      break;
226    case WA_CHARGE:
227      return this->chargeW();
228      break;
229    case WA_RELOAD:
230      return this->reloadW();
231      break;
232    case WA_DEACTIVATE:
233      return this->deactivateW();
234      break;
235    case WA_ACTIVATE:
236      return this->activateW();
237      break;
238  }
239}
240
241
242/**
243 * checks and activates the Weapon.
244 * @return true on success.
245 */
246bool Weapon::activateW()
247{
248//  if (this->currentState == WS_INACTIVE)
249  {
250        // play Sound
251    if (likely(this->soundBuffers[WA_ACTIVATE] != NULL))
252      this->soundSource->play(this->soundBuffers[WA_ACTIVATE]);
253    if (likely(this->animation[WS_ACTIVATING] != NULL))
254      this->animation[WS_ACTIVATING]->replay();
255        // activate
256    PRINTF(4)("Activating the Weapon %s\n", this->getName());
257    this->activate();
258    this->active = true;
259    // setting up for next action
260    this->stateDuration = this->times[WA_ACTIVATE] + this->stateDuration;
261  }
262  this->requestedAction = WA_NONE;
263}
264
265
266/**
267 * checks and deactivates the Weapon
268 * @return true on success.
269 */
270bool Weapon::deactivateW()
271{
272  if (this->currentState != WS_INACTIVE)
273  {
274    PRINTF(4)("Deactivating the Weapon %s\n", this->getName());
275        // play Sound
276    if (this->soundBuffers[WA_DEACTIVATE] != NULL)
277      this->soundSource->play(this->soundBuffers[WA_DEACTIVATE]);
278    if (likely(this->animation[WS_DEACTIVATING] != NULL))
279      this->animation[WS_DEACTIVATING]->replay();
280        // deactivate
281    this->deactivate();
282    this->active = false;
283        // setting up for next action
284    this->stateDuration = this->times[WA_DEACTIVATE] + this->stateDuration;
285  }
286  this->requestedAction = WA_NONE;
287}
288
289/**
290 * checks and charges the Weapon
291 * @return true on success.
292 */
293bool Weapon::chargeW()
294{
295  if ( this->currentState != WS_INACTIVE && this->energyLoaded >= this->minCharge)
296  {
297        // playing Sound
298    if (this->soundBuffers[WA_CHARGE] != NULL)
299      this->soundSource->play(this->soundBuffers[WA_CHARGE]);
300    if (likely(this->animation[WS_CHARGING] != NULL))
301      this->animation[WS_CHARGING]->replay();
302
303        // charge
304    this->charge();
305        // setting up for the next state
306    this->requestedAction = WA_NONE;
307    this->stateDuration = this->times[WA_CHARGE] + this->stateDuration;
308  }
309  else // deactivate the Weapon if we do not have enough energy
310  {
311    this->requestedAction = WA_NONE;
312    this->requestAction(WA_RELOAD);
313  }
314
315}
316
317/**
318 * checks and fires the Weapon
319 * @return true on success.
320 */
321bool Weapon::fireW()
322{
323     //if (likely(this->currentState != WS_INACTIVE))
324  if (this->minCharge <= this->energyLoaded)
325  {
326          // playing Sound
327    if (this->soundBuffers[WA_SHOOT] != NULL)
328      this->soundSource->play(this->soundBuffers[WA_SHOOT]);
329    if (likely(this->animation[WS_SHOOTING] != NULL))
330      this->animation[WS_SHOOTING]->replay();
331          // fire
332    this->fire();
333    this->energyLoaded -= this->minCharge;
334          // setting up for the next state
335    this->stateDuration = this->times[WA_SHOOT] + this->stateDuration;
336    this->requestedAction = WA_NONE;
337  }
338  else  // reload if we still have the charge
339  {
340    this->requestedAction = WA_NONE;
341    this->requestAction(WA_RELOAD);
342  }
343}
344
345
346/**
347 * checks and Reloads the Weapon
348 * @return true on success.
349 */
350bool Weapon::reloadW()
351{
352  PRINTF(4)("Reloading Weapon %s\n", this->getName());
353  if (unlikely(this->energy + this->energyLoaded < this->minCharge))
354  {
355    this->requestAction(WA_DEACTIVATE);
356    return false;
357  }
358
359  float chargeSize = this->energyLoadedMax - this->energyLoaded;       //!< The energy to be charged
360
361  if (this->soundBuffers[WA_RELOAD] != NULL)
362    this->soundSource->play(this->soundBuffers[WA_RELOAD]);
363  if (likely(this->animation[WS_RELOADING] != NULL))
364    this->animation[WS_RELOADING]->replay();
365
366  if (chargeSize > this->energy)
367  {
368    this->energyLoaded += this->energy;
369    this->energy = 0.0;
370    PRINT(3)("Energy empty");
371  }
372  else
373  {
374    PRINTF(3)("Loaded %f energy into the Guns Buffer\n", chargeSize);
375    this->energyLoaded += chargeSize;
376    this->energy -= chargeSize;
377  }
378  this->reload();
379
380  this->requestedAction = WA_NONE;
381  this->stateDuration = this->times[WA_RELOAD] + this->stateDuration;
382
383}
384
385
386/**
387 * tick signal for time dependent/driven stuff
388*/
389void Weapon::tick(float dt)
390{
391  // setting up the timing properties
392  this->stateDuration -= dt;
393
394  if (this->isActive())
395  {
396    if (this->stateDuration <= 0.0 && this->requestedAction != WA_NONE)
397    {
398      this->stateDuration = -dt;
399      this->execute();
400    }
401  }
402  else
403    if (this->requestedAction == WA_ACTIVATE)
404      this->activate();
405
406}
407
408/**
409 *  this will draw the weapon
410*/
411void Weapon::draw ()
412{}
413
414
415
416
417
418//////////////////////
419// HELPER FUNCTIONS //
420//////////////////////
421/**
422 * checks wether all the Weapons functions are valid, and if it is possible to go to action with it.
423 *
424 */
425bool Weapon::check() const
426{
427  bool retVal = true;
428
429  if (this->projectile == NULL)
430  {
431    PRINTF(2)("There was no projectile assigned to the Weapon.\n");
432    retVal = false;
433  }
434
435
436
437
438  return retVal;
439}
440
441/**
442 * some nice debugging information about this Weapon
443 */
444void Weapon::debug() const
445{
446  PRINT(3)("Weapon-Debug %s, state: %s, nexAction: %s\n", this->getName(), Weapon::stateToChar(this->currentState), Weapon::actionToChar(requestedAction));
447  PRINT(3)("Energy: max: %f; current: %f;  loadedMax: %f; loadedCurrent: %f; chargeMin: %f, chargeMax %f\n",
448            this->energyMax, this->energy, this->energyLoadedMax, this->energyLoaded, this->minCharge, this->maxCharge);
449}
450
451
452// static
453/**
454 * Converts a String into an Action.
455 * @param action the String input holding the Action.
456 * @return The Action if known, WA_NONE otherwise.
457 */
458WeaponAction Weapon::charToAction(const char* action)
459{
460  if (!strcmp(action, "none"))
461    return WA_NONE;
462  else if (!strcmp(action, "shoot"))
463    return WA_SHOOT;
464  else if (!strcmp(action, "charge"))
465    return WA_CHARGE;
466  else if (!strcmp(action, "reload"))
467    return WA_RELOAD;
468  else if (!strcmp(action, "acitvate"))
469    return WA_ACTIVATE;
470  else if (!strcmp(action, "deactivate"))
471    return WA_DEACTIVATE;
472  else if (!strcmp(action, "special1"))
473    return WA_SPECIAL1;
474  else
475    {
476      PRINTF(2)("action %s could not be identified.\n", action);
477      return WA_NONE;
478    }
479}
480
481/**
482 * converts an action into a String
483 * @param action the action to convert
484 * @return a String matching the name of the action
485 */
486const char* Weapon::actionToChar(WeaponAction action)
487{
488  switch (action)
489  {
490    case WA_SHOOT:
491      return "shoot";
492      break;
493    case WA_CHARGE:
494      return "charge";
495      break;
496    case WA_RELOAD:
497      return "reload";
498      break;
499    case WA_ACTIVATE:
500      return "activate";
501      break;
502    case WA_DEACTIVATE:
503      return "deactivate";
504      break;
505    case WA_SPECIAL1:
506      return "special1";
507      break;
508    default:
509      return "none";
510      break;
511  }
512}
513
514/**
515 * Converts a String into a State.
516 * @param state the String input holding the State.
517 * @return The State if known, WS_NONE otherwise.
518 */
519WeaponState Weapon::charToState(const char* state)
520{
521  if (!strcmp(state, "none"))
522    return WS_NONE;
523  else if (!strcmp(state, "shooting"))
524    return WS_SHOOTING;
525  else if (!strcmp(state, "charging"))
526    return WS_CHARGING;
527  else if (!strcmp(state, "reloading"))
528    return WS_RELOADING;
529  else if (!strcmp(state, "activating"))
530    return WS_ACTIVATING;
531  else if (!strcmp(state, "deactivating"))
532    return WS_DEACTIVATING;
533  else if (!strcmp(state, "inactive"))
534    return WS_INACTIVE;
535  else if (!strcmp(state, "idle"))
536    return WS_IDLE;
537  else
538    {
539      PRINTF(2)("state %s could not be identified.\n", state);
540      return WS_NONE;
541    }
542}
543
544/**
545 * converts a State into a String
546 * @param state the state to convert
547 * @return a String matching the name of the state
548 */
549const char* Weapon::stateToChar(WeaponState state)
550{
551  switch (state)
552  {
553    case WS_SHOOTING:
554      return "shooting";
555      break;
556    case WS_CHARGING:
557      return "charging";
558      break;
559    case WS_RELOADING:
560      return "reloading";
561      break;
562    case WS_ACTIVATING:
563      return "activating";
564      break;
565    case WS_DEACTIVATING:
566      return "deactivating";
567      break;
568    case WS_IDLE:
569      return "idle";
570      break;
571    default:
572      return "none";
573      break;
574  }
575}
Note: See TracBrowser for help on using the repository browser.