Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file was 10698, checked in by snellen, 17 years ago

merged adm, hud, vs-enhancements : beni's responsible for this commit. blame him!

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