Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged the single_player branche to trunk

File size: 13.5 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
190
191/**
192 * continue the generic animation
193 */
194void GenericNPC::resume()
195{
196  //if()
197  delete this->behaviourList;
198  this->behaviourList = this->animationStack.top();
199  this->animationStack.pop();
200}
201
202
203/**
204 * each animation has to be initialized here
205 */
206void GenericNPC::initNPC()
207{
208  if (!this->behaviourList->empty())
209  {
210    GenericNPC::Anim currentAnimation = this->behaviourList->front();
211
212    switch(this->behaviourList->front().type)
213    {
214      case Walk:
215      {
216        if( this->getAnimation() != RUN)
217          this->setAnimation(RUN, MD2_ANIM_LOOP);
218
219        Vector dir = (currentAnimation.v - this->getAbsCoor());
220        dir.y = 0.0f;
221        dir.getNormalized();
222        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
223
224        this->setAnimationSpeed(0.5f);
225      }
226        break;
227      case Run:
228      {
229        if( this->getAnimation() != RUN)
230          this->setAnimation(RUN, MD2_ANIM_LOOP);
231
232        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
233        dir.y = 0.0f;
234        dir.getNormalized();
235        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
236
237        this->setAnimationSpeed(1.0f);
238      }
239        break;
240      case Crouch:
241      {
242        if( this->getAnimation() != CROUCH_WALK)
243          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
244
245        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
246        dir.y = 0.0f;
247        dir.getNormalized();
248        this->setAbsDir(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)));
249
250        this->setAnimationSpeed(1.0f);
251      }
252        break;
253      case LookAt:
254        if( this->getAnimation() != STAND)
255          this->setAnimation(STAND, MD2_ANIM_LOOP);
256        break;
257      case Shoot:
258        if( this->getAnimation() != STAND)
259          this->setAnimation(STAND, MD2_ANIM_LOOP);
260        break;
261
262      default:
263        if( this->getAnimation() != STAND)
264          this->setAnimation(STAND, MD2_ANIM_LOOP);
265        break;
266
267    }
268  }
269}
270
271
272void GenericNPC::nextStep()
273{
274  if (!this->behaviourList->empty())
275    this->behaviourList->pop_front();
276  else
277    return;
278
279
280  if (!this->behaviourList->empty())
281  {
282    GenericNPC::Anim currentAnimation = this->behaviourList->front();
283
284    switch( currentAnimation.type)
285    {
286      case Walk:
287      {
288        if( this->getAnimation() != RUN)
289          this->setAnimation(RUN, MD2_ANIM_LOOP);
290
291
292        Vector dir = (currentAnimation.v - this->getAbsCoor());
293        dir.y = 0.0f;
294        dir.getNormalized();
295        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
296
297        this->setAnimationSpeed(0.5f);
298      }
299        break;
300      case Run:
301      {
302        if( this->getAnimation() != RUN)
303          this->setAnimation(RUN, MD2_ANIM_LOOP);
304
305        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
306        dir.y = 0.0f;
307        dir.getNormalized();
308        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
309
310        this->setAnimationSpeed(1.0f);
311      }
312        break;
313      case Crouch:
314      {
315        if( this->getAnimation() != CROUCH_WALK)
316          this->setAnimation(CROUCH_WALK, MD2_ANIM_LOOP);
317
318        Vector dir = (currentAnimation.v - this->getAbsCoor()).getNormalized();
319        dir.y = 0.0f;
320        dir.getNormalized();
321        this->setAbsDirSoft(Quaternion(dir, Vector(0.0, 1.0, 0.0)) * Quaternion(-M_PI_2, Vector(0.0, 1.0, 0.0)), 4.0);
322
323        this->setAnimationSpeed(1.0f);
324      }
325        break;
326      case LookAt:
327      {
328        if( this->getAnimation() != STAND)
329          this->setAnimation(STAND, MD2_ANIM_LOOP);
330      }
331        break;
332      case Shoot:
333        if( this->getAnimation() != STAND)
334        this->setAnimation(STAND, MD2_ANIM_LOOP);
335        break;
336
337      default:
338        if( this->getAnimation() != STAND)
339        this->setAnimation(STAND, MD2_ANIM_LOOP);
340        break;
341
342    }
343  }
344  else
345  {
346    this->setAnimation(STAND, MD2_ANIM_LOOP);
347  }
348}
349
350
351
352
353void GenericNPC::walkTo(const Vector& coordinate)
354{
355
356  GenericNPC::Anim anim;
357  anim.v = coordinate;
358  anim.type = Walk;
359  anim.speed = 30.0f;
360
361  if( this->behaviourList->empty())
362  {
363    this->behaviourList->push_back(anim);
364    this->initNPC();
365  }
366  else
367    this->behaviourList->push_back(anim);
368}
369
370void GenericNPC::walkTo(float x, float y, float z)
371{
372  //printf("Walking to %f, %f, %f \n",x,y,z);
373  this->walkTo(Vector(x,y,z));
374
375}
376
377/* running functions */
378void GenericNPC::runTo(const Vector& coordinate)
379{
380  GenericNPC::Anim anim;
381  anim.v = coordinate;
382  anim.type = Run;
383  anim.speed = 60.0f;
384
385  if( this->behaviourList->empty())
386  {
387    this->behaviourList->push_back(anim);
388    this->initNPC();
389  }
390  else
391    this->behaviourList->push_back(anim);
392}
393
394void GenericNPC::runTo(float x, float y, float z)
395{
396  this->runTo(Vector(x,y,z));
397}
398
399/* couching functinos */
400void GenericNPC::crouchTo(const Vector& coordinate)
401{
402  GenericNPC::Anim anim;
403  anim.v = coordinate;
404  anim.type = Crouch;
405
406  if( this->behaviourList->empty())
407  {
408    this->behaviourList->push_back(anim);
409    this->initNPC();
410  }
411  else
412    this->behaviourList->push_back(anim);
413}
414void GenericNPC::crouchTo(float x, float y, float z)
415{
416  this->crouchTo(Vector(x,y,z));
417}
418
419
420
421void GenericNPC::turnTo(float degreeInY)
422{
423  GenericNPC::Anim anim;
424  anim.q = Quaternion(Vector(0,1,0), degreeInY);
425  anim.type = TurnTo;
426
427  if( this->behaviourList->empty())
428  {
429    this->behaviourList->push_back(anim);
430    this->initNPC();
431  }
432  else
433    this->behaviourList->push_back(anim);
434}
435
436
437
438/**
439 * lookat a world entity
440 * @param worldEntity: the worldentity to look at
441 */
442void GenericNPC::lookAt(WorldEntity* worldEntity)
443{
444  GenericNPC::Anim anim;
445  anim.entity = worldEntity;
446  anim.type = LookAt;
447
448  if( this->behaviourList->empty())
449  {
450    this->behaviourList->push_back(anim);
451    this->initNPC();
452  }
453  else
454    this->behaviourList->push_back(anim);
455}
456
457
458
459
460/**
461 * talk to a world entity and play a sound/music/voice
462 * @param worldEntity: entity
463 * @param dialogNr: sound nr to be played (from the xml load tags)
464 */
465void GenericNPC::talkTo(WorldEntity* worldEntity, int dialogNr)
466{}
467
468
469/**
470 * world entity to shoot at if there is any weapon on the npc
471 * @param entity: entity to shoot entity
472 */
473void GenericNPC::shootAt(WorldEntity* entity)
474{}
475
476
477
478
479
480
481
482
483
484
485/**
486 * tick this world entity
487 * @param time: time in seconds expirded since the last tick
488 */
489void GenericNPC::tick (float dt)
490{
491  if( likely(this->getModel(0) != NULL))
492    ((InteractiveModel*)this->getModel(0))->tick(dt);
493
494
495  if (!this->behaviourList->empty())
496  {
497    GenericNPC::Anim currentAnimation = this->behaviourList->front();
498
499    switch( currentAnimation.type)
500    {
501      case Walk:
502        {
503          Vector dest = currentAnimation.v - this->getAbsCoor();
504          dest.y = 0.0f;
505          if (dest.len() < .5)
506          {
507            this->nextStep();
508          }
509          else
510          {
511            Vector move = dest.getNormalized() * currentAnimation.speed * dt;
512            this->shiftCoor(move);
513          }
514        }
515        break;
516
517      case Run:
518      {
519        Vector dest = currentAnimation.v - this->getAbsCoor();
520        if (dest.len() < .5)
521          this->nextStep();
522        else
523        {
524          this->shiftCoor(dest.getNormalized() * currentAnimation.speed * dt);
525        }
526      }
527      break;
528
529      case Crouch:
530      {
531        Vector dest = currentAnimation.v - this->getAbsCoor();
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 TurnTo:
542        //Quaternion direction = this->
543        break;
544
545      case LookAt:
546        break;
547
548      case Shoot:
549        break;
550
551      default:
552        break;
553
554    }
555  }
556
557  // physical falling of the player
558  if( !this->isOnGround())
559  {
560    this->fallVelocity += 300.0f * dt;
561    //velocity -= Vector(0.0, 1.0, 0.0) * this->fallVelocity;
562   // PRINTF(0)("%s is not on ground\n", this->getName());
563    this->shiftCoor(Vector(0, -this->fallVelocity * dt,0));
564
565  }
566  else
567  {
568    this->fallVelocity = 0.0f;
569  }
570
571}
572
573
574
575void GenericNPC::destroy()
576{
577  int randi = (int)(5.0f * (float)rand()/(float)RAND_MAX);
578
579  this->setAnimationSpeed(1.0f);
580
581  if( randi == 1)
582    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
583  else if( randi == 2)
584    this->setAnimation(DEATH_FALLFORWARD, MD2_ANIM_ONCE);
585  else if( randi == 3)
586    this->setAnimation(DEATH_FALLBACKSLOW, MD2_ANIM_ONCE);
587  else if( randi == 4)
588    this->setAnimation(CROUCH_DEATH, MD2_ANIM_ONCE);
589  else
590    this->setAnimation(DEATH_FALLBACK, MD2_ANIM_ONCE);
591}
592
Note: See TracBrowser for help on using the repository browser.