Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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