Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/world_entities/npcs/generic_npc.cc @ 9076

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

npc now stopps

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