1 // Description:
2 // Boss1 enemy controller.
3 //
4 // Copyright (C) 2005 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2 of the License, or (at your option) any later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include <Trace.hpp>
16 #include <Boss1Enemy.hpp>
17
18 #include <Point.hpp>
19 #include <GameState.hpp>
20 #include <Constants.hpp>
21 #include <Random.hpp>
22 #include <LevelPack.hpp>
23 #include <ParticleType.hpp>
24 #include <ParticleGroup.hpp>
25 #include <ParticleGroupManager.hpp>
26 #include <StageManager.hpp>
27 #include <Audio.hpp>
28 #include <ScoreKeeper.hpp>
29 #include <ModelManager.hpp>
30
31 #include "GLee.h"
32
Boss1Enemy(LEnemy * le)33 Boss1Enemy::Boss1Enemy( LEnemy *le):
34 BaseEnemy(le, "Boss1Enemy")
35 {
36 XTRACE();
37
38 ModelManager &mm = *ModelManagerS::instance();
39 string fullModelName = "models/" + _lEnemy->modelName;
40 _model[0] = mm.getModel( fullModelName + "_Leg1");
41 _model[1] = mm.getModel( fullModelName + "_Leg2");
42 _model[2] = mm.getModel( fullModelName + "_Eye1");
43 _model[3] = mm.getModel( fullModelName + "_Eye2");
44 _model[4] = mm.getModel( fullModelName + "_Face");
45 _model[5] = mm.getModel( fullModelName + "_Teeth");
46
47 for( int i=0; i<6; i++)
48 {
49 _offsets[i] = _model[i]->getOffset();
50 }
51
52 norm(_dir);
53 _energy = 10000;
54 _enemyGroup->newParticle( this, _offset.x, _offset.y, 0);
55 }
56
~Boss1Enemy()57 Boss1Enemy::~Boss1Enemy()
58 {
59 XTRACE();
60 }
61
getRadiiCount(void)62 int Boss1Enemy::getRadiiCount(void)
63 {
64 return 6;
65 }
66
getRadius(int radIndex)67 float Boss1Enemy::getRadius(int radIndex)
68 {
69 return _radii[ radIndex];
70 }
71
getOffset(int radIndex)72 vec3 Boss1Enemy::getOffset(int radIndex)
73 {
74 return _offsets[ radIndex];
75 }
76
init(ParticleInfo * p)77 void Boss1Enemy::init( ParticleInfo *p)
78 {
79 // XTRACE();
80 p->position.z = -100.0;
81 p->extra.x = 0;
82 p->extra.y = 0;
83
84 _lastLeft = 0;
85 _lastRight = 0;
86
87 p->damage = 1000;
88 vec3 minpt, maxpt;
89 p->radius = 0.0f;
90 for( int i=0; i<6; i++)
91 {
92 _model[i]->getBoundingBox( minpt, maxpt);
93 _radii[i] = (maxpt.x-minpt.x)/1.8; //2.0; make badies a little easied to hit
94 }
95 p->tod = -1;
96
97 updatePrevs(p);
98 }
99
update(ParticleInfo * p)100 bool Boss1Enemy::update( ParticleInfo *p)
101 {
102 // XTRACE();
103 if( p->tod == 0)
104 {
105 GameState::numObjects--;
106 if( (_moveState==eAttack) || (_moveState==eRetreat))
107 {
108 GameState::enemyAttackCount--;
109 }
110 delete this;
111 return false;
112 }
113
114 float dt = GameState::startOfGameStep - _pathStartTime;
115 if( dt < 0)
116 {
117 return true;
118 }
119 _enableDraw = true;
120
121 float len = _activePath->length();
122
123 _prevDir = _dir;
124 if( dt > len)
125 {
126 //LOG_INFO << "dt = " << dt << ", len = " << len << endl;
127 getNextPath();
128 dt -= len;
129 _pathStartTime += len;
130 _activePath->getTangent( dt, _prevDir);
131 }
132
133 _activePath->getPos( dt, _pos);
134 _activePath->getTangent( dt, _dir);
135 norm(_dir);
136
137 ///LOG_INFO << "dt = " << dt << ", len = " << len << endl;
138 ///LOG_INFO << "-p1 = " << _pos.x << "," << _pos.y << endl;
139 ///LOG_INFO << "-off = " << _offset.x << "," << _offset.y << endl;
140
141 updatePrevs(p);
142
143 p->extra.y += 5.0f*GAME_STEP_SCALE;
144 p->position.x = _pos.x + _offset.x;
145 p->position.y = _pos.y + _offset.y;
146 // p->position.z = _pos.z + _offset.z;
147
148 if( _extraUpdateAfterTransport)
149 {
150 //We transport the enemy to a staging area. We need to update again
151 //to make sure we use the new position in the interpolation step
152 updatePrevs(p);
153 _extraUpdateAfterTransport = false;
154 }
155
156 static ParticleGroup *ebg=
157 ParticleGroupManagerS::instance()->getParticleGroup(
158 ENEMIES_BULLETS_GROUP);
159
160 if( (Random::random() & 0xff) < Skill::getFireProbability())
161 {
162 ParticleInfo pi;
163 int whichLeg = (Random::random()&8)>>3;
164 pi.position = p->position + _offsets[whichLeg];
165 if( whichLeg == 1)
166 {
167 pi.position = pi.position + vec3(5,-5,0);
168 pi.velocity.x = 5.0f*0.2f*GAME_STEP_SCALE;
169 pi.velocity.y = -5.0f*0.2f*GAME_STEP_SCALE;
170 pi.velocity.z = 0.0f*0.2f*GAME_STEP_SCALE;
171 _lastLeft = ebg->newParticle( "SwarmLeader",pi);
172 }
173 else
174 {
175 pi.position = pi.position + vec3(-5,-5,0);
176 pi.velocity.x = -5.0f*0.2f*GAME_STEP_SCALE;
177 pi.velocity.y = -5.0f*0.2f*GAME_STEP_SCALE;
178 pi.velocity.z = 0.0f*0.2f*GAME_STEP_SCALE;
179 _lastRight = ebg->newParticle( "SwarmLeader",pi);
180 }
181 AudioS::instance()->playSample( "sounds/puididl.wav");
182 }
183
184 if( (Random::random() & 0x1f) < Skill::getFireProbability())
185 {
186 ParticleInfo pi;
187
188 if( _lastLeft)
189 {
190 pi.related = _lastLeft;
191
192 vec3 off2(1,1,0);
193 off2 = off2 * ((Random::rangef0_1()-0.5)*5);
194 pi.position = p->position + _offsets[1] + vec3(5,-5,0) + off2;
195 pi.velocity = vec3( 0.7, -0.7, 0);
196
197 ebg->newParticle( "SwarmElement",pi);
198 }
199
200 if( _lastRight)
201 {
202 pi.related = _lastRight;
203
204
205 vec3 off2(-1,1,0);
206 off2 = off2 * ((Random::rangef0_1()-0.5)*5);
207 pi.position = p->position + _offsets[0] + vec3(-5,-5,0) + off2;
208 pi.velocity = vec3( -0.7, -0.7, 0);
209
210 ebg->newParticle( "SwarmElement",pi);
211 }
212 }
213
214 return true;
215 }
216
draw(ParticleInfo * p)217 void Boss1Enemy::draw( ParticleInfo *p)
218 {
219 // XTRACE();
220 if( _enableDraw)
221 {
222 ParticleInfo pi;
223 interpolate( p, pi);
224
225 glPushMatrix();
226
227 glTranslatef( pi.position.x, pi.position.y, pi.position.z);
228 #if 0
229 if( _moveState != eIdle)
230 {
231 float gf = GameState::frameFraction;
232 Point3D _dirInterp;
233 _dirInterp.x = _prevDir.x + (_dir.x - _prevDir.x) * gf;
234 _dirInterp.y = _prevDir.y + (_dir.y - _prevDir.y) * gf;
235 _dirInterp.z = _prevDir.z + (_dir.z - _prevDir.z) * gf;
236
237 alignWith( _dirInterp);
238 }
239 #endif
240 glColor4f(1.0,1.0,1.0,1.0);
241 for( int i=0; i<6; i++)
242 {
243 glPushMatrix();
244 glTranslatef( _offsets[i].x, _offsets[i].y, _offsets[i].z);
245 _model[i]->draw();
246 glPopMatrix();
247 }
248
249 glPopMatrix();
250 }
251 }
252
hit(ParticleInfo * p,ParticleInfo * p2,int)253 void Boss1Enemy::hit( ParticleInfo *p, ParticleInfo *p2, int /*radIndex*/)
254 {
255 // XTRACE();
256 static ParticleGroup *effects =
257 ParticleGroupManagerS::instance()->getParticleGroup( EFFECTS_GROUP2);
258
259 int scoreAdd = 50;
260 if( p2->damage > 400)
261 {
262 _energy -= 10; //workaround for FlankBuster killer
263 scoreAdd = 10;
264 }
265 else
266 _energy -= p2->damage;
267
268 if( (_energy <= 0) && (p->tod != 0))
269 {
270 static ParticleGroup *bonus =
271 ParticleGroupManagerS::instance()->getParticleGroup( BONUS_GROUP);
272
273 p->tod = 0;
274 int newValue = ScoreKeeperS::instance()->addToCurrentScore( 5000);
275
276 ParticleInfo pi;
277 pi.position = p->position;
278 char buf[10];
279 sprintf( buf, "%d", newValue);
280 pi.text = buf;
281
282 pi.color.x = 1.0f;
283 pi.color.y = 1.0f;
284 pi.color.z = 1.0f;
285
286 effects->newParticle( "ScoreHighlight", pi);
287
288 bonus->newParticle( "SuperBonus",
289 p->position.x, p->position.y, p->position.z);
290
291 for( int j=0; j<6; j++)
292 {
293 vec3 pos = p->position + _offsets[j];
294 //spawn explosion
295 for( int i=0; i<(int)(GameState::horsePower/2.0); i++)
296 {
297 effects->newParticle(
298 "ExplosionPiece", pos.x, pos.y, pos.z);
299 }
300 }
301 AudioS::instance()->playSample( "sounds/explosion.wav");
302 }
303 else
304 {
305 //a hit but no kill
306 ScoreKeeperS::instance()->addToCurrentScore( scoreAdd);
307
308 ParticleInfo pi;
309 pi.position = p2->position;
310
311 pi.velocity.x = _dir.x * (0.6f*GAME_STEP_SCALE);
312 pi.velocity.y = _dir.y * (0.6f*GAME_STEP_SCALE);
313 pi.velocity.z = 0;
314
315 effects->newParticle( "MiniSmoke", pi);
316 }
317 }
318