Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/npcs/generic_npc.cc @ 9519

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

merged the presentation back

File size: 13.6 KB
RevLine 
[8514]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
[9003]19#include "generic_npc.h"
[8514]20
[9003]21
[8514]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
[8516]28#include "sound_buffer.h"
29
30#include "loading/resource_manager.h"
31
[8514]32
33CREATE_FACTORY(GenericNPC, CL_GENERIC_NPC);
34
[8894]35#include "script_class.h"
36CREATE_SCRIPTABLE_CLASS(GenericNPC, CL_GENERIC_NPC,
[9003]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))
[9061]42                        ->addMethod("stop", ExecutorLua0<GenericNPC>(&GenericNPC::stop))
43                        ->addMethod("resume", ExecutorLua0<GenericNPC>(&GenericNPC::resume))
44                        ->addMethod("playAnimation", ExecutorLua2<GenericNPC,int,int>(&GenericNPC::playAnimation))
[9003]45                        // Display
[8894]46                        ->addMethod("hide", ExecutorLua0<WorldEntity>(&WorldEntity::hide))
47                        ->addMethod("unhide", ExecutorLua0<WorldEntity>(&WorldEntity::unhide))
[9003]48                        // Coordinates
[8894]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                       );
[8514]55
56
[8894]57
[8514]58/**
59 * constructor
60 */
61GenericNPC::GenericNPC(const TiXmlElement* root)
[9003]62    : NPC(root)
[8514]63{
64  this->init();
65
66  if (root != NULL)
67    this->loadParams(root);
68}
69
70
71/**
72 * deconstructor
73 */
74GenericNPC::~GenericNPC ()
[9003]75{}
[8514]76
77
78/**
79 * initializing the npc enity
80 */
81void GenericNPC::init()
82{
83  this->setClassID(CL_GENERIC_NPC, "GenericNPC");
[9235]84
[8514]85  this->toList(OM_GROUP_00);
[8516]86
87  this->soundBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/rain.wav", WAV);
[8705]88
[8894]89  time = 30.0f;
[9003]90
[9061]91  this->behaviourList = new std::list<GenericNPC::Anim>;
92
[8705]93  // collision reaction registration
[9110]94   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
[8514]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{
[8705]104  NPC::loadParams(root);
[8514]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
[9003]121
[8514]122/**
[9003]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/**
[8514]159 * sets the animation of this npc
160 * @param anumationIndex: the animation index
161 * @param anumPlaybackMode: the playback mode
162 */
[8705]163void GenericNPC::playAnimation(int animationIndex, int animPlaybackMode)
[8514]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 */
[9061]175void GenericNPC::playSound(const std::string& filename)
[9003]176{}
[8705]177
[8514]178
179
180/**
[9003]181 * stops the generic animation
[8514]182 */
[9003]183void GenericNPC::stop()
[9061]184{
185  this->animationStack.push(this->behaviourList);
186  this->behaviourList = new std::list<GenericNPC::Anim>;
[9110]187
188  if( this->getAnimation() != STAND)
189    this->setAnimation(STAND, MD2_ANIM_LOOP);
[9061]190}
[8590]191
[8802]192
[9061]193/**
194 * continue the generic animation
195 */
196void GenericNPC::resume()
197{
[9110]198  if( this->animationStack.size() == 0)
199    return;
200
[9061]201  delete this->behaviourList;
202  this->behaviourList = this->animationStack.top();
203  this->animationStack.pop();
204}
[8802]205
[9061]206
207/**
208 * each animation has to be initialized here
209 */
[9235]210/**
211 *
212 */
[9003]213void GenericNPC::initNPC()
214{
[9061]215  if (!this->behaviourList->empty())
[9003]216  {
[9061]217    GenericNPC::Anim currentAnimation = this->behaviourList->front();
[8802]218
[9061]219    switch(this->behaviourList->front().type)
[9003]220    {
221      case Walk:
222      {
223        if( this->getAnimation() != RUN)
224          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]225
[9003]226        Vector dir = (currentAnimation.v - this->getAbsCoor());
227        dir.y = 0.0f;
[9110]228        dir.normalize();
[9003]229        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8894]230
[9003]231        this->setAnimationSpeed(0.5f);
232      }
233        break;
234      case Run:
235      {
236        if( this->getAnimation() != RUN)
237          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8802]238
[9003]239        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
[9061]240        dir.y = 0.0f;
241        dir.getNormalized();
[9003]242        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8590]243
[9003]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);
[8590]251
[9003]252        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
[9061]253        dir.y = 0.0f;
254        dir.getNormalized();
[9003]255        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8802]256
[9003]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;
[8894]268
[9003]269      default:
270        if( this->getAnimation() != STAND)
271          this->setAnimation(STAND, MD2_ANIM_LOOP);
272        break;
[8894]273
[9003]274    }
275  }
[8802]276}
277
278
[9003]279void GenericNPC::nextStep()
[8805]280{
[9061]281  if (!this->behaviourList->empty())
282    this->behaviourList->pop_front();
[9003]283  else
284    return;
[8805]285
286
[9061]287  if (!this->behaviourList->empty())
[9003]288  {
[9061]289    GenericNPC::Anim currentAnimation = this->behaviourList->front();
[8894]290
[9003]291    switch( currentAnimation.type)
292    {
293      case Walk:
294      {
295        if( this->getAnimation() != RUN)
296          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]297
[9061]298
[9003]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);
[8894]303
[9003]304        this->setAnimationSpeed(0.5f);
305      }
306        break;
307      case Run:
308      {
309        if( this->getAnimation() != RUN)
310          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]311
[9003]312        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
[9061]313        dir.y = 0.0f;
314        dir.getNormalized();
[9003]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);
[8894]316
[9003]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);
[8894]324
[9003]325        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
[9061]326        dir.y = 0.0f;
327        dir.getNormalized();
[9003]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);
[8894]329
[9003]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;
[8894]343
[9003]344      default:
345        if( this->getAnimation() != STAND)
346        this->setAnimation(STAND, MD2_ANIM_LOOP);
347        break;
348
349    }
[8894]350  }
[9003]351  else
352  {
353    this->setAnimation(STAND, MD2_ANIM_LOOP);
354  }
[8894]355}
356
357
358
359
[9003]360void GenericNPC::walkTo(const Vector& coordinate)
[8894]361{
362
[9003]363  GenericNPC::Anim anim;
364  anim.v = coordinate;
365  anim.type = Walk;
366  anim.speed = 30.0f;
[8894]367
[9061]368  if( this->behaviourList->empty())
[8894]369  {
[9061]370    this->behaviourList->push_back(anim);
[9003]371    this->initNPC();
372  }
373  else
[9061]374    this->behaviourList->push_back(anim);
[9003]375}
[8894]376
[9003]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));
[8894]381
[9003]382}
[8894]383
[9003]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;
[8894]391
[9061]392  if( this->behaviourList->empty())
[9003]393  {
[9061]394    this->behaviourList->push_back(anim);
[9003]395    this->initNPC();
[8894]396  }
[9003]397  else
[9061]398    this->behaviourList->push_back(anim);
[9003]399}
[8894]400
[9003]401void GenericNPC::runTo(float x, float y, float z)
402{
403  this->runTo(Vector(x,y,z));
[8894]404}
405
[9003]406/* couching functinos */
407void GenericNPC::crouchTo(const Vector& coordinate)
408{
409  GenericNPC::Anim anim;
410  anim.v = coordinate;
411  anim.type = Crouch;
[8894]412
[9061]413  if( this->behaviourList->empty())
[9003]414  {
[9061]415    this->behaviourList->push_back(anim);
[9003]416    this->initNPC();
417  }
418  else
[9061]419    this->behaviourList->push_back(anim);
[9003]420}
421void GenericNPC::crouchTo(float x, float y, float z)
[8894]422{
[9003]423  this->crouchTo(Vector(x,y,z));
[8894]424}
425
426
427
[9003]428void GenericNPC::turnTo(float degreeInY)
[8894]429{
[9003]430  GenericNPC::Anim anim;
431  anim.q = Quaternion(Vector(0,1,0), degreeInY);
432  anim.type = TurnTo;
[8894]433
[9061]434  if( this->behaviourList->empty())
[8894]435  {
[9061]436    this->behaviourList->push_back(anim);
[9003]437    this->initNPC();
[8894]438  }
[9003]439  else
[9061]440    this->behaviourList->push_back(anim);
[8894]441}
442
443
[9003]444
[8894]445/**
446 * lookat a world entity
447 * @param worldEntity: the worldentity to look at
448 */
[9003]449void GenericNPC::lookAt(WorldEntity* worldEntity)
[8894]450{
[9003]451  GenericNPC::Anim anim;
452  anim.entity = worldEntity;
453  anim.type = LookAt;
[8894]454
[9061]455  if( this->behaviourList->empty())
[8894]456  {
[9061]457    this->behaviourList->push_back(anim);
[9003]458    this->initNPC();
[8894]459  }
[9003]460  else
[9061]461    this->behaviourList->push_back(anim);
[8894]462}
463
464
465
[9003]466
[8894]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 */
[9003]472void GenericNPC::talkTo(WorldEntity* worldEntity, int dialogNr)
[8894]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/**
[8514]493 * tick this world entity
494 * @param time: time in seconds expirded since the last tick
495 */
[9003]496void GenericNPC::tick (float dt)
[8514]497{
498  if( likely(this->getModel(0) != NULL))
[9003]499    ((InteractiveModel*)this->getModel(0))->tick(dt);
[8894]500
[9003]501
[9061]502  if (!this->behaviourList->empty())
[9003]503  {
[9061]504    GenericNPC::Anim currentAnimation = this->behaviourList->front();
[9003]505
506    switch( currentAnimation.type)
507    {
508      case Walk:
509        {
510          Vector dest = currentAnimation.v - this->getAbsCoor();
[9061]511          dest.y = 0.0f;
[9003]512          if (dest.len() < .5)
[9027]513          {
[9003]514            this->nextStep();
[9027]515          }
[9003]516          else
517          {
[9061]518            Vector move = dest.getNormalized() * currentAnimation.speed * dt;
519            this->shiftCoor(move);
[9003]520          }
521        }
522        break;
523
524      case Run:
525      {
526        Vector dest = currentAnimation.v - this->getAbsCoor();
[9110]527        dest.y = 0.0f;
[9003]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();
[9110]540        dest.y = 0.0f;
[9003]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
[9061]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));
[9003]573
[9061]574  }
575  else
576  {
577    this->fallVelocity = 0.0f;
578  }
[9003]579
[8514]580}
581
582
583
[9235]584void GenericNPC::destroy(WorldEntity* killer)
[8514]585{
586  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
587
[9003]588  this->setAnimationSpeed(1.0f);
589
[8514]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.