Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/world_entities/npcs/generic_npc.cc @ 9808

Last change on this file since 9808 was 9808, checked in by bensch, 18 years ago

fixed a copy bug… wow… this took 2 hours again

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