Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

made scripttrigger scriptable

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