Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/world_entities/world_entity.cc @ 9722

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

orxonox: now it is gcc-4.1.1 conform

strangely before this, it was possible to compare and set std::list::iterators to NULL values.
also it now is not allowed to use
void ClassName::functionName(); inside of the header… quite nice feature, and i think compiling is faster too :)

Gentoo Rocks
GCC rocks also with nptl :)

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