Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/world_entities/npcs/adm_turret.cc @ 10704

Last change on this file since 10704 was 10704, checked in by rennerc, 17 years ago

FPSSniperRifle uses BspWeapon now

File size: 9.2 KB
RevLine 
[10663]1/*
2* orxonox - the future of 3D-vertical-scrollers
3*
4* Copyright (C) 2004 orx
5*
6* This program is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation; either version 2, or (at your option)
9* any later version.
10*
11*     ### File Specific:
12*     main-programmer: Reto Luechinger
13*/
14
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
17#include "adm_turret.h"
[10664]18#include "weapons/weapon_manager.h"
19#include "weapons/weapon.h"
[10663]20#include "lib/util/loading/factory.h"
21#include "world_entities/projectiles/projectile.h"
[10664]22#include "loading/load_param.h"
23#include "debug.h"
[10677]24#include "loading/load_param_xml.h"
[10663]25
[10688]26#include "environments/bsp_entity.h"
[10703]27#include "effects/explosion.h"
[10688]28
[10663]29ObjectListDefinition(AdmTurret);
30CREATE_FACTORY(AdmTurret);
31
32/**
33*  Standard constructor
34*/
35AdmTurret::AdmTurret ()
36{
[10664]37        this->init();
[10663]38}
39
40/**
[10666]41* destructs the turret, deletes allocated memory
[10663]42*/
43AdmTurret::~AdmTurret ()
44{
45          // will be deleted
46}
47
[10666]48/**
49* Constructor with XML Element
50*/
[10664]51AdmTurret::AdmTurret (const  TiXmlElement* root)
[10663]52{
[10664]53        this->init();
54        if (root != NULL)
55        {
56                this->loadParams(root);
57        }
[10663]58}
[10677]59/**
60* XML Loader
61*/
62void AdmTurret::loadParams(const TiXmlElement* root)
63{
64        if (root != NULL)
65        {
66                WorldEntity::loadParams(root);
[10664]67
[10677]68                LoadParam(root, "target", this, AdmTurret, setTarget)
69                        .describe("The filename of the World Entity, that is to be shot at")
70                        .defaultValues("");
[10703]71    LoadParam(root, "type", this, AdmTurret, setType)
72      .describe("floor|ceil"); 
[10677]73                LoadParamXML(root, "Cannons", this, AdmTurret, addCannons)
74                        .describe("add cannons to ADM");
75                LoadParamXML(root, "Sensor", this, AdmTurret, addSensor)
76                        .describe("add sensor to ADM");
[10694]77                LoadParamXML(root, "Weapon", this, AdmTurret, addWeapon)
78                        .describe("add weapon to ADM");
[10677]79        }
[10681]80//         this->removeNodeFlags( PNODE_ALL );
[10683]81        this->addNodeFlags( PNODE_ROTATE_AND_MOVE );
82        this->addNodeFlags( PNODE_REPARENT_KEEP_POSITION );
[10679]83       
[10683]84        //HACK this is needed to get the correct coordinates instead (0, 0, 0)
85        this->updateNode( 0 );
86       
[10681]87        if ( this->isCeil )
88        {
89          Vector a = this->sensor->getRelCoor();
90          this->sensor->setRelCoor( -a.x, -a.y, -a.z );
91          a = this->cannons->getRelCoor();
92          this->cannons->setRelCoor( -a.x, -a.y, -a.z );
93        }
[10677]94}
95
96/**
97* Sets Target onto the World Entity with filename "target", given as String
98*/
99void AdmTurret::setTarget(const std::string& target)
100{
101        WorldEntity* targetEntity = WorldEntity::objectList().getObject(target);
102        if (targetEntity != NULL) 
103        {
104                this->myTarget = targetEntity;
105        }
106        else
107        {
108                PRINTF(1)("ERROR ADMTURRET : Target %s does not exist\n", target.c_str());
109        }
110}
111
[10681]112void AdmTurret::setType( const std::string& type )
113{
114  if ( type == "floor" )
115  {
116    this->isCeil = false;
117    return;
118  }
119 
120  if ( type == "ceil" )
121  {
122    this->isCeil = true;
123    return;
124  }
125 
126  //invalid argument
127  PRINTF(1)("%s is not a valid type for AdmTurret\n", type.c_str());
128  assert("false");
129}
130
[10663]131void AdmTurret::init()
132{
[10664]133        this->registerObject(this, AdmTurret::_objectList);
[10703]134        this->setHealthMax(100);
135        this->setHealth(100);
[10681]136        this->bodyAngle = this->cannonAngle = 0.0f;
137        this->isActive = true;
138        this->range = 400;
139        this->isCeil = false;
[10688]140        this->playerVisible = false;
[10698]141        this->weapon = NULL;
[10689]142
143       
[10663]144}
145
[10677]146void AdmTurret::tick(float dt)
[10663]147{
[10677]148  WorldEntity::tick(dt);
[10698]149  if (this->weapon) this->weapon->fire(false);
[10703]150  if ( this->getHealth() <= 0 )
[10689]151  {
[10703]152    this->moveTowards( Vector(0, -1, 0), dt*2 );
153  }
154  else
155  {
156 
[10694]157   
[10703]158    this->updatePlayerVisible();
159 
160    //rotate sensor 2PI/sec
161    this->sensor->setAbsDir( this->sensor->getAbsDir() * Quaternion( PI*2*dt, Vector( 0, -1, 0 ) ) );
162 
163 
164    Vector playerPos = this->myTarget->getAbsCoor() + Vector(0, 12, 0);
165    Vector ds = playerPos - ( this->cannons->getAbsCoor() );
166    if ( isActive && ds.len() <= range && playerVisible )
[10698]167    {
[10703]168      this->moveTowards( ds,  dt);
169     
170      //if target within +/- 2.5 degrees of aim -> fire
171      Vector dv1 = ds;
172      dv1.normalize();
173      Vector dv2 = this->cannons->getAbsDir().apply( Vector(-1, 0, 0));
174      dv2.normalize();
175      float angle = dv1.dot(dv2);
176      if (angle > 0.999)
177      {
178        if (this->weapon) this->weapon->fire(true);
179      }
[10698]180    }
[10703]181    else
182    {
183      if ( !( isActive && ds.len() <= range ) )
184        this->moveTowards( Vector(0, -1, 0), dt );
185    }
[10689]186  }
[10664]187}
[10663]188
[10664]189void AdmTurret::draw() const
190{
[10677]191  WorldEntity::draw();
192
[10694]193#if 0
[10677]194  glMatrixMode(GL_MODELVIEW);
195  glPushMatrix();
196
197  glPushAttrib(GL_ENABLE_BIT);
198
199  glDisable(GL_LIGHTING);
200  glDisable(GL_TEXTURE_2D);
201  glDisable(GL_BLEND);
202  glLineWidth(2.0);
203
204
205  Vector mp = this->cannons->getAbsCoor();
206  Vector op = this->cannons->getAbsDir().apply( Vector(-1, 0, 0) );
207  op *= 100;
208  op += mp;
209
210  glColor3f(1.0, 0.0, 0.0 );
211  glBegin(GL_LINE_STRIP);
212    glVertex3f(mp.x, mp.y, mp.z);
213    glVertex3f(op.x, op.y, op.z);
214  glEnd();
215
216  op = this->myTarget->getAbsCoor() - ( this->cannons->getAbsCoor() );
217  op += mp;
218
219  glColor3f(0.0, 1.0, 0.0 );
220  glBegin(GL_LINE_STRIP);
221    glVertex3f(mp.x, mp.y, mp.z);
222    glVertex3f(op.x, op.y, op.z);
223  glEnd();
224 
225  glPopAttrib();
226  glPopMatrix();
[10694]227#endif
[10664]228}
[10663]229
[10664]230void AdmTurret::collidesWith(WorldEntity* entity, const Vector& location)
231{
232}
[10663]233
[10664]234void AdmTurret::activate()
[10663]235{
236}
[10664]237
238void AdmTurret::deactivate()
239{
[10663]240}
241
[10677]242void AdmTurret::addCannons( const TiXmlElement * root )
243{
[10694]244  this->cannons = new WorldEntity();
[10677]245        this->cannons->setParent(this);
246        this->cannons->loadParams( root );
247
[10679]248        //this->cannons->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
249        //this->cannons->addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE);
[10703]250
[10677]251        this->cannons->toList( getOMListNumber() );
[10694]252}
253
254void AdmTurret::addWeapon( const TiXmlElement * root )
255{
[10704]256        this->weapon = new BspWeapon(getOMListNumber());
[10694]257        this->weapon->setParent( this->cannons );
[10690]258        this->weapon->loadParams(root);
[10689]259        this->weapon->toList( getOMListNumber() );
[10694]260        //this->weapon->setAbsCoor( this->cannons->getAbsCoor() );
[10689]261        this->weapon->setAbsDir( this->weapon->getAbsDir() * Quaternion( PI, Vector(0, 1, 0) ) );
[10677]262}
263
264void AdmTurret::addSensor( const TiXmlElement * root )
265{
[10694]266  this->sensor = new WorldEntity();
[10677]267        this->sensor->setParent(this);
268        this->sensor->loadParams( root );
269
[10679]270        //this->sensor->addNodeFlags(PNODE_PROHIBIT_DELETE_WITH_PARENT);
271        //this->sensor->addNodeFlags(PNODE_PROHIBIT_CHILD_DELETE);
[10677]272        this->sensor->toList( getOMListNumber() );
273}
274
275void AdmTurret::moveTowards( Vector targetDir, float dt )
276{
[10681]277  if ( this->cannons->getParent() != NullParent::getNullParent() )
[10683]278  {
[10681]279    this->cannons->setParent( NullParent::getNullParent() );
[10683]280    this->cannons->shiftCoor( this->getAbsCoor() );
[10703]281
[10683]282    this->sensor->setParent( NullParent::getNullParent() );
283    this->sensor->shiftCoor( this->getAbsCoor() );
284  }
[10703]285
[10681]286  targetDir.normalize();
[10703]287
[10681]288  float dAngle = dt;
[10703]289
[10681]290  float bestResult = -1.0f;
291  Quaternion bestBodyRot;
292  Quaternion bestCannonRot;
293  float bestBodyAngle = 0.0f;
294  float bestCannonAngle = 0.0f;
[10703]295
[10683]296   Quaternion baseRot(0, Vector(1, 0, 0));
297   if ( isCeil )
298   {
299     baseRot = Quaternion( PI, Vector( 1, 0, 0 ) );
300   }
[10703]301
[10681]302  for ( int dBodyAngle = -1; dBodyAngle<2; dBodyAngle++ )
[10679]303  {
[10681]304    for ( int dCannonAngle = -1; dCannonAngle<2; dCannonAngle++ )
305    {
306      float bodyAngle = this->bodyAngle + dBodyAngle*dAngle;
307      float cannonAngle = this->cannonAngle + dCannonAngle*dAngle;
[10703]308
[10681]309      while ( bodyAngle > 2*PI )
310        bodyAngle -= 2*PI;
311      while ( bodyAngle < 0 )
312        bodyAngle += 2*PI;
313      while ( cannonAngle > 2*PI )
314        cannonAngle -= 2*PI;
315      while ( cannonAngle < 0 )
316        cannonAngle += 2*PI;
[10703]317
[10681]318      Quaternion bodyRot( bodyAngle, Vector( 0, 1, 0 ) );
319      Quaternion cannonRot( cannonAngle, Vector( 0, 0, 1) );
[10703]320
[10683]321       bodyRot = baseRot * bodyRot;
322       cannonRot = baseRot * cannonRot;
[10703]323
[10681]324      float result = (bodyRot * cannonRot).apply( Vector( -1, 0, 0 ) ).dot( targetDir );
[10703]325
[10681]326      if ( result > bestResult )
327      {
328        bestResult = result;
329        bestBodyRot = bodyRot;
330        bestBodyAngle = bodyAngle;
331        bestCannonRot = cannonRot;
332        bestCannonAngle = cannonAngle;
333      }
334    }
[10679]335  }
[10703]336
[10681]337  this->bodyAngle = bestBodyAngle;
338  this->cannonAngle = bestCannonAngle;
[10703]339
[10681]340  this->setAbsDir( bestBodyRot );
341  this->cannons->setAbsDir( bestBodyRot * bestCannonRot );
[10677]342}
[10688]343
344void AdmTurret::updatePlayerVisible( )
345{
346  std::list<WorldEntity*>::iterator entityIterator;
347  // for all bsp managers check all entities
348  Vector pos = this->cannons->getAbsCoor();
[10703]349  Vector dir = this->myTarget->getAbsCoor() - pos  + Vector(0, 12, 0);
[10688]350
351  this->playerVisible = true;
352  for( ObjectList<BspEntity>::const_iterator bspIterator = BspEntity::objectList().begin();
353       bspIterator != BspEntity::objectList().end();
354       bspIterator++) {
355      float res = (dynamic_cast<BspEntity*>(*bspIterator)->getBspManager())->checkCollisionRay( pos, dir, dir.len() + 1 );
[10703]356
357      if ( res < dir.len() ) this->playerVisible = false;
[10688]358  }
359}
[10703]360
361void AdmTurret::destroy( WorldEntity * killer )
362{
363  Explosion().explode(this->cannons,Vector(1,1,1));
364}
Note: See TracBrowser for help on using the repository browser.