Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10703 was 10618, checked in by bknecht, 17 years ago

merged cleanup into trunk (only improvements)

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