]> 4ch.mooo.com Git - 16.git/blobdiff - 16/keen456/KEEN4-6/KEEN6/K6_ACT3.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / KEEN6 / K6_ACT3.C
diff --git a/16/keen456/KEEN4-6/KEEN6/K6_ACT3.C b/16/keen456/KEEN4-6/KEEN6/K6_ACT3.C
new file mode 100755 (executable)
index 0000000..81efc99
--- /dev/null
@@ -0,0 +1,765 @@
+/* Reconstructed Commander Keen 4-6 Source Code\r
+ * Copyright (C) 2021 K1n9_Duk3\r
+ *\r
+ * This file is loosely based on:\r
+ * Keen Dreams Source Code\r
+ * Copyright (C) 2014 Javier M. Chavez\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+/*\r
+K6_ACT3.C\r
+=========\r
+\r
+Contains the following actor types (in this order):\r
+\r
+- Fleex\r
+- Bobba\r
+- Babobba\r
+- Blorb\r
+- Ceilick\r
+\r
+*/\r
+\r
+#include "CK_DEF.H"\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 FLEEX\r
+\r
+temp1 = flash countdown\r
+temp2 = health\r
+\r
+=============================================================================\r
+*/\r
+\r
+statetype s_fleexwalk1 = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk2};\r
+statetype s_fleexwalk2 = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
+statetype s_fleexrun1  = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun2};\r
+statetype s_fleexrun2  = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun3};\r
+statetype s_fleexrun3  = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun4};\r
+statetype s_fleexrun4  = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
+statetype s_fleexlook1 = {FLEEXLOOK1SPR,  FLEEXLOOK1SPR,  step,  false, true, 60,   0, 0, NULL, C_Fleex, R_Blooguard, &s_fleexlook2};\r
+statetype s_fleexlook2 = {FLEEXLOOK2SPR,  FLEEXLOOK2SPR,  step,  false, true, 60,   0, 0, T_FleexLook, C_Fleex, R_Blooguard, &s_fleexrun1};\r
+statetype s_fleexstun  = {FLEEXSTUNSPR,   FLEEXSTUNSPR,   think, false, false, 0,   0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
+\r
+/*\r
+===========================\r
+=\r
+= SpawnFleex\r
+=\r
+===========================\r
+*/\r
+\r
+void SpawnFleex(Uint16 tileX, Uint16 tileY)\r
+{\r
+       GetNewObj(false);\r
+       new->obclass = fleexobj;\r
+       new->active = ac_yes;\r
+       new->priority = 0;\r
+       new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
+       new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -40*PIXGLOBAL;\r
+       if (US_RndT() < 0x80)\r
+       {\r
+               new->xdir = 1;\r
+       }\r
+       else\r
+       {\r
+               new->xdir = -1;\r
+       }\r
+       new->ydir = 1;\r
+       NewState(new, &s_fleexwalk1);\r
+       new->temp2 = 4; // health\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_FleexWalk\r
+=\r
+===========================\r
+*/\r
+\r
+void T_FleexWalk(objtype *ob)\r
+{\r
+       if (!player->xmove && !ob->temp1)\r
+       {\r
+               ob->state = &s_fleexlook1;\r
+       }\r
+       else\r
+       {\r
+               ob->xdir = (ob->x < player->x)? 1 : -1;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_FleexLook\r
+=\r
+===========================\r
+*/\r
+\r
+void T_FleexLook(objtype *ob)\r
+{\r
+       ob->xdir = (ob->x < player->x)? 1 : -1;\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= C_Fleex\r
+=\r
+===========================\r
+*/\r
+\r
+void C_Fleex(objtype *ob, objtype *hit)\r
+{\r
+       if (hit->obclass == keenobj)\r
+       {\r
+               KillKeen();\r
+       }\r
+       if (hit->obclass == stunshotobj)        // this is not 'else if' in the original code\r
+       {\r
+               if (--ob->temp2 == 0)\r
+               {\r
+                       StunObj(ob, hit, &s_fleexstun);\r
+                       ob->yspeed = -20;\r
+               }\r
+               else\r
+               {\r
+                       ob->temp1 = 2;  // draw white twice\r
+                       ob->needtoreact = true;\r
+                       ExplodeShot(hit);\r
+                       if (ob->state == &s_fleexlook1 || ob->state == &s_fleexlook2)\r
+                       {\r
+                               ob->xdir = (ob->x < player->x)? 1 : -1;\r
+                               ChangeState(ob, &s_fleexwalk1);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 BOBBA\r
+\r
+temp1 = jump counter\r
+\r
+=============================================================================\r
+*/\r
+\r
+statetype s_bobbajump1       = {BOBBAL2SPR,    BOBBAR2SPR,    stepthink, false, false,  8,  0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
+statetype s_bobbajump2       = {BOBBAL3SPR,    BOBBAR3SPR,    think,     false, false,  8,  0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
+statetype s_bobbastand       = {BOBBAL1SPR,    BOBBAR1SPR,    step,      false, false, 20,  0, 0, T_BobbaStand, C_Bobba, R_Draw, &s_bobbajump1};\r
+statetype s_bobbaattack      = {BOBBAL1SPR,    BOBBAR1SPR,    step,      false, false, 40,  0, 0, NULL, C_Bobba, R_Draw, &s_bobbajump1};\r
+statetype s_bobbashot1       = {BOBBASHOT1SPR, BOBBASHOT1SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot2};\r
+statetype s_bobbashot2       = {BOBBASHOT2SPR, BOBBASHOT2SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot3};\r
+statetype s_bobbashot3       = {BOBBASHOT1SPR, BOBBASHOT1SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot4};\r
+statetype s_bobbashot4       = {BOBBASHOT2SPR, BOBBASHOT2SPR, step,      false, false,  8,  0, 0, T_BobbaShot, NULL, R_Draw, &s_bobbashot5};\r
+statetype s_bobbashot5       = {BOBBASHOT3SPR, BOBBASHOT3SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot6};\r
+statetype s_bobbashot6       = {BOBBASHOT4SPR, BOBBASHOT4SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot7};\r
+statetype s_bobbashot7       = {BOBBASHOT5SPR, BOBBASHOT5SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot8};\r
+statetype s_bobbashot8       = {BOBBASHOT6SPR, BOBBASHOT6SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot5};\r
+statetype s_bobbashotvanish1 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish2};\r
+statetype s_bobbashotvanish2 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish3};\r
+statetype s_bobbashotvanish3 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, NULL};\r
+\r
+/*\r
+===========================\r
+=\r
+= SpawnBobba\r
+=\r
+===========================\r
+*/\r
+\r
+void SpawnBobba(Uint16 tileX, Uint16 tileY)\r
+{\r
+       GetNewObj(false);\r
+       new->obclass = bobbaobj;\r
+       new->active = ac_yes;\r
+       new->priority = 0;\r
+       new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
+       new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
+       if (US_RndT() < 0x80)\r
+       {\r
+               new->xdir = 1;\r
+       }\r
+       else\r
+       {\r
+               new->xdir = -1;\r
+       }\r
+       new->ydir = 1;\r
+       NewState(new, &s_bobbajump1);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_BobbaShot\r
+=\r
+===========================\r
+*/\r
+\r
+#pragma argsused\r
+void T_BobbaShot(objtype *ob)\r
+{\r
+       SD_PlaySound(SND_BOBBASHOT);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_BobbaStand\r
+=\r
+===========================\r
+*/\r
+\r
+void T_BobbaStand(objtype *ob)\r
+{\r
+       Sint16 i;\r
+       Uint16 far *map;\r
+\r
+       if (++ob->temp1 == 3)\r
+       {\r
+               ob->temp1 = 0;\r
+               GetNewObj(true);\r
+               new->active = ac_removable;\r
+               new->obclass = mshotobj;\r
+               new->y = ob->y + 11*PIXGLOBAL;\r
+               new->xdir = ob->xdir;\r
+               if (ob->xdir == 1)\r
+               {\r
+                       new->x = ob->x + 16*PIXGLOBAL;\r
+               }\r
+               else\r
+               {\r
+                       new->x = ob->x + 11*PIXGLOBAL;\r
+               }\r
+               NewState(new, &s_bobbashot1);\r
+               new->priority = 2;\r
+               ob->state = &s_bobbaattack;\r
+       }\r
+       else\r
+       {\r
+               map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
+               for (i=0; i<4; map += ob->xdir, i++)\r
+               {\r
+                       if ( !tinf[*map+NORTHWALL]\r
+                               && !tinf[*(map-mapwidth)+NORTHWALL]\r
+                               && !tinf[*(map+mapwidth)+NORTHWALL] )\r
+                       {\r
+                               ob->xdir = -ob->xdir;\r
+                               break;\r
+                       }\r
+               }\r
+               ob->xspeed = ob->xdir << 5;\r
+               ob->yspeed = -32;\r
+               SD_PlaySound(SND_BOBBAJUMP);\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= C_Bobba\r
+=\r
+===========================\r
+*/\r
+\r
+void C_Bobba(objtype *ob, objtype *hit)\r
+{\r
+       if (hit->obclass == keenobj)\r
+       {\r
+               KillKeen();\r
+       }\r
+       else if (hit->obclass == stunshotobj)\r
+       {\r
+               ExplodeShot(hit);\r
+               if (hit->xdir != 0)\r
+               {\r
+                       ob->xdir = -hit->xdir;\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= R_Bobba\r
+=\r
+===========================\r
+*/\r
+\r
+void R_Bobba(objtype *ob)\r
+{\r
+       if (ob->hiteast)\r
+       {\r
+               ob->xdir = 1;\r
+               ob->xspeed = -ob->xspeed;\r
+       }\r
+       else if (ob->hitwest)\r
+       {\r
+               ob->xdir = -1;\r
+               ob->xspeed = -ob->xspeed;\r
+       }\r
+\r
+       if (ob->hitsouth)\r
+               ob->yspeed = 0;\r
+\r
+       if (ob->hitnorth)\r
+       {\r
+               SD_PlaySound(SND_BOBBALAND);\r
+               ChangeState(ob, &s_bobbastand);\r
+       }\r
+       RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= R_BobbaShot\r
+=\r
+===========================\r
+*/\r
+\r
+void R_BobbaShot(objtype *ob)\r
+{\r
+       if (ob->hitnorth || ob->hitsouth || ob->hiteast || ob->hitwest)\r
+       {\r
+               ChangeState(ob, &s_bobbashotvanish1);\r
+       }\r
+       RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 BABOBBA\r
+\r
+temp1 = jump counter (Babobba) / animation counter (Shot)\r
+\r
+=============================================================================\r
+*/\r
+\r
+statetype s_babobbajump1       = {BABOBBAL2SPR,     BABOBBAR2SPR,     stepthink, false, false,   8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
+statetype s_babobbajump2       = {BABOBBAL3SPR,     BABOBBAR3SPR,     think,     false, false,   8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
+statetype s_babobbastand       = {BABOBBAL1SPR,     BABOBBAR1SPR,     step,      false, false,  20, 0, 0, T_BabobbaStand, C_Babobba, R_Draw, &s_babobbajump1};\r
+statetype s_babobbaattack      = {BABOBBAL1SPR,     BABOBBAR1SPR,     step,      false, false,  70, 0, 0, NULL, C_Babobba, R_Draw, &s_babobbastand};\r
+statetype s_babobbastun1       = {BABOBBAL2SPR,     BABOBBAR2SPR,     think,     false, false,   0, 0, 0, T_Projectile, NULL, R_Stunned, &s_babobbastun2};\r
+statetype s_babobbastun2       = {BABOBBASTUNSPR,   BABOBBASTUNSPR,   think,     false, false,   0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
+statetype s_babobbasleep1      = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep2};\r
+statetype s_babobbasleep2      = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep3};\r
+statetype s_babobbasleep3      = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep4};\r
+statetype s_babobbasleep4      = {BABOBBASLEEP4SPR, BABOBBASLEEP4SPR, step,      false, false, 500, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep5};\r
+statetype s_babobbasleep5      = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep6};\r
+statetype s_babobbasleep6      = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep7};\r
+statetype s_babobbasleep7      = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbastand};\r
+statetype s_babobbashot1       = {BABOBBASHOT1SPR,  BABOBBASHOT1SPR,  think,     false, false,   0, 0, 0, T_Projectile, C_Lethal, R_Bounce, &s_babobbashot2};\r
+statetype s_babobbashot2       = {BABOBBASHOT2SPR,  BABOBBASHOT2SPR,  step,      false, false,   8, 0, 0, T_BabobbaShot, C_Lethal, R_Draw, &s_babobbashot3};\r
+statetype s_babobbashot3       = {BABOBBASHOT1SPR,  BABOBBASHOT1SPR,  step,      false, false,   8, 0, 0, NULL, C_Lethal, R_Draw, &s_babobbashot2};\r
+statetype s_babobbashotvanish1 = {BABOBBASHOT2SPR,  BABOBBASHOT2SPR,  step,      false, false,   8, 0, 0, T_BabobbaShotVanish, C_Lethal, R_Draw, &s_babobbashotvanish2};\r
+statetype s_babobbashotvanish2 = {-1,               -1,               step,      false, false,   8, 0, 0, NULL, NULL, R_Draw, &s_babobbashotvanish1};\r
+\r
+/*\r
+===========================\r
+=\r
+= SpawnBabobba\r
+=\r
+===========================\r
+*/\r
+\r
+void SpawnBabobba(Uint16 tileX, Uint16 tileY)\r
+{\r
+       GetNewObj(false);\r
+       new->obclass = babobbaobj;\r
+       new->active = ac_yes;\r
+       new->priority = 0;\r
+       new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
+       new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
+       if (US_RndT() < 0x80)\r
+       {\r
+               new->xdir = 1;\r
+       }\r
+       else\r
+       {\r
+               new->xdir = -1;\r
+       }\r
+       new->ydir = 1;\r
+       NewState(new, &s_babobbajump1);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_BabobbaStand\r
+=\r
+===========================\r
+*/\r
+\r
+void T_BabobbaStand(objtype *ob)\r
+{\r
+       Sint16 i;\r
+       Uint16 far *map;\r
+\r
+       if (US_RndT() < 4)\r
+       {\r
+               ob->temp1 = 0;\r
+               ob->state = &s_babobbasleep1;\r
+       }\r
+       else if (++ob->temp1 == 3)\r
+       {\r
+               ob->temp1 = 0;\r
+\r
+               GetNewObj(true);\r
+               new->active = ac_removable;\r
+               new->obclass = mshotobj;\r
+               new->y = ob->y + 4*PIXGLOBAL;\r
+               new->xdir = ob->xdir;\r
+               if (ob->xdir == 1)\r
+               {\r
+                       new->x = ob->x + 16*PIXGLOBAL;\r
+               }\r
+               else\r
+               {\r
+                       new->x = ob->x + 11*PIXGLOBAL;\r
+               }\r
+               new->xspeed = new->xdir << 5;\r
+               NewState(new, &s_babobbashot1);\r
+               new->priority = 2;\r
+               ob->state = &s_babobbaattack;\r
+       }\r
+       else\r
+       {\r
+               map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
+               for (i=0; i<4; map += ob->xdir, i++)\r
+               {\r
+                       if ( !tinf[*map+NORTHWALL]\r
+                               && !tinf[*(map-mapwidth)+NORTHWALL]\r
+                               && !tinf[*(map+mapwidth)+NORTHWALL] )\r
+                       {\r
+                               ob->xdir = -ob->xdir;\r
+                               break;\r
+                       }\r
+               }\r
+               ob->xspeed = ob->xdir *24;\r
+               ob->yspeed = -32;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= C_Babobba\r
+=\r
+===========================\r
+*/\r
+\r
+void C_Babobba(objtype *ob, objtype *hit)\r
+{\r
+       if (hit->obclass == keenobj)\r
+       {\r
+               KillKeen();\r
+       }\r
+       else if (hit->obclass == stunshotobj)\r
+       {\r
+               StunObj(ob, hit, &s_babobbastun1);\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= C_BabobbaSleep\r
+=\r
+===========================\r
+*/\r
+\r
+void C_BabobbaSleep(objtype *ob, objtype *hit)\r
+{\r
+       if (hit->obclass == stunshotobj)\r
+       {\r
+               StunObj(ob, hit, &s_babobbastun1);\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= R_Babobba\r
+=\r
+===========================\r
+*/\r
+\r
+void R_Babobba(objtype *ob)\r
+{\r
+       if (ob->hiteast)\r
+       {\r
+               ob->xdir = 1;\r
+               ob->xspeed = -ob->xspeed;\r
+       }\r
+       else if (ob->hitwest)\r
+       {\r
+               ob->xdir = -1;\r
+               ob->xspeed = -ob->xspeed;\r
+       }\r
+\r
+       if (ob->hitsouth)\r
+               ob->yspeed = 0;\r
+\r
+       if (ob->hitnorth)\r
+       {\r
+               ChangeState(ob, &s_babobbastand);\r
+       }\r
+       RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_BabobbaShot\r
+=\r
+===========================\r
+*/\r
+\r
+void T_BabobbaShot(objtype *ob)\r
+{\r
+       if (++ob->temp1 == 10)\r
+       {\r
+               ob->temp1 = 0;\r
+               ob->state = &s_babobbashotvanish1;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_BabobbaShotVanish\r
+=\r
+===========================\r
+*/\r
+\r
+void T_BabobbaShotVanish(objtype *ob)\r
+{\r
+       if (++ob->temp1 == 5)\r
+       {\r
+               RemoveObj(ob);\r
+       }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 BLORB\r
+\r
+=============================================================================\r
+*/\r
+\r
+statetype s_blorb1        = {BLORB1SPR, BLORB1SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb2};\r
+statetype s_blorb2        = {BLORB2SPR, BLORB2SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb3};\r
+statetype s_blorb3        = {BLORB3SPR, BLORB3SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb1};\r
+\r
+/*\r
+===========================\r
+=\r
+= SpawnBlorb\r
+=\r
+===========================\r
+*/\r
+\r
+void SpawnBlorb(Uint16 tileX, Uint16 tileY)\r
+{\r
+       GetNewObj(false);\r
+       new->obclass = blorbobj;\r
+       new->active = ac_yes;\r
+       new->priority = 0;\r
+       new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
+       new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
+       if (US_RndT() < 0x80)\r
+       {\r
+               new->xdir = 1;\r
+       }\r
+       else\r
+       {\r
+               new->xdir = -1;\r
+       }\r
+       if (US_RndT() < 0x80)\r
+       {\r
+               new->ydir = 1;\r
+       }\r
+       else\r
+       {\r
+               new->ydir = -1;\r
+       }\r
+       new->needtoclip = cl_fullclip;\r
+       NewState(new, &s_blorb1);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= R_Blorb\r
+=\r
+===========================\r
+*/\r
+\r
+void R_Blorb(objtype *ob)\r
+{\r
+       if (ob->hitnorth)\r
+       {\r
+               ob->ydir = -1;\r
+               SD_PlaySound(SND_BLORBBOUNCE);\r
+       }\r
+       else if (ob->hitsouth)\r
+       {\r
+               ob->ydir = 1;\r
+               SD_PlaySound(SND_BLORBBOUNCE);\r
+       }\r
+       if (ob->hitwest)\r
+       {\r
+               ob->xdir = -1;\r
+               SD_PlaySound(SND_BLORBBOUNCE);\r
+       }\r
+       else if (ob->hiteast)\r
+       {\r
+               ob->xdir = 1;\r
+               SD_PlaySound(SND_BLORBBOUNCE);\r
+       }\r
+       RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 CEILICK\r
+\r
+temp1 = initial y position\r
+\r
+=============================================================================\r
+*/\r
+\r
+statetype s_ceilickhidden   = {TONGUE1SPR,     TONGUE1SPR,     think, false, false, 20, 0,   0, T_CeilickHidden, NULL, R_Draw, NULL};\r
+statetype s_ceilickattack1  = {TONGUE1SPR,     TONGUE1SPR,     step,  false, false,  6, 0,   0, NULL, NULL, R_Draw, &s_ceilickattack2};\r
+statetype s_ceilickattack2  = {TONGUE2SPR,     TONGUE2SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack3};\r
+statetype s_ceilickattack3  = {TONGUE3SPR,     TONGUE3SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack4};\r
+statetype s_ceilickattack4  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack5};\r
+statetype s_ceilickattack5  = {TONGUE5SPR,     TONGUE5SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack6};\r
+statetype s_ceilickattack6  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack7};\r
+statetype s_ceilickattack7  = {TONGUE3SPR,     TONGUE3SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack8};\r
+statetype s_ceilickattack8  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack9};\r
+statetype s_ceilickattack9  = {TONGUE5SPR,     TONGUE5SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack10};\r
+statetype s_ceilickattack10 = {TONGUE2SPR,     TONGUE2SPR,     step,  false, false, 10, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack11};\r
+statetype s_ceilickattack11 = {TONGUE1SPR,     TONGUE1SPR,     step,  false, false, 10, 0,   0, NULL, NULL, R_Draw, &s_ceilicklaugh1};\r
+statetype s_ceilicklaugh1   = {CEILICK1SPR,    CEILICK1SPR,    slide, true,  false, 16, 0,  16, T_CeilickLaugh, C_Ceilick, R_Draw, &s_ceilicklaugh2};\r
+statetype s_ceilicklaugh2   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh3};\r
+statetype s_ceilicklaugh3   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh4};\r
+statetype s_ceilicklaugh4   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh5};\r
+statetype s_ceilicklaugh5   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh6};\r
+statetype s_ceilicklaugh6   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh7};\r
+statetype s_ceilicklaugh7   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh8};\r
+statetype s_ceilicklaugh8   = {CEILICK1SPR,    CEILICK1SPR,    slide, true,  false, 16, 0, -16, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh9};\r
+statetype s_ceilicklaugh9   = {-1,             -1,             step,  true,  false, 60, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilickhidden};\r
+statetype s_ceilickstun     = {CEILICKSTUNSPR, CEILICKSTUNSPR, think, true,  false,  0, 0,   0, T_CeilickStunned, NULL, R_Stunned, NULL};\r
+\r
+/*\r
+===========================\r
+=\r
+= SpawnCeilick\r
+=\r
+===========================\r
+*/\r
+\r
+void SpawnCeilick(Uint16 tileX, Uint16 tileY)\r
+{\r
+       GetNewObj(false);\r
+       new->obclass = ceilickobj;\r
+       new->active = ac_yes;\r
+       new->priority = 0;\r
+       new->needtoclip = cl_noclip;\r
+       new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
+       new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
+       new->ydir = 1;\r
+       NewState(new, &s_ceilickhidden);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_CeilickHidden\r
+=\r
+===========================\r
+*/\r
+\r
+void T_CeilickHidden(objtype *ob)\r
+{\r
+       if ( player->y - ob->y <= 40*PIXGLOBAL\r
+               && player->left < ob->right+PIXGLOBAL\r
+               && player->right > ob->left-PIXGLOBAL )\r
+       {\r
+               SD_PlaySound(SND_CEILICKATTACK);\r
+               ob->state = &s_ceilickattack1;\r
+       }\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_CeilickLaugh\r
+=\r
+===========================\r
+*/\r
+\r
+#pragma argsused\r
+void T_CeilickLaugh(objtype *ob)\r
+{\r
+       SD_PlaySound(SND_CEILICKLAUGH);\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= T_CeilickStunned\r
+=\r
+===========================\r
+*/\r
+\r
+void T_CeilickStunned(objtype *ob)\r
+{\r
+       ob->needtoreact = true; // to make sure the stunned stars animate\r
+}\r
+\r
+/*\r
+===========================\r
+=\r
+= C_Ceilick\r
+=\r
+===========================\r
+*/\r
+\r
+void C_Ceilick(objtype *ob, objtype *hit)\r
+{\r
+       if (hit->obclass == stunshotobj)\r
+       {\r
+               ob->y = ob->temp1;\r
+               ExplodeShot(hit);\r
+               ob->temp1 = ob->temp2 = ob->temp3 = 0;\r
+               ob->temp4 = ob->obclass;\r
+               ChangeState(ob, &s_ceilickstun);\r
+               ob->obclass = stunnedobj;\r
+       }\r
+}
\ No newline at end of file