Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/world_entities/npcs/actionbox_enemy.cc @ 10766

Last change on this file since 10766 was 10758, checked in by nicolasc, 18 years ago

added shield functionality, reverted paeddae's MP patch - does not work

File size: 10.6 KB
Line 
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: Christoph Renner
13   co-programmer:
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
17
18#include "loading/factory.h"
19#include "debug.h"
20#include "loading/load_param.h"
21#include "util/loading/load_param_xml.h"
22#include "state.h"
23#include "player.h"
24#include "playable.h"
25
26#include "particles/dot_emitter.h"
27#include "particles/emitter_node.h"
28#include "particles/sprite_particles.h"
29
30#include "actionbox_enemy.h"
31
32ObjectListDefinition(ActionboxEnemy);
33CREATE_FACTORY(ActionboxEnemy);
34
35ActionboxEnemy::ActionboxEnemy(const TiXmlElement* root)
36  :weaponMan(this)
37{
38  PRINTF(0)("ActionboxEnemy\n");
39 
40  this->registerObject(this, ActionboxEnemy::_objectList);
41  this->toList(OM_GROUP_00);
42 
43  this->isActive = true;
44 
45  this->pitch = 0.0f;
46  this->dPitch = 0.0;
47 
48  this->maxSpeed = 30;
49  this->acceleration = 3;
50  this->speed = 0;
51  this->agility = 1;
52 
53  this->onEscape = false;
54  this->escaped = false;
55  this->endPoint = Vector(0, 0, 0);
56 
57  this->weaponMan.setParentEntity( this);
58  //weapons:
59
60  this->weaponMan.setParentEntity( this);
61
62  this->weaponMan.setSlotCount(8);
63
64  this->weaponMan.createWeaponSlot(0, 3.270, 1.028, .155, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
65  this->weaponMan.createWeaponSlot(1, 3.270, 1.028, -.155, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
66  this->weaponMan.createWeaponSlot(2, 4.385, .063, .876, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
67  this->weaponMan.createWeaponSlot(3, 4.385, -.063, -.876, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
68  this->weaponMan.createWeaponSlot(4, 1.635, -.612, 2.691, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
69  this->weaponMan.createWeaponSlot(5, 1.536, -.612, -2.691, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
70  this->weaponMan.createWeaponSlot(6, 1.536, -.612, 3.254, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
71  this->weaponMan.createWeaponSlot(7, 1.536, -.612, -3.254, WTYPE_ALLDIRS | WTYPE_DIRECTIONAL);
72
73
74  this->weaponMan.addWeaponToSlot(0, 0, "RFCannon");
75  this->weaponMan.addWeaponToSlot(0, 1, "RFCannon");
76//   this->weaponMan.addWeaponToSlot(0, 2, "RFCannon");
77//   this->weaponMan.addWeaponToSlot(0, 3, "RFCannon");
78//   this->weaponMan.addWeaponToSlot(1, 0, "RFCannon");
79//   this->weaponMan.addWeaponToSlot(1, 1, "RFCannon");
80//   this->weaponMan.addWeaponToSlot(1, 2, "RFCannon");
81//   this->weaponMan.addWeaponToSlot(1, 3, "RFCannon");
82
83/*  this->weaponMan.addWeaponToSlot(0, 4, "NadionLaser");
84  this->weaponMan.addWeaponToSlot(0, 5, "NadionLaser");
85  this->weaponMan.addWeaponToSlot(2, 4, "NadionLaser");
86  this->weaponMan.addWeaponToSlot(2, 5, "NadionLaser");
87
88  this->weaponMan.addWeaponToSlot(0, 6, "Disruptor");
89  this->weaponMan.addWeaponToSlot(0, 7, "Disruptor");
90  this->weaponMan.addWeaponToSlot(3, 6, "Disruptor");
91  this->weaponMan.addWeaponToSlot(3, 7, "Disruptor");*/
92 
93  this->weaponMan.changeWeaponConfig(0);
94 
95  this->weaponMan.getFixedTarget()->setParent(this);
96  this->weaponMan.getFixedTarget()->setRelCoor(100000,0,0);
97  this->weaponMan.hideCrosshair();
98 
99  if ( root )
100  {
101    this->loadParams( root );
102  }
103}
104
105ActionboxEnemy::~ActionboxEnemy()
106{
107}
108
109void ActionboxEnemy::loadParams(const TiXmlElement* root)
110{
111  WorldEntity::loadParams( root );
112 
113  LoadParam(root, "endPoint", this, ActionboxEnemy, setEndPoint);
114  LoadParam(root, "maxSpeed", this, ActionboxEnemy, setMaxSpeed);
115  LoadParam(root, "agility", this, ActionboxEnemy, setAgility);
116  LoadParam(root, "acceleration", this, ActionboxEnemy, setAcceleration);
117  LoadParam(root, "active", this, ActionboxEnemy, setActive);
118}
119
120void ActionboxEnemy::tick( float dt )
121{
122  // printf("ABEGROUP: %d\n", this->getOMListNumber());
123 
124  if ( escaped )
125  {
126    moveTowards( endPoint, endPoint - this->getAbsCoor(), dt );
127    return;
128  }
129 
130  weaponMan.tick( dt );
131  this->bFire = false;
132 
133  if ( !State::getPlayer() || !State::getPlayer()->getPlayable() )
134    return;
135 
136  Vector playerDir = State::getPlayer()->getPlayable()->getAbsDir().apply( Vector(1, 0, 0) );
137  Vector dist = this->getAbsCoor() - State::getPlayer()->getPlayable()->getAbsCoor();
138 
139  bool behindPlayer = playerDir.dot( dist ) < 0;
140 
141  if ( behindPlayer )
142  {
143    this->escaped = true;
144    PRINTF(0)("MOVING TOWARDS ENDPOINT\n");
145    return;
146  }
147 
148  myDir = this->getAbsDir();
149  myCoor = this->getAbsCoor();
150 
151  this->pitch += this->dPitch*dt;
152  while ( pitch > 2*PI )
153    pitch -= 2*PI;
154  while ( pitch < 0 )
155    pitch += 2*PI;
156 
157  myDir *= qPitch.inverse();
158 
159  qPitch = Quaternion( pitch, Vector( 1, 0, 0 ) );
160 
161  if ( isActive && State::getActionBox() )
162  {
163    ActionBox* box = State::getActionBox();
164    if ( box->isPointInBox( this->getAbsCoor() ) )
165    {
166      attackPlayer( box, dt );
167    }
168    else
169    {
170      moveTowardsBox( box, dt );
171      onEscape = false;
172    }
173  }
174 
175  myDir *= qPitch;
176 
177  this->setAbsDir( myDir );
178  this->setAbsCoor( myCoor );
179}
180
181void ActionboxEnemy::attackPlayer( ActionBox * box, float dt )
182{
183  if ( !State::getPlayer() || !State::getPlayer()->getPlayable() || !box )
184    return;
185 
186  float distance = (State::getPlayer()->getPlayable()->getAbsCoor() - getAbsCoor() ).len();
187 
188  if ( distance > box->getDepth()/4.0 && !onEscape )
189  {
190    Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor();
191    Vector targetDir = State::getPlayer()->getPlayable()->getAbsCoor()-this->getAbsCoor();
192    moveTowards( targetPos, targetDir, dt );
193    if ( this->getAbsDir().apply( Vector(1, 0, 0) ).dot(targetDir) > 0.9 && State::getPlayer()->getPlayable()->getOMListNumber()!=OM_DEAD )
194    {
195      this->bFire = true;
196      weaponMan.fire();
197    }
198  }
199  else
200  {
201    if ( !onEscape )
202    {
203      Vector ds = this->getAbsCoor() - State::getPlayer()->getPlayable()->getAbsCoor();
204      float projy = box->getAbsDir().apply( Vector(0, 1, 0) ).dot( ds );
205      float projz = box->getAbsDir().apply( Vector(0, 0, 1) ).dot( ds );
206      this->escapePoint = Vector( 0, projy, projz );
207      this->escapePoint.normalize();
208      this->escapePoint*= 2*box->getWidth_2();
209      PRINTF(0)("ESCAPE\n");
210    }
211    onEscape = true;
212   
213    Vector rEscapePoint = box->getAbsDir().apply(escapePoint + Vector( -10, 0, 0 ));
214    Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor() + rEscapePoint;
215    Vector targetDir = State::getPlayer()->getPlayable()->getAbsCoor() + rEscapePoint - this->getAbsCoor();
216    moveTowards( targetPos, targetDir, dt );
217  }
218}
219
220void ActionboxEnemy::moveTowards( Vector targetPos, Vector targetDir, float dt )
221{
222  Quaternion cur = myDir;
223  Quaternion rx( agility*dt, Vector( 0, 0, 1 ) );
224 
225  Quaternion tmp1 = cur * rx;
226  Quaternion tmp2 = cur * rx.inverse();
227 
228  Quaternion dec;
229  if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(1, 0, 0)).dot(targetDir) )
230    dec = tmp1;
231  else
232    dec = tmp2;
233 
234  float dp = dec.apply( Vector(1, 0, 0) ).dot(Vector(0, 1, 0));
235  if ( dp > -0.9 && dp < 0.9 )
236  {
237    cur = dec;
238  }
239 
240  Quaternion ry( agility*dt, cur.inverse().apply( Vector( 0, 1, 0 ) ) );
241 
242  tmp1 = cur * ry;
243  tmp2 = cur * ry.inverse();
244 
245  if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(1, 0, 0)).dot(targetDir) )
246    cur = tmp1;
247  else
248    cur = tmp2;
249 
250  myDir = cur;
251 
252  Vector fw = cur.apply( Vector(1, 0, 0) );
253 
254  this->speed += this->acceleration*dt;
255  if ( this->speed > this->maxSpeed )
256    this->speed = this->maxSpeed;
257  this->myCoor += fw*speed*dt;
258}
259
260void ActionboxEnemy::moveTowardsBox( ActionBox * box, float dt )
261{
262  Vector targetPos = box->getAbsCoor() + box->getAbsDir().apply( Vector( 1, 0, 0 ) )*box->getDepth()*0.66f;
263  Vector targetDir = targetPos - myCoor;
264 
265  Vector boxDir = box->getAbsDir().apply( Vector(1, 0, 0 ) );
266  float boxDist = boxDir.dot( targetDir );
267 
268  if ( boxDist > 0 )
269  {
270    Vector myRelCoor = this->getAbsCoor() - box->getAbsCoor();
271    float newDist = boxDir.dot( myRelCoor );
272    targetPos = box->getAbsCoor() + box->getAbsDir().apply( Vector( 1, 0, 0 ) )* newDist * 0.8;
273    targetDir = targetPos - myCoor;
274  }
275 
276  moveTowards(targetPos, targetDir, dt);
277}
278
279void ActionboxEnemy::draw( ) const
280{
281#if 0
282  Vector fw = this->getAbsDir().apply( Vector( 1, 0, 0 ) );
283  fw.normalize();
284  fw = fw * 100;
285
286  Vector mp = this->getAbsCoor();
287  Vector op = mp + fw;
288
289  Vector targetPos = State::getPlayer()->getPlayable()->getAbsCoor();
290  Vector dv = targetPos - this->getAbsCoor();
291  dv.normalize();
292  dv *= 100;
293  dv += mp;
294
295  Vector spUp = this->getAbsDir().inverse().apply( this->getAbsDir().apply( Vector( 0, 1, 0 ) ) );
296  spUp.normalize();
297  spUp *= 100;
298  spUp += mp;
299
300  Vector up = fw.cross( dv );
301  up += mp;
302
303  //PRINTF(0)("DEBUG\n");
304  //mp.debug();
305  //op.debug();
306
307  glMatrixMode(GL_MODELVIEW);
308  glPushMatrix();
309
310  glPushAttrib(GL_ENABLE_BIT);
311
312  glDisable(GL_LIGHTING);
313  glDisable(GL_TEXTURE_2D);
314  glDisable(GL_BLEND);
315  glLineWidth(2.0);
316  glColor3f(1.0, 0.0, 0.0 );
317 
318 
319  glBegin(GL_LINE_STRIP);
320    glVertex3f(mp.x, mp.y, mp.z);
321    glVertex3f(op.x, op.y, op.z);
322  glEnd();
323 
324  glColor3f(0.0, 1.0, 0.0 );
325  glBegin(GL_LINE_STRIP);
326    glVertex3f(mp.x, mp.y, mp.z);
327    glVertex3f(dv.x, dv.y, dv.z);
328  glEnd();
329 
330  glColor3f(0.0, 0.0, 1.0 );
331  glBegin(GL_LINE_STRIP);
332    glVertex3f(mp.x, mp.y, mp.z);
333    glVertex3f(up.x, up.y, up.z);
334  glEnd();
335 
336  glColor3f(1.0, 1.0, 1.0 );
337  glBegin(GL_LINE_STRIP);
338    glVertex3f(mp.x, mp.y, mp.z);
339    glVertex3f(spUp.x, spUp.y, spUp.z);
340  glEnd();
341
342  glPopMatrix();
343#endif
344  WorldEntity::draw();
345}
346
347void ActionboxEnemy::destroy( WorldEntity * killer )
348{
349  EmitterNode* node  = NULL;
350  DotEmitter* emitter = NULL;
351  SpriteParticles*  explosionParticles  = NULL;
352
353  explosionParticles = new SpriteParticles(2000);
354  explosionParticles->setName("SpaceShipExplosionParticles");
355  explosionParticles->setLifeSpan(.3, .7);
356  explosionParticles->setRadius(0.0, 10.0);
357  explosionParticles->setRadius(.5, 6.0);
358  explosionParticles->setRadius(1.0, 3.0);
359  explosionParticles->setColor(0.0, 1,1,1,.9);
360  explosionParticles->setColor(0.1,  1,1,0,.9);
361  explosionParticles->setColor(0.5, .8,.4,0,.5);
362  explosionParticles->setColor(1.0, .2,.2,.2,.5);
363
364
365  emitter = new DotEmitter( 2000, 70, 360);
366  emitter->setEmissionRate( 200.0);
367
368  node  = new EmitterNode( .4f );
369  node->setupParticle( emitter, explosionParticles);
370  node->setAbsDir( this->getAbsDir());
371  node->setVelocity( this->getVelocity() * .9f);
372  node->setAbsCoor( this->getAbsCoor());
373  if( !node->start())
374    PRINTF(0)("Explosion node not correctly started!");
375 
376  this->setAbsCoor( this->getAbsCoor() + Vector(100,0,0) + Vector(1,0,0) * VECTOR_RAND(150).dot(Vector(1,0,0)));
377 
378  toList( OM_DEAD );
379}
380
Note: See TracBrowser for help on using the repository browser.