Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/vs-enhencements/src/world_entities/weapons/weapon.cc @ 10684

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

some hack, but still does not work

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