Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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