--- /dev/null
+/* 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