]> 4ch.mooo.com Git - 16.git/blobdiff - src/lib/hb/kd_act2.c
[16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / src / lib / hb / kd_act2.c
diff --git a/src/lib/hb/kd_act2.c b/src/lib/hb/kd_act2.c
new file mode 100755 (executable)
index 0000000..e186540
--- /dev/null
@@ -0,0 +1,1509 @@
+/* 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
+// KD_ACT1.C\r
+#include "KD_DEF.H"\r
+#pragma hdrstop\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define PLACESPRITE RF_PlaceSprite (&ob->sprite,ob->x,ob->y,ob->shapenum, \\r
+       spritedraw,0);\r
+\r
+\r
+void   ProjectileReact (objtype *ob);\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                  TATER TROOPER\r
+\r
+temp1 = chasing player\r
+temp2 = nothink time\r
+\r
+=============================================================================\r
+*/\r
+\r
+void TaterThink (objtype *ob);\r
+void BackupReact (objtype *ob);\r
+\r
+extern statetype s_taterwalk1;\r
+extern statetype s_taterwalk2;\r
+extern statetype s_taterwalk3;\r
+extern statetype s_taterwalk4;\r
+\r
+\r
+extern statetype s_taterattack1;\r
+extern statetype s_taterattack2;\r
+extern statetype s_taterattack3;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_taterwalk1 = {TATERTROOPWALKL1SPR,TATERTROOPWALKR1SPR,step,false,\r
+       true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk2};\r
+statetype s_taterwalk2 = {TATERTROOPWALKL2SPR,TATERTROOPWALKR2SPR,step,false,\r
+       true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk3};\r
+statetype s_taterwalk3 = {TATERTROOPWALKL3SPR,TATERTROOPWALKR3SPR,step,false,\r
+       true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk4};\r
+statetype s_taterwalk4 = {TATERTROOPWALKL4SPR,TATERTROOPWALKR4SPR,step,false,\r
+       true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk1};\r
+\r
+statetype s_taterattack1= {TATERTROOPLUNGEL1SPR,TATERTROOPLUNGER1SPR,step,false,\r
+       false,12, 0,0, NULL, NULL, BackupReact, &s_taterattack2};\r
+statetype s_taterattack2= {TATERTROOPLUNGEL2SPR,TATERTROOPLUNGER2SPR,step,false,\r
+       false,20, 0,0, NULL, NULL, DrawReact, &s_taterattack3};\r
+statetype s_taterattack3= {TATERTROOPLUNGEL1SPR,TATERTROOPLUNGER1SPR,step,false,\r
+       false,8, 0,0, NULL, NULL, DrawReact, &s_taterwalk1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnTater\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnTater (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = taterobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE + 15;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       NewState (new,&s_taterwalk1);\r
+       new->hitnorth = 1;\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= TaterThink\r
+=\r
+====================\r
+*/\r
+\r
+void TaterThink (objtype *ob)\r
+{\r
+       int delta;\r
+\r
+       if (ob->top > player->bottom || ob->bottom < player->top)\r
+               return;\r
+\r
+       if ( ob->xdir == -1 )\r
+       {\r
+               delta = ob->left - player->right;\r
+               if (delta > TILEGLOBAL)\r
+                       return;\r
+               if (delta < -8*PIXGLOBAL)\r
+               {\r
+                       ob->xdir = 1;\r
+                       return;\r
+               }\r
+               SD_PlaySound (TATERSWINGSND);\r
+               ob->state = &s_taterattack1;\r
+               return;\r
+       }\r
+       else\r
+       {\r
+               delta = player->left - ob->right;\r
+               if (delta > TILEGLOBAL)\r
+                       return;\r
+               if (delta < -8*PIXGLOBAL)\r
+               {\r
+                       ob->xdir = -1;\r
+                       return;\r
+               }\r
+               SD_PlaySound (TATERSWINGSND);\r
+               ob->state = &s_taterattack1;\r
+               return;\r
+       }\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= BackupReact\r
+=\r
+====================\r
+*/\r
+\r
+void BackupReact (objtype *ob)\r
+{\r
+       if (!ob->hitnorth)\r
+       {\r
+               ob->x-=ob->xmove;\r
+               ob->y-=ob->ymove;\r
+       }\r
+\r
+       PLACESPRITE;\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                  CANTELOUPE CART\r
+\r
+=============================================================================\r
+*/\r
+\r
+extern statetype s_cartroll1;\r
+extern statetype s_cartroll2;\r
+\r
+void CartReact (objtype *ob);\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_cartroll1  = {CANTCARTL1SPR,CANTCARTL1SPR,slide,true,\r
+       false,5, 32,0, NULL, NULL, CartReact, &s_cartroll2};\r
+statetype s_cartroll2  = {CANTCARTL2SPR,CANTCARTL2SPR,slide,true,\r
+       false,5, 32,0, NULL, NULL, CartReact, &s_cartroll1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnCart\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnCart (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = cartobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-3*PIXGLOBAL;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       new->active = allways;\r
+       NewState (new,&s_cartroll1);\r
+}\r
+\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= CartReact\r
+=\r
+====================\r
+*/\r
+\r
+void CartReact (objtype *ob)\r
+{\r
+       unsigned far *map;\r
+\r
+       if (ob->xdir == 1 && ob->hitwest)\r
+       {\r
+               ob->xdir = -1;\r
+       }\r
+       else if (ob->xdir == -1 && ob->hiteast)\r
+       {\r
+               ob->xdir = 1;\r
+       }\r
+\r
+       map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2;\r
+       if (ob->xdir == 1)\r
+               map += ob->tileright;\r
+       else\r
+               map += ob->tileleft;\r
+\r
+       if ( !tinf[NORTHWALL + *map] )\r
+               ob->xdir = -ob->xdir;\r
+\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       FRENCHY\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define FRYXSPEED      40\r
+#define FRYYSPEED      -20\r
+\r
+\r
+void FrenchyThink (objtype *ob);\r
+void FrenchyRunThink (objtype *ob);\r
+void FrenchyThrow (objtype *ob);\r
+\r
+extern statetype s_frenchywalk1;\r
+extern statetype s_frenchywalk2;\r
+extern statetype s_frenchywalk3;\r
+extern statetype s_frenchywalk4;\r
+\r
+extern statetype s_frenchyrun1;\r
+extern statetype s_frenchyrun2;\r
+extern statetype s_frenchyrun3;\r
+extern statetype s_frenchyrun4;\r
+\r
+extern statetype s_frenchythrow1;\r
+extern statetype s_frenchythrow2;\r
+extern statetype s_frenchythrow3;\r
+\r
+extern statetype s_fry1;\r
+extern statetype s_fry2;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_frenchywalk1       = {FRENCHYRUNL1SPR,FRENCHYRUNR1SPR,step,false,\r
+       true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk2};\r
+statetype s_frenchywalk2       = {FRENCHYRUNL2SPR,FRENCHYRUNR2SPR,step,false,\r
+       true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk3};\r
+statetype s_frenchywalk3       = {FRENCHYRUNL3SPR,FRENCHYRUNR3SPR,step,false,\r
+       true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk4};\r
+statetype s_frenchywalk4       = {FRENCHYRUNL4SPR,FRENCHYRUNR4SPR,step,false,\r
+       true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk1};\r
+\r
+statetype s_frenchyrun1        = {FRENCHYRUNL1SPR,FRENCHYRUNR1SPR,step,true,\r
+       true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun2};\r
+statetype s_frenchyrun2        = {FRENCHYRUNL2SPR,FRENCHYRUNR2SPR,step,true,\r
+       true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun3};\r
+statetype s_frenchyrun3        = {FRENCHYRUNL3SPR,FRENCHYRUNR3SPR,step,true,\r
+       true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun4};\r
+statetype s_frenchyrun4        = {FRENCHYRUNL4SPR,FRENCHYRUNR4SPR,step,true,\r
+       true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun1};\r
+\r
+statetype s_frenchythrow1      = {FRENCHYTHROWL1SPR,FRENCHYTHROWR1SPR,step,false,\r
+       false,10, 0,0, NULL, NULL, DrawReact, &s_frenchythrow2};\r
+statetype s_frenchythrow2      = {FRENCHYTHROWL2SPR,FRENCHYTHROWR2SPR,step,false,\r
+       false,1, 0,0, FrenchyThrow, NULL, DrawReact, &s_frenchythrow3};\r
+statetype s_frenchythrow3      = {FRENCHYTHROWL2SPR,FRENCHYTHROWR2SPR,step,false,\r
+       false,10, -128,0, NULL, NULL, DrawReact, &s_frenchywalk1};\r
+\r
+statetype s_fry1               = {FRENCHFRY1SPR,FRENCHFRY1SPR,stepthink,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_fry2};\r
+statetype s_fry2               = {FRENCHFRY2SPR,FRENCHFRY2SPR,stepthink,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_fry1};\r
+\r
+\r
+#pragma warn +sus\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnFrenchy\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnFrenchy (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = frenchyobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       NewState (new,&s_frenchywalk1);\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= FrenchyRunThink\r
+=\r
+====================\r
+*/\r
+\r
+void FrenchyRunThink (objtype *ob)\r
+{\r
+       ob->state = &s_frenchywalk1;\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= FrenchyThrow\r
+=\r
+====================\r
+*/\r
+\r
+void FrenchyThrow (objtype *ob)\r
+{\r
+       GetNewObj (true);\r
+       new->obclass = shotobj;\r
+       if (ob->xdir == 1)\r
+       {\r
+               new->x = ob->x+24*16;\r
+               new->y = ob->y+8*16;\r
+       }\r
+       else\r
+       {\r
+               new->x = ob->x;\r
+               new->y = ob->y+8*16;\r
+       }\r
+       new->xdir = ob->xdir;\r
+       new->ydir = 1;\r
+       new->xspeed = ob->xdir * FRYXSPEED-(US_RndT()>>4);\r
+       new->yspeed = FRYYSPEED;\r
+       new->active = removable;\r
+       NewState (new,&s_fry1);\r
+\r
+       ob->nothink = 2;\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= FrenchyThink\r
+=\r
+====================\r
+*/\r
+\r
+void FrenchyThink (objtype *ob)\r
+{\r
+       int delta;\r
+\r
+       if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
+       {\r
+               if (US_RndT()<8)\r
+                       ob->xdir = -ob->xdir;           // turn randomly\r
+               return;\r
+       }\r
+\r
+       delta = player->x - ob->x;\r
+\r
+       if (delta < -8*TILEGLOBAL)\r
+       {\r
+       // walk closer\r
+               ob->xdir = -1;\r
+       }\r
+       if (delta < -4*TILEGLOBAL)\r
+       {\r
+       // throw\r
+               ob->xdir = -1;\r
+               ob->state = &s_frenchythrow1;\r
+       }\r
+       else if (delta < 0)\r
+       {\r
+       // run away\r
+               ob->xdir = 1;\r
+               ob->state = &s_frenchyrun1;\r
+               ob->nothink = 8;\r
+       }\r
+       else if (delta < 4*TILEGLOBAL)\r
+       {\r
+       // run away\r
+               ob->xdir = -1;\r
+               ob->state = &s_frenchyrun1;\r
+               ob->nothink = 8;\r
+       }\r
+       else if (delta < 8*TILEGLOBAL)\r
+       {\r
+       // throw and walk closer\r
+               ob->xdir = 1;\r
+               ob->state = &s_frenchythrow1;\r
+       }\r
+       else\r
+       {\r
+       // walk closer\r
+               ob->xdir = 1;\r
+       }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                 MELON LIPS\r
+\r
+ob->temp1 = direction : 0 = left, 1 = right, 2 = down\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define SPITXSPEED     48\r
+#define SPITYSPEED     -20\r
+\r
+void MelonSpitThink (objtype *ob);\r
+void   ProjectileReact (objtype *ob);\r
+\r
+extern statetype s_melonside;\r
+extern statetype s_melonsidespit;\r
+extern statetype s_melonsidespit2;\r
+\r
+extern statetype s_melondown;\r
+extern statetype s_melondownspit;\r
+extern statetype s_melondownspit2;\r
+\r
+extern statetype s_melonseed1;\r
+extern statetype s_melonseed2;\r
+\r
+extern statetype s_melonseedd1;\r
+extern statetype s_melonseedd2;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_melonside  = {MELONLIPSL1SPR,MELONLIPSR1SPR,step,false,\r
+       false,200, 0,0, NULL, NULL, DrawReact, &s_melonsidespit};\r
+statetype s_melonsidespit= {MELONLIPSL2SPR,MELONLIPSR2SPR,step,false,\r
+       false,6, 0,0, MelonSpitThink, NULL, DrawReact, &s_melonsidespit2};\r
+statetype s_melonsidespit2= {MELONLIPSL2SPR,MELONLIPSR2SPR,step,false,\r
+       false,6, 0,0, NULL, NULL, DrawReact, &s_melonside};\r
+\r
+statetype s_melondown  = {MELONLIPSD1SPR,MELONLIPSD1SPR,step,false,\r
+       false,200, 0,0, NULL, NULL, DrawReact, &s_melondownspit};\r
+statetype s_melondownspit      = {MELONLIPSD2SPR,MELONLIPSD2SPR,step,false,\r
+       false,6, 0,0, MelonSpitThink, NULL, DrawReact, &s_melondownspit2};\r
+statetype s_melondownspit2     = {MELONLIPSD2SPR,MELONLIPSD2SPR,step,false,\r
+       false,6, 0,0, NULL, NULL, DrawReact, &s_melondown};\r
+\r
+statetype s_melonseed1 = {MELONSEEDL1SPR,MELONSEEDR1SPR,think,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseed2};\r
+statetype s_melonseed2 = {MELONSEEDL2SPR,MELONSEEDR2SPR,think,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseed1};\r
+\r
+statetype s_melonseedd1        = {MELONSEEDD1SPR,MELONSEEDD1SPR,stepthink,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseedd2};\r
+statetype s_melonseedd2        = {MELONSEEDD2SPR,MELONSEEDD2SPR,stepthink,false,\r
+       false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseedd1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnMelon\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnMelon (int tilex, int tiley,int dir)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = melonobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = tiley<<G_T_SHIFT;\r
+       if (dir)\r
+               new->xdir = 1;\r
+       else\r
+               new->xdir = -1;\r
+       if (dir <2)\r
+               NewState (new,&s_melonside);\r
+       else\r
+               NewState (new,&s_melondown);\r
+\r
+       new->ticcount = US_RndT()>>1;\r
+       new->temp1 = dir;\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= MelonSpitThink\r
+=\r
+====================\r
+*/\r
+\r
+void MelonSpitThink (objtype *ob)\r
+{\r
+       GetNewObj (false);\r
+       new->obclass = shotobj;\r
+       switch (ob->temp1)\r
+       {\r
+       case 0:\r
+               new->x = ob->x+24*16;\r
+               new->y = ob->y+8*16;\r
+               new->xdir = ob->xdir;\r
+               new->ydir = 1;\r
+               new->xspeed = -SPITXSPEED-(US_RndT()>>4);\r
+               new->yspeed = SPITYSPEED;\r
+               NewState (new,&s_melonseed1);\r
+               break;\r
+       case 1:\r
+               new->x = ob->x;\r
+               new->y = ob->y+8*16;\r
+               new->xdir = ob->xdir;\r
+               new->ydir = 1;\r
+               new->xspeed = SPITXSPEED+(US_RndT()>>4);\r
+               new->yspeed = SPITYSPEED;\r
+               NewState (new,&s_melonseed1);\r
+               break;\r
+       case 2:\r
+               new->x = ob->x+8*16;\r
+               new->y = ob->y+24*16;\r
+               new->ydir = 1;\r
+               new->yspeed = -SPITYSPEED;\r
+               NewState (new,&s_melonseedd1);\r
+               break;\r
+       }\r
+\r
+       new->active = removable;\r
+}\r
+\r
+/*\r
+============================\r
+=\r
+= ProjectileReact\r
+=\r
+============================\r
+*/\r
+\r
+void   ProjectileReact (objtype *ob)\r
+{\r
+       unsigned wall,absx,absy,angle,newangle;\r
+       unsigned long speed;\r
+\r
+       PLACESPRITE;\r
+       if (ob->hiteast || ob->hitwest)\r
+               ob->xspeed= -ob->xspeed/2;\r
+\r
+       if (ob->hitsouth)\r
+               ob->yspeed= -ob->yspeed/2;\r
+\r
+       wall = ob->hitnorth;\r
+       if (wall)\r
+       {\r
+               if (ob->yspeed < 0)\r
+                       ob->yspeed = 0;\r
+\r
+               absx = abs(ob->xspeed);\r
+               absy = ob->yspeed;\r
+               if (absx>absy)\r
+               {\r
+                       if (absx>absy*2)        // 22 degrees\r
+                       {\r
+                               angle = 0;\r
+                               speed = absx*286;       // x*sqrt(5)/2\r
+                       }\r
+                       else                            // 45 degrees\r
+                       {\r
+                               angle = 1;\r
+                               speed = absx*362;       // x*sqrt(2)\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       if (absy>absx*2)        // 90 degrees\r
+                       {\r
+                               angle = 3;\r
+                               speed = absy*256;\r
+                       }\r
+                       else\r
+                       {\r
+                               angle = 2;              // 67 degrees\r
+                               speed = absy*286;       // y*sqrt(5)/2\r
+                       }\r
+               }\r
+               if (ob->xspeed > 0)\r
+                       angle = 7-angle;\r
+\r
+               speed >>= 1;\r
+               newangle = bounceangle[ob->hitnorth][angle];\r
+               switch (newangle)\r
+               {\r
+               case 0:\r
+                       ob->xspeed = speed / 286;\r
+                       ob->yspeed = -ob->xspeed / 2;\r
+                       break;\r
+               case 1:\r
+                       ob->xspeed = speed / 362;\r
+                       ob->yspeed = -ob->xspeed;\r
+                       break;\r
+               case 2:\r
+                       ob->yspeed = -(speed / 286);\r
+                       ob->xspeed = -ob->yspeed / 2;\r
+                       break;\r
+               case 3:\r
+\r
+               case 4:\r
+                       ob->xspeed = 0;\r
+                       ob->yspeed = -(speed / 256);\r
+                       break;\r
+               case 5:\r
+                       ob->yspeed = -(speed / 286);\r
+                       ob->xspeed = ob->yspeed / 2;\r
+                       break;\r
+               case 6:\r
+                       ob->xspeed = ob->yspeed = -(speed / 362);\r
+                       break;\r
+               case 7:\r
+                       ob->xspeed = -(speed / 286);\r
+                       ob->yspeed = ob->xspeed / 2;\r
+                       break;\r
+\r
+               case 8:\r
+                       ob->xspeed = -(speed / 286);\r
+                       ob->yspeed = -ob->xspeed / 2;\r
+                       break;\r
+               case 9:\r
+                       ob->xspeed = -(speed / 362);\r
+                       ob->yspeed = -ob->xspeed;\r
+                       break;\r
+               case 10:\r
+                       ob->yspeed = speed / 286;\r
+                       ob->xspeed = -ob->yspeed / 2;\r
+                       break;\r
+               case 11:\r
+\r
+               case 12:\r
+                       ob->xspeed = 0;\r
+                       ob->yspeed = -(speed / 256);\r
+                       break;\r
+               case 13:\r
+                       ob->yspeed = speed / 286;\r
+                       ob->xspeed = ob->yspeed / 2;\r
+                       break;\r
+               case 14:\r
+                       ob->xspeed = speed / 362;\r
+                       ob->yspeed = speed / 362;\r
+                       break;\r
+               case 15:\r
+                       ob->xspeed = speed / 286;\r
+                       ob->yspeed = ob->xspeed / 2;\r
+                       break;\r
+               }\r
+\r
+               if (speed < 256*16)\r
+                       RemoveObj (ob);\r
+       }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       SQUASHER\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define SPDSQUASHLEAPY  50\r
+\r
+\r
+void SquasherThink (objtype *ob);\r
+void SquasherJumpReact (objtype *ob);\r
+\r
+extern statetype s_squasherwalk1;\r
+extern statetype s_squasherwalk2;\r
+\r
+extern statetype s_squasherjump1;\r
+extern statetype s_squasherjump2;\r
+\r
+extern statetype s_squasherwait;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_squasherwalk1      = {SQUASHERWALKL1SPR,SQUASHERWALKR1SPR,step,false,\r
+       true,10, 128,0, SquasherThink, NULL, WalkReact, &s_squasherwalk2};\r
+statetype s_squasherwalk2      = {SQUASHERWALKL2SPR,SQUASHERWALKR2SPR,step,false,\r
+       true,10, 128,0, SquasherThink, NULL, WalkReact, &s_squasherwalk1};\r
+\r
+statetype s_squasherjump1      = {SQUASHERJUMPL1SPR,SQUASHERJUMPR1SPR,stepthink,false,\r
+       false,20, 0,0, ProjectileThink, NULL, SquasherJumpReact, &s_squasherjump2};\r
+statetype s_squasherjump2      = {SQUASHERJUMPL2SPR,SQUASHERJUMPR2SPR,think,false,\r
+       false,0, 0,0, ProjectileThink, NULL, SquasherJumpReact, NULL};\r
+\r
+statetype s_squasherwait       = {SQUASHERJUMPL2SPR,SQUASHERJUMPR2SPR,step,false,\r
+       false,10, 0,0, ProjectileThink, NULL, DrawReact, &s_squasherwalk1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnSquasher\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnSquasher (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = squashobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       NewState (new,&s_squasherwalk1);\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= SquasherThink\r
+=\r
+====================\r
+*/\r
+\r
+void SquasherThink (objtype *ob)\r
+{\r
+       int delta;\r
+\r
+       if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
+       {\r
+               if (US_RndT()<8)\r
+                       ob->xdir = -ob->xdir;           // turn randomly\r
+               return;\r
+       }\r
+\r
+\r
+       delta = player->x - ob->x;\r
+\r
+       if ( ob->xdir == -1 )\r
+       {\r
+               if (delta < -6*TILEGLOBAL)\r
+                       return;\r
+               if (delta > 8*PIXGLOBAL)\r
+               {\r
+                       ob->xdir = 1;\r
+                       return;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (delta > 6*TILEGLOBAL)\r
+                       return;\r
+               if (delta < -8*PIXGLOBAL)\r
+               {\r
+                       ob->xdir = 1;\r
+                       return;\r
+               }\r
+       }\r
+\r
+       ob->yspeed = -SPDSQUASHLEAPY;\r
+       ob->xspeed = delta/60;\r
+       ob->state = &s_squasherjump1;\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= SquasherJumpReact\r
+=\r
+====================\r
+*/\r
+\r
+void SquasherJumpReact (objtype *ob)\r
+{\r
+       if (ob->hitsouth)\r
+               ob->yspeed = 0;\r
+\r
+       if (ob->hitnorth)\r
+               ChangeState (ob,&s_squasherwait);\r
+\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                               APEL\r
+\r
+temp4 = pole x coordinate\r
+\r
+=============================================================================\r
+*/\r
+\r
+void ApelThink (objtype *ob);\r
+void ApelClimbThink (objtype *ob);\r
+void ApelSlideThink (objtype *ob);\r
+void ApelFallThink (objtype *ob);\r
+\r
+void ApelClimbReact (objtype *ob);\r
+void ApelSlideReact (objtype *ob);\r
+void ApelFallReact (objtype *ob);\r
+\r
+extern statetype s_apelwalk1;\r
+extern statetype s_apelwalk2;\r
+extern statetype s_apelwalk3;\r
+\r
+extern statetype s_apelclimb1;\r
+extern statetype s_apelclimb2;\r
+\r
+extern statetype s_apelslide1;\r
+extern statetype s_apelslide2;\r
+extern statetype s_apelslide3;\r
+extern statetype s_apelslide4;\r
+\r
+extern statetype s_apelfall;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_apelwalk1  = {APELWALKL1SPR,APELWALKR1SPR,step,false,\r
+       true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk2};\r
+statetype s_apelwalk2  = {APELWALKL2SPR,APELWALKR2SPR,step,false,\r
+       true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk3};\r
+statetype s_apelwalk3  = {APELWALKL3SPR,APELWALKR3SPR,step,false,\r
+       true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk1};\r
+\r
+statetype s_apelclimb1 = {APELSHINNY1SPR,APELSHINNY1SPR,slide,false,\r
+       false,6, 0,-16, ApelClimbThink, NULL, ApelClimbReact, &s_apelclimb2};\r
+statetype s_apelclimb2 = {APELSHINNY2SPR,APELSHINNY2SPR,slide,false,\r
+       false,6, 0,-16, ApelClimbThink, NULL, ApelClimbReact, &s_apelclimb1};\r
+\r
+statetype s_apelslide1 = {APELSLIDE1SPR,APELSLIDE1SPR,slide,false,\r
+       false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide2};\r
+statetype s_apelslide2 = {APELSLIDE2SPR,APELSLIDE2SPR,slide,false,\r
+       false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide3};\r
+statetype s_apelslide3 = {APELSLIDE3SPR,APELSLIDE3SPR,slide,false,\r
+       false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide4};\r
+statetype s_apelslide4 = {APELSLIDE4SPR,APELSLIDE4SPR,slide,false,\r
+       false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide1};\r
+\r
+statetype s_apelfall = {APELWALKL1SPR,APELWALKR1SPR,think,false,\r
+       false,0, 0,0, ProjectileThink, NULL, ApelFallReact, NULL};\r
+\r
+#pragma warn +sus\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnApel\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnApel (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = apelobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       NewState (new,&s_apelwalk1);\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ApelThink\r
+=\r
+====================\r
+*/\r
+\r
+void ApelThink (objtype *ob)\r
+{\r
+       int     x,y;\r
+       unsigned far *map;\r
+\r
+       if (ob->top > player->bottom || ob->bottom < player->top)\r
+       {\r
+       //\r
+       // try to climb a pole to reach player\r
+       //\r
+               if (ob->y < player->y)\r
+                       y = ob->tilebottom;\r
+               else\r
+                       y = ob->tiletop;\r
+\r
+               map = (unsigned _seg *)mapsegs[1]+\r
+                       mapbwidthtable[y]/2 + ob->tilemidx;\r
+\r
+               if ((tinf[INTILE+*map]&0x7f) == 1)\r
+               {\r
+                       ob->xmove = (ob->tilemidx<<G_T_SHIFT) - ob->x;\r
+                       ob->ymove = 0;\r
+                       ob->temp4 = ob->tilemidx;       // for future reference\r
+                       ob->needtoclip = false;         // can climb through pole holes\r
+                       if (ob->y < player->y)\r
+                               ob->state = &s_apelslide1;\r
+                       else\r
+                               ob->state = &s_apelclimb1;\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if (US_RndT()>32)               // don't turn around all the time\r
+               return;\r
+\r
+       if (ob->x < player->x)\r
+               ob->xdir = 1;\r
+       else\r
+               ob->xdir = -1;\r
+\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ApelClimbThink\r
+=\r
+====================\r
+*/\r
+\r
+void ApelClimbThink (objtype *ob)\r
+{\r
+       unsigned far *map;\r
+\r
+       map = (unsigned _seg *)mapsegs[1]+\r
+               mapbwidthtable[ob->tiletop]/2 + ob->temp4;\r
+\r
+       if ((tinf[INTILE+*map]&0x7f) != 1)\r
+       {\r
+               ob->needtoclip = true;\r
+               ob->state = &s_apelfall;\r
+       }\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ApelSlideThink\r
+=\r
+====================\r
+*/\r
+\r
+void ApelSlideThink (objtype *ob)\r
+{\r
+       unsigned far *map;\r
+\r
+       map = (unsigned _seg *)mapsegs[1]+\r
+               mapbwidthtable[ob->tilebottom]/2 + ob->temp4;\r
+\r
+       if ((tinf[INTILE+*map]&0x7f) != 1)\r
+       {\r
+               ob->needtoclip = true;\r
+               ob->state = &s_apelfall;\r
+       }\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ApelClimbReact\r
+=\r
+====================\r
+*/\r
+\r
+void ApelClimbReact (objtype *ob)\r
+{\r
+       if (ob->hitsouth)\r
+               ChangeState (ob,&s_apelfall);\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= ApelFallReact\r
+=\r
+====================\r
+*/\r
+\r
+void ApelFallReact (objtype *ob)\r
+{\r
+       if (ob->hitnorth)\r
+               ChangeState (ob,&s_apelwalk1);\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                               PEA BRAIN\r
+\r
+=============================================================================\r
+*/\r
+\r
+void PeaBrainThink (objtype *ob);\r
+void PeaFlyReact (objtype *ob);\r
+\r
+extern statetype s_peabrainfly;\r
+\r
+extern statetype s_peabrainwalk1;\r
+extern statetype s_peabrainwalk2;\r
+extern statetype s_peabrainwalk3;\r
+extern statetype s_peabrainwalk4;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_peabrainfly        = {PEABRAINWALKL1SPR,PEABRAINWALKR1SPR,think,false,\r
+       false,0, 0,0, ProjectileThink, NULL, PeaFlyReact, NULL};\r
+\r
+statetype s_peabrainwalk1      = {PEABRAINWALKL1SPR,PEABRAINWALKR1SPR,step,false,\r
+       true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk2};\r
+statetype s_peabrainwalk2      = {PEABRAINWALKL2SPR,PEABRAINWALKR2SPR,step,false,\r
+       true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk3};\r
+statetype s_peabrainwalk3      = {PEABRAINWALKL3SPR,PEABRAINWALKR3SPR,step,false,\r
+       true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk4};\r
+statetype s_peabrainwalk4      = {PEABRAINWALKL4SPR,PEABRAINWALKR4SPR,step,false,\r
+       true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnPeaBrain\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnPeaBrain (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = peabrainobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = tiley<<G_T_SHIFT;\r
+       NewState (new,&s_peabrainwalk1);\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= PeaBrainThink\r
+=\r
+====================\r
+*/\r
+\r
+void PeaBrainThink (objtype *ob)\r
+{\r
+       ob++;\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= PeaFlyReact\r
+=\r
+====================\r
+*/\r
+\r
+void PeaFlyReact (objtype *ob)\r
+{\r
+       if (ob->hitnorth)\r
+               ChangeState (ob,&s_peabrainwalk1);\r
+\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                               PEA POD\r
+\r
+temp1 = number of peas spit\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define MAXPEASPIT     4\r
+\r
+#define PEAXSPEED      48\r
+#define PEAYSPEED      -20\r
+\r
+\r
+void PeaPodThink (objtype *ob);\r
+void SpitPeaBrain (objtype *ob);\r
+\r
+extern statetype s_peapodwalk1;\r
+extern statetype s_peapodwalk2;\r
+extern statetype s_peapodwalk3;\r
+extern statetype s_peapodwalk4;\r
+\r
+extern statetype s_peapodspit1;\r
+extern statetype s_peapodspit2;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_peapodwalk1        = {PEAPODRUNL1SPR,PEAPODRUNR1SPR,step,false,\r
+       true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk2};\r
+statetype s_peapodwalk2        = {PEAPODRUNL2SPR,PEAPODRUNR2SPR,step,false,\r
+       true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk3};\r
+statetype s_peapodwalk3        = {PEAPODRUNL3SPR,PEAPODRUNR3SPR,step,false,\r
+       true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk4};\r
+statetype s_peapodwalk4        = {PEAPODRUNL4SPR,PEAPODRUNR4SPR,step,false,\r
+       true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk1};\r
+\r
+statetype s_peapodspit1        = {PEAPODSPITLSPR,PEAPODSPITRSPR,step,false,\r
+       true,30, 0,0, SpitPeaBrain, NULL, DrawReact, &s_peapodspit2};\r
+statetype s_peapodspit2        = {PEAPODSPITLSPR,PEAPODSPITRSPR,step,false,\r
+       true,30, 0,0, NULL, NULL, DrawReact, &s_peapodwalk1};\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnPeaPod\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnPeaPod (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = peapodobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
+       new->xdir = 1;\r
+       new->ydir = 1;\r
+       NewState (new,&s_peapodwalk1);\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= SpitPeaBrain\r
+=\r
+====================\r
+*/\r
+\r
+void SpitPeaBrain (objtype *ob)\r
+{\r
+       GetNewObj (true);\r
+       new->obclass = peabrainobj;\r
+       if (ob->xdir == 1)\r
+       {\r
+               new->x = ob->x+8*16;\r
+               new->y = ob->y+8*16;\r
+       }\r
+       else\r
+       {\r
+               new->x = ob->x;\r
+               new->y = ob->y+8*16;\r
+       }\r
+       new->xdir = ob->xdir;\r
+       new->ydir = 1;\r
+       new->xspeed = ob->xdir * PEAXSPEED-(US_RndT()>>4);\r
+       new->yspeed = PEAYSPEED;\r
+       NewState (new,&s_peabrainfly);\r
+}\r
+\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= PeaPodThink\r
+=\r
+====================\r
+*/\r
+\r
+void PeaPodThink (objtype *ob)\r
+{\r
+       int delta;\r
+\r
+       if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
+               return;\r
+\r
+       if (player->x < ob->x && ob->xdir == 1)\r
+               return;\r
+\r
+       if (player->x > ob->x && ob->xdir == -1)\r
+               return;\r
+\r
+       if (US_RndT()<8 && ob->temp1 < MAXPEASPIT)\r
+       {\r
+               ob->temp1 ++;\r
+               ob->state = &s_peapodspit1;\r
+               ob->xmove = 0;\r
+       }\r
+}\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       BOOBUS TUBOR\r
+\r
+temp4 = hit points\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define PREFRAGTHINK   60\r
+#define POSTFRAGTHINK  60\r
+\r
+#define SPDBOOBUSJUMP  60\r
+#define SPDBOOBUSRUNJUMP 24\r
+\r
+void BoobusThink (objtype *ob);\r
+void FinishThink (objtype *ob);\r
+void FragThink (objtype *ob);\r
+void BoobusGroundReact (objtype *ob);\r
+void BoobusAirReact (objtype *ob);\r
+\r
+extern statetype s_boobuswalk1;\r
+extern statetype s_boobuswalk2;\r
+extern statetype s_boobuswalk3;\r
+extern statetype s_boobuswalk4;\r
+\r
+extern statetype s_boobusjump;\r
+\r
+extern statetype s_deathwait1;\r
+extern statetype s_deathwait2;\r
+extern statetype s_deathwait3;\r
+extern statetype s_deathboom1;\r
+extern statetype s_deathboom2;\r
+extern statetype s_deathboom3;\r
+extern statetype s_deathboom4;\r
+extern statetype s_deathboom5;\r
+extern statetype s_deathboom6;\r
+\r
+#pragma warn -sus\r
+\r
+statetype s_boobuswalk1        = {BOOBUSWALKL1SPR,BOOBUSWALKR1SPR,step,false,\r
+       true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk2};\r
+statetype s_boobuswalk2        = {BOOBUSWALKL2SPR,BOOBUSWALKR2SPR,step,false,\r
+       true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk3};\r
+statetype s_boobuswalk3        = {BOOBUSWALKL3SPR,BOOBUSWALKR3SPR,step,false,\r
+       true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk4};\r
+statetype s_boobuswalk4        = {BOOBUSWALKL4SPR,BOOBUSWALKR4SPR,step,false,\r
+       true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk1};\r
+\r
+statetype s_boobusjump = {BOOBUSJUMPSPR,BOOBUSJUMPSPR,think,false,\r
+       false,0, 0,0, ProjectileThink, NULL, BoobusAirReact, NULL};\r
+\r
+statetype s_boobusdie  = {BOOBUSJUMPSPR,BOOBUSJUMPSPR,step,false,\r
+       false,4, 0,0, FragThink, NULL, DrawReact, &s_boobusdie};\r
+statetype s_boobusdie2 = {NULL,NULL,step,false,\r
+       false,4, 0,0, FragThink, NULL, NULL, &s_boobusdie2};\r
+statetype s_boobusdie3 = {NULL,NULL,step,false,\r
+       false,250, 0,0, FinishThink, NULL, NULL, NULL};\r
+\r
+statetype s_deathboom1 = {BOOBUSBOOM1SPR,BOOBUSBOOM1SPR,step,false,\r
+       false,20, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom2};\r
+statetype s_deathboom2 = {BOOBUSBOOM2SPR,BOOBUSBOOM2SPR,step,false,\r
+       false,20, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom3};\r
+statetype s_deathboom3 = {POOF1SPR,POOF1SPR,step,false,\r
+       false,40, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom4};\r
+statetype s_deathboom4 = {POOF2SPR,POOF2SPR,step,false,\r
+       false,30, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom5};\r
+statetype s_deathboom5 = {POOF3SPR,POOF3SPR,step,false,\r
+       false,30, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom6};\r
+statetype s_deathboom6 = {POOF4SPR,POOF4SPR,step,false,\r
+       false,30, 0,0, ProjectileThink, NULL, DrawReact3, NULL};\r
+\r
+\r
+#pragma warn +sus\r
+\r
+/*\r
+====================\r
+=\r
+= SpawnBoobus\r
+=\r
+====================\r
+*/\r
+\r
+void SpawnBoobus (int tilex, int tiley)\r
+{\r
+       GetNewObj (false);\r
+\r
+       new->obclass = boobusobj;\r
+       new->x = tilex<<G_T_SHIFT;\r
+       new->y = (tiley<<G_T_SHIFT)-11*BLOCKSIZE;\r
+       new->xdir = -1;\r
+       NewState (new,&s_boobuswalk1);\r
+       new->temp4 = 12;                        // hit points\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= FragThink\r
+=\r
+===================\r
+*/\r
+\r
+void FragThink (objtype *ob)\r
+{\r
+       if (++ob->temp1 == PREFRAGTHINK)\r
+               ob->state = &s_boobusdie2;\r
+       if (++ob->temp1 == POSTFRAGTHINK)\r
+       {\r
+               RF_RemoveSprite (&ob->sprite);\r
+               ob->state = &s_boobusdie3;\r
+       }\r
+\r
+       SD_PlaySound (BOMBBOOMSND);\r
+       GetNewObj (true);\r
+       new->x = ob->x-BLOCKSIZE + 5*US_RndT();\r
+       new->y = ob->y-BLOCKSIZE + 5*US_RndT();\r
+       new->xspeed = 0; //US_RndT()/4-32;\r
+       new->yspeed = 0; //US_RndT()/4-32;\r
+       US_RndT();                                      // keep rnd from even wrapping\r
+       ChangeState (new,&s_deathboom1);\r
+}\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= FinishThink\r
+=\r
+===================\r
+*/\r
+\r
+void FinishThink (objtype *ob)\r
+{\r
+       playstate = victorious;\r
+       ob++;\r
+       SD_PlaySound (BOOBUSGONESND);\r
+}\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= BoobusThink\r
+=\r
+====================\r
+*/\r
+\r
+void BoobusThink (objtype *ob)\r
+{\r
+       unsigned        move;\r
+       boolean inline = false;\r
+\r
+       if (ob->left > player->right)\r
+               ob->xdir = -1;\r
+       else if (ob->right < player->left)\r
+               ob->xdir = 1;\r
+       else\r
+               inline = true;\r
+\r
+       if (player->top < ob->bottom && player->bottom > ob->top)\r
+       {\r
+       // on same level as player, so charge!\r
+\r
+       }\r
+       else\r
+       {\r
+       // above or below player, so get directly in line and jump\r
+               if (inline)\r
+               {\r
+                       if (ob->y < player->y)\r
+                       {\r
+                       // drop down\r
+                               move = PIXGLOBAL*8;\r
+                               ob->tilebottom++;\r
+                               ob->bottom += move;\r
+                               ob->y += move;\r
+                               ob->state = &s_boobusjump;\r
+                               ob->yspeed = ob->xmove = ob->xspeed = ob->ymove = 0;\r
+                       }\r
+                       else\r
+                       {\r
+                       // jump up\r
+                               ob->state = &s_boobusjump;\r
+                               ob->yspeed = -SPDBOOBUSJUMP;\r
+                               ob->xspeed = 0;\r
+                       }\r
+\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= BoobusGroundReact\r
+=\r
+====================\r
+*/\r
+\r
+void BoobusGroundReact (objtype *ob)\r
+{\r
+       if (ob->xdir == 1 && ob->hitwest)\r
+       {\r
+               ob->x -= ob->xmove;\r
+               ob->xdir = -1;\r
+               ob->nothink = US_RndT()>>5;\r
+               ChangeState (ob,ob->state);\r
+       }\r
+       else if (ob->xdir == -1 && ob->hiteast)\r
+       {\r
+               ob->x -= ob->xmove;\r
+               ob->xdir = 1;\r
+               ob->nothink = US_RndT()>>5;\r
+               ChangeState (ob,ob->state);\r
+       }\r
+       else if (!ob->hitnorth)\r
+       {\r
+               if (ob->bottom >= player->bottom)\r
+               {\r
+                // jump over\r
+                       ob->x -= ob->xmove;\r
+                       ob->y -= ob->ymove;\r
+                       ob->yspeed = -SPDBOOBUSJUMP;\r
+                       ob->xspeed = ob->xdir * SPDBOOBUSRUNJUMP;\r
+               }\r
+               else\r
+               {\r
+               // drop down\r
+                       ob->xspeed = ob->yspeed = 0;\r
+               }\r
+               ChangeState (ob,&s_boobusjump);\r
+       }\r
+\r
+       PLACESPRITE;\r
+}\r
+\r
+\r
+\r
+/*\r
+====================\r
+=\r
+= BoobusAirReact\r
+=\r
+====================\r
+*/\r
+\r
+void BoobusAirReact (objtype *ob)\r
+{\r
+       if (ob->hitsouth)\r
+               ob->yspeed = 0;\r
+\r
+       if (ob->hitnorth)\r
+               ChangeState (ob,&s_boobuswalk1);\r
+\r
+       PLACESPRITE;\r
+}\r