Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain/src/world_entities/world_entity.cc @ 9777

Last change on this file since 9777 was 9406, checked in by bensch, 18 years ago

orxonox/trunk: merged the proxy back

merged with commandsvn merge -r9346:HEAD https://svn.orxonox.net/orxonox/branches/proxy .

no conflicts

File size: 22.6 KB
Line 
1
2
3/*
4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer: Christian Meyer
16*/
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
18
19#include "world_entity.h"
20#include "shell_command.h"
21
22#include "model.h"
23#include "md2/md2Model.h"
24#include "md3/md3_model.h"
25
26#include "aabb_tree_node.h"
27
28#include "util/loading/resource_manager.h"
29#include "util/loading/load_param.h"
30#include "vector.h"
31#include "obb_tree.h"
32
33#include "elements/glgui_energywidget.h"
34
35#include "state.h"
36#include "camera.h"
37
38#include "collision_handle.h"
39#include "collision_event.h"
40#include "game_rules.h"
41#include "kill.h"
42
43
44SHELL_COMMAND(model, WorldEntity, loadModel)
45->describe("sets the Model of the WorldEntity")
46->defaultValues("models/ships/fighter.obj", 1.0f);
47
48SHELL_COMMAND(debugEntity, WorldEntity, debugWE);
49
50/**
51 *  Loads the WordEntity-specific Part of any derived Class
52 *
53 * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves,
54 *              that can calls WorldEntities loadParams for itself.
55 */
56WorldEntity::WorldEntity()
57    : Synchronizeable()
58{
59  this->setClassID(CL_WORLD_ENTITY, "WorldEntity");
60
61  this->obbTree = NULL;
62  this->aabbNode = NULL;
63  this->healthWidget = NULL;
64  this->healthMax = 1.0f;
65  this->health = 1.0f;
66  this->damage = 0.0f; // no damage dealt by a default entity
67  this->scaling = 1.0f;
68
69  /* OSOLETE */
70  this->bVisible = true;
71  this->bCollide = true;
72
73  this->objectListNumber = OM_INIT;
74  this->lastObjectListNumber = OM_INIT;
75  this->objectListIterator = NULL;
76
77  // reset all collision handles to NULL == unsubscribed state
78  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
79    this->collisionHandles[i] = NULL;
80  this->bReactive = false;
81  this->bOnGround = false;
82
83  // registering default reactions:
84  this->subscribeReaction(CREngine::CR_OBJECT_DAMAGE, /*CL_WORLD_ENTITY*/ CL_PROJECTILE);
85
86  this->toList(OM_NULL);
87
88  registerVar( new SynchronizeableString( &this->md2TextureFileName, &this->md2TextureFileName, "md2TextureFileName" ) );
89  modelFileName_handle = registerVarId( new SynchronizeableString( &modelFileName, &modelFileName, "modelFileName" ) );
90  scaling_handle = registerVarId( new SynchronizeableFloat( &scaling, &scaling, "scaling" ) );
91  list_handle = registerVarId( new SynchronizeableInt( (int*)&objectListNumber, &list_write, "list" ) );
92
93  health_handle = registerVarId( new SynchronizeableFloat( &this->health, &this->health_write, "health" ) );
94  healthMax_handle = registerVarId( new SynchronizeableFloat( &this->healthMax, &this->healthMax_write, "maxHealth" ) );
95}
96
97/**
98 *  standard destructor
99*/
100WorldEntity::~WorldEntity ()
101{
102  State::getObjectManager()->toList(this, OM_INIT);
103
104  // Delete the model (unregister it with the ResourceManager)
105  for (unsigned int i = 0; i < this->models.size(); i++)
106    this->setModel(NULL, i);
107
108  // Delete the obbTree
109  if( this->obbTree != NULL)
110    delete this->obbTree;
111
112  if (this->healthWidget != NULL)
113    delete this->healthWidget;
114
115  this->unsubscribeReaction();
116}
117
118/**
119 * loads the WorldEntity Specific Parameters.
120 * @param root: the XML-Element to load the Data From
121 */
122void WorldEntity::loadParams(const TiXmlElement* root)
123{
124  // Do the PNode loading stuff
125  PNode::loadParams(root);
126
127  LoadParam(root, "md2texture", this, WorldEntity, loadMD2Texture)
128  .describe("the fileName of the texture, that should be loaded onto this world-entity. (must be relative to the data-dir)")
129  .defaultValues("");
130
131  // Model Loading
132  LoadParam(root, "model", this, WorldEntity, loadModel)
133  .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
134  .defaultValues("", 1.0f, 0);
135
136  LoadParam(root, "maxHealth", this, WorldEntity, setHealthMax)
137  .describe("The Maximum health that can be loaded onto this entity")
138  .defaultValues(1.0f);
139
140  LoadParam(root, "health", this, WorldEntity, setHealth)
141  .describe("The Health the WorldEntity has at this moment")
142  .defaultValues(1.0f);
143}
144
145
146/**
147 * loads a Model onto a WorldEntity
148 * @param fileName the name of the model to load
149 * @param scaling the Scaling of the model
150 *
151 * FIXME
152 * @todo: separate the obb tree generation from the model
153 */
154void WorldEntity::loadModel(const std::string& fileName, float scaling, unsigned int modelNumber, unsigned int obbTreeDepth)
155{
156  this->modelLODName = fileName;
157  this->scaling = scaling;
158
159  std::string name = fileName;
160
161  if (  name.find( ResourceManager::getInstance()->getDataDir() ) == 0 )
162  {
163    name.erase(ResourceManager::getInstance()->getDataDir().size());
164  }
165
166  this->modelFileName = name;
167
168  if (!fileName.empty())
169  {
170    // search for the special character # in the LoadParam
171    if (fileName.find('#') != std::string::npos)
172    {
173      PRINTF(4)("Found # in %s... searching for LOD's\n", fileName.c_str());
174      std::string lodFile = fileName;
175      unsigned int offset = lodFile.find('#');
176      for (unsigned int i = 0; i < 3; i++)
177      {
178        lodFile[offset] = 48+(int)i;
179        if (ResourceManager::isInDataDir(lodFile))
180          this->loadModel(lodFile, scaling, i);
181      }
182      return;
183    }
184    if (this->scaling <= 0.0)
185    {
186      PRINTF(1)("YOU GAVE ME A CRAPY SCALE resetting to 1.0\n");
187      this->scaling = 1.0;
188    }
189    if(fileName.find(".obj") != std::string::npos)
190    {
191      PRINTF(4)("fetching OBJ file: %s\n", fileName.c_str());
192      BaseObject* loadedModel = ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, this->scaling);
193      if (loadedModel != NULL)
194        this->setModel(dynamic_cast<Model*>(loadedModel), modelNumber);
195      else
196        PRINTF(1)("OBJ-File %s not found.\n", fileName.c_str());
197
198      if( modelNumber == 0 && !this->isA(CL_WEAPON))
199        this->buildObbTree(obbTreeDepth);
200    }
201    else if(fileName.find(".md2") != std::string::npos)
202    {
203      PRINTF(4)("fetching MD2 file: %s\n", fileName.c_str());
204      Model* m = new MD2Model(fileName, this->md2TextureFileName, this->scaling);
205      //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
206      this->setModel(m, 0);
207
208      if( m != NULL)
209        this->buildObbTree(obbTreeDepth);
210    }
211    else if(fileName.find(".md3") != std::string::npos)
212    {
213      PRINTF(4)("fetching MD3 file: %s\n", fileName.c_str());
214      Model* m = new md3::MD3Model(fileName, this->scaling);
215      this->setModel(m, 0);
216
217//       if( m != NULL)
218//         this->buildObbTree(obbTreeDepth);
219    }
220  }
221  else
222  {
223    this->setModel(NULL);
224  }
225}
226
227/**
228 * sets a specific Model for the Object.
229 * @param model The Model to set
230 * @param modelNumber the n'th model in the List to get.
231 */
232void WorldEntity::setModel(Model* model, unsigned int modelNumber)
233{
234  if (this->models.size() <= modelNumber)
235    this->models.resize(modelNumber+1, NULL);
236
237  if (this->models[modelNumber] != NULL)
238  {
239    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(dynamic_cast<BaseObject*>(this->models[modelNumber]));
240    if (resource != NULL)
241      ResourceManager::getInstance()->unload(resource, RP_LEVEL);
242    else
243    {
244      PRINTF(4)("Forcing model deletion\n");
245      delete this->models[modelNumber];
246    }
247  }
248
249  this->models[modelNumber] = model;
250}
251
252
253/**
254 * builds the obb-tree
255 * @param depth the depth to calculate
256 */
257bool WorldEntity::buildObbTree(int depth)
258{
259  if (this->obbTree)
260    delete this->obbTree;
261
262  if (this->models[0] != NULL)
263    this->obbTree = new OBBTree(depth, models[0]->getModelInfo(), this);
264  else
265  {
266    PRINTF(1)("could not create obb-tree, because no model was loaded yet\n");
267    this->obbTree = NULL;
268    return false;
269  }
270
271
272  // create the axis aligned bounding box
273  if( this->aabbNode != NULL)
274  {
275    delete this->aabbNode;
276    this->aabbNode = NULL;
277  }
278
279  if( this->models[0] != NULL) {
280    this->aabbNode = new AABBTreeNode();
281    this->aabbNode->spawnBVTree(this->models[0]);
282  }
283  return true;
284}
285
286
287/**
288 * subscribes this world entity to a collision reaction
289 *  @param type the type of reaction to subscribe to
290 *  @param target1 a filter target (classID)
291 */
292void WorldEntity::subscribeReaction(CREngine::CRType type, long target1)
293{
294  this->subscribeReaction(type);
295
296  // add the target filter
297  this->collisionHandles[type]->addTarget(target1);
298}
299
300
301/**
302 * subscribes this world entity to a collision reaction
303 *  @param type the type of reaction to subscribe to
304 *  @param target1 a filter target (classID)
305 */
306void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2)
307{
308  this->subscribeReaction(type);
309
310  // add the target filter
311  this->collisionHandles[type]->addTarget(target1);
312  this->collisionHandles[type]->addTarget(target2);
313}
314
315
316/**
317 * subscribes this world entity to a collision reaction
318 *  @param type the type of reaction to subscribe to
319 *  @param target1 a filter target (classID)
320 */
321void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3)
322{
323  this->subscribeReaction(type);
324
325  // add the target filter
326  this->collisionHandles[type]->addTarget(target1);
327  this->collisionHandles[type]->addTarget(target2);
328  this->collisionHandles[type]->addTarget(target3);
329}
330
331
332/**
333 * subscribes this world entity to a collision reaction
334 *  @param type the type of reaction to subscribe to
335 *  @param target1 a filter target (classID)
336 */
337void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3, long target4)
338{
339  this->subscribeReaction(type);
340
341  // add the target filter
342  this->collisionHandles[type]->addTarget(target1);
343  this->collisionHandles[type]->addTarget(target2);
344  this->collisionHandles[type]->addTarget(target3);
345  this->collisionHandles[type]->addTarget(target4);
346}
347
348
349/**
350 * subscribes this world entity to a collision reaction
351 *  @param type the type of reaction to subscribe to
352 *  @param nrOfTargets number of target filters
353 *  @param ... the targets as classIDs
354 */
355void WorldEntity::subscribeReaction(CREngine::CRType type)
356{
357  if( this->collisionHandles[type] != NULL)  {
358    PRINTF(2)("Registering for a CollisionReaction already subscribed to! Skipping\n");
359    return;
360  }
361
362  this->collisionHandles[type] = CREngine::getInstance()->subscribeReaction(this, type);
363
364  // now there is at least one collision reaction subscribed
365  this->bReactive = true;
366}
367
368
369/**
370 * unsubscribes a specific reaction from the worldentity
371 *  @param type the reaction to unsubscribe
372 */
373void WorldEntity::unsubscribeReaction(CREngine::CRType type)
374{
375  if( this->collisionHandles[type] == NULL)
376    return;
377
378  CREngine::getInstance()->unsubscribeReaction(this->collisionHandles[type]);
379  this->collisionHandles[type] = NULL;
380
381  // check if there is still any handler registered
382  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
383  {
384    if( this->collisionHandles[i] != NULL)
385    {
386      this->bReactive = true;
387      return;
388    }
389  }
390  this->bReactive = false;
391}
392
393
394/**
395 * unsubscribes all collision reactions
396 */
397void WorldEntity::unsubscribeReaction()
398{
399  for( int i = 0; i < CREngine::CR_NUMBER; i++)
400    this->unsubscribeReaction((CREngine::CRType)i);
401
402  // there are no reactions subscribed from now on
403  this->bReactive = false;
404}
405
406
407/**
408 * registers a new collision event to this world entity
409 *  @param entityA entity of the collision
410 *  @param entityB entity of the collision
411 *  @param bvA colliding bounding volume of entityA
412 *  @param bvB colliding bounding volume of entityA
413 */
414bool WorldEntity::registerCollision(WorldEntity* entityA, WorldEntity* entityB, BoundingVolume* bvA, BoundingVolume* bvB)
415{
416  PRINTF(5)("registering collision of type: %s vs %s\n", entityA->getClassCName(), entityB->getClassCName());
417  // is there any handler listening?
418  if( !this->bReactive)
419    return false;
420
421  // get a collision event
422  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
423  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
424  c->collide(COLLISION_TYPE_OBB, entityA, entityB, bvA, bvB);
425
426  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
427    if( this->collisionHandles[i] != NULL)
428      this->collisionHandles[i]->registerCollisionEvent(c);
429  return true;
430}
431
432
433/**
434 * registers a new collision event to this woeld entity
435 *  @param entity the entity that collides
436 *  @param plane it stands on
437 *  @param position it collides on the plane
438 */
439bool WorldEntity::registerCollision(int type, WorldEntity* entity, WorldEntity* groundEntity, Vector normal, Vector position, bool bInWall)
440{
441  // is there any handler listening?
442  if( !this->bReactive)
443    return false;
444
445  // get a collision event
446  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
447  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
448  c->collide(type, entity, groundEntity, normal, position, bInWall);
449
450  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
451    if( this->collisionHandles[i] != NULL)
452      this->collisionHandles[i]->registerCollisionEvent(c);
453  return true;
454}
455
456
457/**
458 * @brief moves this entity to the List OM_List
459 * @param list the list to set this Entity to.
460 *
461 * this is the same as a call to State::getObjectManager()->toList(entity , list);
462 * directly, but with an easier interface.
463 *
464 * @todo inline this (peut etre)
465 */
466void WorldEntity::toList(OM_LIST list)
467{
468  State::getObjectManager()->toList(this, list);
469}
470
471void WorldEntity::toReflectionList()
472{
473  State::getObjectManager()->toReflectionList( this );
474}
475
476void removeFromReflectionList()
477{
478/// TODO
479///  State::getObject
480}
481
482/**
483 * sets the character attributes of a worldentity
484 * @param character attributes
485 *
486 * these attributes don't have to be set, only use them, if you need them
487*/
488//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
489//{}
490
491
492/**
493 *  this function is called, when two entities collide
494 * @param entity: the world entity with whom it collides
495 *
496 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
497 */
498void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
499{
500  /**
501   * THIS IS A DEFAULT COLLISION-Effect.
502   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
503   * USE::
504   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
505   *
506   * You can always define a default Action.... don't be affraid just test it :)
507   */
508  //  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassCName(), entity->getClassCName(), location.x, location.y, location.z);
509}
510
511
512/**
513 *  this function is called, when two entities collide
514 * @param entity: the world entity with whom it collides
515 *
516 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
517 */
518void WorldEntity::collidesWithGround(const Vector& location)
519{
520  PRINTF(0)("BSP_GROUND: %s collides \n", this->getClassCName() );
521}
522
523void WorldEntity::collidesWithGround(const Vector& feet, const Vector& ray_1, const Vector& ray_2)
524{
525
526  // PRINTF(0)("BSP_GROUND: Player collides \n", this->getClassCName() );
527
528  Vector v = this->getAbsDirX();
529  v.x *= 10.1;
530  v.y *= 10.1;
531  v.z *= 10.1;
532  Vector u = Vector(0.0,-20.0,0.0);
533
534
535  if(!(this->getAbsCoor().x == ray_2.x && this->getAbsCoor().y == ray_2.y && this->getAbsCoor().z == ray_2.z) )
536  {
537
538  this->setAbsCoor(ray_2 - v);
539
540  }
541    else
542  {
543    if(ray_1.x == this->getAbsCoor().x + v.x && ray_1.y == this->getAbsCoor().y + v.y + 0.1 && ray_1.z ==this->getAbsCoor().z + v.z)
544    {
545      this->setAbsCoor(feet -u );
546    }
547
548    this->setAbsCoor(ray_2 - v);
549
550  }
551
552
553}
554
555/**
556 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
557 *
558 */
559void WorldEntity::postSpawn ()
560{}
561
562
563/**
564 *  this method is called by the world if the WorldEntity leaves the game
565 */
566void WorldEntity::leaveWorld ()
567{}
568
569
570/**
571 * resets the WorldEntity to its initial values. eg. used for multiplayer games: respawning
572 */
573void WorldEntity::reset()
574{
575  this->setHealth( this->getHealthMax() );
576}
577
578/**
579 *  this method is called every frame
580 * @param time: the time in seconds that has passed since the last tick
581 *
582 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
583*/
584void WorldEntity::tick(float time)
585{}
586
587
588/**
589 *  the entity is drawn onto the screen with this function
590 *
591 * This is a central function of an entity: call it to let the entity painted to the screen.
592 * Just override this function with whatever you want to be drawn.
593*/
594void WorldEntity::draw() const
595{
596  //PRINTF(0)("(%s::%s)\n", this->getClassCName(), this->getName());
597  //  assert(!unlikely(this->models.empty()));
598  {
599    glMatrixMode(GL_MODELVIEW);
600    glPushMatrix();
601
602    /* translate */
603    glTranslatef (this->getAbsCoor ().x,
604                  this->getAbsCoor ().y,
605                  this->getAbsCoor ().z);
606    Vector tmpRot = this->getAbsDir().getSpacialAxis();
607    glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
608
609
610    // This Draws the LOD's
611    float cameraDistance = State::getCamera()->distance(this);
612    if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
613    {
614      this->models[2]->draw();
615    }
616    else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
617    {
618      this->models[1]->draw();
619    }
620    else if (this->models.size() >= 1 && this->models[0] != NULL)
621    {
622      this->models[0]->draw();
623    }
624
625//     if( this->aabbNode != NULL)
626//       this->aabbNode->drawBV(0, DRAW_BV_POLYGON, Vector(1, 0.6, 0.2), true);
627
628    glPopMatrix();
629  }
630}
631
632/**
633 * @param health the Health to add.
634 * @returns the health left (this->healthMax - health+this->health)
635 */
636float WorldEntity::increaseHealth(float health)
637{
638  this->health += health;
639  if (this->health > this->healthMax)
640  {
641    float retHealth = this->healthMax - this->health;
642    this->health = this->healthMax;
643    this->updateHealthWidget();
644    return retHealth;
645  }
646  this->updateHealthWidget();
647  return 0.0;
648}
649
650/**
651 * @param health the Health to be removed
652 * @returns 0.0 or the rest, that was not substracted (bellow 0.0)
653 */
654float WorldEntity::decreaseHealth(float health)
655{
656  this->health -= health;
657
658  if (this->health < 0)
659  {
660    float retHealth = -this->health;
661    this->health = 0.0f;
662    this->updateHealthWidget();
663    return retHealth;
664  }
665  this->updateHealthWidget();
666  return 0.0;
667
668}
669
670/**
671 * @param maxHealth the maximal health that can be loaded onto the entity.
672 */
673void WorldEntity::setHealthMax(float healthMax)
674{
675  this->healthMax = healthMax;
676  if (this->health > this->healthMax)
677  {
678    PRINTF(3)("new maxHealth is bigger as the old health. Did you really intend to do this for (%s::%s)\n", this->getClassCName(), this->getCName());
679    this->health = this->healthMax;
680  }
681  this->updateHealthWidget();
682}
683
684/**
685 * @brief creates the HealthWidget
686 *
687 * since not all entities need an HealthWidget, it is only created on request.
688 */
689void WorldEntity::createHealthWidget()
690{
691  if (this->healthWidget == NULL)
692  {
693    this->healthWidget = new OrxGui::GLGuiEnergyWidget();
694    this->healthWidget->setDisplayedName(std::string(this->getClassName()) + " Energy:");
695    this->healthWidget->setSize2D(30,400);
696    this->healthWidget->setAbsCoor2D(10,100);
697
698    this->updateHealthWidget();
699  }
700  else
701    PRINTF(3)("Allready created the HealthWidget for %s::%s\n", this->getClassCName(), this->getCName());
702}
703
704void WorldEntity::increaseHealthMax(float increaseHealth)
705{
706  this->healthMax += increaseHealth;
707  this->updateHealthWidget();
708}
709
710
711OrxGui::GLGuiWidget* WorldEntity::getHealthWidget()
712{
713  this->createHealthWidget();
714  return this->healthWidget;
715}
716
717/**
718 * @param visibility shows or hides the health-bar
719 * (creates the widget if needed)
720 */
721void WorldEntity::setHealthWidgetVisibilit(bool visibility)
722{
723  if (visibility)
724  {
725    if (this->healthWidget != NULL)
726      this->healthWidget->show();
727    else
728    {
729      this->createHealthWidget();
730      this->updateHealthWidget();
731      this->healthWidget->show();
732    }
733  }
734  else if (this->healthWidget != NULL)
735    this->healthWidget->hide();
736}
737
738
739/**
740 * hit the world entity with
741 *  @param damage damage to be dealt
742 */
743void WorldEntity::hit(float damage, WorldEntity* killer)
744{
745  this->decreaseHealth(damage);
746
747  PRINTF(5)("Hit me: %s::%s now only %f/%f health\n", this->getClassCName(), this->getCName(), this->getHealth(), this->getHealthMax());
748
749  if( this->getHealth() > 0)
750  {
751    // any small explosion animaitions
752  }
753  else
754  {
755    this->destroy( killer );
756  }
757}
758
759
760/**
761 * destoys the world entity
762 */
763void WorldEntity::destroy(WorldEntity* killer)
764{
765  this->toList(OM_DEAD);
766}
767
768
769/**
770 * @brief updates the HealthWidget
771 */
772void WorldEntity::updateHealthWidget()
773{
774  if (this->healthWidget != NULL)
775  {
776    this->healthWidget->setMaximum(this->healthMax);
777    this->healthWidget->setValue(this->health);
778  }
779}
780
781
782/**
783 * DEBUG-DRAW OF THE BV-Tree.
784 * @param depth What depth to draw
785 * @param drawMode the mode to draw this entity under
786 */
787void WorldEntity::drawBVTree(int depth, int drawMode) const
788{
789  glMatrixMode(GL_MODELVIEW);
790  glPushMatrix();
791  /* translate */
792  glTranslatef (this->getAbsCoor ().x,
793                this->getAbsCoor ().y,
794                this->getAbsCoor ().z);
795  /* rotate */
796  Vector tmpRot = this->getAbsDir().getSpacialAxis();
797  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
798
799
800  if (this->obbTree)
801    this->obbTree->drawBV(depth, drawMode);
802
803
804  glPopMatrix();
805}
806
807
808/**
809 * Debug the WorldEntity
810 */
811void WorldEntity::debugEntity() const
812{
813  PRINT(0)("WorldEntity %s::%s  (DEBUG)\n", this->getClassCName(), this->getCName());
814  this->debugNode();
815  PRINT(0)("List: %s ; ModelCount %d - ", ObjectManager::OMListToString(this->objectListNumber) , this->models.size());
816  for (unsigned int i = 0; i < this->models.size(); i++)
817  {
818    if (models[i] != NULL)
819      PRINT(0)(" : %d:%s", i, this->models[i]->getCName());
820  }
821  PRINT(0)("\n");
822
823}
824
825
826/**
827 * handler for changes on registred vars
828 * @param id id's which changed
829 */
830void WorldEntity::varChangeHandler( std::list< int > & id )
831{
832  if ( std::find( id.begin(), id.end(), modelFileName_handle ) != id.end() ||
833       std::find( id.begin(), id.end(), scaling_handle ) != id.end()
834     )
835  {
836    loadModel( modelFileName, scaling );
837  }
838
839  if ( std::find( id.begin(), id.end(), list_handle ) != id.end() )
840  {
841    this->toList( (OM_LIST)list_write );
842  }
843
844  if ( std::find( id.begin(), id.end(), health_handle ) != id.end() )
845  {
846    this->setHealth( health_write );
847  }
848
849  if ( std::find( id.begin(), id.end(), healthMax_handle ) != id.end() )
850  {
851    this->setHealthMax( healthMax_write );
852  }
853
854  PNode::varChangeHandler( id );
855}
856
Note: See TracBrowser for help on using the repository browser.