1 /* Reconstructed Commander Keen 4-6 Source Code
\r
2 * Copyright (C) 2021 K1n9_Duk3
\r
4 * This file is loosely based on:
\r
5 * Keen Dreams Source Code
\r
6 * Copyright (C) 2014 Javier M. Chavez
\r
8 * This program is free software; you can redistribute it and/or modify
\r
9 * it under the terms of the GNU General Public License as published by
\r
10 * the Free Software Foundation; either version 2 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU General Public License along
\r
19 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
27 Contains the following actor types (in this order):
\r
29 - Miragia (world map)
\r
43 =============================================================================
\r
47 =============================================================================
\r
50 statetype s_miragia0 = {0, 0, step, false, false, 300, 0, 0, T_Miragia0, NULL, NULL, &s_miragia1};
\r
51 statetype s_miragia1 = {0, 0, step, false, false, 30, 0, 0, T_Miragia1, NULL, NULL, &s_miragia2};
\r
52 statetype s_miragia2 = {0, 0, step, false, false, 30, 0, 0, T_Miragia2, NULL, NULL, &s_miragia3};
\r
53 statetype s_miragia3 = {0, 0, step, false, false, 30, 0, 0, T_Miragia3, NULL, NULL, &s_miragia4};
\r
54 statetype s_miragia4 = {0, 0, step, false, false, 300, 0, 0, T_Miragia4, NULL, NULL, &s_miragia5};
\r
55 statetype s_miragia5 = {0, 0, step, false, false, 30, 0, 0, T_Miragia5, NULL, NULL, &s_miragia6};
\r
56 statetype s_miragia6 = {0, 0, step, false, false, 30, 0, 0, T_Miragia6, NULL, NULL, &s_miragia7};
\r
57 statetype s_miragia7 = {0, 0, step, false, false, 30, 0, 0, T_Miragia7, NULL, NULL, &s_miragia0};
\r
60 ===========================
\r
64 ===========================
\r
67 void SpawnMiragia(Sint16 x, Sint16 y)
\r
70 new->obclass = inertobj;
\r
71 new->active = ac_allways;
\r
74 new->state = &s_miragia0;
\r
78 ===========================
\r
82 ===========================
\r
85 void T_Miragia0(objtype *ob)
\r
87 if (player->tileright >= ob->x && player->tileleft <= ob->x+5
\r
88 && player->tiletop >= ob->y && player->tilebottom <= ob->y+4)
\r
90 //don't let miragia appear if player is in the area, so player won't get stuck
\r
91 ob->state = &s_miragia7;
\r
95 RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);
\r
100 ===========================
\r
104 ===========================
\r
107 void T_Miragia1(objtype *ob)
\r
109 RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);
\r
113 ===========================
\r
117 ===========================
\r
120 void T_Miragia2(objtype *ob)
\r
122 RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);
\r
126 ===========================
\r
130 ===========================
\r
133 void T_Miragia3(objtype *ob)
\r
135 RF_MapToMap(26, 60, ob->x, ob->y, 6, 4);
\r
139 ===========================
\r
143 ===========================
\r
146 void T_Miragia4(objtype *ob)
\r
148 RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);
\r
152 ===========================
\r
156 ===========================
\r
159 void T_Miragia5(objtype *ob)
\r
161 RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);
\r
165 ===========================
\r
169 ===========================
\r
172 void T_Miragia6(objtype *ob)
\r
174 RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);
\r
178 ===========================
\r
182 ===========================
\r
185 void T_Miragia7(objtype *ob)
\r
187 RF_MapToMap(2, 60, ob->x, ob->y, 6, 4);
\r
191 =============================================================================
\r
196 temp2 = base shape number
\r
197 temp3 = last animated shape number +1
\r
199 =============================================================================
\r
202 statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2};
\r
203 statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1};
\r
204 statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL};
\r
206 statetype s_splash1 = {DROPSPLASH1SPR, DROPSPLASH1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash2};
\r
207 statetype s_splash2 = {DROPSPLASH2SPR, DROPSPLASH2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash3};
\r
208 statetype s_splash3 = {DROPSPLASH3SPR, DROPSPLASH3SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};
\r
210 Uint16 bonusshape[] = {REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR, SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR, SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR, ONEUPASPR, STUNCLIP1SPR};
\r
213 ===========================
\r
217 ===========================
\r
220 void SpawnBonus(Sint16 x, Sint16 y, Sint16 type)
\r
223 new->needtoclip = cl_noclip;
\r
225 new->obclass = bonusobj;
\r
226 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
227 new->y = CONVERT_TILE_TO_GLOBAL(y);
\r
230 new->temp2 = new->shapenum = bonusshape[type];
\r
231 new->temp3 = new->temp2 + 2;
\r
232 NewState(new, &s_bonus1);
\r
236 ===========================
\r
240 ===========================
\r
243 void SpawnSplash(Sint16 x, Sint16 y)
\r
246 new->needtoclip = cl_noclip;
\r
248 new->obclass = inertobj;
\r
249 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
250 new->y = CONVERT_TILE_TO_GLOBAL(y);
\r
251 NewState(new, &s_splash1);
\r
255 ===========================
\r
259 ===========================
\r
262 void T_Bonus(objtype *ob)
\r
265 if (ob->shapenum == ob->temp3)
\r
266 ob->shapenum = ob->temp2;
\r
270 =============================================================================
\r
274 =============================================================================
\r
277 statetype s_councilwalk1 = {COUNCILWALKL1SPR, COUNCILWALKR1SPR, step, false, true, 10, 64, 0, T_Council, NULL, R_Walk, &s_councilwalk2};
\r
278 statetype s_councilwalk2 = {COUNCILWALKL2SPR, COUNCILWALKR2SPR, step, false, true, 10, 64, 0, T_Council, NULL, R_Walk, &s_councilwalk1};
\r
279 statetype s_councilstand = {COUNCILTHINKLSPR, COUNCILTHINKRSPR, step, false, false, 120, 128, 0, NULL, NULL, R_Draw, &s_councilwalk1};
\r
282 ===========================
\r
286 ===========================
\r
289 void SpawnCouncil(Sint16 x, Sint16 y)
\r
292 new->obclass = oracleobj;
\r
293 new->active = ac_yes;
\r
295 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
296 new->y = CONVERT_TILE_TO_GLOBAL(y) -0x171; //TODO: wierd
\r
297 if (US_RndT() < 0x80)
\r
306 NewState(new, &s_councilwalk1);
\r
310 ===========================
\r
314 ===========================
\r
317 void T_Council(objtype *ob)
\r
321 randnum = US_RndT();
\r
322 if (tics*8 > randnum)
\r
324 // BUG: might be about to move off a ledge, causing it to get stuck
\r
325 // after standing (the stand state doesn't use R_Walk)!
\r
326 // To avoid that, set xtry to 0 here.
\r
327 ob->state = &s_councilstand;
\r
332 =============================================================================
\r
336 =============================================================================
\r
339 statetype s_slugwalk1 = {SLUGWALKL1SPR, SLUGWALKR1SPR, step, false, true, 8, 64, 0, NULL, C_Slug, R_WalkNormal, &s_slugwalk2};
\r
340 statetype s_slugwalk2 = {SLUGWALKL2SPR, SLUGWALKR2SPR, step, false, true, 8, 64, 0, T_Slug, C_Slug, R_WalkNormal, &s_slugwalk1};
\r
341 statetype s_slugpiss1 = {SLUGPISSLSPR, SLUGPISSRSPR, step, false, true, 60, 64, 0, T_SlugPiss, C_Slug, R_WalkNormal, &s_slugwalk1};
\r
342 statetype s_slugstun = {SLUGSTUN1SPR, SLUGSTUN1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};
\r
343 statetype s_slugstunalt = {SLUGSTUN2SPR, SLUGSTUN2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};
\r
344 statetype s_slugslime = {SLUGSLIME1SPR, SLUGSLIME1SPR, step, false, false, 300, 0, 0, NULL, C_Lethal, R_Draw, &s_slugslime2};
\r
345 statetype s_slugslime2 = {SLUGSLIME2SPR, SLUGSLIME2SPR, step, false, false, 60, 0, 0, NULL, NULL, R_Draw, NULL};
\r
348 ===========================
\r
352 ===========================
\r
355 void SpawnSlug(Sint16 x, Sint16 y)
\r
358 new->obclass = slugobj;
\r
359 new->active = ac_yes;
\r
361 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
362 new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;
\r
363 if (US_RndT() < 0x80)
\r
372 NewState(new, &s_slugwalk1);
\r
376 ===========================
\r
380 ===========================
\r
383 void T_Slug(objtype *ob)
\r
385 if (US_RndT() < 16)
\r
387 if (ob->x < player->x)
\r
395 ob->state = &s_slugpiss1;
\r
396 SD_PlaySound(SND_SLUGPOO);
\r
397 // Note: might be a good idea to set xtry to 0 here
\r
402 ===========================
\r
406 ===========================
\r
409 void T_SlugPiss(objtype *ob)
\r
412 new->obclass = inertobj;
\r
413 new->active = ac_removable;
\r
416 new->y = ob->bottom - 8*PIXGLOBAL;
\r
417 NewState(new, &s_slugslime);
\r
421 ===========================
\r
425 ===========================
\r
428 void C_Slug(objtype *ob, objtype *hit)
\r
430 if (hit->obclass == keenobj)
\r
434 else if (hit->obclass == stunshotobj)
\r
436 if (US_RndT() < 0x80)
\r
438 StunObj(ob, hit, &s_slugstun);
\r
442 StunObj(ob, hit, &s_slugstunalt);
\r
445 ob->xspeed = ob->xdir*8;
\r
450 =============================================================================
\r
454 temp1 = jump counter
\r
456 =============================================================================
\r
459 statetype s_mushroom1 = {MADMUSHROOML1SPR, MADMUSHROOMR1SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom2};
\r
460 statetype s_mushroom2 = {MADMUSHROOML2SPR, MADMUSHROOMR2SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom1};
\r
463 ===========================
\r
467 ===========================
\r
470 void SpawnMadMushroom(Sint16 x, Sint16 y)
\r
473 new->obclass = madmushroomobj;
\r
474 new->active = ac_yes;
\r
476 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
477 new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;
\r
480 NewState(new, &s_mushroom1);
\r
484 ===========================
\r
488 ===========================
\r
491 void T_Mushroom(objtype *ob)
\r
493 if (player->x < ob->x)
\r
502 // BUG: this might be executed twice during the same frame if the
\r
503 // object's animation/state changed during that frame, causing the
\r
504 // object to move at twice the speed during that frame!
\r
505 // To avoid that, return if ytry is not 0.
\r
510 ===========================
\r
514 ===========================
\r
517 void C_Mushroom(objtype *ob, objtype *hit)
\r
519 ob++; // shut up compiler
\r
520 if (hit->obclass == stunshotobj)
\r
524 else if (hit->obclass == keenobj)
\r
531 ===========================
\r
535 ===========================
\r
538 void R_Mushroom(objtype *ob)
\r
546 if (++ob->temp1 == 3)
\r
550 SD_PlaySound(SND_BOUNCE2);
\r
554 SD_PlaySound(SND_BOUNCE1);
\r
558 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
562 =============================================================================
\r
566 temp1 = blocked flag for flying eggbird (cannot change xdir to chase Keen
\r
567 while this is non-zero)
\r
569 =============================================================================
\r
572 statetype s_egg = {EGGSPR, EGGSPR, think, false, true, 8, 0, 0, NULL, C_Egg, R_Draw, NULL};
\r
573 statetype s_eggbroke = {EGGBROKESPR, EGGBROKESPR, step, false, false, 30000, 0, 0, NULL, NULL, R_Draw, NULL};
\r
574 statetype s_eggchip1 = {EGGCHIP1SPR, EGGCHIP1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};
\r
575 statetype s_eggchip2 = {EGGCHIP2SPR, EGGCHIP2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};
\r
576 statetype s_eggchip3 = {EGGCHIP3SPR, EGGCHIP3SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};
\r
578 statetype s_eggbirdpause = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 120, 128, 0, NULL, C_EggbirdStun, R_Eggbird, &s_eggbirdwalk2};
\r
579 statetype s_eggbirdwalk1 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk2};
\r
580 statetype s_eggbirdwalk2 = {BIRDWALKL2SPR, BIRDWALKR2SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk3};
\r
581 statetype s_eggbirdwalk3 = {BIRDWALKL3SPR, BIRDWALKR3SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk4};
\r
582 statetype s_eggbirdwalk4 = {BIRDWALKL4SPR, BIRDWALKR4SPR, step, false, true, 7, 128, 0, T_Eggbird, C_Eggbird, R_Eggbird, &s_eggbirdwalk1};
\r
583 statetype s_eggbirdfly1 = {BIRDFLY1SPR, BIRDFLY1SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly2};
\r
584 statetype s_eggbirdfly2 = {BIRDFLY2SPR, BIRDFLY2SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly3};
\r
585 statetype s_eggbirdfly3 = {BIRDFLY3SPR, BIRDFLY3SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly4};
\r
586 statetype s_eggbirdfly4 = {BIRDFLY4SPR, BIRDFLY4SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly1};
\r
587 statetype s_eggbirddrop = {BIRDFLY4SPR, BIRDFLY4SPR, think, false, false, 8, 128, 0, T_WeakProjectile, C_Eggbird, R_EggbirdDrop, NULL};
\r
588 statetype s_eggbirdstun = {BIRDSTUNSPR, BIRDSTUNSPR, stepthink, false, false, 240, 0, 0, T_Projectile, C_EggbirdStun, R_Draw, &s_eggbirdstun2};
\r
589 statetype s_eggbirdstun2 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun3};
\r
590 statetype s_eggbirdstun3 = {BIRDSTUNSPR, BIRDSTUNSPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun4};
\r
591 statetype s_eggbirdstun4 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun5};
\r
592 statetype s_eggbirdstun5 = {BIRDSTUNSPR, BIRDSTUNSPR, step, false, true, 20, 0, 0, T_EggUnstun, C_EggbirdStun, R_Draw, &s_eggbirdwalk1};
\r
595 ===========================
\r
599 ===========================
\r
602 void SpawnEggbird(Sint16 x, Sint16 y)
\r
605 new->obclass = eggobj;
\r
606 new->active = ac_yes;
\r
608 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
609 new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;
\r
612 NewState(new, &s_egg);
\r
616 ===========================
\r
620 ===========================
\r
623 void T_EggUnstun(objtype *ob)
\r
625 ob->obclass = eggbirdobj;
\r
629 ===========================
\r
633 ===========================
\r
636 void SpawnEggbirdOut(Sint16 x, Sint16 y)
\r
639 new->obclass = eggbirdobj;
\r
640 new->active = ac_yes;
\r
642 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
643 new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;
\r
644 if (new->x < player->x)
\r
653 NewState(new, &s_eggbirdpause);
\r
657 ===========================
\r
661 ===========================
\r
664 void C_Egg(objtype *ob, objtype *hit)
\r
666 if (hit->obclass == stunshotobj || hit->obclass == keenobj)
\r
668 if (hit->obclass == stunshotobj)
\r
671 ob->obclass = inertobj;
\r
672 ob->active = ac_removable;
\r
673 ChangeState(ob, &s_eggbroke);
\r
676 new->obclass = eggbirdobj;
\r
677 new->active = ac_yes;
\r
679 new->y = ob->y - 8*PIXGLOBAL;
\r
680 if (ob->x < player->x)
\r
689 NewState(new, &s_eggbirdpause);
\r
692 new->obclass = inertobj;
\r
693 new->active = ac_removable;
\r
698 NewState(new, &s_eggchip1);
\r
701 new->obclass = inertobj;
\r
702 new->active = ac_removable;
\r
707 NewState(new, &s_eggchip2);
\r
710 new->obclass = inertobj;
\r
711 new->active = ac_removable;
\r
716 NewState(new, &s_eggchip3);
\r
721 ===========================
\r
725 ===========================
\r
728 void T_Eggbird(objtype *ob)
\r
730 if (ob->x < player->x)
\r
738 if (ob->bottom >= player->bottom + 3*TILEGLOBAL && player->hitnorth
\r
739 && StatePositionOk(ob, &s_eggbirdfly1)) // BUG: StatePositionOk() only works for normal clipping, not for full clipping
\r
741 // Note: might be a good idea to set xtry to 0 here
\r
742 ob->state = &s_eggbirdfly1;
\r
743 ob->needtoclip = cl_fullclip;
\r
750 ===========================
\r
754 ===========================
\r
757 void T_EggbirdFly(objtype *ob)
\r
759 if (ob->temp1 == 0)
\r
761 if (ob->x < player->x)
\r
770 AccelerateXv(ob, ob->xdir, 16);
\r
771 if (ob->y < player->y)
\r
773 AccelerateY(ob, 1, 16);
\r
777 AccelerateY(ob, -1, 16);
\r
782 ===========================
\r
786 ===========================
\r
789 void C_Eggbird(objtype *ob, objtype *hit)
\r
791 if (hit->obclass == keenobj)
\r
795 else if (hit->obclass == stunshotobj)
\r
798 ob->needtoclip = cl_midclip;
\r
799 StunObj(ob, hit, &s_eggbirdstun);
\r
804 ===========================
\r
808 ===========================
\r
811 void C_EggbirdStun(objtype *ob, objtype *hit)
\r
813 if (hit->obclass == stunshotobj)
\r
816 StunObj(ob, hit, &s_eggbirdstun);
\r
821 ===========================
\r
825 ===========================
\r
828 void R_Eggbird(objtype *ob)
\r
830 if (ob->xdir == 1 && ob->hitwest)
\r
832 ob->x -= ob->xmove;
\r
834 ob->nothink = US_RndT() >> 5;
\r
835 ChangeState(ob, ob->state);
\r
837 else if (ob->xdir == -1 && ob->hiteast)
\r
839 ob->x -= ob->xmove;
\r
841 ob->nothink = US_RndT() >> 5;
\r
842 ChangeState(ob, ob->state);
\r
847 ob->needtoclip = cl_fullclip;
\r
848 ChangeState(ob, &s_eggbirdfly1);
\r
850 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
854 ===========================
\r
858 ===========================
\r
861 void R_EggbirdDrop(objtype *ob) //never actually used
\r
865 ChangeState(ob, &s_eggbirdwalk1);
\r
867 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
871 ===========================
\r
875 ===========================
\r
878 void R_Chip(objtype *ob)
\r
881 ob->xspeed = ob->yspeed = 0;
\r
883 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
887 ===========================
\r
891 ===========================
\r
894 void R_Eggbirdfly(objtype *ob)
\r
896 statetype *oldstate;
\r
898 if ((ob->hitsouth || ob->hitnorth) && !ob->temp1)
\r
901 if (ob->hiteast && ob->xspeed < 0 || ob->hitwest && ob->xspeed > 0)
\r
904 ob->xdir = -ob->xdir;
\r
906 if (ob->hitnorth == 1 && player->bottom - ob->bottom < 8*PIXGLOBAL) // BUG? unsigned comparison!
\r
908 oldstate = ob->state;
\r
909 ob->needtoclip = cl_midclip;
\r
910 ChangeState(ob, &s_eggbirdwalk1);
\r
912 ytry = 8*PIXGLOBAL;
\r
916 ob->needtoclip = cl_fullclip;
\r
917 ChangeState(ob, oldstate);
\r
919 return; // BUG: sprite isn't updated
\r
922 if (!ob->hitsouth && !ob->hitnorth)
\r
925 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
929 =============================================================================
\r
933 =============================================================================
\r
936 statetype s_arach1 = {ARACHNUTWALK1SPR, ARACHNUTWALK4SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach2};
\r
937 statetype s_arach2 = {ARACHNUTWALK2SPR, ARACHNUTWALK3SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach3};
\r
938 statetype s_arach3 = {ARACHNUTWALK3SPR, ARACHNUTWALK2SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach4};
\r
939 statetype s_arach4 = {ARACHNUTWALK4SPR, ARACHNUTWALK1SPR, step, false, true, 6, 128, 0, T_Arach, C_Arach, R_Walk, &s_arach1};
\r
940 statetype s_arachstun = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 240, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun2};
\r
941 statetype s_arachstun2 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun3};
\r
942 statetype s_arachstun3 = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun4};
\r
943 statetype s_arachstun4 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun5};
\r
944 statetype s_arachstun5 = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arach1};
\r
947 ===========================
\r
951 ===========================
\r
954 void SpawnArachnut(Sint16 x, Sint16 y)
\r
957 new->obclass = arachnutobj;
\r
958 new->active = ac_yes;
\r
960 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
961 new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x171;
\r
962 if (US_RndT() < 0x80)
\r
971 NewState(new, &s_arach1);
\r
975 ===========================
\r
979 ===========================
\r
982 void T_Arach(objtype *ob)
\r
984 if (ob->x > player->x)
\r
995 ===========================
\r
999 ===========================
\r
1002 void C_Arach(objtype *ob, objtype *hit)
\r
1004 if (hit->obclass == stunshotobj)
\r
1006 StunObj(ob, hit, &s_arachstun);
\r
1008 else if (hit->obclass == keenobj)
\r
1015 ===========================
\r
1019 ===========================
\r
1022 void C_ArachStun(objtype *ob, objtype *hit)
\r
1024 if (hit->obclass == stunshotobj)
\r
1026 StunObj(ob, hit, &s_arachstun);
\r
1031 =============================================================================
\r
1035 =============================================================================
\r
1038 statetype s_pestfly1 = {SKYPESTFLYL1SPR, SKYPESTFLYR1SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly2};
\r
1039 statetype s_pestfly2 = {SKYPESTFLYL2SPR, SKYPESTFLYR2SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly1};
\r
1040 statetype s_squashedpest = {SKYPESTSQUASHEDSPR, SKYPESTSQUASHEDSPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, &s_squashedpest};
\r
1041 statetype s_pestrest1 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest2};
\r
1042 statetype s_pestrest2 = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest3};
\r
1043 statetype s_pestrest3 = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest4};
\r
1044 statetype s_pestrest4 = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest5};
\r
1045 statetype s_pestrest5 = {SKYPESTSIT4SPR, SKYPESTSIT4SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest6};
\r
1046 statetype s_pestrest6 = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest7};
\r
1047 statetype s_pestrest7 = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest8};
\r
1048 statetype s_pestrest8 = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest9};
\r
1049 statetype s_pestrest9 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 60, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest10};
\r
1050 statetype s_pestrest10 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest11};
\r
1051 statetype s_pestrest11 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest12};
\r
1052 statetype s_pestrest12 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest13};
\r
1053 statetype s_pestrest13 = {SKYPESTSIT8SPR, SKYPESTSIT8SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest14};
\r
1054 statetype s_pestrest14 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest15};
\r
1055 statetype s_pestrest15 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest16};
\r
1056 statetype s_pestrest16 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest17};
\r
1057 statetype s_pestrest17 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, T_PestRest, C_Squashable, R_Draw, &s_pestfly1};
\r
1060 ===========================
\r
1064 ===========================
\r
1067 void SpawnSkypest(Sint16 x, Sint16 y)
\r
1070 new->obclass = skypestobj;
\r
1071 new->active = ac_yes;
\r
1072 new->priority = 0;
\r
1073 new->x = CONVERT_TILE_TO_GLOBAL(x);
\r
1074 new->y = CONVERT_TILE_TO_GLOBAL(y);
\r
1075 if (US_RndT() < 0x80)
\r
1083 if (US_RndT() < 0x80)
\r
1091 NewState(new, &s_pestfly1);
\r
1095 ===========================
\r
1099 ===========================
\r
1102 void T_PestFly(objtype *ob)
\r
1104 // BUG: this might be executed twice during the same frame if the
\r
1105 // object's animation/state changed during that frame, causing the
\r
1106 // object to move at twice the speed during that frame!
\r
1107 // To avoid that, return if xtry is not 0 or ytry is not 0.
\r
1109 if (US_RndT() < tics)
\r
1110 ob->xdir = -ob->xdir;
\r
1112 if (ob->ydir == -1 && US_RndT() < tics)
\r
1115 if (ob->ydir == 1 && US_RndT() < tics*2)
\r
1116 ob->ydir = -ob->ydir;
\r
1118 AccelerateX(ob, ob->xdir, 20);
\r
1119 AccelerateY(ob, ob->ydir, 20);
\r
1123 ===========================
\r
1127 ===========================
\r
1130 void C_PestFly(objtype *ob, objtype *hit)
\r
1132 if (hit->obclass == keenobj)
\r
1135 if (hit->obclass == stunshotobj)
\r
1137 if (hit->xdir == 1)
\r
1141 else if (hit->xdir == -1)
\r
1145 else if (hit->ydir == 1)
\r
1149 else if (hit->ydir == -1)
\r
1158 ===========================
\r
1162 ===========================
\r
1165 void C_Squashable(objtype *ob, objtype *hit)
\r
1167 if (hit->state == &s_keenpogodown || hit->state == &s_keenpogo || hit->state == &s_keenpogo2)
\r
1169 ChangeState(ob, &s_squashedpest);
\r
1170 SD_PlaySound(SND_SQUISH);
\r
1171 ob->obclass = inertobj;
\r
1176 ===========================
\r
1180 ===========================
\r
1183 void T_PestRest(objtype *ob)
\r
1191 ===========================
\r
1195 ===========================
\r
1198 void R_Pest(objtype *ob)
\r
1205 if (ob->hitnorth && !ob->hiteast && !ob->hitwest)
\r
1207 ob->y += 8*PIXGLOBAL;
\r
1208 ChangeState(ob, &s_pestrest1);
\r
1220 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r