Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed a copy bug… wow… this took 2 hours again

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