Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged the collision reaction branche back to trunk

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