Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/new_class_id: new Executor construct, that is much more typesafe, faster, and easier to extend…

Also changed the LoadParam process, and adapted ScriptEngine calls

Then at the end, some missing headers appeared, and appended them to all the cc-files again.

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