1 /* Reconstructed Commander Keen 4-6 Source Code
\r
2 * Copyright (C) 2021 K1n9_Duk3
\r
4 * This file is loosely based on:
\r
5 * Keen Dreams Source Code
\r
6 * Copyright (C) 2014 Javier M. Chavez
\r
8 * This program is free software; you can redistribute it and/or modify
\r
9 * it under the terms of the GNU General Public License as published by
\r
10 * the Free Software Foundation; either version 2 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU General Public License along
\r
19 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
27 Contains the following actor types (in this order):
\r
39 =============================================================================
\r
43 temp1 = charge countdown
\r
45 =============================================================================
\r
48 statetype s_sparkywalk1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, false, true, 8, 128, 0, T_Sparky, C_Sparky, R_Sparky, &s_sparkywalk2};
\r
49 statetype s_sparkywalk2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk3};
\r
50 statetype s_sparkywalk3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk4};
\r
51 statetype s_sparkywalk4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk1};
\r
52 statetype s_sparkylook1 = {SPARKYTURN1SPR, SPARKYTURN1SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook2};
\r
53 statetype s_sparkylook2 = {SPARKYTURN2SPR, SPARKYTURN2SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook3};
\r
54 statetype s_sparkylook3 = {SPARKYTURN3SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook4};
\r
55 statetype s_sparkylook4 = {SPARKYWALKR1SPR, SPARKYWALKR1SPR, step, false, true, 6, 0, 0, T_SparkyLookL, C_Sparky, R_Sparky, &s_sparkylook5};
\r
56 statetype s_sparkylook5 = {SPARKYTURN3SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook6};
\r
57 statetype s_sparkylook6 = {SPARKYTURN2SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook7};
\r
58 statetype s_sparkylook7 = {SPARKYTURN1SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook8};
\r
59 statetype s_sparkylook8 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, false, true, 6, 0, 0, T_SparkyLookR, C_Sparky, R_Sparky, &s_sparkywalk2};
\r
60 statetype s_sparkyspeed1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed2};
\r
61 statetype s_sparkyspeed2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed3};
\r
62 statetype s_sparkyspeed3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed4};
\r
63 statetype s_sparkyspeed4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, true, true, 4, 0, 0, T_ChargeCount, C_Sparky, R_Sparky, &s_sparkyspeed1};
\r
64 statetype s_sparkycharge1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, true, true, 4, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkycharge2};
\r
65 statetype s_sparkycharge2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, true, true, 4, 128, 0, T_RunSnd1, C_Sparky, R_Sparky, &s_sparkycharge3};
\r
66 statetype s_sparkycharge3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, true, true, 4, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkycharge4};
\r
67 statetype s_sparkycharge4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, true, true, 4, 128, 0, T_RunSnd2, C_Sparky, R_Sparky, &s_sparkycharge1};
\r
68 statetype s_sparkyturn1 = {SPARKYTURN3SPR, SPARKYTURN1SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkyturn2};
\r
69 statetype s_sparkyturn2 = {SPARKYTURN2SPR, SPARKYTURN2SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkyturn3};
\r
70 statetype s_sparkyturn3 = {SPARKYTURN1SPR, SPARKYTURN3SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkywalk1};
\r
71 statetype s_sparkystun = {SPARKYSTUNSPR, SPARKYSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};
\r
74 ===========================
\r
78 ===========================
\r
81 void SpawnSparky(Uint16 tileX, Uint16 tileY)
\r
84 new->obclass = sparkyobj;
\r
85 new->active = ac_yes;
\r
87 new->x = CONVERT_TILE_TO_GLOBAL(tileX);
\r
88 new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;
\r
89 if (US_RndT() < 0x80)
\r
98 NewState(new, &s_sparkywalk1);
\r
102 ===========================
\r
106 ===========================
\r
109 void T_Sparky(objtype *ob)
\r
111 if (US_RndT() < 0x40)
\r
113 ob->state = &s_sparkylook1;
\r
119 ===========================
\r
123 ===========================
\r
126 void T_ChargeCount(objtype *ob)
\r
128 if (--ob->temp1 == 0)
\r
129 ob->state = &s_sparkycharge1;
\r
133 ===========================
\r
137 ===========================
\r
140 void T_SparkyLookL(objtype *ob)
\r
142 Uint16 dist = player->bottom + TILEGLOBAL - ob->bottom;
\r
143 if (dist > 2*TILEGLOBAL)
\r
146 if (player->x < ob->x)
\r
149 SD_PlaySound(SND_SPARKYCHARGE);
\r
150 ob->state = &s_sparkyspeed1;
\r
156 ===========================
\r
160 ===========================
\r
163 void T_SparkyLookR(objtype *ob)
\r
165 Uint16 dist = player->bottom + TILEGLOBAL - ob->bottom;
\r
166 if (dist > 2*TILEGLOBAL)
\r
169 if (player->x > ob->x)
\r
172 SD_PlaySound(SND_SPARKYCHARGE);
\r
173 ob->state = &s_sparkyspeed1;
\r
179 ===========================
\r
183 ===========================
\r
187 void T_RunSnd1(objtype *ob)
\r
189 SD_PlaySound(SND_WORLDWALK1);
\r
193 ===========================
\r
197 ===========================
\r
201 void T_RunSnd2(objtype *ob)
\r
203 SD_PlaySound(SND_WORLDWALK1);
\r
207 ===========================
\r
211 ===========================
\r
214 void C_Sparky(objtype *ob, objtype *hit)
\r
216 if (hit->obclass == keenobj)
\r
220 else if (hit->obclass == stunshotobj)
\r
222 StunObj(ob, hit, &s_sparkystun);
\r
227 ===========================
\r
231 ===========================
\r
234 void R_Sparky(objtype *ob)
\r
236 if (ob->xdir == 1 && ob->hitwest)
\r
238 ob->x -= ob->xmove;
\r
240 ob->nothink = US_RndT() >> 5;
\r
241 ChangeState(ob, &s_sparkyturn1);
\r
243 else if (ob->xdir == -1 && ob->hiteast)
\r
245 ob->x -= ob->xmove;
\r
247 ob->nothink = US_RndT() >> 5;
\r
248 ChangeState(ob, &s_sparkyturn1);
\r
250 else if (!ob->hitnorth)
\r
252 ob->x -= ob->xmove;
\r
253 ob->xdir = -ob->xdir;
\r
254 ob->nothink = US_RndT() >> 5;
\r
255 ChangeState(ob, &s_sparkyturn1);
\r
257 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
261 =============================================================================
\r
265 =============================================================================
\r
268 statetype s_amptonwalk1 = {AMTONWALKL1SPR, AMPTONWALKR1SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk2};
\r
269 statetype s_amptonwalk2 = {AMTONWALKL2SPR, AMPTONWALKR2SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk3};
\r
270 statetype s_amptonwalk3 = {AMTONWALKL3SPR, AMPTONWALKR3SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk4};
\r
271 statetype s_amptonwalk4 = {AMTONWALKL4SPR, AMPTONWALKR4SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk1};
\r
272 statetype s_amptonturn = {AMPTONFACESPR, AMPTONFACESPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonwalk1};
\r
273 statetype s_amptongrab1 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptongrab2};
\r
274 statetype s_amptongrab2 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonclimb};
\r
275 statetype s_amptonclimb = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, slidethink, false, false, 0, 0, 32, T_AmptonClimb, C_Ampton, R_Draw, NULL};
\r
276 statetype s_amptonrelease1 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, false, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonrelease2};
\r
277 statetype s_amptonrelease2 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, false, 8, 0, 0, T_SetNoThink, C_Ampton, R_Draw, &s_amptonwalk1};
\r
278 statetype s_amptonfiddle1 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle2};
\r
279 statetype s_amptonfiddle2 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle3};
\r
280 statetype s_amptonfiddle3 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle4};
\r
281 statetype s_amptonfiddle4 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle5};
\r
282 statetype s_amptonfiddle5 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, T_SetNoThink, C_Ampton, R_Draw, &s_amptonwalk1};
\r
283 statetype s_amptonstun = {AMPTONSTUNSPR, AMPTONSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};
\r
286 ===========================
\r
290 ===========================
\r
293 void SpawnAmpton(Uint16 tileX, Uint16 tileY)
\r
296 new->obclass = amptonobj;
\r
297 new->active = ac_yes;
\r
299 new->x = CONVERT_TILE_TO_GLOBAL(tileX);
\r
300 new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;
\r
301 if (US_RndT() < 0x80)
\r
310 NewState(new, &s_amptonwalk1);
\r
314 ===========================
\r
318 ===========================
\r
321 void T_Ampton(objtype *ob)
\r
324 Uint16 intile, var8;
\r
325 boolean poleup, poledown;
\r
327 if (ob->state == &s_amptonwalk1)
\r
329 SD_PlaySound(SND_AMPTONWALK1);
\r
331 else if (ob->state == &s_amptonwalk3)
\r
333 SD_PlaySound(SND_AMPTONWALK2);
\r
337 map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft + 1;
\r
338 intile = tinf[*map + INTILE] & INTILE_TYPEMASK;
\r
339 if (intile == INTILE_AMPTONCOMPUTER)
\r
341 ob->state = &s_amptonfiddle1;
\r
343 else if (intile == INTILE_POLE && US_RndT() < 196)
\r
345 if ((tinf[*(map + mapwidth*2) + INTILE] & INTILE_TYPEMASK) == INTILE_POLE)
\r
353 if ((tinf[*(map - mapwidth*2) + INTILE] & INTILE_TYPEMASK) == INTILE_POLE)
\r
361 if (poleup && poledown)
\r
363 if (US_RndT() < 0x80)
\r
372 ob->state = &s_amptongrab1;
\r
373 ob->needtoclip = cl_noclip;
\r
380 ob->state = &s_amptongrab1;
\r
381 ob->needtoclip = cl_noclip;
\r
390 ===========================
\r
394 ===========================
\r
397 void T_AmptonClimb(objtype *ob)
\r
403 newtile = CONVERT_GLOBAL_TO_TILE(ob->bottom + ytry);
\r
404 if (ob->tilebottom != newtile)
\r
406 if (ob->ydir == -1)
\r
408 map = mapsegs[1] + mapbwidthtable[newtile]/2 + ob->tileleft + 1;
\r
409 if (!tinf[map[0] + NORTHWALL] && tinf[map[mapwidth]+NORTHWALL])
\r
411 if ((tinf[*(map-4*mapwidth)+INTILE] & INTILE_TYPEMASK) == INTILE_POLE && US_RndT() < 0x80)
\r
414 move = (ob->bottom & 0xFF) + 1;
\r
416 ob->bottom -= move;
\r
417 ob->needtoclip = cl_midclip;
\r
418 ob->state = &s_amptonrelease1;
\r
425 if ((tinf[*(map-mapwidth)+INTILE] & INTILE_TYPEMASK) != INTILE_POLE)
\r
433 map = mapsegs[1] + mapbwidthtable[newtile]/2 + ob->tileleft + 1;
\r
434 if (tinf[map[0] + NORTHWALL] && !tinf[*(map-mapwidth)+NORTHWALL])
\r
436 if ((tinf[map[2*mapwidth] + INTILE] & INTILE_TYPEMASK) == INTILE_POLE && US_RndT() < 0x80)
\r
439 move = 0xFF - (ob->bottom & 0xFF);
\r
441 ob->bottom += move;
\r
442 ob->needtoclip = cl_midclip;
\r
443 ob->state = &s_amptonrelease1;
\r
449 if ((tinf[map[0] + INTILE] & INTILE_TYPEMASK) != INTILE_POLE)
\r
459 ===========================
\r
463 ===========================
\r
466 void T_SetNoThink(objtype *ob)
\r
472 ===========================
\r
476 ===========================
\r
479 void C_Ampton(objtype *ob, objtype *hit)
\r
481 if (hit->obclass == keenobj)
\r
483 if (ob->state == &s_amptonclimb)
\r
489 ClipToSpriteSide(hit, ob);
\r
492 else if (hit->obclass == stunshotobj)
\r
494 ob->needtoclip = cl_midclip;
\r
497 SD_PlaySound(SND_AMPTONDIE);
\r
498 StunObj(ob, hit, &s_amptonstun);
\r
503 ===========================
\r
507 ===========================
\r
510 void R_Ampton(objtype *ob)
\r
512 if (ob->xdir == 1 && ob->hitwest)
\r
514 ob->x -= ob->xmove;
\r
516 ChangeState(ob, &s_amptonturn);
\r
518 else if (ob->xdir == -1 && ob->hiteast)
\r
520 ob->x -= ob->xmove;
\r
522 ChangeState(ob, &s_amptonturn);
\r
524 else if (!ob->hitnorth)
\r
526 ob->x -= ob->xmove;
\r
527 ob->xdir = -ob->xdir;
\r
528 ChangeState(ob, &s_amptonturn);
\r
530 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
534 =============================================================================
\r
540 =============================================================================
\r
543 statetype s_slicestarslide = {SLICESTARSPR, SLICESTARSPR, think, false, false, 0, 0, 0, T_Platform, C_Slicestar, R_Draw, NULL};
\r
544 statetype s_slicestarbounce = {SLICESTARSPR, SLICESTARSPR, slide, false, false, 0, 24, 24, NULL, C_Slicestar, R_Slicestar, &s_slicestarbounce};
\r
545 statetype s_slicestarboom = {SLICESTARBOOMSPR, SLICESTARBOOMSPR, step, false, false, 20, 0, 0, NULL, NULL, R_Draw, NULL};
\r
548 ===========================
\r
550 = SpawnSlicestarSlide
\r
552 ===========================
\r
555 void SpawnSlicestarSlide(Uint16 tileX, Uint16 tileY, Sint16 dir)
\r
558 new->obclass = slicestarobj;
\r
559 new->active = ac_yes;
\r
561 new->x = CONVERT_TILE_TO_GLOBAL(tileX);
\r
562 new->y = CONVERT_TILE_TO_GLOBAL(tileY);
\r
563 new->temp4 = 20; // health!
\r
582 NewState(new, &s_slicestarslide);
\r
586 ===========================
\r
588 = SpawnSlicestarBounce
\r
590 ===========================
\r
593 void SpawnSlicestarBounce(Uint16 tileX, Uint16 tileY)
\r
596 new->obclass = slicestarobj;
\r
597 new->active = ac_yes;
\r
599 new->needtoclip = cl_fullclip;
\r
600 new->x = CONVERT_TILE_TO_GLOBAL(tileX);
\r
601 new->y = CONVERT_TILE_TO_GLOBAL(tileY);
\r
602 new->temp4 = 50; // health!
\r
603 switch (US_RndT() / 0x40)
\r
621 NewState(new, &s_slicestarbounce);
\r
625 ===========================
\r
629 ===========================
\r
632 void C_Slicestar(objtype *ob, objtype *hit)
\r
634 if (hit->obclass == keenobj)
\r
638 else if (hit->obclass == stunshotobj)
\r
641 if (--ob->temp4 == 0)
\r
643 ChangeState(ob, &s_slicestarboom);
\r
649 ===========================
\r
653 ===========================
\r
656 void R_Slicestar(objtype *ob)
\r
661 SD_PlaySound(SND_SLICESTARBOUNCE);
\r
663 else if (ob->hitsouth)
\r
666 SD_PlaySound(SND_SLICESTARBOUNCE);
\r
671 SD_PlaySound(SND_SLICESTARBOUNCE);
\r
673 else if (ob->hiteast)
\r
676 SD_PlaySound(SND_SLICESTARBOUNCE);
\r
678 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
682 =============================================================================
\r
686 =============================================================================
\r
689 statetype s_shellywalk1 = {SHELLEYL1SPR, SHELLEYR1SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk2};
\r
690 statetype s_shellywalk2 = {SHELLEYL2SPR, SHELLEYR2SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk3};
\r
691 statetype s_shellywalk3 = {SHELLEYL3SPR, SHELLEYR3SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk4};
\r
692 statetype s_shellywalk4 = {SHELLEYL4SPR, SHELLEYR4SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk1};
\r
693 statetype s_shellylook = {SHELLEYL2SPR, SHELLEYR2SPR, stepthink, false, true, 100, 0, 0, T_ShellyLook, C_Shelly, R_Draw, &s_shellylook2};
\r
694 statetype s_shellylook2 = {SHELLEYL2SPR, SHELLEYR2SPR, step, true, true, 1, 0, 0, T_Turn, C_Shelly, R_Draw, &s_shellywalk1};
\r
695 statetype s_shellyjump1 = {SHELLEYJUMPLSPR, SHELLEYJUMPRSPR, stepthink, false, false, 8, 0, 0, T_Projectile, C_Shelly, R_Shell, &s_shellyjump2};
\r
696 statetype s_shellyjump2 = {SHELLEYFALLLSPR, SHELLEYFALLRSPR, think, false, false, 8, 0, 0, T_Projectile, C_Shelly, R_Shell, NULL};
\r
697 statetype s_shellydie = {SHELLEYFALLLSPR, SHELLEYFALLRSPR, step, false, false, 8, 0, 0, T_ShellyFrag, NULL, R_Shell, NULL};
\r
698 statetype s_shellydieup = {SHELLEYL2SPR, SHELLEYR2SPR, step, false, false, 8, 0, 0, T_ShellyFrag, NULL, R_Shell, NULL};
\r
699 statetype s_shellyboom1 = {SHELLEYBOOM1SPR, SHELLEYBOOM1SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom2};
\r
700 statetype s_shellyboom2 = {SHELLEYBOOM2SPR, SHELLEYBOOM2SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom3};
\r
701 statetype s_shellyboom3 = {SHELLEYBOOM3SPR, SHELLEYBOOM3SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom4};
\r
702 statetype s_shellyboom4 = {SHELLEYBOOM4SPR, SHELLEYBOOM4SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, NULL};
\r
703 statetype s_shellypiece1 = {SHELLEYPIECE1SPR, SHELLEYPIECE1SPR, think, false, false, 8, 0, 0, T_Projectile, C_Lethal, R_Bounce, NULL};
\r
704 statetype s_shellypiece2 = {SHELLEYPIECE2SPR, SHELLEYPIECE2SPR, think, false, false, 8, 0, 0, T_Projectile, C_Lethal, R_Bounce, NULL};
\r
707 ===========================
\r
711 ===========================
\r
714 void SpawnShelly(Uint16 tileX, Uint16 tileY)
\r
717 new->obclass = sparkyobj; // BUG: should use shelleyobj
\r
718 new->active = ac_yes;
\r
720 new->x = CONVERT_TILE_TO_GLOBAL(tileX);
\r
721 new->y = CONVERT_TILE_TO_GLOBAL(tileY);
\r
722 if (US_RndT() < 0x80)
\r
731 NewState(new, &s_shellywalk1);
\r
735 ===========================
\r
739 ===========================
\r
742 void T_ShellyLook(objtype *ob)
\r
746 if (player->top < ob->bottom)
\r
749 xdist = player->midx - ob->midx;
\r
752 if (xdist > 1*TILEGLOBAL && xdist < 3*TILEGLOBAL)
\r
756 ob->state = &s_shellyjump1;
\r
762 if (xdist < -1*TILEGLOBAL && xdist > -3*TILEGLOBAL)
\r
766 ob->state = &s_shellyjump1;
\r
773 ===========================
\r
777 ===========================
\r
780 void T_Turn(objtype *ob)
\r
782 ob->xdir = -ob->xdir;
\r
786 ===========================
\r
790 ===========================
\r
793 void T_ShellyFrag(objtype *ob)
\r
800 NewState(new, &s_shellypiece1);
\r
807 NewState(new, &s_shellypiece2);
\r
811 ===========================
\r
815 ===========================
\r
818 void C_Shelly(objtype *ob, objtype *hit)
\r
820 if (hit->obclass == keenobj)
\r
822 ClipToSpriteSide(hit, ob);
\r
823 if (player->midx < ob->left || player->midx > ob->right)
\r
826 else if (hit->obclass == stunshotobj)
\r
830 else if (hit->obclass == mshotobj)
\r
838 SD_PlaySound(SND_SHELLEYEXPLODE);
\r
841 ChangeState(ob, &s_shellydieup);
\r
845 ChangeState(ob, &s_shellydie);
\r
850 NewState(new, &s_shellyboom1);
\r
854 ===========================
\r
858 ===========================
\r
861 void R_Shelly(objtype *ob)
\r
863 if (ob->xdir == 1 && ob->hitwest)
\r
865 ob->x -= ob->xmove;
\r
868 else if (ob->xdir == -1 && ob->hiteast)
\r
870 ob->x -= ob->xmove;
\r
873 else if (!ob->hitnorth)
\r
875 ob->x -= ob->xmove;
\r
876 ChangeState(ob, &s_shellylook);
\r
878 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r
882 ===========================
\r
886 ===========================
\r
889 void R_Shell(objtype *ob)
\r
891 if (ob->hiteast || ob->hitwest)
\r
897 SD_PlaySound(SND_SHELLEYEXPLODE);
\r
898 ChangeState(ob, &s_shellydie);
\r
903 NewState(new, &s_shellyboom1);
\r
905 RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);
\r