Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9031 was 9031, checked in by snellen, 18 years ago

added some methods to generic npcs scriptable

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