1 /*************************************************************************
2
3 "I Have No Tomatoes"
4 Copyright (c) 2004, Mika Halttunen
5
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute
12 it freely, subject to the following restrictions:
13
14 1. The origin of this software must not be misrepresented; you must
15 not claim that you wrote the original software. If you use this
16 software in a product, an acknowledgment in the product documentation
17 would be appreciated but is not required.
18
19 2. Altered source versions must be plainly marked as such, and must
20 not be misrepresented as being the original software.
21
22 3. This notice may not be removed or altered from any source
23 distribution.
24
25
26 Mika Halttunen <lsoft@mbnet.fi>
27
28 *************************************************************************/
29
30 #include <stdio.h>
31 #include "SDL.h"
32 #include "SDL_opengl.h"
33 #include "SDL_image.h"
34 #include "texture.h"
35 #include "game.h"
36 #include "init.h"
37 #include "player.h"
38 #include "mymath.h"
39 #include "tilemap.h"
40 #include "enemy.h"
41 #include "particle.h"
42 #include "bonus.h"
43 #include "helpers.h"
44 #include "effects.h"
45 #include "special_power.h"
46 #include "trap.h"
47 #include "soundmusic.h"
48 #include "levels.h"
49
50
51 // Enemy list
52 list<ENEMY> enemylist;
53
54 // Enemy animations
55 GLuint enemy_anim[3];
56 static int anim_frames[4] = { 0, 1, 0, 2 };
57
58
59 // Texture from player.cpp
60 extern GLuint sprite_shadow;
61
62 // From bonus.cpp
63 extern int killed_5_diamonds;
64
65
66 // The counter for the continuous enemy creation
67 int enemy_creation_counter;
68
69 // Amount of time between two enemy creation periods
70 const int enemy_creation_interval = 90;
71
72 // Enemy burning time
73 int enemy_burn_time = 420;
74
75
76 // Load the enemies
load_enemies()77 void load_enemies() {
78
79 // Load the red enemy animations
80 enemy_anim[0] = load_png("enemy1.png", true, false, false);
81 enemy_anim[1] = load_png("enemy2.png", true, false, false);
82 enemy_anim[2] = load_png("enemy3.png", true, false, false);
83
84 }
85
86
87 // Helper function which checks if the players are right next to
88 // a location or in the same region
is_player_close(int x,int y)89 bool is_player_close(int x, int y) {
90
91 // Check distance to the players
92 int dx = x - (int)p1.get_real_x();
93 int dy = y - (int)p1.get_real_y();
94 if(dx*dx + dy*dy <= 49) // 49 == 7*7
95 return true;
96
97 if(two_players) {
98 dx = x - (int)p2.get_real_x();
99 dy = y - (int)p2.get_real_y();
100 if(dx*dx + dy*dy <= 49) // 49 == 7*7
101 return true;
102 }
103
104
105 // Determine the regions (4x4)
106 int p1reg = 0, p2reg = 0;
107 if(p1.x < 7 && p1.y <= 7)
108 p1reg = 1;
109 else if(p1.x < 7 && p1.y > 7)
110 p1reg = 3;
111 else if(p1.x >= 7 && p1.y <= 7)
112 p1reg = 2;
113 else
114 p1reg = 4;
115
116
117 if(two_players) {
118 if(p2.x < 7 && p2.y <= 7)
119 p2reg = 1;
120 else if(p2.x < 7 && p2.y > 7)
121 p2reg = 3;
122 else if(p2.x >= 7 && p2.y <= 7)
123 p2reg = 2;
124 else
125 p2reg = 4;
126 }
127
128 int ereg;
129 if(x < 7 && y <= 7)
130 ereg = 1;
131 else if(x < 7 && y > 7)
132 ereg = 3;
133 else if(x >= 7 && y <= 7)
134 ereg = 2;
135 else
136 ereg = 4;
137
138 // Check the region
139 if(p1reg == ereg)
140 return true;
141 if(two_players && p2reg == ereg)
142 return true;
143
144 return false;
145 }
146
147
148 // Helper function which adds an new enemy while checking
149 // for bad places
new_enemy(int & ex,int & ey)150 bool new_enemy(int &ex, int &ey) {
151 // Add a new enemy
152 ENEMY e;
153 e.clear();
154
155 // Check for bad places
156 int x = RAND(0, MAP_W-1);
157 int y = RAND(0, MAP_H-1);
158 int counter = 0;
159 while((!can_teleport(x, y) || is_player_close(x,y)) && counter < 10000) {
160 x = RAND(0, MAP_W-1);
161 y = RAND(0, MAP_H-1);
162 counter++;
163 }
164
165 if(counter >= 10000)
166 return false;
167
168 e.x = x;
169 e.y = y;
170 ex = x;
171 ey = y;
172 e.tx = e.x;
173 e.ty = e.y;
174 e.type = RAND(0,2);
175 e.alive = true;
176 enemylist.push_back(e);
177 return true;
178 }
179
180
181 // Move the enemies
move_enemies()182 void move_enemies() {
183 // Create new enemies if there's less than enemy_amount of them
184 // (but don't create enemies until all the diamonds from Killed-5 have
185 // been collected)
186 int num_enemies = enemylist.size();
187 if(num_enemies < ENEMY_AMOUNT && !killed_5_diamonds && !level_pause) {
188 enemy_creation_counter--;
189 if(enemy_creation_counter < 0) {
190 bool created = false;
191 // Add enemies to maintain the certain enemy amount
192 for(int i=0; i < (ENEMY_AMOUNT - num_enemies); i++) {
193 // Add a new enemy
194 int ex, ey;
195 if(new_enemy(ex, ey)) {
196 // Create the teleport effect
197 create_teleport_effect(ex, ey);
198 created = true;
199 }
200 }
201
202 // Play the appear sound
203 if(created) {
204 play_sound(SND_APPEAR, false);
205 enemy_creation_counter = enemy_creation_interval;
206 }
207 }
208
209 }
210
211 // Move the active enemies
212 if(enemylist.size() == 0)
213 return;
214
215 list<ENEMY>::iterator i;
216 for(i = enemylist.begin(); i != enemylist.end(); ++i) {
217 (*i).move();
218 // Remove the dead enemies
219 if((*i).alive == false) {
220 i = enemylist.erase(i);
221 }
222 }
223
224 }
225
226
227 // Draw the enemies
draw_enemies()228 void draw_enemies() {
229 if(enemylist.size() == 0)
230 return;
231
232 list<ENEMY>::iterator i;
233 for(i = enemylist.begin(); i != enemylist.end(); ++i) {
234 (*i).draw();
235 }
236 }
237
238
239 // Clear the enemy list
clear_enemies()240 void clear_enemies() {
241 enemylist.clear();
242 enemy_creation_counter = 30;
243 }
244
245
246 // Helper function which computes the right direction
get_dir(int dx,int dy)247 int get_dir(int dx, int dy) {
248 if(dx == 0 && dy == -1)
249 return DIR_N;
250 else if(dx == 1 && dy == 0)
251 return DIR_E;
252 else if(dx == 0 && dy == 1)
253 return DIR_S;
254 else
255 return DIR_W;
256 }
257
258
259 // Look for a player and chase him
look_player()260 void ENEMY::look_player() {
261 // Movement deltas for each direction
262 const int dx[4] = { 0, 1, 0, -1 };
263 const int dy[4] = { -1, 0, 1, 0 };
264
265 // Sweep in a straigth line and check for the player presence
266 for(int pos=1; pos < MAP_W; pos++) {
267 int xx, yy;
268 xx = x + dx[dir] * pos;
269 yy = y + dy[dir] * pos;
270
271 // Check for solid tile
272 if(map_solid(xx, yy))
273 break;
274
275 // Check for the players
276 if((int)p1.get_real_x() == xx && (int)p1.get_real_y() == yy && p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
277 // Begin the chase
278 chase = 1; // 1 for player one
279 speed += 0.03f;
280 break;
281 }
282 else if(two_players && (int)p2.get_real_x() == xx && (int)p2.get_real_y() == yy && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
283 // Begin the chase
284 chase = 2; // 2 for player two
285 speed += 0.03f;
286 break;
287 }
288 }
289
290 }
291
292
293 // Lightning special power instance from special_power.cpp
294 extern SP_LIGHTNING sp_lightning;
295
296
297 // Move the enemy
move()298 void ENEMY::move() {
299 // Advance the animation
300 if(!chase && !burning)
301 anim += 0.10f;
302 else
303 anim += 0.20f;
304 if((int)anim > 3 || kicked)
305 anim = 0.0f;
306
307 // Advance the dying animation if we're actually dying
308 if(dying) {
309 die_anim -= 0.03f;
310
311 // Create the blue "burning down" effect
312 float px = get_real_x();
313 float py = get_real_y();
314 for(int f=0; f < RAND(2,10); f++) {
315 float rnd = RANDF(-0.3f, 0.3f);
316 VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py);
317 pos.x += rnd;
318 pos.z -= rnd;
319 if(pos.y < 0.0f)
320 pos.y = 0.0f;
321 if(turning)
322 pos.y += (turning_raise * 0.85f);
323 VECT dir = 0.0f;
324 float c1[4] = { 0.1f, 0.7f, 1, 1 };
325 float c2[4] = { 0.1f, 0.7f, 1, 0 };
326 add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star);
327 }
328
329 if(die_anim < 0.0f) {
330 die_anim = 0.0f;
331 alive = false;
332 }
333
334 return;
335 }
336
337
338 // Create some particle fire from the burning enemies
339 if(burning) {
340 VECT ppos(get_real_x(), 0.5f, get_real_y());
341 create_fire(ppos);
342 }
343
344 // Advance the turning animation
345 if(turning) {
346 // Raise up
347 if(turning == 1) {
348 turning_raise += 0.035f;
349 if(turning_raise >= 1.0f) {
350 turning_raise = 1.0f;
351 turning++;
352 }
353 }
354 // Turn
355 else if(turning == 2) {
356 turning_counter++;
357 if(turning_counter == 5) {
358 dir = nextdir;
359 nextdir = dir + 1;
360 if(nextdir > DIR_W)
361 nextdir = DIR_N;
362 }
363 else if(turning_counter == 10) {
364 dir = nextdir;
365 turning++;
366 }
367 }
368 // Go down
369 else if(turning == 3) {
370 turning_raise -= 0.035f;
371 if(turning_raise <= 0.0f) {
372 turning_raise = 0.0f;
373 turning = 0;
374 }
375 }
376
377 // Check the collision between the player #1
378 if(p1.alive && !p1.jumping) {
379 float dx = get_real_x() - p1.get_real_x();
380 float dy = get_real_y() - p1.get_real_y();
381 if(dx*dx + dy*dy <= 0.9f) {
382 // Collision happened!
383
384 // Kill the player and die
385 p1.die();
386 die();
387 }
388 }
389
390 // Check the collision between the player #2
391 if(alive && two_players && p2.alive && !p2.jumping) {
392 float dx = get_real_x() - p2.get_real_x();
393 float dy = get_real_y() - p2.get_real_y();
394 if(dx*dx + dy*dy <= 0.9f) {
395 // Collision happened!
396
397 // Kill the player and die
398 p2.die();
399 die();
400 }
401 }
402
403 return;
404 }
405
406
407 // If there is the lightning special power in progress, don't move the enemies which are
408 // suffering from the lightning strikes
409 if(special_power_pause && which_special_power == BLUE_POWER_LIGHTNING) {
410 // Check if we're a target
411 for(int f=0; f<ENEMY_AMOUNT; f++) {
412 if(sp_lightning.targets[f] == this) {
413 anim += 0.30f;
414 if((int)anim > 3)
415 anim = 0.0f;
416 return;
417 }
418 }
419 }
420
421 // Don't move if the level is finished
422 if(level_pause)
423 return;
424
425
426 // Check the traps
427 if(traplist.size() > 0) {
428 list<TRAP>::iterator t;
429 for(t = traplist.begin(); t != traplist.end(); ++t) {
430 if(x == (*t).x && y == (*t).y) {
431 die();
432 return;
433 }
434 }
435 }
436
437
438 // Handle the burning, that is run around aimlessly
439 if(burning) {
440 if(!kicked) {
441 // Reduce the burning time
442 burn_time--;
443 if(burn_time == 0) {
444 die();
445 return;
446 }
447
448 // Choose a random direction
449 if(RAND(0,100) > 50 && offset == 0.0f) {
450 if(RAND(0,100) > 50)
451 dir++;
452 else
453 dir--;
454 if(dir > DIR_W)
455 dir = DIR_N;
456 else if(dir < DIR_N)
457 dir = DIR_W;
458 }
459
460 // Move one step
461 if(tx == x && ty == y) {
462 offset = 0.0f;
463
464 // Don't stop until there's a wall.
465 switch(dir) {
466 default:
467 case DIR_N: tx = x; ty = y - 1; break;
468 case DIR_E: tx = x + 1; ty = y; break;
469 case DIR_S: tx = x; ty = y + 1; break;
470 case DIR_W: tx = x - 1; ty = y; break;
471 }
472
473 // Check if the target is passable?
474 if(map_solid(tx, ty)) {
475 // Stop and choose a new dir
476 tx = x;
477 ty = y;
478
479 dir += RAND(-1,1);
480 if(dir < DIR_N)
481 dir = DIR_W;
482 else if(dir > DIR_W)
483 dir = DIR_N;
484 return;
485 }
486
487 }
488
489 // Move towards the target tile
490 if(offset < 1.0f && (tx != x || ty != y)) {
491 offset += speed;
492
493 // Check the collision between the player #1
494 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
495 float dx = get_real_x() - p1.get_real_x();
496 float dy = get_real_y() - p1.get_real_y();
497 if(dx*dx + dy*dy <= 0.9f) {
498 // Collision happened!
499
500 // Turn around and run
501 tx = x;
502 ty = y;
503 offset = 0.0f;
504 dir += 2;
505 if(dir > DIR_W)
506 dir -= 4;
507 }
508 }
509
510 // Check the collision between the player #2
511 if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
512 float dx = get_real_x() - p2.get_real_x();
513 float dy = get_real_y() - p2.get_real_y();
514 if(dx*dx + dy*dy <= 0.9f) {
515 // Collision happened!
516
517 // Turn around and run
518 tx = x;
519 ty = y;
520 offset = 0.0f;
521 dir += 2;
522 if(dir > DIR_W)
523 dir -= 4;
524 }
525 }
526
527 // Check the collision between the potato men
528 if(potatoman.collide_with(this) && !kicked) {
529 // Potatoman "kicked" us
530 potatoman.kick(this);
531 }
532
533
534 // If we're reached the target tile, move again
535 if(offset >= 1.0f) {
536 x = tx;
537 y = ty;
538 offset = 0.0f;
539 }
540 }
541 }
542
543 // Check collisions with other enemies and spread the fire
544 bool burnt_somebody = false;
545 list<ENEMY>::iterator e;
546 for(e = enemylist.begin(); e != enemylist.end(); ++e) {
547 if(this != &(*e) && !(*e).burning) {
548 // Check the distance
549 float dx = get_real_x() - (*e).get_real_x();
550 float dy = get_real_y() - (*e).get_real_y();
551 if(dx*dx + dy*dy <= 0.9f) {
552 // Burn the other enemy
553 (*e).burning = true;
554 (*e).burn_time = enemy_burn_time;
555 (*e).speed += 0.06f;
556 burnt_somebody = true;
557 }
558 }
559 }
560
561 // Play the burning sound
562 if(burnt_somebody)
563 play_sound(SND_WILDFIRE, false);
564
565 if(!kicked)
566 return;
567 }
568
569
570 // Not burning below here
571
572 // Choose a random destination
573 if(path_pos == -1) {
574 // Choose a valid target
575 int dx = RAND(0, MAP_W-1);
576 int dy = RAND(0, MAP_H-1);
577 while(map_solid(dx, dy) || dx == x || dy == y) {
578 dx = RAND(0, MAP_W-1);
579 dy = RAND(0, MAP_H-1);
580 }
581
582 // Calculate the path
583 if(pf.find_path(x, y, dx, dy) == PATH_FAILED) {
584 // Well, tough luck. We'll just wait and try again later.
585 return;
586 }
587
588 // Now we've got a nice path for us!
589 path_pos = 0;
590 offset = 0.0f;
591 tx = pf.path[0].x;
592 ty = pf.path[0].y;
593 dir = get_dir(tx - x, ty - y);
594 look_player();
595 }
596
597 // Move one step
598 if(tx == x && ty == y && path_pos > -1) {
599 offset = 0.0f;
600
601 // Follow the path if we're not chasing
602 if(chase == 0 && !kicked) {
603 path_pos++;
604 tx = pf.path[path_pos].x;
605 ty = pf.path[path_pos].y;
606 dir = get_dir(tx - x, ty - y);
607 look_player();
608 }
609 else if(chase && !kicked) {
610 // We are chasing. Don't stop until there's a wall.
611 switch(dir) {
612 default:
613 case DIR_N: tx = x; ty = y - 1; break;
614 case DIR_E: tx = x + 1; ty = y; break;
615 case DIR_S: tx = x; ty = y + 1; break;
616 case DIR_W: tx = x - 1; ty = y; break;
617 }
618
619 // Check if the target is passable?
620 if(map_solid(tx, ty)) {
621 // Stop and choose a new path
622 tx = x;
623 ty = y;
624
625 path_pos = -1;
626 chase = 0;
627 speed -= 0.03f;
628 }
629 }
630 else if(kicked) {
631 // Potatoman has kicked us. "Fly" straight until we hit a wall.
632 switch(dir) {
633 default:
634 case DIR_N: tx = x; ty = y - 1; break;
635 case DIR_E: tx = x + 1; ty = y; break;
636 case DIR_S: tx = x; ty = y + 1; break;
637 case DIR_W: tx = x - 1; ty = y; break;
638 }
639
640 // Check for the wall
641 if(map_solid(tx, ty)) {
642 die();
643 return;
644 }
645 }
646 }
647
648 // Move towards the target tile
649 if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) {
650 offset += speed;
651
652 // Check the collision between the player #1
653 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
654 float dx = get_real_x() - p1.get_real_x();
655 float dy = get_real_y() - p1.get_real_y();
656 if(dx*dx + dy*dy <= 0.9f) {
657 // Collision happened!
658
659 // Kill the player and die
660 p1.die();
661 die();
662 }
663 }
664
665 // Check the collision between the player #2
666 if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
667 float dx = get_real_x() - p2.get_real_x();
668 float dy = get_real_y() - p2.get_real_y();
669 if(dx*dx + dy*dy <= 0.9f) {
670 // Collision happened!
671
672 // Kill the player and die
673 p2.die();
674 die();
675 }
676 }
677
678
679 // Check the collision between the potato men
680 if(potatoman.collide_with(this) && !kicked) {
681 // Potatoman "kicked" us
682 potatoman.kick(this);
683 }
684
685
686 // If we're reached the target tile, move again
687 if(offset >= 1.0f) {
688 x = tx;
689 y = ty;
690 offset = 0.0f;
691
692 // If this is the final destination, stay put and choose a new path
693 // on the next cycle
694 if(x == pf.dx && y == pf.dy && !chase && !kicked)
695 path_pos = -1;
696 }
697 }
698
699 }
700
701
702 // Kill the enemy
die()703 void ENEMY::die() {
704 if(dying)
705 return; // Hey, don't you die twice, man! ;)
706 dying = true;
707 kill_count++;
708 die_anim = 1.0f;
709
710 // Create a bonus
711 add_bonus((int)get_real_x(), (int)get_real_y(), type);
712
713 // Play the sound
714 static int last_sound = -1;
715 int sound = last_sound;
716 while(sound == last_sound)
717 sound = RAND(SND_DIE1, SND_DIE6);
718 play_sound(sound, false);
719 last_sound = sound;
720 }
721
722
723 // Get current x with offset
get_real_x()724 float ENEMY::get_real_x() {
725 // Calculate the offset
726 float offx = 0;
727 if(dir == DIR_E)
728 offx = offset;
729 else if(dir == DIR_W)
730 offx = -offset;
731
732 return (float)x + offx + 0.5f;
733 }
734
735
736 // Get current y with offset
get_real_y()737 float ENEMY::get_real_y() {
738 // Calculate the offset
739 float offy = 0;
740 if(dir == DIR_N)
741 offy = -offset;
742 else if(dir == DIR_S)
743 offy = offset;
744
745 return (float)y + offy + 0.5f;
746 }
747
748
749 // Draw the enemy
draw()750 void ENEMY::draw() {
751 // Calculate the offset
752 float offx = 0, offz = 0;
753 switch(dir) {
754 default:
755 case DIR_N: offz = -offset; break;
756 case DIR_E: offx = offset; break;
757 case DIR_S: offz = offset; break;
758 case DIR_W: offx = -offset; break;
759 }
760
761 // Translate to the position
762 glPushMatrix();
763 glTranslatef(x + offx + 0.5f, size - 0.20f, y + offz + 0.5f);
764
765 // Draw the shadow
766 glDepthMask(GL_FALSE);
767 glColor3f(1,1,1);
768 BIND_TEXTURE(sprite_shadow);
769 float sh = -(size - 0.21f);
770 glBegin(GL_TRIANGLE_STRIP);
771 glTexCoord2f(1,1); glVertex3f( 0.6f, sh, -0.6f);
772 glTexCoord2f(0,1); glVertex3f(-0.6f, sh, -0.6f);
773 glTexCoord2f(1,0); glVertex3f( 0.6f, sh, 0.6f);
774 glTexCoord2f(0,0); glVertex3f(-0.6f, sh, 0.6f);
775 glEnd();
776 glDepthMask(GL_TRUE);
777
778 // Raise up if we're turning
779 if(turning)
780 glTranslatef(0, turning_raise * 0.85f, 0);
781
782
783 // Negate the camera rotation
784 glMultMatrixf(cam_neg_matrix);
785 // glRotatef(45.0f, 0,1,0);
786 // glRotatef(-30.0f, 1,0,0);
787
788 // Draw the sprite
789 if(burning)
790 glColor3f(.5f,.5f,.5f);
791
792 // Compute the texture coords according the animation frame and direction
793 BIND_TEXTURE(enemy_anim[type]);
794 int f = anim_frames[(int)anim];
795 float textx = 0.25f * f;
796 float texty = 0.25f * (3-dir);
797
798 if(!dying) {
799 glBegin(GL_TRIANGLE_STRIP);
800 glTexCoord2f(textx + 0.25f, texty + 0.25f); glVertex3f( size, size, size);
801 glTexCoord2f(textx, texty + 0.25f); glVertex3f(-size, size, size);
802 glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
803 glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
804 glEnd();
805 }
806 else {
807 // Draw the dying animation
808 float z = size - (2*size*(1-die_anim));
809 glBegin(GL_TRIANGLE_STRIP);
810 glTexCoord2f(textx + 0.25f, texty + (die_anim*0.25f)); glVertex3f( size, z, z);
811 glTexCoord2f(textx, texty + (die_anim*0.25f)); glVertex3f(-size, z, z);
812 glTexCoord2f(textx + 0.25f, texty); glVertex3f( size, -size, -size);
813 glTexCoord2f(textx, texty); glVertex3f(-size, -size, -size);
814 glEnd();
815
816 }
817
818 glPopMatrix();
819 }
820
821
822 // Clear the enemy
clear()823 void ENEMY::clear() {
824 x = y = 0;
825 tx = ty = 0;
826 offset = 0.0f;
827 speed = 0.05f;
828 dir = RAND(DIR_N, DIR_W);
829 nextdir = dir;
830 size = 0.85f;
831 anim = 0.0f;
832 type = 0;
833 alive = false;
834 dying = false;
835 die_anim = 1.0f;
836 path_pos = -1;
837 chase = 0;
838 burning = false;
839 burn_time = 0;
840 turning = 0;
841 turning_counter = 0;
842 turning_raise = 0.0f;
843 kicked = false;
844 }
845
846
847