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
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                        // Display
43                        ->addMethod("hide", ExecutorLua0<WorldEntity>(&WorldEntity::hide))
44                        ->addMethod("unhide", ExecutorLua0<WorldEntity>(&WorldEntity::unhide))
45                        // Coordinates
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))
51
52                       );
53
54
55
56/**
57 * constructor
58 */
59GenericNPC::GenericNPC(const TiXmlElement* root)
60    : NPC(root)
61{
62  this->init();
63
64  if (root != NULL)
65    this->loadParams(root);
66}
67
68
69/**
70 * deconstructor
71 */
72GenericNPC::~GenericNPC ()
73{}
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);
83
84  if (this->soundBuffer != NULL)
85    ResourceManager::getInstance()->unload(this->soundBuffer);
86  this->soundBuffer = (OrxSound::SoundBuffer*)ResourceManager::getInstance()->load("sound/rain.wav", WAV);
87
88  time = 30.0f;
89
90  // collision reaction registration
91//   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
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{
101  NPC::loadParams(root);
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
118
119/**
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/**
156 * sets the animation of this npc
157 * @param anumationIndex: the animation index
158 * @param anumPlaybackMode: the playback mode
159 */
160void GenericNPC::playAnimation(int animationIndex, int animPlaybackMode)
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 */
172void GenericNPC::playSound(std::string filename)
173{}
174
175
176
177/**
178 * stops the generic animation
179 */
180void GenericNPC::stop()
181{}
182
183
184
185void GenericNPC::initNPC()
186{
187  if (!this->behaviourList.empty())
188  {
189    GenericNPC::Anim currentAnimation = this->behaviourList.front();
190
191    switch(this->behaviourList.front().type)
192    {
193      case Walk:
194      {
195        if( this->getAnimation() != RUN)
196          this->setAnimation(RUN, MD2_ANIM_LOOP);
197
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)));
202
203        this->setAnimationSpeed(0.5f);
204      }
205        break;
206      case Run:
207      {
208        if( this->getAnimation() != RUN)
209          this->setAnimation(RUN, MD2_ANIM_LOOP);
210
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)));
213
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);
221
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)));
224
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;
236
237      default:
238        if( this->getAnimation() != STAND)
239          this->setAnimation(STAND, MD2_ANIM_LOOP);
240        break;
241
242    }
243  }
244}
245
246
247void GenericNPC::nextStep()
248{
249  if (!this->behaviourList.empty())
250    this->behaviourList.pop_front();
251  else
252    return;
253
254
255  if (!this->behaviourList.empty())
256  {
257    GenericNPC::Anim currentAnimation = this->behaviourList.front();
258
259    switch( currentAnimation.type)
260    {
261      case Walk:
262      {
263        if( this->getAnimation() != RUN)
264          this->setAnimation(RUN, MD2_ANIM_LOOP);
265
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);
270
271        this->setAnimationSpeed(0.5f);
272      }
273        break;
274      case Run:
275      {
276        if( this->getAnimation() != RUN)
277          this->setAnimation(RUN, MD2_ANIM_LOOP);
278
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);
281
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);
289
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);
292
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;
306
307      default:
308        if( this->getAnimation() != STAND)
309        this->setAnimation(STAND, MD2_ANIM_LOOP);
310        break;
311
312    }
313  }
314  else
315  {
316    this->setAnimation(STAND, MD2_ANIM_LOOP);
317  }
318}
319
320
321
322
323void GenericNPC::walkTo(const Vector& coordinate)
324{
325
326  GenericNPC::Anim anim;
327  anim.v = coordinate;
328  anim.type = Walk;
329  anim.speed = 30.0f;
330
331  if( this->behaviourList.empty())
332  {
333    this->behaviourList.push_back(anim);
334    this->initNPC();
335  }
336  else
337    this->behaviourList.push_back(anim);
338}
339
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));
344
345}
346
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;
354
355  if( this->behaviourList.empty())
356  {
357    this->behaviourList.push_back(anim);
358    this->initNPC();
359  }
360  else
361    this->behaviourList.push_back(anim);
362}
363
364void GenericNPC::runTo(float x, float y, float z)
365{
366  this->runTo(Vector(x,y,z));
367}
368
369/* couching functinos */
370void GenericNPC::crouchTo(const Vector& coordinate)
371{
372  GenericNPC::Anim anim;
373  anim.v = coordinate;
374  anim.type = Crouch;
375
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)
385{
386  this->crouchTo(Vector(x,y,z));
387}
388
389
390
391void GenericNPC::turnTo(float degreeInY)
392{
393  GenericNPC::Anim anim;
394  anim.q = Quaternion(Vector(0,1,0), degreeInY);
395  anim.type = TurnTo;
396
397  if( this->behaviourList.empty())
398  {
399    this->behaviourList.push_back(anim);
400    this->initNPC();
401  }
402  else
403    this->behaviourList.push_back(anim);
404}
405
406
407
408/**
409 * lookat a world entity
410 * @param worldEntity: the worldentity to look at
411 */
412void GenericNPC::lookAt(WorldEntity* worldEntity)
413{
414  GenericNPC::Anim anim;
415  anim.entity = worldEntity;
416  anim.type = LookAt;
417
418  if( this->behaviourList.empty())
419  {
420    this->behaviourList.push_back(anim);
421    this->initNPC();
422  }
423  else
424    this->behaviourList.push_back(anim);
425}
426
427
428
429
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 */
435void GenericNPC::talkTo(WorldEntity* worldEntity, int dialogNr)
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/**
456 * tick this world entity
457 * @param time: time in seconds expirded since the last tick
458 */
459void GenericNPC::tick (float dt)
460{
461  if( likely(this->getModel(0) != NULL))
462    ((InteractiveModel*)this->getModel(0))->tick(dt);
463
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
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//   }
537
538
539
540}
541
542
543
544void GenericNPC::destroy()
545{
546  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
547
548  this->setAnimationSpeed(1.0f);
549
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.