Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain.older/src/world_entities/npcs/generic_npc.cc @ 10764

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

orxonox/trunk: merged the Presentation back

File size: 13.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:
16*/
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
18
19#include "generic_npc.h"
20
21
22#include "util/loading/factory.h"
23#include "util/loading/load_param.h"
24
25#include "interactive_model.h"
26#include "md2/md2Model.h"
27
28#include "sound_buffer.h"
29
30#include "loading/resource_manager.h"
31
32
33CREATE_FACTORY(GenericNPC, CL_GENERIC_NPC);
34
35#include "script_class.h"
36CREATE_SCRIPTABLE_CLASS(GenericNPC, CL_GENERIC_NPC,
37                        // Move
38                        addMethod("walkTo", ExecutorLua3<GenericNPC,float,float,float>(&GenericNPC::walkTo))
39                        ->addMethod("runTo", ExecutorLua3<GenericNPC,float,float,float>(&GenericNPC::runTo))
40                        ->addMethod("turnTo", ExecutorLua1<GenericNPC,float>(&GenericNPC::turnTo))
41                        ->addMethod("finalGoalReached", ExecutorLua0ret<GenericNPC,bool>(&GenericNPC::finalGoalReached))
42                        ->addMethod("stop", ExecutorLua0<GenericNPC>(&GenericNPC::stop))
43                        ->addMethod("resume", ExecutorLua0<GenericNPC>(&GenericNPC::resume))
44                        ->addMethod("playAnimation", ExecutorLua2<GenericNPC,int,int>(&GenericNPC::playAnimation))
45                        // Display
46                        ->addMethod("hide", ExecutorLua0<WorldEntity>(&WorldEntity::hide))
47                        ->addMethod("unhide", ExecutorLua0<WorldEntity>(&WorldEntity::unhide))
48                        // Coordinates
49                        ->addMethod("getAbsCoorX", ExecutorLua0ret<PNode, float>(&PNode::getAbsCoorX))
50                        ->addMethod("getAbsCoorY", ExecutorLua0ret<PNode, float>(&PNode::getAbsCoorY))
51                        ->addMethod("getAbsCoorZ", ExecutorLua0ret<PNode, float>(&PNode::getAbsCoorZ))
52                        ->addMethod("setAbsCoor", ExecutorLua3<PNode,float,float,float>(&PNode::setAbsCoor))
53                        ->addMethod("setAbsDir", ExecutorLua4<PNode,float,float,float,float>(&PNode::setAbsDir))
54                       );
55
56
57
58/**
59 * constructor
60 */
61GenericNPC::GenericNPC(const TiXmlElement* root)
62    : NPC(root)
63{
64  this->init();
65
66  if (root != NULL)
67    this->loadParams(root);
68}
69
70
71/**
72 * deconstructor
73 */
74GenericNPC::~GenericNPC ()
75{}
76
77
78/**
79 * initializing the npc enity
80 */
81void GenericNPC::init()
82{
83  this->setClassID(CL_GENERIC_NPC, "GenericNPC");
84  this->toList(OM_GROUP_00);
85
86  this->soundBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/rain.wav", WAV);
87
88  time = 30.0f;
89
90  this->behaviourList = new std::list<GenericNPC::Anim>;
91
92  // collision reaction registration
93   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
94}
95
96
97/**
98 * loads the Settings of a MD2Creature from an XML-element.
99 * @param root the XML-element to load the MD2Creature's properties from
100 */
101void GenericNPC::loadParams(const TiXmlElement* root)
102{
103  NPC::loadParams(root);
104
105}
106
107
108/**
109 * sets the animation of this npc
110 * @param anumationIndex: the animation index
111 * @param anumPlaybackMode: the playback mode
112 */
113void GenericNPC::setAnimation(int animationIndex, int animPlaybackMode)
114{
115  if( likely(this->getModel(0) != NULL))
116    ((InteractiveModel*)this->getModel(0))->setAnimation(animationIndex, animPlaybackMode);
117}
118
119
120
121/**
122 * @returns the current animation number
123 */
124int GenericNPC::getAnimation()
125{
126  if( likely(this->getModel(0) != NULL))
127    return ((InteractiveModel*)this->getModel(0))->getAnimation();
128  else
129    return -1;
130}
131
132
133
134/**
135 * @returns true if animation is finished
136 */
137bool GenericNPC::isAnimationFinished()
138{
139  if( likely(this->getModel(0) != NULL))
140    return ((InteractiveModel*)this->getModel(0))->isAnimationFinished();
141  else
142    return false;
143}
144
145
146/**
147 * sets the animation speed of this entity
148 */
149void GenericNPC::setAnimationSpeed(float speed)
150{
151  if( likely(this->getModel(0) != NULL))
152    ((InteractiveModel*)this->getModel(0))->setAnimationSpeed(speed);
153}
154
155
156
157/**
158 * sets the animation of this npc
159 * @param anumationIndex: the animation index
160 * @param anumPlaybackMode: the playback mode
161 */
162void GenericNPC::playAnimation(int animationIndex, int animPlaybackMode)
163{
164  if( likely(this->getModel(0) != NULL))
165    ((InteractiveModel*)this->getModel(0))->setAnimation(animationIndex, animPlaybackMode);
166
167}
168
169
170/**
171 * play a sound
172 * @param filename: name of the file
173 */
174void GenericNPC::playSound(const std::string& filename)
175{}
176
177
178
179/**
180 * stops the generic animation
181 */
182void GenericNPC::stop()
183{
184  this->animationStack.push(this->behaviourList);
185  this->behaviourList = new std::list<GenericNPC::Anim>;
186
187  if( this->getAnimation() != STAND)
188    this->setAnimation(STAND, MD2_ANIM_LOOP);
189}
190
191
192/**
193 * continue the generic animation
194 */
195void GenericNPC::resume()
196{
197  if( this->animationStack.size() == 0)
198    return;
199
200  delete this->behaviourList;
201  this->behaviourList = this->animationStack.top();
202  this->animationStack.pop();
203}
204
205
206/**
207 * each animation has to be initialized here
208 */
209void GenericNPC::initNPC()
210{
211  if (!this->behaviourList->empty())
212  {
213    GenericNPC::Anim currentAnimation = this->behaviourList->front();
214
215    switch(this->behaviourList->front().type)
216    {
217      case Walk:
218      {
219        if( this->getAnimation() != RUN)
220          this->setAnimation(RUN, MD2_ANIM_LOOP);
221
222        Vector dir = (currentAnimation.v - this->getAbsCoor());
223        dir.y = 0.0f;
224        dir.normalize();
225        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
226
227        this->setAnimationSpeed(0.5f);
228      }
229        break;
230      case Run:
231      {
232        if( this->getAnimation() != RUN)
233          this->setAnimation(RUN, MD2_ANIM_LOOP);
234
235        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
236        dir.y = 0.0f;
237        dir.getNormalized();
238        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
239
240        this->setAnimationSpeed(1.0f);
241      }
242        break;
243      case Crouch:
244      {
245        if( this->getAnimation() != CROUCH_WALK)
246          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
247
248        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
249        dir.y = 0.0f;
250        dir.getNormalized();
251        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
252
253        this->setAnimationSpeed(1.0f);
254      }
255        break;
256      case LookAt:
257        if( this->getAnimation() != STAND)
258          this->setAnimation(STAND, MD2_ANIM_LOOP);
259        break;
260      case Shoot:
261        if( this->getAnimation() != STAND)
262          this->setAnimation(STAND, MD2_ANIM_LOOP);
263        break;
264
265      default:
266        if( this->getAnimation() != STAND)
267          this->setAnimation(STAND, MD2_ANIM_LOOP);
268        break;
269
270    }
271  }
272}
273
274
275void GenericNPC::nextStep()
276{
277  if (!this->behaviourList->empty())
278    this->behaviourList->pop_front();
279  else
280    return;
281
282
283  if (!this->behaviourList->empty())
284  {
285    GenericNPC::Anim currentAnimation = this->behaviourList->front();
286
287    switch( currentAnimation.type)
288    {
289      case Walk:
290      {
291        if( this->getAnimation() != RUN)
292          this->setAnimation(RUN, MD2_ANIM_LOOP);
293
294
295        Vector dir = (currentAnimation.v - this->getAbsCoor());
296        dir.y = 0.0f;
297        dir.getNormalized();
298        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
299
300        this->setAnimationSpeed(0.5f);
301      }
302        break;
303      case Run:
304      {
305        if( this->getAnimation() != RUN)
306          this->setAnimation(RUN, MD2_ANIM_LOOP);
307
308        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
309        dir.y = 0.0f;
310        dir.getNormalized();
311        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
312
313        this->setAnimationSpeed(1.0f);
314      }
315        break;
316      case Crouch:
317      {
318        if( this->getAnimation() != CROUCH_WALK)
319          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
320
321        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
322        dir.y = 0.0f;
323        dir.getNormalized();
324        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
325
326        this->setAnimationSpeed(1.0f);
327      }
328        break;
329      case LookAt:
330      {
331        if( this->getAnimation() != STAND)
332          this->setAnimation(STAND, MD2_ANIM_LOOP);
333      }
334        break;
335      case Shoot:
336        if( this->getAnimation() != STAND)
337        this->setAnimation(STAND, MD2_ANIM_LOOP);
338        break;
339
340      default:
341        if( this->getAnimation() != STAND)
342        this->setAnimation(STAND, MD2_ANIM_LOOP);
343        break;
344
345    }
346  }
347  else
348  {
349    this->setAnimation(STAND, MD2_ANIM_LOOP);
350  }
351}
352
353
354
355
356void GenericNPC::walkTo(const Vector& coordinate)
357{
358
359  GenericNPC::Anim anim;
360  anim.v = coordinate;
361  anim.type = Walk;
362  anim.speed = 30.0f;
363
364  if( this->behaviourList->empty())
365  {
366    this->behaviourList->push_back(anim);
367    this->initNPC();
368  }
369  else
370    this->behaviourList->push_back(anim);
371}
372
373void GenericNPC::walkTo(float x, float y, float z)
374{
375  //printf("Walking to %f, %f, %f \n",x,y,z);
376  this->walkTo(Vector(x,y,z));
377
378}
379
380/* running functions */
381void GenericNPC::runTo(const Vector& coordinate)
382{
383  GenericNPC::Anim anim;
384  anim.v = coordinate;
385  anim.type = Run;
386  anim.speed = 60.0f;
387
388  if( this->behaviourList->empty())
389  {
390    this->behaviourList->push_back(anim);
391    this->initNPC();
392  }
393  else
394    this->behaviourList->push_back(anim);
395}
396
397void GenericNPC::runTo(float x, float y, float z)
398{
399  this->runTo(Vector(x,y,z));
400}
401
402/* couching functinos */
403void GenericNPC::crouchTo(const Vector& coordinate)
404{
405  GenericNPC::Anim anim;
406  anim.v = coordinate;
407  anim.type = Crouch;
408
409  if( this->behaviourList->empty())
410  {
411    this->behaviourList->push_back(anim);
412    this->initNPC();
413  }
414  else
415    this->behaviourList->push_back(anim);
416}
417void GenericNPC::crouchTo(float x, float y, float z)
418{
419  this->crouchTo(Vector(x,y,z));
420}
421
422
423
424void GenericNPC::turnTo(float degreeInY)
425{
426  GenericNPC::Anim anim;
427  anim.q = Quaternion(Vector(0,1,0), degreeInY);
428  anim.type = TurnTo;
429
430  if( this->behaviourList->empty())
431  {
432    this->behaviourList->push_back(anim);
433    this->initNPC();
434  }
435  else
436    this->behaviourList->push_back(anim);
437}
438
439
440
441/**
442 * lookat a world entity
443 * @param worldEntity: the worldentity to look at
444 */
445void GenericNPC::lookAt(WorldEntity* worldEntity)
446{
447  GenericNPC::Anim anim;
448  anim.entity = worldEntity;
449  anim.type = LookAt;
450
451  if( this->behaviourList->empty())
452  {
453    this->behaviourList->push_back(anim);
454    this->initNPC();
455  }
456  else
457    this->behaviourList->push_back(anim);
458}
459
460
461
462
463/**
464 * talk to a world entity and play a sound/music/voice
465 * @param worldEntity: entity
466 * @param dialogNr: sound nr to be played (from the xml load tags)
467 */
468void GenericNPC::talkTo(WorldEntity* worldEntity, int dialogNr)
469{}
470
471
472/**
473 * world entity to shoot at if there is any weapon on the npc
474 * @param entity: entity to shoot entity
475 */
476void GenericNPC::shootAt(WorldEntity* entity)
477{}
478
479
480
481
482
483
484
485
486
487
488/**
489 * tick this world entity
490 * @param time: time in seconds expirded since the last tick
491 */
492void GenericNPC::tick (float dt)
493{
494  if( likely(this->getModel(0) != NULL))
495    ((InteractiveModel*)this->getModel(0))->tick(dt);
496
497
498  if (!this->behaviourList->empty())
499  {
500    GenericNPC::Anim currentAnimation = this->behaviourList->front();
501
502    switch( currentAnimation.type)
503    {
504      case Walk:
505        {
506          Vector dest = currentAnimation.v - this->getAbsCoor();
507          dest.y = 0.0f;
508          if (dest.len() < .5)
509          {
510            this->nextStep();
511          }
512          else
513          {
514            Vector move = dest.getNormalized() * currentAnimation.speed * dt;
515            this->shiftCoor(move);
516          }
517        }
518        break;
519
520      case Run:
521      {
522        Vector dest = currentAnimation.v - this->getAbsCoor();
523        dest.y = 0.0f;
524        if (dest.len() < .5)
525          this->nextStep();
526        else
527        {
528          this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
529        }
530      }
531      break;
532
533      case Crouch:
534      {
535        Vector dest = currentAnimation.v - this->getAbsCoor();
536        dest.y = 0.0f;
537        if (dest.len() < .5)
538          this->nextStep();
539        else
540        {
541          this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
542        }
543      }
544      break;
545
546      case TurnTo:
547        //Quaternion direction = this->
548        break;
549
550      case LookAt:
551        break;
552
553      case Shoot:
554        break;
555
556      default:
557        break;
558
559    }
560  }
561
562  // physical falling of the player
563  if( !this->isOnGround())
564  {
565    this->fallVelocity += 300.0f * dt;
566    //velocity -= Vector(0.0, 1.0, 0.0) * this->fallVelocity;
567   // PRINTF(0)("%s is not on ground\n", this->getName());
568    this->shiftCoor(Vector(0, -this->fallVelocity * dt,0));
569
570  }
571  else
572  {
573    this->fallVelocity = 0.0f;
574  }
575
576}
577
578
579
580void GenericNPC::destroy()
581{
582  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
583
584  this->setAnimationSpeed(1.0f);
585
586  if( randi == 1)
587    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
588  else if( randi == 2)
589    this->setAnimation(DEATH_FALLFORWARD, MD2_ANIM_ONCE);
590  else if( randi == 3)
591    this->setAnimation(DEATH_FALLBACKSLOW, MD2_ANIM_ONCE);
592  else if( randi == 4)
593    this->setAnimation(CROUCH_DEATH, MD2_ANIM_ONCE);
594  else
595    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
596}
597
Note: See TracBrowser for help on using the repository browser.