Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/world_entities/npcs/generic_npc.cc @ 9833

Last change on this file since 9833 was 9833, checked in by bensch, 18 years ago

orxonox/new_class_id: almost killed off the old ResourceManager

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