Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9026 was 9026, checked in by patrick, 18 years ago

trunk: npcs are walking again

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