]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/KEEN4/K4_ACT1.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / KEEN4 / K4_ACT1.C
1 /* Reconstructed Commander Keen 4-6 Source Code\r
2  * Copyright (C) 2021 K1n9_Duk3\r
3  *\r
4  * This file is loosely based on:\r
5  * Keen Dreams Source Code\r
6  * Copyright (C) 2014 Javier M. Chavez\r
7  *\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
12  *\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
17  *\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
21  */\r
22 \r
23 /*\r
24 K4_ACT1.C\r
25 =========\r
26 \r
27 Contains the following actor types (in this order):\r
28 \r
29 - Miragia (world map)\r
30 - Bonus Items\r
31 - Council Member\r
32 - Poison Slug\r
33 - Mad Mushroom\r
34 - Egg & Eggbird\r
35 - Arachnut\r
36 - Skypest\r
37 \r
38 */\r
39 \r
40 #include "CK_DEF.H"\r
41 \r
42 /*\r
43 =============================================================================\r
44 \r
45                                                   MIRAGIA\r
46 \r
47 =============================================================================\r
48 */\r
49 \r
50 statetype s_miragia0 = {0, 0, step, false, false, 300, 0, 0, T_Miragia0, NULL, NULL, &s_miragia1};\r
51 statetype s_miragia1 = {0, 0, step, false, false,  30, 0, 0, T_Miragia1, NULL, NULL, &s_miragia2};\r
52 statetype s_miragia2 = {0, 0, step, false, false,  30, 0, 0, T_Miragia2, NULL, NULL, &s_miragia3};\r
53 statetype s_miragia3 = {0, 0, step, false, false,  30, 0, 0, T_Miragia3, NULL, NULL, &s_miragia4};\r
54 statetype s_miragia4 = {0, 0, step, false, false, 300, 0, 0, T_Miragia4, NULL, NULL, &s_miragia5};\r
55 statetype s_miragia5 = {0, 0, step, false, false,  30, 0, 0, T_Miragia5, NULL, NULL, &s_miragia6};\r
56 statetype s_miragia6 = {0, 0, step, false, false,  30, 0, 0, T_Miragia6, NULL, NULL, &s_miragia7};\r
57 statetype s_miragia7 = {0, 0, step, false, false,  30, 0, 0, T_Miragia7, NULL, NULL, &s_miragia0};\r
58 \r
59 /*\r
60 ===========================\r
61 =\r
62 = SpawnMiragia\r
63 =\r
64 ===========================\r
65 */\r
66 \r
67 void SpawnMiragia(Sint16 x, Sint16 y)\r
68 {\r
69         GetNewObj(false);\r
70         new->obclass = inertobj;\r
71         new->active = ac_allways;\r
72         new->x = x;\r
73         new->y = y;\r
74         new->state = &s_miragia0;\r
75 }\r
76 \r
77 /*\r
78 ===========================\r
79 =\r
80 = T_Miragia0\r
81 =\r
82 ===========================\r
83 */\r
84 \r
85 void T_Miragia0(objtype *ob)\r
86 {\r
87         if (player->tileright >= ob->x && player->tileleft <= ob->x+5\r
88                 && player->tiletop >= ob->y && player->tilebottom <= ob->y+4)\r
89         {\r
90                 //don't let miragia appear if player is in the area, so player won't get stuck\r
91                 ob->state = &s_miragia7;\r
92         }\r
93         else\r
94         {\r
95                 RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);\r
96         }\r
97 }\r
98 \r
99 /*\r
100 ===========================\r
101 =\r
102 = T_Miragia1\r
103 =\r
104 ===========================\r
105 */\r
106 \r
107 void T_Miragia1(objtype *ob)\r
108 {\r
109         RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);\r
110 }\r
111 \r
112 /*\r
113 ===========================\r
114 =\r
115 = T_Miragia2\r
116 =\r
117 ===========================\r
118 */\r
119 \r
120 void T_Miragia2(objtype *ob)\r
121 {\r
122         RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);\r
123 }\r
124 \r
125 /*\r
126 ===========================\r
127 =\r
128 = T_Miragia3\r
129 =\r
130 ===========================\r
131 */\r
132 \r
133 void T_Miragia3(objtype *ob)\r
134 {\r
135         RF_MapToMap(26, 60, ob->x, ob->y, 6, 4);\r
136 }\r
137 \r
138 /*\r
139 ===========================\r
140 =\r
141 = T_Miragia4\r
142 =\r
143 ===========================\r
144 */\r
145 \r
146 void T_Miragia4(objtype *ob)\r
147 {\r
148         RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);\r
149 }\r
150 \r
151 /*\r
152 ===========================\r
153 =\r
154 = T_Miragia5\r
155 =\r
156 ===========================\r
157 */\r
158 \r
159 void T_Miragia5(objtype *ob)\r
160 {\r
161         RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);\r
162 }\r
163 \r
164 /*\r
165 ===========================\r
166 =\r
167 = T_Miragia6\r
168 =\r
169 ===========================\r
170 */\r
171 \r
172 void T_Miragia6(objtype *ob)\r
173 {\r
174         RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);\r
175 }\r
176 \r
177 /*\r
178 ===========================\r
179 =\r
180 = T_Miragia7\r
181 =\r
182 ===========================\r
183 */\r
184 \r
185 void T_Miragia7(objtype *ob)\r
186 {\r
187         RF_MapToMap(2, 60, ob->x, ob->y, 6, 4);\r
188 }\r
189 \r
190 /*\r
191 =============================================================================\r
192 \r
193                                                   BONUS ITEMS\r
194 \r
195 temp1 = bonus type\r
196 temp2 = base shape number\r
197 temp3 = last animated shape number +1\r
198 \r
199 =============================================================================\r
200 */\r
201 \r
202 statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2};\r
203 statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1};\r
204 statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL};\r
205 \r
206 statetype s_splash1 = {DROPSPLASH1SPR, DROPSPLASH1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash2};\r
207 statetype s_splash2 = {DROPSPLASH2SPR, DROPSPLASH2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash3};\r
208 statetype s_splash3 = {DROPSPLASH3SPR, DROPSPLASH3SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
209 \r
210 Uint16 bonusshape[] = {REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR, SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR, SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR, ONEUPASPR, STUNCLIP1SPR};\r
211 \r
212 /*\r
213 ===========================\r
214 =\r
215 = SpawnBonus\r
216 =\r
217 ===========================\r
218 */\r
219 \r
220 void SpawnBonus(Sint16 x, Sint16 y, Sint16 type)\r
221 {\r
222         GetNewObj(false);\r
223         new->needtoclip = cl_noclip;\r
224         new->priority = 2;\r
225         new->obclass = bonusobj;\r
226         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
227         new->y = CONVERT_TILE_TO_GLOBAL(y);\r
228         new->ydir = -1;\r
229         new->temp1 = type;\r
230         new->temp2 = new->shapenum = bonusshape[type];\r
231         new->temp3 = new->temp2 + 2;\r
232         NewState(new, &s_bonus1);\r
233 }\r
234 \r
235 /*\r
236 ===========================\r
237 =\r
238 = SpawnSplash\r
239 =\r
240 ===========================\r
241 */\r
242 \r
243 void SpawnSplash(Sint16 x, Sint16 y)\r
244 {\r
245         GetNewObj(true);\r
246         new->needtoclip = cl_noclip;\r
247         new->priority = 3;\r
248         new->obclass = inertobj;\r
249         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
250         new->y = CONVERT_TILE_TO_GLOBAL(y);\r
251         NewState(new, &s_splash1);\r
252 }\r
253 \r
254 /*\r
255 ===========================\r
256 =\r
257 = T_Bonus\r
258 =\r
259 ===========================\r
260 */\r
261 \r
262 void T_Bonus(objtype *ob)\r
263 {\r
264         ob->shapenum++;\r
265         if (ob->shapenum == ob->temp3)\r
266                 ob->shapenum = ob->temp2;\r
267 }\r
268 \r
269 /*\r
270 =============================================================================\r
271 \r
272                                                   COUNCIL MEMBER\r
273 \r
274 =============================================================================\r
275 */\r
276 \r
277 statetype s_councilwalk1 = {COUNCILWALKL1SPR, COUNCILWALKR1SPR, step, false, true,   10,  64, 0, T_Council, NULL, R_Walk, &s_councilwalk2};\r
278 statetype s_councilwalk2 = {COUNCILWALKL2SPR, COUNCILWALKR2SPR, step, false, true,   10,  64, 0, T_Council, NULL, R_Walk, &s_councilwalk1};\r
279 statetype s_councilstand = {COUNCILTHINKLSPR, COUNCILTHINKRSPR, step, false, false, 120, 128, 0, NULL, NULL, R_Draw, &s_councilwalk1};\r
280 \r
281 /*\r
282 ===========================\r
283 =\r
284 = SpawnCouncil\r
285 =\r
286 ===========================\r
287 */\r
288 \r
289 void SpawnCouncil(Sint16 x, Sint16 y)\r
290 {\r
291         GetNewObj(false);\r
292         new->obclass = oracleobj;\r
293         new->active = ac_yes;\r
294         new->priority = 0;\r
295         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
296         new->y = CONVERT_TILE_TO_GLOBAL(y) -0x171;      //TODO: wierd\r
297         if (US_RndT() < 0x80)\r
298         {\r
299                 new->xdir = 1;\r
300         }\r
301         else\r
302         {\r
303                 new->xdir = -1;\r
304         }\r
305         new->ydir = 1;\r
306         NewState(new, &s_councilwalk1);\r
307 }\r
308 \r
309 /*\r
310 ===========================\r
311 =\r
312 = T_Council\r
313 =\r
314 ===========================\r
315 */\r
316 \r
317 void T_Council(objtype *ob)\r
318 {\r
319         Uint16 randnum;\r
320 \r
321         randnum = US_RndT();\r
322         if (tics*8 > randnum)\r
323         {\r
324                 // BUG: might be about to move off a ledge, causing it to get stuck\r
325                 // after standing (the stand state doesn't use R_Walk)!\r
326                 // To avoid that, set xtry to 0 here.\r
327                 ob->state = &s_councilstand;\r
328         }\r
329 }\r
330 \r
331 /*\r
332 =============================================================================\r
333 \r
334                                                   POINSON SLUG\r
335 \r
336 =============================================================================\r
337 */\r
338 \r
339 statetype s_slugwalk1   = {SLUGWALKL1SPR,   SLUGWALKR1SPR,   step,  false, true,    8, 64, 0, NULL, C_Slug, R_WalkNormal, &s_slugwalk2};\r
340 statetype s_slugwalk2   = {SLUGWALKL2SPR,   SLUGWALKR2SPR,   step,  false, true,    8, 64, 0, T_Slug, C_Slug, R_WalkNormal, &s_slugwalk1};\r
341 statetype s_slugpiss1   = {SLUGPISSLSPR,    SLUGPISSRSPR,    step,  false, true,   60, 64, 0, T_SlugPiss, C_Slug, R_WalkNormal, &s_slugwalk1};\r
342 statetype s_slugstun    = {SLUGSTUN1SPR,    SLUGSTUN1SPR,    think, false, false,   0,  0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
343 statetype s_slugstunalt = {SLUGSTUN2SPR,    SLUGSTUN2SPR,    think, false, false,   0,  0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
344 statetype s_slugslime   = {SLUGSLIME1SPR,   SLUGSLIME1SPR,   step,  false, false, 300,  0, 0, NULL, C_Lethal, R_Draw, &s_slugslime2};\r
345 statetype s_slugslime2  = {SLUGSLIME2SPR,   SLUGSLIME2SPR,   step,  false, false,  60,  0, 0, NULL, NULL, R_Draw, NULL};\r
346 \r
347 /*\r
348 ===========================\r
349 =\r
350 = SpawnSlug\r
351 =\r
352 ===========================\r
353 */\r
354 \r
355 void SpawnSlug(Sint16 x, Sint16 y)\r
356 {\r
357         GetNewObj(false);\r
358         new->obclass = slugobj;\r
359         new->active = ac_yes;\r
360         new->priority = 2;\r
361         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
362         new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;\r
363         if (US_RndT() < 0x80)\r
364         {\r
365                 new->xdir = 1;\r
366         }\r
367         else\r
368         {\r
369                 new->xdir = -1;\r
370         }\r
371         new->ydir = 1;\r
372         NewState(new, &s_slugwalk1);\r
373 }\r
374 \r
375 /*\r
376 ===========================\r
377 =\r
378 = T_Slug\r
379 =\r
380 ===========================\r
381 */\r
382 \r
383 void T_Slug(objtype *ob)\r
384 {\r
385         if (US_RndT() < 16)\r
386         {\r
387                 if (ob->x < player->x)\r
388                 {\r
389                         ob->xdir = 1;\r
390                 }\r
391                 else\r
392                 {\r
393                         ob->xdir = -1;\r
394                 }\r
395                 ob->state = &s_slugpiss1;\r
396                 SD_PlaySound(SND_SLUGPOO);\r
397                 // Note: might be a good idea to set xtry to 0 here\r
398         }\r
399 }\r
400 \r
401 /*\r
402 ===========================\r
403 =\r
404 = T_SlugPiss\r
405 =\r
406 ===========================\r
407 */\r
408 \r
409 void T_SlugPiss(objtype *ob)\r
410 {\r
411         GetNewObj(true);\r
412         new->obclass = inertobj;\r
413         new->active = ac_removable;\r
414         new->priority = 0;\r
415         new->x = ob->x;\r
416         new->y = ob->bottom - 8*PIXGLOBAL;\r
417         NewState(new, &s_slugslime);\r
418 }\r
419 \r
420 /*\r
421 ===========================\r
422 =\r
423 = C_Slug\r
424 =\r
425 ===========================\r
426 */\r
427 \r
428 void C_Slug(objtype *ob, objtype *hit)\r
429 {\r
430         if (hit->obclass == keenobj)\r
431         {\r
432                 KillKeen();\r
433         }\r
434         else if (hit->obclass == stunshotobj)\r
435         {\r
436                 if (US_RndT() < 0x80)\r
437                 {\r
438                         StunObj(ob, hit, &s_slugstun);\r
439                 }\r
440                 else\r
441                 {\r
442                         StunObj(ob, hit, &s_slugstunalt);\r
443                 }\r
444                 ob->yspeed = -24;\r
445                 ob->xspeed = ob->xdir*8;\r
446         }\r
447 }\r
448 \r
449 /*\r
450 =============================================================================\r
451 \r
452                                                   MAD MUSHROOM\r
453 \r
454 temp1 = jump counter\r
455 \r
456 =============================================================================\r
457 */\r
458 \r
459 statetype s_mushroom1 = {MADMUSHROOML1SPR, MADMUSHROOMR1SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom2};\r
460 statetype s_mushroom2 = {MADMUSHROOML2SPR, MADMUSHROOMR2SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom1};\r
461 \r
462 /*\r
463 ===========================\r
464 =\r
465 = SpawnMadMushroom\r
466 =\r
467 ===========================\r
468 */\r
469 \r
470 void SpawnMadMushroom(Sint16 x, Sint16 y)\r
471 {\r
472         GetNewObj(false);\r
473         new->obclass = madmushroomobj;\r
474         new->active = ac_yes;\r
475         new->priority = 0;\r
476         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
477         new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;\r
478         new->xdir = 1;\r
479         new->ydir = 1;\r
480         NewState(new, &s_mushroom1);\r
481 }\r
482 \r
483 /*\r
484 ===========================\r
485 =\r
486 = T_Mushroom\r
487 =\r
488 ===========================\r
489 */\r
490 \r
491 void T_Mushroom(objtype *ob)\r
492 {\r
493         if (player->x < ob->x)\r
494         {\r
495                 ob->xdir = -1;\r
496         }\r
497         else\r
498         {\r
499                 ob->xdir = 1;\r
500         }\r
501 \r
502         // BUG: this might be executed twice during the same frame if the\r
503         // object's animation/state changed during that frame, causing the\r
504         // object to move at twice the speed during that frame!\r
505         // To avoid that, return if ytry is not 0.\r
506         DoWeakGravity(ob);\r
507 }\r
508 \r
509 /*\r
510 ===========================\r
511 =\r
512 = C_Mushroom\r
513 =\r
514 ===========================\r
515 */\r
516 \r
517 void C_Mushroom(objtype *ob, objtype *hit)\r
518 {\r
519         ob++;                   // shut up compiler\r
520         if (hit->obclass == stunshotobj)\r
521         {\r
522                 ExplodeShot(hit);\r
523         }\r
524         else if (hit->obclass == keenobj)\r
525         {\r
526                 KillKeen();\r
527         }\r
528 }\r
529 \r
530 /*\r
531 ===========================\r
532 =\r
533 = R_Mushroom\r
534 =\r
535 ===========================\r
536 */\r
537 \r
538 void R_Mushroom(objtype *ob)\r
539 {\r
540         if (ob->hitsouth)\r
541                 ob->yspeed = 0;\r
542 \r
543         if (ob->hitnorth)\r
544         {\r
545                 ob->yspeed = 0;\r
546                 if (++ob->temp1 == 3)\r
547                 {\r
548                         ob->temp1 = 0;\r
549                         ob->yspeed = -68;\r
550                         SD_PlaySound(SND_BOUNCE2);\r
551                 }\r
552                 else\r
553                 {\r
554                         SD_PlaySound(SND_BOUNCE1);\r
555                         ob->yspeed = -40;\r
556                 }\r
557         }\r
558         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
559 }\r
560 \r
561 /*\r
562 =============================================================================\r
563 \r
564                                                   EGGBIRD\r
565 \r
566 temp1 = blocked flag for flying eggbird (cannot change xdir to chase Keen\r
567         while this is non-zero)\r
568 \r
569 =============================================================================\r
570 */\r
571 \r
572 statetype s_egg      = {EGGSPR,      EGGSPR,      think, false, true,      8, 0, 0, NULL, C_Egg, R_Draw, NULL};\r
573 statetype s_eggbroke = {EGGBROKESPR, EGGBROKESPR, step,  false, false, 30000, 0, 0, NULL, NULL, R_Draw, NULL};\r
574 statetype s_eggchip1 = {EGGCHIP1SPR, EGGCHIP1SPR, think, false, false,     0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
575 statetype s_eggchip2 = {EGGCHIP2SPR, EGGCHIP2SPR, think, false, false,     0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
576 statetype s_eggchip3 = {EGGCHIP3SPR, EGGCHIP3SPR, think, false, false,     0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
577 \r
578 statetype s_eggbirdpause = {BIRDWALKL1SPR, BIRDWALKR1SPR, step,       false, true,  120, 128, 0, NULL, C_EggbirdStun, R_Eggbird, &s_eggbirdwalk2};\r
579 statetype s_eggbirdwalk1 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step,       false, true,    7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk2};\r
580 statetype s_eggbirdwalk2 = {BIRDWALKL2SPR, BIRDWALKR2SPR, step,       false, true,    7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk3};\r
581 statetype s_eggbirdwalk3 = {BIRDWALKL3SPR, BIRDWALKR3SPR, step,       false, true,    7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk4};\r
582 statetype s_eggbirdwalk4 = {BIRDWALKL4SPR, BIRDWALKR4SPR, step,       false, true,    7, 128, 0, T_Eggbird, C_Eggbird, R_Eggbird, &s_eggbirdwalk1};\r
583 statetype s_eggbirdfly1  = {BIRDFLY1SPR,   BIRDFLY1SPR,   slidethink, false, false,   8,   0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly2};\r
584 statetype s_eggbirdfly2  = {BIRDFLY2SPR,   BIRDFLY2SPR,   slidethink, false, false,   8,   0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly3};\r
585 statetype s_eggbirdfly3  = {BIRDFLY3SPR,   BIRDFLY3SPR,   slidethink, false, false,   8,   0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly4};\r
586 statetype s_eggbirdfly4  = {BIRDFLY4SPR,   BIRDFLY4SPR,   slidethink, false, false,   8,   0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly1};\r
587 statetype s_eggbirddrop  = {BIRDFLY4SPR,   BIRDFLY4SPR,   think,      false, false,   8, 128, 0, T_WeakProjectile, C_Eggbird, R_EggbirdDrop, NULL};\r
588 statetype s_eggbirdstun  = {BIRDSTUNSPR,   BIRDSTUNSPR,   stepthink,  false, false, 240,   0, 0, T_Projectile, C_EggbirdStun, R_Draw, &s_eggbirdstun2};\r
589 statetype s_eggbirdstun2 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step,       false, true,   20,   0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun3};\r
590 statetype s_eggbirdstun3 = {BIRDSTUNSPR,   BIRDSTUNSPR,   step,       false, true,   20,   0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun4};\r
591 statetype s_eggbirdstun4 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step,       false, true,   20,   0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun5};\r
592 statetype s_eggbirdstun5 = {BIRDSTUNSPR,   BIRDSTUNSPR,   step,       false, true,   20,   0, 0, T_EggUnstun, C_EggbirdStun, R_Draw, &s_eggbirdwalk1};\r
593 \r
594 /*\r
595 ===========================\r
596 =\r
597 = SpawnEggbird\r
598 =\r
599 ===========================\r
600 */\r
601 \r
602 void SpawnEggbird(Sint16 x, Sint16 y)\r
603 {\r
604         GetNewObj(false);\r
605         new->obclass = eggobj;\r
606         new->active = ac_yes;\r
607         new->priority = 2;\r
608         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
609         new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;\r
610         new->xdir = 1;\r
611         new->ydir = 1;\r
612         NewState(new, &s_egg);\r
613 }\r
614 \r
615 /*\r
616 ===========================\r
617 =\r
618 = T_EggUnstun\r
619 =\r
620 ===========================\r
621 */\r
622 \r
623 void T_EggUnstun(objtype *ob)\r
624 {\r
625         ob->obclass = eggbirdobj;\r
626 }\r
627 \r
628 /*\r
629 ===========================\r
630 =\r
631 = SpawnEggbirdOut\r
632 =\r
633 ===========================\r
634 */\r
635 \r
636 void SpawnEggbirdOut(Sint16 x, Sint16 y)\r
637 {\r
638         GetNewObj(true);\r
639         new->obclass = eggbirdobj;\r
640         new->active = ac_yes;\r
641         new->priority = 2;\r
642         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
643         new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;\r
644         if (new->x < player->x)\r
645         {\r
646                 new->xdir = 1;\r
647         }\r
648         else\r
649         {\r
650                 new->xdir = -1;\r
651         }\r
652         new->ydir = 1;\r
653         NewState(new, &s_eggbirdpause);\r
654 }\r
655 \r
656 /*\r
657 ===========================\r
658 =\r
659 = C_Egg\r
660 =\r
661 ===========================\r
662 */\r
663 \r
664 void C_Egg(objtype *ob, objtype *hit)\r
665 {\r
666         if (hit->obclass == stunshotobj || hit->obclass == keenobj)\r
667         {\r
668                 if (hit->obclass == stunshotobj)\r
669                         ExplodeShot(hit);\r
670 \r
671                 ob->obclass = inertobj;\r
672                 ob->active = ac_removable;\r
673                 ChangeState(ob, &s_eggbroke);\r
674 \r
675                 GetNewObj(true);\r
676                 new->obclass = eggbirdobj;\r
677                 new->active = ac_yes;\r
678                 new->x = ob->x;\r
679                 new->y = ob->y - 8*PIXGLOBAL;\r
680                 if (ob->x < player->x)\r
681                 {\r
682                         new->xdir = 1;\r
683                 }\r
684                 else\r
685                 {\r
686                         new->xdir = -1;\r
687                 }\r
688                 new->ydir = 1;\r
689                 NewState(new, &s_eggbirdpause);\r
690 \r
691                 GetNewObj(true);\r
692                 new->obclass = inertobj;\r
693                 new->active = ac_removable;\r
694                 new->x = ob->x;\r
695                 new->y = ob->y;\r
696                 new->xspeed = -28;\r
697                 new->yspeed = -40;\r
698                 NewState(new, &s_eggchip1);\r
699 \r
700                 GetNewObj(true);\r
701                 new->obclass = inertobj;\r
702                 new->active = ac_removable;\r
703                 new->x = ob->x;\r
704                 new->y = ob->y;\r
705                 new->xspeed = 28;\r
706                 new->yspeed = -40;\r
707                 NewState(new, &s_eggchip2);\r
708 \r
709                 GetNewObj(true);\r
710                 new->obclass = inertobj;\r
711                 new->active = ac_removable;\r
712                 new->x = ob->x;\r
713                 new->y = ob->y;\r
714                 new->xspeed = 0;\r
715                 new->yspeed = -56;\r
716                 NewState(new, &s_eggchip3);\r
717         }\r
718 }\r
719 \r
720 /*\r
721 ===========================\r
722 =\r
723 = T_Eggbird\r
724 =\r
725 ===========================\r
726 */\r
727 \r
728 void T_Eggbird(objtype *ob)\r
729 {\r
730         if (ob->x < player->x)\r
731         {\r
732                 ob->xdir = 1;\r
733         }\r
734         else\r
735         {\r
736                 ob->xdir = -1;\r
737         }\r
738         if (ob->bottom >= player->bottom + 3*TILEGLOBAL && player->hitnorth\r
739                 && StatePositionOk(ob, &s_eggbirdfly1)) // BUG: StatePositionOk() only works for normal clipping, not for full clipping\r
740         {\r
741                 // Note: might be a good idea to set xtry to 0 here\r
742                 ob->state = &s_eggbirdfly1;\r
743                 ob->needtoclip = cl_fullclip;\r
744                 ob->yspeed = -8;\r
745                 ob->temp1 = 0;\r
746         }\r
747 }\r
748 \r
749 /*\r
750 ===========================\r
751 =\r
752 = T_EggbirdFly\r
753 =\r
754 ===========================\r
755 */\r
756 \r
757 void T_EggbirdFly(objtype *ob)\r
758 {\r
759         if (ob->temp1 == 0)\r
760         {\r
761                 if (ob->x < player->x)\r
762                 {\r
763                         ob->xdir = 1;\r
764                 }\r
765                 else\r
766                 {\r
767                         ob->xdir = -1;\r
768                 }\r
769         }\r
770         AccelerateXv(ob, ob->xdir, 16);\r
771         if (ob->y < player->y)\r
772         {\r
773                 AccelerateY(ob, 1, 16);\r
774         }\r
775         else\r
776         {\r
777                 AccelerateY(ob, -1, 16);\r
778         }\r
779 }\r
780 \r
781 /*\r
782 ===========================\r
783 =\r
784 = C_Eggbird\r
785 =\r
786 ===========================\r
787 */\r
788 \r
789 void C_Eggbird(objtype *ob, objtype *hit)\r
790 {\r
791         if (hit->obclass == keenobj)\r
792         {\r
793                 KillKeen();\r
794         }\r
795         else if (hit->obclass == stunshotobj)\r
796         {\r
797                 ob->xspeed = 0;\r
798                 ob->needtoclip = cl_midclip;\r
799                 StunObj(ob, hit, &s_eggbirdstun);\r
800         }\r
801 }\r
802 \r
803 /*\r
804 ===========================\r
805 =\r
806 = C_EggbirdStun\r
807 =\r
808 ===========================\r
809 */\r
810 \r
811 void C_EggbirdStun(objtype *ob, objtype *hit)\r
812 {\r
813         if (hit->obclass == stunshotobj)\r
814         {\r
815                 ob->xspeed = 0;\r
816                 StunObj(ob, hit, &s_eggbirdstun);\r
817         }\r
818 }\r
819 \r
820 /*\r
821 ===========================\r
822 =\r
823 = R_Eggbird\r
824 =\r
825 ===========================\r
826 */\r
827 \r
828 void R_Eggbird(objtype *ob)\r
829 {\r
830         if (ob->xdir == 1 && ob->hitwest)\r
831         {\r
832                 ob->x -= ob->xmove;\r
833                 ob->xdir = -1;\r
834                 ob->nothink = US_RndT() >> 5;\r
835                 ChangeState(ob, ob->state);\r
836         }\r
837         else if (ob->xdir == -1 && ob->hiteast)\r
838         {\r
839                 ob->x -= ob->xmove;\r
840                 ob->xdir = 1;\r
841                 ob->nothink = US_RndT() >> 5;\r
842                 ChangeState(ob, ob->state);\r
843         }\r
844         if (!ob->hitnorth)\r
845         {\r
846                 ob->yspeed = -16;\r
847                 ob->needtoclip = cl_fullclip;\r
848                 ChangeState(ob, &s_eggbirdfly1);\r
849         }\r
850         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
851 }\r
852 \r
853 /*\r
854 ===========================\r
855 =\r
856 = R_EggbirdDrop\r
857 =\r
858 ===========================\r
859 */\r
860 \r
861 void R_EggbirdDrop(objtype *ob) //never actually used\r
862 {\r
863         if (ob->hitnorth)\r
864         {\r
865                 ChangeState(ob, &s_eggbirdwalk1);\r
866         }\r
867         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
868 }\r
869 \r
870 /*\r
871 ===========================\r
872 =\r
873 = R_Chip\r
874 =\r
875 ===========================\r
876 */\r
877 \r
878 void R_Chip(objtype *ob)\r
879 {\r
880         if (ob->hitnorth)\r
881                 ob->xspeed = ob->yspeed = 0;\r
882 \r
883         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
884 }\r
885 \r
886 /*\r
887 ===========================\r
888 =\r
889 = R_Eggbirdfly\r
890 =\r
891 ===========================\r
892 */\r
893 \r
894 void R_Eggbirdfly(objtype *ob)\r
895 {\r
896         statetype *oldstate;\r
897 \r
898         if ((ob->hitsouth || ob->hitnorth) && !ob->temp1)\r
899                 ob->temp1++;\r
900 \r
901         if (ob->hiteast && ob->xspeed < 0 || ob->hitwest && ob->xspeed > 0)\r
902         {\r
903                 ob->xspeed = 0;\r
904                 ob->xdir = -ob->xdir;\r
905         }\r
906         if (ob->hitnorth == 1 && player->bottom - ob->bottom < 8*PIXGLOBAL)     // BUG? unsigned comparison!\r
907         {\r
908                 oldstate = ob->state;\r
909                 ob->needtoclip = cl_midclip;\r
910                 ChangeState(ob, &s_eggbirdwalk1);\r
911                 xtry = 0;\r
912                 ytry = 8*PIXGLOBAL;\r
913                 PushObj(ob);\r
914                 if (!ob->hitnorth)\r
915                 {\r
916                         ob->needtoclip = cl_fullclip;\r
917                         ChangeState(ob, oldstate);\r
918                 }\r
919                 return; // BUG: sprite isn't updated\r
920         }\r
921 \r
922         if (!ob->hitsouth && !ob->hitnorth)\r
923                 ob->temp1 = 0;\r
924 \r
925         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
926 }\r
927 \r
928 /*\r
929 =============================================================================\r
930 \r
931                                                   ARACHNUT\r
932 \r
933 =============================================================================\r
934 */\r
935 \r
936 statetype s_arach1     = {ARACHNUTWALK1SPR, ARACHNUTWALK4SPR, step, false, true,   6, 128, 0, NULL, C_Arach, R_Walk, &s_arach2};\r
937 statetype s_arach2     = {ARACHNUTWALK2SPR, ARACHNUTWALK3SPR, step, false, true,   6, 128, 0, NULL, C_Arach, R_Walk, &s_arach3};\r
938 statetype s_arach3     = {ARACHNUTWALK3SPR, ARACHNUTWALK2SPR, step, false, true,   6, 128, 0, NULL, C_Arach, R_Walk, &s_arach4};\r
939 statetype s_arach4     = {ARACHNUTWALK4SPR, ARACHNUTWALK1SPR, step, false, true,   6, 128, 0, T_Arach, C_Arach, R_Walk, &s_arach1};\r
940 statetype s_arachstun  = {ARACHNUTSTUNSPR,  ARACHNUTSTUNSPR,  step, false, true, 240,   0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun2};\r
941 statetype s_arachstun2 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true,  20,   0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun3};\r
942 statetype s_arachstun3 = {ARACHNUTSTUNSPR,  ARACHNUTSTUNSPR,  step, false, true,  20,   0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun4};\r
943 statetype s_arachstun4 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true,  20,   0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun5};\r
944 statetype s_arachstun5 = {ARACHNUTSTUNSPR,  ARACHNUTSTUNSPR,  step, false, true,  20,   0, 0, NULL, C_ArachStun, R_Draw, &s_arach1};\r
945 \r
946 /*\r
947 ===========================\r
948 =\r
949 = SpawnArachnut\r
950 =\r
951 ===========================\r
952 */\r
953 \r
954 void SpawnArachnut(Sint16 x, Sint16 y)\r
955 {\r
956         GetNewObj(false);\r
957         new->obclass = arachnutobj;\r
958         new->active = ac_yes;\r
959         new->priority = 0;\r
960         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
961         new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x171;\r
962         if (US_RndT() < 0x80)\r
963         {\r
964                 new->xdir = 1;\r
965         }\r
966         else\r
967         {\r
968                 new->xdir = -1;\r
969         }\r
970         new->ydir = 1;\r
971         NewState(new, &s_arach1);\r
972 }\r
973 \r
974 /*\r
975 ===========================\r
976 =\r
977 = T_Arach\r
978 =\r
979 ===========================\r
980 */\r
981 \r
982 void T_Arach(objtype *ob)\r
983 {\r
984         if (ob->x > player->x)\r
985         {\r
986                 ob->xdir = -1;\r
987         }\r
988         else\r
989         {\r
990                 ob->xdir = 1;\r
991         }\r
992 }\r
993 \r
994 /*\r
995 ===========================\r
996 =\r
997 = C_Arach\r
998 =\r
999 ===========================\r
1000 */\r
1001 \r
1002 void C_Arach(objtype *ob, objtype *hit)\r
1003 {\r
1004         if (hit->obclass == stunshotobj)\r
1005         {\r
1006                 StunObj(ob, hit, &s_arachstun);\r
1007         }\r
1008         else if (hit->obclass == keenobj)\r
1009         {\r
1010                 KillKeen();\r
1011         }\r
1012 }\r
1013 \r
1014 /*\r
1015 ===========================\r
1016 =\r
1017 = C_ArachStun\r
1018 =\r
1019 ===========================\r
1020 */\r
1021 \r
1022 void C_ArachStun(objtype *ob, objtype *hit)\r
1023 {\r
1024         if (hit->obclass == stunshotobj)\r
1025         {\r
1026                 StunObj(ob, hit, &s_arachstun);\r
1027         }\r
1028 }\r
1029 \r
1030 /*\r
1031 =============================================================================\r
1032 \r
1033                                                   SKYPEST\r
1034 \r
1035 =============================================================================\r
1036 */\r
1037 \r
1038 statetype s_pestfly1 = {SKYPESTFLYL1SPR, SKYPESTFLYR1SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly2};\r
1039 statetype s_pestfly2 = {SKYPESTFLYL2SPR, SKYPESTFLYR2SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly1};\r
1040 statetype s_squashedpest = {SKYPESTSQUASHEDSPR, SKYPESTSQUASHEDSPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, &s_squashedpest};\r
1041 statetype s_pestrest1  = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest2};\r
1042 statetype s_pestrest2  = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest3};\r
1043 statetype s_pestrest3  = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest4};\r
1044 statetype s_pestrest4  = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest5};\r
1045 statetype s_pestrest5  = {SKYPESTSIT4SPR, SKYPESTSIT4SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest6};\r
1046 statetype s_pestrest6  = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest7};\r
1047 statetype s_pestrest7  = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest8};\r
1048 statetype s_pestrest8  = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest9};\r
1049 statetype s_pestrest9  = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 60, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest10};\r
1050 statetype s_pestrest10 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest11};\r
1051 statetype s_pestrest11 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest12};\r
1052 statetype s_pestrest12 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest13};\r
1053 statetype s_pestrest13 = {SKYPESTSIT8SPR, SKYPESTSIT8SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest14};\r
1054 statetype s_pestrest14 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest15};\r
1055 statetype s_pestrest15 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest16};\r
1056 statetype s_pestrest16 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest17};\r
1057 statetype s_pestrest17 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, T_PestRest, C_Squashable, R_Draw, &s_pestfly1};\r
1058 \r
1059 /*\r
1060 ===========================\r
1061 =\r
1062 = SpawnSkypest\r
1063 =\r
1064 ===========================\r
1065 */\r
1066 \r
1067 void SpawnSkypest(Sint16 x, Sint16 y)\r
1068 {\r
1069         GetNewObj(false);\r
1070         new->obclass = skypestobj;\r
1071         new->active = ac_yes;\r
1072         new->priority = 0;\r
1073         new->x = CONVERT_TILE_TO_GLOBAL(x);\r
1074         new->y = CONVERT_TILE_TO_GLOBAL(y);\r
1075         if (US_RndT() < 0x80)\r
1076         {\r
1077                 new->xdir = 1;\r
1078         }\r
1079         else\r
1080         {\r
1081                 new->xdir = -1;\r
1082         }\r
1083         if (US_RndT() < 0x80)\r
1084         {\r
1085                 new->ydir = 1;\r
1086         }\r
1087         else\r
1088         {\r
1089                 new->ydir = -1;\r
1090         }\r
1091         NewState(new, &s_pestfly1);\r
1092 }\r
1093 \r
1094 /*\r
1095 ===========================\r
1096 =\r
1097 = T_PestFly\r
1098 =\r
1099 ===========================\r
1100 */\r
1101 \r
1102 void T_PestFly(objtype *ob)\r
1103 {\r
1104         // BUG: this might be executed twice during the same frame if the\r
1105         // object's animation/state changed during that frame, causing the\r
1106         // object to move at twice the speed during that frame!\r
1107         // To avoid that, return if xtry is not 0 or ytry is not 0.\r
1108 \r
1109         if (US_RndT() < tics)\r
1110                 ob->xdir = -ob->xdir;\r
1111 \r
1112         if (ob->ydir == -1 && US_RndT() < tics)\r
1113                 ob->ydir = 1;\r
1114 \r
1115         if (ob->ydir == 1 && US_RndT() < tics*2)\r
1116                 ob->ydir = -ob->ydir;\r
1117 \r
1118         AccelerateX(ob, ob->xdir, 20);\r
1119         AccelerateY(ob, ob->ydir, 20);\r
1120 }\r
1121 \r
1122 /*\r
1123 ===========================\r
1124 =\r
1125 = C_PestFly\r
1126 =\r
1127 ===========================\r
1128 */\r
1129 \r
1130 void C_PestFly(objtype *ob, objtype *hit)\r
1131 {\r
1132         if (hit->obclass == keenobj)\r
1133                 KillKeen();\r
1134 \r
1135         if (hit->obclass == stunshotobj)\r
1136         {\r
1137                 if (hit->xdir == 1)\r
1138                 {\r
1139                         ob->xspeed = 20;\r
1140                 }\r
1141                 else if (hit->xdir == -1)\r
1142                 {\r
1143                         ob->xspeed = -20;\r
1144                 }\r
1145                 else if (hit->ydir == 1)\r
1146                 {\r
1147                         ob->yspeed = 20;\r
1148                 }\r
1149                 else if (hit->ydir == -1)\r
1150                 {\r
1151                         ob->yspeed = -20;\r
1152                 }\r
1153                 ExplodeShot(hit);\r
1154         }\r
1155 }\r
1156 \r
1157 /*\r
1158 ===========================\r
1159 =\r
1160 = C_Squashable\r
1161 =\r
1162 ===========================\r
1163 */\r
1164 \r
1165 void C_Squashable(objtype *ob, objtype *hit)\r
1166 {\r
1167         if (hit->state == &s_keenpogodown || hit->state == &s_keenpogo || hit->state == &s_keenpogo2)\r
1168         {\r
1169                 ChangeState(ob, &s_squashedpest);\r
1170                 SD_PlaySound(SND_SQUISH);\r
1171                 ob->obclass = inertobj;\r
1172         }\r
1173 }\r
1174 \r
1175 /*\r
1176 ===========================\r
1177 =\r
1178 = T_PestRest\r
1179 =\r
1180 ===========================\r
1181 */\r
1182 \r
1183 void T_PestRest(objtype *ob)\r
1184 {\r
1185         ob->ydir = -1;\r
1186         ob->yspeed = -16;\r
1187         ytry = -144;\r
1188 }\r
1189 \r
1190 /*\r
1191 ===========================\r
1192 =\r
1193 = R_Pest\r
1194 =\r
1195 ===========================\r
1196 */\r
1197 \r
1198 void R_Pest(objtype *ob)\r
1199 {\r
1200         if (ob->hitsouth)\r
1201         {\r
1202                 ob->yspeed = 8;\r
1203                 ob->ydir = 1;\r
1204         }\r
1205         if (ob->hitnorth && !ob->hiteast && !ob->hitwest)\r
1206         {\r
1207                 ob->y += 8*PIXGLOBAL;\r
1208                 ChangeState(ob, &s_pestrest1);\r
1209         }\r
1210         if (ob->hitwest)\r
1211         {\r
1212                 ob->xspeed = 0;\r
1213                 ob->xdir = -1;\r
1214         }\r
1215         if (ob->hiteast)\r
1216         {\r
1217                 ob->xspeed = 0;\r
1218                 ob->xdir = 1;\r
1219         }\r
1220         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
1221 }\r