1
2 #include "../stdai.h"
3 #include "weed.fdh"
4
INITFUNC(AIRoutines)5 INITFUNC(AIRoutines)
6 {
7 ONTICK(OBJ_CRITTER_FLYING, ai_critter);
8 ONTICK(OBJ_POWER_CRITTER, ai_critter);
9
10 ONTICK(OBJ_BAT_HANG, ai_bat_hang);
11 ONTICK(OBJ_BAT_CIRCLE, ai_bat_circle);
12
13 ONTICK(OBJ_JELLY, ai_jelly);
14 ONTICK(OBJ_GIANT_JELLY, ai_giant_jelly);
15
16 ONTICK(OBJ_MANNAN, ai_mannan);
17 ONTICK(OBJ_MANNAN_SHOT, ai_mannan_shot);
18
19 ONTICK(OBJ_FROG, ai_frog);
20 ONTICK(OBJ_MINIFROG, ai_frog);
21
22 ONTICK(OBJ_SANTAS_KEY, ai_animate2);
23
24 ONTICK(OBJ_HEY_SPAWNER, ai_hey_spawner);
25 ONTICK(OBJ_MOTORBIKE, ai_motorbike);
26
27 ONTICK(OBJ_POWERCOMP, ai_animate3);
28 ONTICK(OBJ_POWERSINE, ai_animate1);
29 ONTICK(OBJ_MALCO, ai_malco);
30 ONTICK(OBJ_MALCO_BROKEN, ai_malco_broken);
31 }
32
33 /*
34 void c------------------------------() {}
35 */
36
ai_critter(Object * o)37 void ai_critter(Object *o)
38 {
39 switch(o->state)
40 {
41 case 0:
42 {
43 if (o->type == OBJ_POWER_CRITTER)
44 { // altered physics for Power Critter
45 o->critter.jumpheight = 0x2800;
46 o->critter.jumpgrav = 0x1C;
47 o->critter.falldmg = 12;
48 }
49 else
50 {
51 o->critter.jumpheight = 0;
52 o->critter.jumpgrav = 0x40;
53 o->critter.falldmg = 3;
54
55 if (o->type == OBJ_CRITTER_HOPPING_BLUE || // first cave
56 o->type == OBJ_CRITTER_HOPPING_GREEN || // egg 1
57 o->type == OBJ_CRITTER_HOPPING_AQUA || // egg 2
58 o->type == OBJ_CRITTER_HOPPING_RED) // last cave
59 {
60 o->critter.canfly = false;
61
62 // critters in egg1 only 2 dmg
63 if (o->type == OBJ_CRITTER_HOPPING_GREEN)
64 o->critter.falldmg = 2;
65
66 // critters in First Cave don't jump as high
67 if (o->type != OBJ_CRITTER_HOPPING_BLUE)
68 {
69 o->critter.jumpgrav = 0x2C;
70 }
71 }
72 else
73 {
74 // critters are purple in Maze
75 o->sprite = SPR_CRITTER_FLYING_CYAN;
76
77 o->critter.canfly = true;
78 }
79 }
80
81 o->state = 1;
82 } //fall thru
83 case 1:
84 {
85 o->frame = 0;
86
87 if (o->timer >= 8)
88 {
89 int attack_dist = (o->critter.canfly) ? (96 << CSF) : (64 << CSF);
90
91 // close enough to attack?
92 if (pdistlx(attack_dist) && pdistly2(96<<CSF, 48<<CSF))
93 {
94 o->state = 2;
95 o->frame = 0;
96 o->timer = 0;
97 }
98 else if (pdistlx(attack_dist + (32<<CSF)) && pdistly2(128<<CSF, 48<<CSF))
99 { // no, but close enough to look up at "attention" and watch player
100 FACEPLAYER;
101 o->frame = 1;
102 o->timer = 8; // reset timer to stop watching
103 }
104 else
105 {
106 // once a little time has passed stop watching him if he turns his back
107 if ((o->x > player->x && player->dir==LEFT) || \
108 (o->x < player->x && player->dir==RIGHT))
109 {
110 if (++o->timer >= 150)
111 {
112 o->frame = 0;
113 o->timer = 8;
114 }
115 }
116 else o->timer = 8;
117 }
118 }
119 else
120 {
121 o->timer++;
122 }
123
124 if (o->shaketime)
125 { // attack if shot
126 o->state = 2;
127 o->frame = 0;
128 o->timer = 0;
129 }
130 }
131 break;
132
133 case 2: // start jump
134 {
135 if (++o->timer > 8)
136 {
137 o->state = 3;
138 o->frame = 2;
139 o->yinertia = -1228;
140 sound(SND_ENEMY_JUMP);
141
142 FACEPLAYER;
143 XMOVE(0x100);
144 }
145 }
146 break;
147
148 case 3: // jumping
149 {
150 // enter flying phase as we start to come down or
151 // if we hit the ceiling.
152 if (o->yinertia > 0x100 || o->blocku)
153 {
154 // during flight we will sine-wave oscilliate around this position
155 o->ymark = (o->y - o->critter.jumpheight);
156
157 o->state = 4;
158 o->frame = 2;
159 o->timer = 0;
160 }
161 else
162 {
163 if (o->blockd && o->yinertia >= 0)
164 { // jumped onto a platform before we got to fly--land immediately
165 goto landed;
166 }
167 break;
168 }
169 } // fall-thru
170 case 4: // flying
171 {
172 FACEPLAYER;
173
174 // time to come down yet?
175 // (come down immediately if we are not one of the flying critters)
176 if (!o->critter.canfly || \
177 o->blockl || o->blockr || o->blocku || \
178 ++o->timer > 100)
179 {
180 o->damage = o->critter.falldmg; // increased damage if falls on player
181 o->state = 5;
182 o->frame = 2;
183 o->yinertia /= 2;
184 }
185 else
186 {
187 // run the propeller
188 ANIMATE(0, 3, 5);
189 if ((o->timer & 3)==1) sound(SND_CRITTER_FLY);
190
191 if (o->blockd) o->yinertia = -0x200;
192 }
193 }
194 break;
195
196 case 5: // coming down from flight
197 {
198 if (o->blockd)
199 { // landed
200 landed: ;
201 o->damage = 2; // reset to normal damage
202 o->state = 1;
203
204 o->frame = 0;
205 o->timer = 0;
206 o->xinertia = 0;
207
208 sound(SND_THUD);
209 }
210 }
211 break;
212 }
213
214 if (o->state == 4) // flying
215 {
216 // fly towards player
217 o->xinertia += (o->x > player->x) ? -0x20 : 0x20;
218 // sine-wave oscillate
219 o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
220
221 LIMITX(0x200);
222 LIMITY(0x200);
223 }
224 else if (o->state == 3 && o->yinertia < 0) // jumping up
225 {
226 o->yinertia += o->critter.jumpgrav;
227 }
228 else
229 {
230 o->yinertia += 0x40;
231 }
232
233 LIMITY(0x5ff);
234 }
235
236 /*
237 void c------------------------------() {}
238 */
239
ai_bat_hang(Object * o)240 void ai_bat_hang(Object *o)
241 {
242 switch(o->state)
243 {
244 case 0:
245 o->state = 1;
246 case 1: // hanging and waiting
247 if (!random(0, 100))
248 {
249 o->state = 2;
250 o->timer = 0;
251 o->frame = 1;
252 }
253
254 if (pdistlx(0x1000) && pdistly2(0x1000, 0x9000))
255 {
256 o->frame = 0;
257 o->state = 3;
258 }
259 break;
260
261 case 2: // blinking
262 if (++o->timer > 8)
263 {
264 o->state = 1;
265 o->frame = 0;
266 }
267 break;
268
269 case 3: // at attention
270 o->frame = 0;
271 if (o->shaketime || pdistlx(0x2800))
272 {
273 o->frame = 1;
274 o->animtimer = 0;
275 o->state = 4;
276 o->timer = 0;
277 }
278 break;
279
280 case 4: // falling
281 o->yinertia += 0x20;
282 LIMITY(0x5ff);
283
284 o->timer++;
285 if (o->timer > 20 || o->blockd)
286 {
287 if (o->blockd || ((player->y - 0x2000) < o->y))
288 { // start flying
289 o->animtimer = 0;
290 o->frame = 2;
291 o->state = 5;
292 o->ymark = o->y;
293 if (o->blockd) o->yinertia = -0x200;
294 }
295 }
296 break;
297
298 case 5: // flying
299 ANIMATE(1, 2, 4);
300 FACEPLAYER;
301
302 o->xinertia += (o->x > player->x) ? -0x20 : 0x20;
303 o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
304
305 LIMITX(0x200);
306 LIMITY(0x200);
307
308 if (o->blockd) o->yinertia = -0x200;
309 if (o->blockr) o->yinertia = 0x200;
310 break;
311 }
312 }
313
ai_bat_circle(Object * o)314 void ai_bat_circle(Object *o)
315 {
316 switch(o->state)
317 {
318 case 0:
319 {
320 uint8_t angle;
321 o->state = 1;
322
323 // set up initial direction and target x,y
324 angle = random(0, 255);
325 o->xinertia = sin_table[angle];
326
327 angle += 64;
328 o->xmark = (o->x + (sin_table[angle] * 8));
329
330 angle = random(0, 255);
331 o->yinertia = sin_table[angle];
332
333 angle += 64;
334 o->ymark = (o->y + (sin_table[angle] * 8));
335 }
336 case 1:
337 // circle around our target point
338 ANIMATE(1, 2, 4);
339 FACEPLAYER;
340 o->xinertia += (o->x > o->xmark) ? -0x10 : 0x10;
341 o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
342 LIMITX(0x200);
343 LIMITY(0x200);
344
345 if (!o->timer2)
346 {
347 if (pdistlx(0x1000) && (player->y > o->y) && pdistly(0xC000))
348 { // dive attack
349 o->xinertia /= 2;
350 o->yinertia = 0;
351 o->state = 2;
352 o->frame = 5; // mouth showing teeth
353 }
354 }
355 else o->timer2--;
356 break;
357
358 case 2: // dive attack
359 o->yinertia += 0x40;
360 LIMITY(0x5ff);
361
362 if (o->blockd)
363 {
364 o->yinertia = 0;
365 o->xinertia *= 2;
366 o->timer2 = 120; // delay before can dive again
367 o->state = 1;
368 }
369 break;
370 }
371 }
372
373 /*
374 void c------------------------------() {}
375 */
376
ai_jelly(Object * o)377 void ai_jelly(Object *o)
378 {
379 switch(o->state)
380 {
381 case 0:
382 {
383 o->nxflags |= NXFLAG_SLOW_WHEN_HURT;
384 o->timer = random(0, 20);
385 o->xmark = o->x;
386 o->ymark = o->y;
387
388 o->xinertia = (o->dir == LEFT) ? 0x200 : -0x200;
389 o->state = 1;
390 }
391 case 1:
392 {
393 if (--o->timer <= 0)
394 {
395 o->state = 10;
396 }
397 else break;
398 }
399 case 10:
400 {
401 if (++o->timer > 10)
402 {
403 o->timer = o->frame = 0;
404 o->state = 11;
405 }
406 }
407 break;
408
409 case 11:
410 {
411 if (++o->animtimer > 5)
412 {
413 o->animtimer = 0;
414 o->frame++;
415 }
416
417 if (o->frame == 2)
418 {
419 o->xinertia += (o->dir == LEFT) ? -0x100 : +0x100;
420 o->yinertia -= 0x200;
421 }
422 else if (o->frame > 2)
423 {
424 o->state = 12;
425 o->frame = 3;
426 }
427 }
428 break;
429
430 case 12:
431 {
432 o->timer++;
433 if (o->y > o->ymark && o->timer > 10)
434 {
435 o->timer = 0;
436 o->state = 10;
437 o->frame = 0;
438 }
439 }
440 break;
441 }
442
443 o->dir = (o->x > o->xmark) ? LEFT : RIGHT;
444
445 if (o->blockl) o->dir = RIGHT;
446 if (o->blockr) o->dir = LEFT;
447 if (o->blockd) o->yinertia = -0x200;
448
449 o->yinertia += 0x20;
450
451 LIMITX(0x100);
452 LIMITY(0x200);
453 }
454
455 // Kulala
ai_giant_jelly(Object * o)456 void ai_giant_jelly(Object *o)
457 {
458 switch(o->state)
459 {
460 case 0: // frozen/in stasis. waiting for player to shoot.
461 o->frame = 4;
462 if (o->shaketime)
463 {
464 quake(30);
465 o->state = 10;
466 o->frame = 0;
467 o->timer = 0;
468 }
469 break;
470
471 case 10: // falling
472 {
473 o->flags |= FLAG_SHOOTABLE;
474 o->flags &= ~FLAG_INVULNERABLE;
475
476 if (++o->timer > 40)
477 {
478 o->timer = 0;
479 o->animtimer = 0;
480 o->state = 11;
481 }
482 }
483 break;
484
485 case 11: // animate thrust
486 {
487 ANIMATE_FWD(5);
488 if (o->frame >= 3)
489 {
490 o->frame = 3;
491 o->state = 12;
492 }
493 }
494 break;
495
496 case 12: // thrusting upwards
497 {
498 o->yinertia = -0x155;
499 if (++o->timer > 20)
500 {
501 o->state = 10;
502 o->frame = 0;
503 o->timer = 0;
504 }
505 }
506 break;
507
508 case 20: // shot/freeze over/go invulnerable
509 {
510 o->frame = 4;
511 o->xinertia >>= 1;
512 o->yinertia += 0x20;
513
514 if (!o->shaketime)
515 {
516 o->state = 10;
517 o->frame = 0;
518 o->timer = 30;
519 }
520 }
521 break;
522 }
523
524 if (o->shaketime)
525 {
526 if (++o->timer3 > 12)
527 {
528 o->state = 20;
529 o->frame = 4;
530 o->flags &= ~FLAG_SHOOTABLE;
531 o->flags |= FLAG_INVULNERABLE;
532 }
533 }
534 else
535 {
536 o->timer3 = 0;
537 }
538
539 if (o->state >= 10)
540 {
541 if (o->blockl) { o->timer2 = 50; o->dir = RIGHT; }
542 if (o->blockr) { o->timer2 = 50; o->dir = LEFT; }
543
544 if (o->timer2 > 0)
545 {
546 o->timer2--;
547 XACCEL(0x80);
548 }
549 else
550 {
551 o->timer2 = 50;
552 FACEPLAYER;
553 }
554
555 o->yinertia += 0x10;
556 if (o->blockd) o->yinertia = -0x300;
557 }
558
559 LIMITX(0x100);
560 LIMITY(0x300);
561 }
562
563
564 /*
565 void c------------------------------() {}
566 */
567
ai_mannan(Object * o)568 void ai_mannan(Object *o)
569 {
570 // check if we were "killed"
571 if (o->state < 3 && o->hp < 90)
572 {
573 sound(SND_LITTLE_CRASH);
574 SmokeClouds(o, 8, 12, 12);
575 o->SpawnXP(objprop[o->type].xponkill);
576 o->flags &= ~FLAG_SHOOTABLE;
577 o->state = 3;
578 o->timer = 0;
579 o->frame = 2;
580 o->damage = 0;
581 }
582
583 switch(o->state)
584 {
585 case 0:
586 if (o->shaketime)
587 {
588 SpawnObjectAtActionPoint(o, OBJ_MANNAN_SHOT);
589 o->frame = 1;
590 o->state = 2;
591 o->timer = 0;
592 }
593 break;
594
595 case 2: // firing
596 if (++o->timer > 20)
597 {
598 o->timer = o->state = o->frame = 0;
599 }
600 break;
601
602 case 3: // dead/blinking
603 switch(++o->timer)
604 {
605 case 50: case 60: o->frame = 3; break;
606 case 53: case 63: o->frame = 2; break;
607 case 100: o->state = 4; break;
608 }
609 break;
610 }
611 }
612
ai_mannan_shot(Object * o)613 void ai_mannan_shot(Object *o)
614 {
615 XACCEL(0x20);
616 ANIMATE(0, 1, 2);
617
618 if ((o->timer & 3) == 1)
619 sound(SND_IRONH_SHOT_FLY);
620
621 if (++o->timer > 100)
622 o->Delete();
623 }
624
625 /*
626 void c------------------------------() {}
627 */
628
629 // there is an apparent bug on the sprite sheet for this monster:
630 // right-facing frame 1 is a duplicate of frame 0,
631 // so the mouth-twitch animation does not work when
632 // the frog is facing right.
ai_frog(Object * o)633 void ai_frog(Object *o)
634 {
635 switch(o->state)
636 {
637 case 0:
638 {
639 o->timer = 0;
640 o->xinertia = 0;
641 o->yinertia = 0;
642
643 // non-normal dirs are used to indicate that this frog was
644 // spawned by balfrog: we are falling out of ceiling during fight
645 if (o->dir != LEFT && o->dir != RIGHT)
646 {
647 o->dir = random(0, 1) ? LEFT : RIGHT;
648 o->flags |= FLAG_IGNORE_SOLID;
649
650 o->state = 3;
651 o->frame = 2;
652 }
653 else
654 {
655 o->flags &= ~FLAG_IGNORE_SOLID;
656 o->state = 1;
657 }
658 }
659 case 1: // standing
660 {
661 o->timer++;
662
663 if (!random(0, 50))
664 { // mouth-flitter animation
665 o->state = 2;
666 o->frame = 0;
667 o->timer = 0;
668 o->animtimer = 0;
669 }
670 }
671 break;
672
673 case 2: // mouth flitter
674 {
675 ANIMATE(2, 0, 1);
676
677 if (++o->timer > 18)
678 o->state = 1;
679 }
680 break;
681
682 case 3: // falling out of ceiling during balfrog fight
683 {
684 if (++o->timer > 40)
685 {
686 o->flags &= ~FLAG_IGNORE_SOLID;
687
688 if (o->blockd)
689 {
690 o->state = 0;
691 o->frame = 0;
692 o->timer = 0;
693 }
694 }
695 }
696 break;
697
698 case 10: // jumping
699 case 11:
700 {
701 if (o->blockl && o->xinertia < 0)
702 {
703 o->dir = RIGHT;
704 o->xinertia = -o->xinertia;
705 }
706
707 if (o->blockr && o->xinertia > 0)
708 {
709 o->dir = LEFT;
710 o->xinertia = -o->xinertia;
711 }
712
713 if (o->blockd)
714 {
715 o->state = 0;
716 o->frame = 0;
717 o->timer = 0;
718 }
719 }
720 break;
721 }
722
723 // random jumping, and jump when shot
724 if (o->state < 3 && o->timer > 10)
725 {
726 bool dojump = false;
727
728 if (o->shaketime)
729 {
730 dojump = true;
731 }
732 else if (pdistlx(0x14000) && pdistly(0x8000))
733 {
734 if (!random(0, 50))
735 {
736 dojump = true;
737 }
738 }
739
740 if (dojump)
741 {
742 FACEPLAYER;
743 o->state = 10;
744 o->frame = 2;
745 o->yinertia = -0x5ff;
746
747 // no jumping sound in cutscenes at ending
748 if (!player->inputs_locked && !player->disabled)
749 sound(SND_ENEMY_JUMP);
750
751 XMOVE(0x200);
752 }
753 }
754
755 o->yinertia += 0x80;
756 LIMITY(0x5ff);
757 }
758
759 /*
760 void c------------------------------() {}
761 */
762
ai_hey_spawner(Object * o)763 void ai_hey_spawner(Object *o)
764 {
765 if (!o->state)
766 {
767 effect(o->x, o->y - (8<<CSF), EFFECT_HEY);
768 o->state = 1;
769 }
770 }
771
ai_motorbike(Object * o)772 void ai_motorbike(Object *o)
773 {
774
775 switch(o->state)
776 {
777 case 0: // parked
778 break;
779
780 case 10: // kazuma and booster mounted
781 o->y -= (sprites[SPR_MOTORBIKE_MOUNTED].h - sprites[SPR_MOTORBIKE].h) << CSF;
782 o->sprite = SPR_MOTORBIKE_MOUNTED;
783 o->state++;
784 break;
785
786 case 20: // kazuma and booster start the engine
787 {
788 o->state = 21;
789 o->timer = 1;
790
791 o->xmark = o->x;
792 o->ymark = o->y;
793 }
794 case 21:
795 {
796 o->x = o->xmark + (random(-1, 1) << CSF);
797 o->y = o->ymark + (random(-1, 1) << CSF);
798
799 if (++o->timer > 30)
800 o->state = 30;
801 }
802 break;
803
804 case 30: // kazuma and booster take off
805 {
806 o->state = 31;
807 o->timer = 1;
808
809 o->xinertia = -0x800;
810 o->ymark = o->y;
811
812 sound(SND_MISSILE_HIT);
813 }
814 case 31:
815 {
816 o->xinertia += 0x20;
817 o->timer++;
818
819 o->y = o->ymark + (random(-1, 1) << CSF);
820
821 if (o->timer > 10) o->dir = RIGHT;
822 if (o->timer > 200) o->state = 40;
823 }
824 break;
825
826 case 40: // flying away (fast out-of-control)
827 {
828 o->state = 41;
829 o->timer = 2;
830 o->dir = LEFT;
831 o->y -= (48 << CSF); // move up...
832 o->xinertia = -0x1000; // ...and fly fast
833 }
834 case 41:
835 {
836 o->timer += 2; // makes exhaust sound go faster
837 if (o->timer > 1200)
838 o->Delete();
839 }
840 break;
841 }
842
843 if (o->state >= 20 && (o->timer & 3) == 0)
844 {
845 sound(SND_FIREBALL);
846
847 // make exhaust puffs, and make them go out horizontal
848 // instead of straight up as this effect usually does
849 Caret *puff = effect(o->ActionPointX(), o->ActionPointY(), EFFECT_SMOKETRAIL_SLOW);
850 puff->yinertia = 0;
851 puff->xinertia = (o->dir == LEFT) ? 0x280 : -0x280;
852 }
853 }
854
855 /*
856 void c------------------------------() {}
857 */
858
ai_malco(Object * o)859 void ai_malco(Object *o)
860 {
861
862 switch(o->state)
863 {
864 case 0:
865 o->state = 1;
866 o->frame = 0;
867
868 // smushed into ground, used on re-entry to room
869 // if player does not choose to pull him out
870 // after Balrog fight
871 if (o->dir == RIGHT)
872 o->frame = 5;
873 break;
874
875 case 10:
876 o->state = 11;
877 o->timer = 0;
878 o->timer = 0;
879 SmokeClouds(o, 4, 16, 16);
880 case 11: // beeping and eyes flickering
881 if (++o->timer < 100)
882 {
883 if ((o->timer & 1)==0)
884 {
885 sound(SND_COMPUTER_BEEP);
886 o->frame ^= 1;
887 }
888 }
889 else if (o->timer > 150)
890 {
891 o->timer = 0;
892 o->state = 15;
893 }
894 break;
895
896 case 15: // shaking
897 if (o->timer & 2)
898 {
899 o->x += (1<<CSF);
900 sound(SND_DOOR);
901 }
902 else
903 {
904 o->x -= (1<<CSF);
905 }
906 if (++o->timer > 50) o->state = 16;
907 break;
908
909 case 16: // stand up
910 o->state = 17;
911 o->frame = 2;
912 o->timer = 0;
913 sound(SND_BLOCK_DESTROY);
914 SmokeClouds(o, 4, 16, 16);
915 case 17:
916 if (++o->timer > 150)
917 {
918 o->state = 18;
919 }
920 break;
921
922 case 18: // gawking/bobbing up and down
923 o->state = 19;
924 o->timer = 0;
925 // go into gawk frame first time
926 o->animtimer = 999; o->frame = 9;
927 case 19:
928 if (++o->animtimer > 3)
929 {
930 o->animtimer = 0;
931 if (++o->frame > 4) o->frame = 3;
932 if (o->frame==3) sound(SND_DOOR);
933 }
934 if (++o->timer > 100)
935 {
936 o->state = 20;
937 sound(SND_DOOR);
938 SmokeClouds(o, 4, 16, 16);
939 }
940 break;
941
942 case 20: o->frame = 4; break;
943
944 case 21: // got smushed!
945 o->state = 22;
946 o->frame = 5;
947 sound(SND_ENEMY_HURT);
948 break;
949
950 case 22:
951 break;
952
953 case 100: // "baby" malcos waking up during credits
954 {
955 o->state = 101;
956 o->frame = 3;
957 o->animtimer = 0;
958 }
959 case 101:
960 {
961 ANIMATE(4, 3, 4);
962 }
963 break;
964 case 110: // the one that blows up
965 {
966 SmokeClouds(o, 16, 4, 4);
967 o->Delete();
968 }
969 break;
970 }
971 }
972
ai_malco_broken(Object * o)973 void ai_malco_broken(Object *o)
974 {
975 switch(o->state)
976 {
977 case 10: // set when pulled out of ground
978 sound(SND_BLOCK_DESTROY);
979 SmokeClouds(o, 4, 16, 16);
980 o->state = 0;
981 break;
982
983 case 0:
984 {
985 o->frame = 0;
986 randblink(o, 1, 8, 50);
987
988 if (game.mode != GM_CREDITS)
989 FACEPLAYER;
990 }
991 break;
992 }
993 }
994
995
996
997
998
999
1000