Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

npc does not yet move again. strange

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{
[9027]187
188  this->unsubscribeReaction();
189
[9003]190  if (!this->behaviourList.empty())
191  {
192    GenericNPC::Anim currentAnimation = this->behaviourList.front();
[8802]193
[9003]194    switch(this->behaviourList.front().type)
195    {
196      case Walk:
197      {
198        if( this->getAnimation() != RUN)
199          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]200
[9003]201        Vector dir = (currentAnimation.v - this->getAbsCoor());
202        dir.y = 0.0f;
203        dir.getNormalized();
204        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8894]205
[9003]206        this->setAnimationSpeed(0.5f);
207      }
208        break;
209      case Run:
210      {
211        if( this->getAnimation() != RUN)
212          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8802]213
[9003]214        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
215        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8590]216
[9003]217        this->setAnimationSpeed(1.0f);
218      }
219        break;
220      case Crouch:
221      {
222        if( this->getAnimation() != CROUCH_WALK)
223          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
[8590]224
[9003]225        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
226        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
[8802]227
[9003]228        this->setAnimationSpeed(1.0f);
229      }
230        break;
231      case LookAt:
232        if( this->getAnimation() != STAND)
233          this->setAnimation(STAND, MD2_ANIM_LOOP);
234        break;
235      case Shoot:
236        if( this->getAnimation() != STAND)
237          this->setAnimation(STAND, MD2_ANIM_LOOP);
238        break;
[8894]239
[9003]240      default:
241        if( this->getAnimation() != STAND)
242          this->setAnimation(STAND, MD2_ANIM_LOOP);
243        break;
[8894]244
[9003]245    }
246  }
[8802]247}
248
249
[9003]250void GenericNPC::nextStep()
[8805]251{
[9003]252  if (!this->behaviourList.empty())
253    this->behaviourList.pop_front();
254  else
255    return;
[8805]256
257
[9003]258  if (!this->behaviourList.empty())
259  {
260    GenericNPC::Anim currentAnimation = this->behaviourList.front();
[8894]261
[9003]262    switch( currentAnimation.type)
263    {
264      case Walk:
265      {
266        if( this->getAnimation() != RUN)
267          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]268
[9003]269        Vector dir = (currentAnimation.v - this->getAbsCoor());
270        dir.y = 0.0f;
271        dir.getNormalized();
272        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]273
[9003]274        this->setAnimationSpeed(0.5f);
275      }
276        break;
277      case Run:
278      {
279        if( this->getAnimation() != RUN)
280          this->setAnimation(RUN, MD2_ANIM_LOOP);
[8894]281
[9003]282        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
283        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]284
[9003]285        this->setAnimationSpeed(1.0f);
286      }
287        break;
288      case Crouch:
289      {
290        if( this->getAnimation() != CROUCH_WALK)
291          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
[8894]292
[9003]293        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
294        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]295
[9003]296        this->setAnimationSpeed(1.0f);
297      }
298        break;
299      case LookAt:
300      {
301        if( this->getAnimation() != STAND)
302          this->setAnimation(STAND, MD2_ANIM_LOOP);
303      }
304        break;
305      case Shoot:
306        if( this->getAnimation() != STAND)
307        this->setAnimation(STAND, MD2_ANIM_LOOP);
308        break;
[8894]309
[9003]310      default:
311        if( this->getAnimation() != STAND)
312        this->setAnimation(STAND, MD2_ANIM_LOOP);
313        break;
314
315    }
[8894]316  }
[9003]317  else
318  {
319    this->setAnimation(STAND, MD2_ANIM_LOOP);
320  }
[8894]321}
322
323
324
325
[9003]326void GenericNPC::walkTo(const Vector& coordinate)
[8894]327{
328
[9003]329  GenericNPC::Anim anim;
330  anim.v = coordinate;
331  anim.type = Walk;
332  anim.speed = 30.0f;
[8894]333
[9003]334  if( this->behaviourList.empty())
[8894]335  {
[9003]336    this->behaviourList.push_back(anim);
337    this->initNPC();
338  }
339  else
340    this->behaviourList.push_back(anim);
341}
[8894]342
[9003]343void GenericNPC::walkTo(float x, float y, float z)
344{
345  //printf("Walking to %f, %f, %f \n",x,y,z);
346  this->walkTo(Vector(x,y,z));
[8894]347
[9003]348}
[8894]349
[9003]350/* running functions */
351void GenericNPC::runTo(const Vector& coordinate)
352{
353  GenericNPC::Anim anim;
354  anim.v = coordinate;
355  anim.type = Run;
356  anim.speed = 60.0f;
[8894]357
[9003]358  if( this->behaviourList.empty())
359  {
360    this->behaviourList.push_back(anim);
361    this->initNPC();
[8894]362  }
[9003]363  else
364    this->behaviourList.push_back(anim);
365}
[8894]366
[9003]367void GenericNPC::runTo(float x, float y, float z)
368{
369  this->runTo(Vector(x,y,z));
[8894]370}
371
[9003]372/* couching functinos */
373void GenericNPC::crouchTo(const Vector& coordinate)
374{
375  GenericNPC::Anim anim;
376  anim.v = coordinate;
377  anim.type = Crouch;
[8894]378
[9003]379  if( this->behaviourList.empty())
380  {
381    this->behaviourList.push_back(anim);
382    this->initNPC();
383  }
384  else
385    this->behaviourList.push_back(anim);
386}
387void GenericNPC::crouchTo(float x, float y, float z)
[8894]388{
[9003]389  this->crouchTo(Vector(x,y,z));
[8894]390}
391
392
393
[9003]394void GenericNPC::turnTo(float degreeInY)
[8894]395{
[9003]396  GenericNPC::Anim anim;
397  anim.q = Quaternion(Vector(0,1,0), degreeInY);
398  anim.type = TurnTo;
[8894]399
[9003]400  if( this->behaviourList.empty())
[8894]401  {
[9003]402    this->behaviourList.push_back(anim);
403    this->initNPC();
[8894]404  }
[9003]405  else
406    this->behaviourList.push_back(anim);
[8894]407}
408
409
[9003]410
[8894]411/**
412 * lookat a world entity
413 * @param worldEntity: the worldentity to look at
414 */
[9003]415void GenericNPC::lookAt(WorldEntity* worldEntity)
[8894]416{
[9003]417  GenericNPC::Anim anim;
418  anim.entity = worldEntity;
419  anim.type = LookAt;
[8894]420
[9003]421  if( this->behaviourList.empty())
[8894]422  {
[9003]423    this->behaviourList.push_back(anim);
424    this->initNPC();
[8894]425  }
[9003]426  else
427    this->behaviourList.push_back(anim);
[8894]428}
429
430
431
[9003]432
[8894]433/**
434 * talk to a world entity and play a sound/music/voice
435 * @param worldEntity: entity
436 * @param dialogNr: sound nr to be played (from the xml load tags)
437 */
[9003]438void GenericNPC::talkTo(WorldEntity* worldEntity, int dialogNr)
[8894]439{}
440
441
442/**
443 * world entity to shoot at if there is any weapon on the npc
444 * @param entity: entity to shoot entity
445 */
446void GenericNPC::shootAt(WorldEntity* entity)
447{}
448
449
450
451
452
453
454
455
456
457
458/**
[8514]459 * tick this world entity
460 * @param time: time in seconds expirded since the last tick
461 */
[9003]462void GenericNPC::tick (float dt)
[8514]463{
464  if( likely(this->getModel(0) != NULL))
[9003]465    ((InteractiveModel*)this->getModel(0))->tick(dt);
[8894]466
[9003]467
468  if (!this->behaviourList.empty())
469  {
470    GenericNPC::Anim currentAnimation = this->behaviourList.front();
471
472    switch( currentAnimation.type)
473    {
474      case Walk:
475        {
476          Vector dest = currentAnimation.v - this->getAbsCoor();
477          if (dest.len() < .5)
[9027]478          {
[9003]479            this->nextStep();
[9027]480          }
[9003]481          else
482          {
483            dest.y = 0.0f;
484            this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
485          }
486        }
487        break;
488
489      case Run:
490      {
491        Vector dest = currentAnimation.v - this->getAbsCoor();
492        if (dest.len() < .5)
493          this->nextStep();
494        else
495        {
496          this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
497        }
498      }
499      break;
500
501      case Crouch:
502      {
503        Vector dest = currentAnimation.v - this->getAbsCoor();
504        if (dest.len() < .5)
505          this->nextStep();
506        else
507        {
508          this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
509        }
510      }
511      break;
512
513      case TurnTo:
514        //Quaternion direction = this->
515        break;
516
517      case LookAt:
518        break;
519
520      case Shoot:
521        break;
522
523      default:
524        break;
525
526    }
527  }
528
529  // physical falling of the player
[9026]530//   if( !this->isOnGround())
531//   {
532//     this->fallVelocity += 300.0f * dt;
533//     velocity -= Vector(0.0, 1.0, 0.0) * this->fallVelocity;
534//    // PRINTF(0)("%s is not on ground\n", this->getName());
535//     this->shiftCoor(Vector(0, -this->fallVelocity * dt,0));
536//   }
537//   else
538//   {
539//     this->fallVelocity = 0.0f;
540//   }
[9003]541
542
[9026]543
[8514]544}
545
546
547
548void GenericNPC::destroy()
549{
550  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
551
[9003]552  this->setAnimationSpeed(1.0f);
553
[8514]554  if( randi == 1)
555    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
556  else if( randi == 2)
557    this->setAnimation(DEATH_FALLFORWARD, MD2_ANIM_ONCE);
558  else if( randi == 3)
559    this->setAnimation(DEATH_FALLBACKSLOW, MD2_ANIM_ONCE);
560  else if( randi == 4)
561    this->setAnimation(CROUCH_DEATH, MD2_ANIM_ONCE);
562  else
563    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
564}
565
Note: See TracBrowser for help on using the repository browser.