Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/single_player_map/src/world_entities/npcs/generic_npc.cc @ 9037

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

some of the npc walk on the ground

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