|
|
1.1 root 1:
2: //**************************************************************************
3: //**
4: //** a_action.c : Heretic 2 : Raven Software, Corp.
5: //**
6: //** $RCSfile: a_action.c,v $
7: //** $Revision: 1.86 $
8: //** $Date: 96/03/22 13:15:33 $
9: //** $Author: bgokey $
10: //**
11: //**************************************************************************
12:
13: // HEADER FILES ------------------------------------------------------------
14:
15: #include "h2def.h"
16: #include "p_local.h"
17: #include "soundst.h"
18:
19: // MACROS ------------------------------------------------------------------
20:
21: // TYPES -------------------------------------------------------------------
22:
23: // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
24:
25: // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
26:
27: // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
28:
29: // EXTERNAL DATA DECLARATIONS ----------------------------------------------
30: extern fixed_t FloatBobOffsets[64];
31:
32: // PUBLIC DATA DEFINITIONS -------------------------------------------------
33: int orbitTableX[256]=
34: {
35: 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490,
36: 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025,
37: 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310,
38: 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690,
39: 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725,
40: 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010,
41: 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010,
42: 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745,
43: -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420,
44: -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135,
45: -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230,
46: -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105,
47: -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925,
48: -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845,
49: -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235,
50: -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740,
51: -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490,
52: -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025,
53: -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310,
54: -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690,
55: -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725,
56: -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010,
57: -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010,
58: -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745,
59: 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420,
60: 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135,
61: 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230,
62: 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105,
63: 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925,
64: 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845,
65: 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235,
66: 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740
67: };
68:
69: int orbitTableY[256]=
70: {
71: 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420,
72: 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135,
73: 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230,
74: 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105,
75: 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925,
76: 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845,
77: 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235,
78: 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740,
79: 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490,
80: 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025,
81: 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310,
82: 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690,
83: 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725,
84: 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010,
85: 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010,
86: 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745,
87: -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420,
88: -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135,
89: -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230,
90: -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105,
91: -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925,
92: -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845,
93: -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235,
94: -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740,
95: -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490,
96: -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025,
97: -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310,
98: -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690,
99: -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725,
100: -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010,
101: -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010,
102: -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745
103: };
104:
105: // PRIVATE DATA DEFINITIONS ------------------------------------------------
106:
107: // CODE --------------------------------------------------------------------
108:
109: //--------------------------------------------------------------------------
110: //
111: // Environmental Action routines
112: //
113: //--------------------------------------------------------------------------
114:
115: //==========================================================================
116: //
117: // A_DripBlood
118: //
119: //==========================================================================
120:
121: /*
122: void A_DripBlood(mobj_t *actor)
123: {
124: mobj_t *mo;
125:
126: mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<11),
127: actor->y+((P_Random()-P_Random())<<11), actor->z, MT_BLOOD);
128: mo->momx = (P_Random()-P_Random())<<10;
129: mo->momy = (P_Random()-P_Random())<<10;
130: mo->flags2 |= MF2_LOGRAV;
131: }
132: */
133:
134: //============================================================================
135: //
136: // A_PotteryExplode
137: //
138: //============================================================================
139:
140: void A_PotteryExplode(mobj_t *actor)
141: {
142: mobj_t *mo=NULL;
143: int i;
144:
145: for(i = (P_Random()&3)+3; i; i--)
146: {
147: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_POTTERYBIT1);
148: P_SetMobjState(mo, mo->info->spawnstate+(P_Random()%5));
149: if(mo)
150: {
151: mo->momz = ((P_Random()&7)+5)*(3*FRACUNIT/4);
152: mo->momx = (P_Random()-P_Random())<<(FRACBITS-6);
153: mo->momy = (P_Random()-P_Random())<<(FRACBITS-6);
154: }
155: }
156: S_StartSound(mo, SFX_POTTERY_EXPLODE);
157: if(actor->args[0])
158: { // Spawn an item
159: if(!nomonsters
160: || !(mobjinfo[TranslateThingType[actor->args[0]]].flags&MF_COUNTKILL))
161: { // Only spawn monsters if not -nomonsters
162: P_SpawnMobj(actor->x, actor->y, actor->z,
163: TranslateThingType[actor->args[0]]);
164: }
165: }
166: P_RemoveMobj(actor);
167: }
168:
169: //============================================================================
170: //
171: // A_PotteryChooseBit
172: //
173: //============================================================================
174:
175: void A_PotteryChooseBit(mobj_t *actor)
176: {
177: P_SetMobjState(actor, actor->info->deathstate+(P_Random()%5)+1);
178: actor->tics = 256+(P_Random()<<1);
179: }
180:
181: //============================================================================
182: //
183: // A_PotteryCheck
184: //
185: //============================================================================
186:
187: void A_PotteryCheck(mobj_t *actor)
188: {
189: int i;
190: mobj_t *pmo;
191:
192: if(!netgame)
193: {
194: pmo = players[consoleplayer].mo;
195: if(P_CheckSight(actor, pmo) && (abs(R_PointToAngle2(pmo->x,
196: pmo->y, actor->x, actor->y)-pmo->angle) <= ANGLE_45))
197: { // Previous state (pottery bit waiting state)
198: P_SetMobjState(actor, actor->state-&states[0]-1);
199: }
200: else
201: {
202: return;
203: }
204: }
205: else
206: {
207: for(i = 0; i < MAXPLAYERS; i++)
208: {
209: if(!playeringame[i])
210: {
211: continue;
212: }
213: pmo = players[i].mo;
214: if(P_CheckSight(actor, pmo) && (abs(R_PointToAngle2(pmo->x,
215: pmo->y, actor->x, actor->y)-pmo->angle) <= ANGLE_45))
216: { // Previous state (pottery bit waiting state)
217: P_SetMobjState(actor, actor->state-&states[0]-1);
218: return;
219: }
220: }
221: }
222: }
223:
224: //============================================================================
225: //
226: // A_CorpseBloodDrip
227: //
228: //============================================================================
229:
230: void A_CorpseBloodDrip(mobj_t *actor)
231: {
232: if(P_Random() > 128)
233: {
234: return;
235: }
236: P_SpawnMobj(actor->x, actor->y, actor->z+actor->height/2,
237: MT_CORPSEBLOODDRIP);
238: }
239:
240: //============================================================================
241: //
242: // A_CorpseExplode
243: //
244: //============================================================================
245:
246: void A_CorpseExplode(mobj_t *actor)
247: {
248: mobj_t *mo;
249: int i;
250:
251: for(i = (P_Random()&3)+3; i; i--)
252: {
253: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT);
254: P_SetMobjState(mo, mo->info->spawnstate+(P_Random()%3));
255: if(mo)
256: {
257: mo->momz = ((P_Random()&7)+5)*(3*FRACUNIT/4);
258: mo->momx = (P_Random()-P_Random())<<(FRACBITS-6);
259: mo->momy = (P_Random()-P_Random())<<(FRACBITS-6);
260: }
261: }
262: // Spawn a skull
263: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT);
264: P_SetMobjState(mo, S_CORPSEBIT_4);
265: if(mo)
266: {
267: mo->momz = ((P_Random()&7)+5)*(3*FRACUNIT/4);
268: mo->momx = (P_Random()-P_Random())<<(FRACBITS-6);
269: mo->momy = (P_Random()-P_Random())<<(FRACBITS-6);
270: S_StartSound(mo, SFX_FIRED_DEATH);
271: }
272: P_RemoveMobj(actor);
273: }
274:
275: //============================================================================
276: //
277: // A_LeafSpawn
278: //
279: //============================================================================
280:
281: void A_LeafSpawn(mobj_t *actor)
282: {
283: mobj_t *mo;
284: int i;
285:
286: for(i = (P_Random()&3)+1; i; i--)
287: {
288: mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<14), actor->y+
289: ((P_Random()-P_Random())<<14), actor->z+(P_Random()<<14),
290: MT_LEAF1+(P_Random()&1));
291: if(mo)
292: {
293: P_ThrustMobj(mo, actor->angle, (P_Random()<<9)+3*FRACUNIT);
294: mo->target = actor;
295: mo->special1 = 0;
296: }
297: }
298: }
299:
300: //============================================================================
301: //
302: // A_LeafThrust
303: //
304: //============================================================================
305:
306: void A_LeafThrust(mobj_t *actor)
307: {
308: if(P_Random() > 96)
309: {
310: return;
311: }
312: actor->momz += (P_Random()<<9)+FRACUNIT;
313: }
314:
315: //============================================================================
316: //
317: // A_LeafCheck
318: //
319: //============================================================================
320:
321: void A_LeafCheck(mobj_t *actor)
322: {
323: actor->special1++;
324: if(actor->special1 >= 20)
325: {
326: P_SetMobjState(actor, S_NULL);
327: return;
328: }
329: if(P_Random() > 64)
330: {
331: if(!actor->momx && !actor->momy)
332: {
333: P_ThrustMobj(actor, actor->target->angle,
334: (P_Random()<<9)+FRACUNIT);
335: }
336: return;
337: }
338: P_SetMobjState(actor, S_LEAF1_8);
339: actor->momz = (P_Random()<<9)+FRACUNIT;
340: P_ThrustMobj(actor, actor->target->angle, (P_Random()<<9)+2*FRACUNIT);
341: actor->flags |= MF_MISSILE;
342: }
343:
344: /*
345: #define ORBIT_RADIUS (15*FRACUNIT)
346: void GenerateOrbitTable(void)
347: {
348: int angle;
349:
350: for (angle=0; angle<256; angle++)
351: {
352: orbitTableX[angle] = FixedMul(ORBIT_RADIUS, finecosine[angle<<5]);
353: orbitTableY[angle] = FixedMul(ORBIT_RADIUS, finesine[angle<<5]);
354: }
355:
356: printf("int orbitTableX[256]=\n{\n");
357: for (angle=0; angle<256; angle+=8)
358: {
359: printf("%d, %d, %d, %d, %d, %d, %d, %d,\n",
360: orbitTableX[angle],
361: orbitTableX[angle+1],
362: orbitTableX[angle+2],
363: orbitTableX[angle+3],
364: orbitTableX[angle+4],
365: orbitTableX[angle+5],
366: orbitTableX[angle+6],
367: orbitTableX[angle+7]);
368: }
369: printf("};\n\n");
370:
371: printf("int orbitTableY[256]=\n{\n");
372: for (angle=0; angle<256; angle+=8)
373: {
374: printf("%d, %d, %d, %d, %d, %d, %d, %d,\n",
375: orbitTableY[angle],
376: orbitTableY[angle+1],
377: orbitTableY[angle+2],
378: orbitTableY[angle+3],
379: orbitTableY[angle+4],
380: orbitTableY[angle+5],
381: orbitTableY[angle+6],
382: orbitTableY[angle+7]);
383: }
384: printf("};\n");
385: }
386: */
387:
388: // New bridge stuff
389: // Parent
390: // special1 true == removing from world
391: //
392: // Child
393: // target pointer to center mobj
394: // args[0] angle of ball
395:
396: void A_BridgeOrbit(mobj_t *actor)
397: {
398: if (actor->target->special1)
399: {
400: P_SetMobjState(actor, S_NULL);
401: }
402: actor->args[0]+=3;
403: actor->x = actor->target->x + orbitTableX[actor->args[0]];
404: actor->y = actor->target->y + orbitTableY[actor->args[0]];
405: actor->z = actor->target->z;
406: }
407:
408:
409: void A_BridgeInit(mobj_t *actor)
410: {
411: byte startangle;
412: mobj_t *ball1, *ball2, *ball3;
413: fixed_t cx,cy,cz;
414:
415: // GenerateOrbitTable();
416:
417: cx = actor->x;
418: cy = actor->y;
419: cz = actor->z;
420: startangle = P_Random();
421: actor->special1 = 0;
422:
423: // Spawn triad into world
424: ball1 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
425: ball1->args[0] = startangle;
426: ball1->target = actor;
427:
428: ball2 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
429: ball2->args[0] = (startangle+85)&255;
430: ball2->target = actor;
431:
432: ball3 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
433: ball3->args[0] = (startangle+170)&255;
434: ball3->target = actor;
435:
436: A_BridgeOrbit(ball1);
437: A_BridgeOrbit(ball2);
438: A_BridgeOrbit(ball3);
439: }
440:
441: void A_BridgeRemove(mobj_t *actor)
442: {
443: actor->special1 = true; // Removing the bridge
444: actor->flags &= ~MF_SOLID;
445: P_SetMobjState(actor, S_FREE_BRIDGE1);
446: }
447:
448:
449: //==========================================================================
450: //
451: // A_GhostOn
452: //
453: //==========================================================================
454:
455: /*
456: void A_GhostOn(mobj_t *actor)
457: {
458: actor->flags |= MF_SHADOW;
459: }
460: */
461:
462: //==========================================================================
463: //
464: // A_GhostOff
465: //
466: //==========================================================================
467:
468: /*
469: void A_GhostOff(mobj_t *actor)
470: {
471: actor->flags &= ~MF_SHADOW;
472: }
473: */
474:
475: //==========================================================================
476: //
477: // A_HideThing
478: //
479: //==========================================================================
480:
481: void A_HideThing(mobj_t *actor)
482: {
483: actor->flags2 |= MF2_DONTDRAW;
484: }
485:
486: //==========================================================================
487: //
488: // A_UnHideThing
489: //
490: //==========================================================================
491:
492: void A_UnHideThing(mobj_t *actor)
493: {
494: actor->flags2 &= ~MF2_DONTDRAW;
495: }
496:
497: //==========================================================================
498: //
499: // A_SetShootable
500: //
501: //==========================================================================
502:
503: void A_SetShootable(mobj_t *actor)
504: {
505: actor->flags2 &= ~MF2_NONSHOOTABLE;
506: actor->flags |= MF_SHOOTABLE;
507: }
508:
509: //==========================================================================
510: //
511: // A_UnSetShootable
512: //
513: //==========================================================================
514:
515: void A_UnSetShootable(mobj_t *actor)
516: {
517: actor->flags2 |= MF2_NONSHOOTABLE;
518: actor->flags &= ~MF_SHOOTABLE;
519: }
520:
521: //==========================================================================
522: //
523: // A_SetAltShadow
524: //
525: //==========================================================================
526:
527: void A_SetAltShadow(mobj_t *actor)
528: {
529: actor->flags &= ~MF_SHADOW;
530: actor->flags |= MF_ALTSHADOW;
531: }
532:
533: //==========================================================================
534: //
535: // A_UnSetAltShadow
536: //
537: //==========================================================================
538:
539: /*
540: void A_UnSetAltShadow(mobj_t *actor)
541: {
542: actor->flags &= ~MF_ALTSHADOW;
543: }
544: */
545:
546: //--------------------------------------------------------------------------
547: //
548: // Sound Action Routines
549: //
550: //--------------------------------------------------------------------------
551:
552: //==========================================================================
553: //
554: // A_ContMobjSound
555: //
556: //==========================================================================
557:
558: void A_ContMobjSound(mobj_t *actor)
559: {
560: switch(actor->type)
561: {
562: case MT_SERPENTFX:
563: S_StartSound(actor, SFX_SERPENTFX_CONTINUOUS);
564: break;
565: case MT_HAMMER_MISSILE:
566: S_StartSound(actor, SFX_FIGHTER_HAMMER_CONTINUOUS);
567: break;
568: case MT_QUAKE_FOCUS:
569: S_StartSound(actor, SFX_EARTHQUAKE);
570: break;
571: default:
572: break;
573: }
574: }
575:
576: //==========================================================================
577: //
578: // PROC A_ESound
579: //
580: //==========================================================================
581:
582: void A_ESound(mobj_t *mo)
583: {
584: int sound;
585:
586: switch(mo->type)
587: {
588: case MT_SOUNDWIND:
589: sound = SFX_WIND;
590: break;
591: default:
592: sound = SFX_NONE;
593: break;
594: }
595: S_StartSound(mo, sound);
596: }
597:
598:
599:
600: //==========================================================================
601: // Summon Minotaur -- see p_enemy for variable descriptions
602: //==========================================================================
603:
604:
605: void A_Summon(mobj_t *actor)
606: {
607: mobj_t *mo;
608: mobj_t *master;
609:
610: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINOTAUR);
611: if (mo)
612: {
613: if(P_TestMobjLocation(mo) == false || !actor->special1)
614: { // Didn't fit - change back to artifact
615: P_SetMobjState(mo, S_NULL);
616: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SUMMONMAULATOR);
617: if (mo) mo->flags2 |= MF2_DROPPED;
618: return;
619: }
620:
621: memcpy((void *)mo->args, &leveltime, sizeof(leveltime));
622: master = (mobj_t *)actor->special1;
623: if (master->flags&MF_CORPSE)
624: { // Master dead
625: mo->special1 = 0; // No master
626: }
627: else
628: {
629: mo->special1 = actor->special1; // Pointer to master (mobj_t *)
630: P_GivePower(master->player, pw_minotaur);
631: }
632:
633: // Make smoke puff
634: P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE);
635: S_StartSound(actor, SFX_MAULATOR_ACTIVE);
636: }
637: }
638:
639:
640:
641: //==========================================================================
642: // Fog Variables:
643: //
644: // args[0] Speed (0..10) of fog
645: // args[1] Angle of spread (0..128)
646: // args[2] Frequency of spawn (1..10)
647: // args[3] Lifetime countdown
648: // args[4] Boolean: fog moving?
649: // special1 Internal: Counter for spawn frequency
650: // special2 Internal: Index into floatbob table
651: //
652: //==========================================================================
653:
654: void A_FogSpawn(mobj_t *actor)
655: {
656: mobj_t *mo=NULL;
657: angle_t delta;
658:
659: if (actor->special1-- > 0) return;
660:
661: actor->special1 = actor->args[2]; // Reset frequency count
662:
663: switch(P_Random()%3)
664: {
665: case 0:
666: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHS);
667: break;
668: case 1:
669: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHM);
670: break;
671: case 2:
672: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHL);
673: break;
674: }
675:
676: if (mo)
677: {
678: delta = actor->args[1];
679: if (delta==0) delta=1;
680: mo->angle = actor->angle + (((P_Random()%delta)-(delta>>1))<<24);
681: mo->target = actor;
682: if (actor->args[0] < 1) actor->args[0] = 1;
683: mo->args[0] = (P_Random() % (actor->args[0]))+1; // Random speed
684: mo->args[3] = actor->args[3]; // Set lifetime
685: mo->args[4] = 1; // Set to moving
686: mo->special2 = P_Random()&63;
687: }
688: }
689:
690:
691: void A_FogMove(mobj_t *actor)
692: {
693: int speed = actor->args[0]<<FRACBITS;
694: angle_t angle;
695: int weaveindex;
696:
697: if (!(actor->args[4])) return;
698:
699: if (actor->args[3]-- <= 0)
700: {
701: P_SetMobjStateNF(actor, actor->info->deathstate);
702: return;
703: }
704:
705: if ((actor->args[3] % 4) == 0)
706: {
707: weaveindex = actor->special2;
708: actor->z += FloatBobOffsets[weaveindex]>>1;
709: actor->special2 = (weaveindex+1)&63;
710: }
711:
712: angle = actor->angle>>ANGLETOFINESHIFT;
713: actor->momx = FixedMul(speed, finecosine[angle]);
714: actor->momy = FixedMul(speed, finesine[angle]);
715: }
716:
717: //===========================================================================
718: //
719: // A_PoisonBagInit
720: //
721: //===========================================================================
722:
723: void A_PoisonBagInit(mobj_t *actor)
724: {
725: mobj_t *mo;
726:
727: mo = P_SpawnMobj(actor->x, actor->y, actor->z+28*FRACUNIT,
728: MT_POISONCLOUD);
729: if(!mo)
730: {
731: return;
732: }
733: mo->momx = 1; // missile objects must move to impact other objects
734: mo->special1 = 24+(P_Random()&7);
735: mo->special2 = 0;
736: mo->target = actor->target;
737: mo->radius = 20*FRACUNIT;
738: mo->height = 30*FRACUNIT;
739: mo->flags &= ~MF_NOCLIP;
740: }
741:
742: //===========================================================================
743: //
744: // A_PoisonBagCheck
745: //
746: //===========================================================================
747:
748: void A_PoisonBagCheck(mobj_t *actor)
749: {
750: if(!--actor->special1)
751: {
752: P_SetMobjState(actor, S_POISONCLOUD_X1);
753: }
754: else
755: {
756: return;
757: }
758: }
759:
760: //===========================================================================
761: //
762: // A_PoisonBagDamage
763: //
764: //===========================================================================
765:
766: void A_PoisonBagDamage(mobj_t *actor)
767: {
768: int bobIndex;
769:
770: extern void A_Explode(mobj_t *actor);
771:
772: A_Explode(actor);
773:
774: bobIndex = actor->special2;
775: actor->z += FloatBobOffsets[bobIndex]>>4;
776: actor->special2 = (bobIndex+1)&63;
777: }
778:
779: //===========================================================================
780: //
781: // A_PoisonShroom
782: //
783: //===========================================================================
784:
785: void A_PoisonShroom(mobj_t *actor)
786: {
787: actor->tics = 128+(P_Random()<<1);
788: }
789:
790: //===========================================================================
791: //
792: // A_CheckThrowBomb
793: //
794: //===========================================================================
795:
796: void A_CheckThrowBomb(mobj_t *actor)
797: {
798: if(abs(actor->momx) < 1.5*FRACUNIT && abs(actor->momy) < 1.5*FRACUNIT
799: && actor->momz < 2*FRACUNIT
800: && actor->state == &states[S_THROWINGBOMB6])
801: {
802: P_SetMobjState(actor, S_THROWINGBOMB7);
803: actor->z = actor->floorz;
804: actor->momz = 0;
805: actor->flags2 &= ~MF2_FLOORBOUNCE;
806: actor->flags &= ~MF_MISSILE;
807: }
808: if(!--actor->health)
809: {
810: P_SetMobjState(actor, actor->info->deathstate);
811: }
812: }
813:
814: //===========================================================================
815: // Quake variables
816: //
817: // args[0] Intensity on richter scale (2..9)
818: // args[1] Duration in tics
819: // args[2] Radius for damage
820: // args[3] Radius for tremor
821: // args[4] TID of map thing for focus of quake
822: //
823: //===========================================================================
824:
825: //===========================================================================
826: //
827: // A_LocalQuake
828: //
829: //===========================================================================
830:
831: boolean A_LocalQuake(byte *args, mobj_t *actor)
832: {
833: mobj_t *focus, *target;
834: int lastfound=0;
835: int success=false;
836:
837: actor=actor; // suppress warning
838:
839: // Find all quake foci
840: do
841: {
842: target = P_FindMobjFromTID(args[4], &lastfound);
843: if (target)
844: {
845: focus = P_SpawnMobj(target->x,
846: target->y,
847: target->z, MT_QUAKE_FOCUS);
848: if (focus)
849: {
850: focus->args[0] = args[0];
851: focus->args[1] = args[1]>>1; // decremented every 2 tics
852: focus->args[2] = args[2];
853: focus->args[3] = args[3];
854: focus->args[4] = args[4];
855: success = true;
856: }
857: }
858: }while(target != NULL);
859:
860: return(success);
861: }
862:
863:
864: //===========================================================================
865: //
866: // A_Quake
867: //
868: //===========================================================================
869: int localQuakeHappening[MAXPLAYERS];
870:
871: void A_Quake(mobj_t *actor)
872: {
873: angle_t an;
874: player_t *player;
875: mobj_t *victim;
876: int richters = actor->args[0];
877: int playnum;
878: fixed_t dist;
879:
880: if (actor->args[1]-- > 0)
881: {
882: for (playnum=0; playnum < MAXPLAYERS; playnum++)
883: {
884: player = &players[playnum];
885: if (!playeringame[playnum]) continue;
886:
887: victim = player->mo;
888: dist = P_AproxDistance(actor->x - victim->x,
889: actor->y - victim->y) >> (FRACBITS+6);
890: // Tested in tile units (64 pixels)
891: if (dist < actor->args[3]) // In tremor radius
892: {
893: localQuakeHappening[playnum] = richters;
894: }
895: // Check if in damage radius
896: if ((dist < actor->args[2]) &&
897: (victim->z <= victim->floorz))
898: {
899: if (P_Random() < 50)
900: {
901: P_DamageMobj(victim, NULL, NULL, HITDICE(1));
902: }
903: // Thrust player around
904: an = victim->angle + ANGLE_1*P_Random();
905: P_ThrustMobj(victim,an,richters<<(FRACBITS-1));
906: }
907: }
908: }
909: else
910: {
911: for (playnum=0; playnum < MAXPLAYERS; playnum++)
912: {
913: localQuakeHappening[playnum] = false;
914: }
915: P_SetMobjState(actor, S_NULL);
916: }
917: }
918:
919:
920:
921:
922: //===========================================================================
923: //
924: // Teleport other stuff
925: //
926: //===========================================================================
927:
928: #define TELEPORT_LIFE 1
929:
930: void A_TeloSpawnA(mobj_t *actor)
931: {
932: mobj_t *mo;
933:
934: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX2);
935: if (mo)
936: {
937: mo->special1 = TELEPORT_LIFE; // Lifetime countdown
938: mo->angle = actor->angle;
939: mo->target = actor->target;
940: mo->momx = actor->momx>>1;
941: mo->momy = actor->momy>>1;
942: mo->momz = actor->momz>>1;
943: }
944: }
945:
946: void A_TeloSpawnB(mobj_t *actor)
947: {
948: mobj_t *mo;
949:
950: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX3);
951: if (mo)
952: {
953: mo->special1 = TELEPORT_LIFE; // Lifetime countdown
954: mo->angle = actor->angle;
955: mo->target = actor->target;
956: mo->momx = actor->momx>>1;
957: mo->momy = actor->momy>>1;
958: mo->momz = actor->momz>>1;
959: }
960: }
961:
962: void A_TeloSpawnC(mobj_t *actor)
963: {
964: mobj_t *mo;
965:
966: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX4);
967: if (mo)
968: {
969: mo->special1 = TELEPORT_LIFE; // Lifetime countdown
970: mo->angle = actor->angle;
971: mo->target = actor->target;
972: mo->momx = actor->momx>>1;
973: mo->momy = actor->momy>>1;
974: mo->momz = actor->momz>>1;
975: }
976: }
977:
978: void A_TeloSpawnD(mobj_t *actor)
979: {
980: mobj_t *mo;
981:
982: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX5);
983: if (mo)
984: {
985: mo->special1 = TELEPORT_LIFE; // Lifetime countdown
986: mo->angle = actor->angle;
987: mo->target = actor->target;
988: mo->momx = actor->momx>>1;
989: mo->momy = actor->momy>>1;
990: mo->momz = actor->momz>>1;
991: }
992: }
993:
994: void A_CheckTeleRing(mobj_t *actor)
995: {
996: if (actor->special1-- <= 0)
997: {
998: P_SetMobjState(actor, actor->info->deathstate);
999: }
1000: }
1001:
1002:
1003:
1004:
1005: // Dirt stuff
1006:
1007: void P_SpawnDirt(mobj_t *actor, fixed_t radius)
1008: {
1009: fixed_t x,y,z;
1010: int dtype=0;
1011: mobj_t *mo;
1012: angle_t angle;
1013:
1014: angle = P_Random()<<5; // <<24 >>19
1015: x = actor->x + FixedMul(radius,finecosine[angle]);
1016: y = actor->y + FixedMul(radius,finesine[angle]);
1017: // x = actor->x + ((P_Random()-P_Random())%radius)<<FRACBITS;
1018: // y = actor->y + ((P_Random()-P_Random()<<FRACBITS)%radius);
1019: z = actor->z + (P_Random()<<9) + FRACUNIT;
1020: switch(P_Random()%6)
1021: {
1022: case 0:
1023: dtype = MT_DIRT1;
1024: break;
1025: case 1:
1026: dtype = MT_DIRT2;
1027: break;
1028: case 2:
1029: dtype = MT_DIRT3;
1030: break;
1031: case 3:
1032: dtype = MT_DIRT4;
1033: break;
1034: case 4:
1035: dtype = MT_DIRT5;
1036: break;
1037: case 5:
1038: dtype = MT_DIRT6;
1039: break;
1040: }
1041: mo = P_SpawnMobj(x,y,z,dtype);
1042: if (mo)
1043: {
1044: mo->momz = P_Random()<<10;
1045: }
1046: }
1047:
1048:
1049:
1050:
1051: //===========================================================================
1052: //
1053: // Thrust floor stuff
1054: //
1055: // Thrust Spike Variables
1056: // special1 pointer to dirt clump mobj
1057: // special2 speed of raise
1058: // args[0] 0 = lowered, 1 = raised
1059: // args[1] 0 = normal, 1 = bloody
1060: //===========================================================================
1061:
1062: void A_ThrustInitUp(mobj_t *actor)
1063: {
1064: actor->special2 = 5; // Raise speed
1065: actor->args[0] = 1; // Mark as up
1066: actor->floorclip = 0;
1067: actor->flags = MF_SOLID;
1068: actor->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP;
1069: actor->special1 = 0L;
1070: }
1071:
1072: void A_ThrustInitDn(mobj_t *actor)
1073: {
1074: mobj_t *mo;
1075: actor->special2 = 5; // Raise speed
1076: actor->args[0] = 0; // Mark as down
1077: actor->floorclip = actor->info->height;
1078: actor->flags = 0;
1079: actor->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP|MF2_DONTDRAW;
1080: mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_DIRTCLUMP);
1081: actor->special1 = (int)mo;
1082: }
1083:
1084:
1085: void A_ThrustRaise(mobj_t *actor)
1086: {
1087: if (A_RaiseMobj(actor))
1088: { // Reached it's target height
1089: actor->args[0] = 1;
1090: if (actor->args[1])
1091: P_SetMobjStateNF(actor, S_BTHRUSTINIT2_1);
1092: else
1093: P_SetMobjStateNF(actor, S_THRUSTINIT2_1);
1094: }
1095:
1096: // Lose the dirt clump
1097: if ((actor->floorclip < actor->height) && actor->special1)
1098: {
1099: P_RemoveMobj( (mobj_t *)actor->special1 );
1100: actor->special1 = 0;
1101: }
1102:
1103: // Spawn some dirt
1104: if (P_Random()<40)
1105: P_SpawnDirt(actor, actor->radius);
1106: actor->special2++; // Increase raise speed
1107: }
1108:
1109: void A_ThrustLower(mobj_t *actor)
1110: {
1111: if (A_SinkMobj(actor))
1112: {
1113: actor->args[0] = 0;
1114: if (actor->args[1])
1115: P_SetMobjStateNF(actor, S_BTHRUSTINIT1_1);
1116: else
1117: P_SetMobjStateNF(actor, S_THRUSTINIT1_1);
1118: }
1119: }
1120:
1121: void A_ThrustBlock(mobj_t *actor)
1122: {
1123: actor->flags |= MF_SOLID;
1124: }
1125:
1126: void A_ThrustImpale(mobj_t *actor)
1127: {
1128: // Impale all shootables in radius
1129: PIT_ThrustSpike(actor);
1130: }
1131:
1132: //===========================================================================
1133: //
1134: // A_SoAExplode - Suit of Armor Explode
1135: //
1136: //===========================================================================
1137:
1138: void A_SoAExplode(mobj_t *actor)
1139: {
1140: mobj_t *mo;
1141: int i;
1142:
1143: for(i = 0; i < 10; i++)
1144: {
1145: mo = P_SpawnMobj(actor->x+((P_Random()-128)<<12),
1146: actor->y+((P_Random()-128)<<12),
1147: actor->z+(P_Random()*actor->height/256), MT_ZARMORCHUNK);
1148: P_SetMobjState(mo, mo->info->spawnstate+i);
1149: if(mo)
1150: {
1151: mo->momz = ((P_Random()&7)+5)*FRACUNIT;
1152: mo->momx = (P_Random()-P_Random())<<(FRACBITS-6);
1153: mo->momy = (P_Random()-P_Random())<<(FRACBITS-6);
1154: }
1155: }
1156: if(actor->args[0])
1157: { // Spawn an item
1158: if(!nomonsters
1159: || !(mobjinfo[TranslateThingType[actor->args[0]]].flags&MF_COUNTKILL))
1160: { // Only spawn monsters if not -nomonsters
1161: P_SpawnMobj(actor->x, actor->y, actor->z,
1162: TranslateThingType[actor->args[0]]);
1163: }
1164: }
1165: S_StartSound(mo, SFX_SUITOFARMOR_BREAK);
1166: P_RemoveMobj(actor);
1167: }
1168:
1169: //===========================================================================
1170: //
1171: // A_BellReset1
1172: //
1173: //===========================================================================
1174:
1175: void A_BellReset1(mobj_t *actor)
1176: {
1177: actor->flags |= MF_NOGRAVITY;
1178: actor->height <<= 2;
1179: }
1180:
1181: //===========================================================================
1182: //
1183: // A_BellReset2
1184: //
1185: //===========================================================================
1186:
1187: void A_BellReset2(mobj_t *actor)
1188: {
1189: actor->flags |= MF_SHOOTABLE;
1190: actor->flags &= ~MF_CORPSE;
1191: actor->health = 5;
1192: }
1193:
1194:
1195: //===========================================================================
1196: //
1197: // A_FlameCheck
1198: //
1199: //===========================================================================
1200:
1201: void A_FlameCheck(mobj_t *actor)
1202: {
1203: if(!actor->args[0]--) // Called every 8 tics
1204: {
1205: P_SetMobjState(actor, S_NULL);
1206: }
1207: }
1208:
1209:
1210: //===========================================================================
1211: // Bat Spawner Variables
1212: // special1 frequency counter
1213: // special2
1214: // args[0] frequency of spawn (1=fastest, 10=slowest)
1215: // args[1] spread angle (0..255)
1216: // args[2]
1217: // args[3] duration of bats (in octics)
1218: // args[4] turn amount per move (in degrees)
1219: //
1220: // Bat Variables
1221: // special2 lifetime counter
1222: // args[4] turn amount per move (in degrees)
1223: //===========================================================================
1224:
1225: void A_BatSpawnInit(mobj_t *actor)
1226: {
1227: actor->special1 = 0; // Frequency count
1228: }
1229:
1230: void A_BatSpawn(mobj_t *actor)
1231: {
1232: mobj_t *mo;
1233: int delta;
1234: angle_t angle;
1235:
1236: // Countdown until next spawn
1237: if (actor->special1-- > 0) return;
1238: actor->special1 = actor->args[0]; // Reset frequency count
1239:
1240: delta = actor->args[1];
1241: if (delta==0) delta=1;
1242: angle = actor->angle + (((P_Random()%delta)-(delta>>1))<<24);
1243: mo = P_SpawnMissileAngle(actor, MT_BAT, angle, 0);
1244: if (mo)
1245: {
1246: mo->args[0] = P_Random()&63; // floatbob index
1247: mo->args[4] = actor->args[4]; // turn degrees
1248: mo->special2 = actor->args[3]<<3; // Set lifetime
1249: mo->target = actor;
1250: }
1251: }
1252:
1253:
1254: void A_BatMove(mobj_t *actor)
1255: {
1256: angle_t newangle;
1257: fixed_t speed;
1258:
1259: if (actor->special2 < 0)
1260: {
1261: P_SetMobjState(actor, actor->info->deathstate);
1262: }
1263: actor->special2 -= 2; // Called every 2 tics
1264:
1265: if (P_Random()<128)
1266: {
1267: newangle = actor->angle + ANGLE_1*actor->args[4];
1268: }
1269: else
1270: {
1271: newangle = actor->angle - ANGLE_1*actor->args[4];
1272: }
1273:
1274: // Adjust momentum vector to new direction
1275: newangle >>= ANGLETOFINESHIFT;
1276: speed = FixedMul(actor->info->speed, P_Random()<<10);
1277: actor->momx = FixedMul(speed, finecosine[newangle]);
1278: actor->momy = FixedMul(speed, finesine[newangle]);
1279:
1280: if (P_Random()<15)
1281: S_StartSound(actor, SFX_BAT_SCREAM);
1282:
1283: // Handle Z movement
1284: actor->z = actor->target->z + 2*FloatBobOffsets[actor->args[0]];
1285: actor->args[0] = (actor->args[0]+3)&63;
1286: }
1287:
1288: //===========================================================================
1289: //
1290: // A_TreeDeath
1291: //
1292: //===========================================================================
1293:
1294: void A_TreeDeath(mobj_t *actor)
1295: {
1296: if(!(actor->flags2&MF2_FIREDAMAGE))
1297: {
1298: actor->height <<= 2;
1299: actor->flags |= MF_SHOOTABLE;
1300: actor->flags &= ~(MF_CORPSE+MF_DROPOFF);
1301: actor->health = 35;
1302: return;
1303: }
1304: else
1305: {
1306: P_SetMobjState(actor, actor->info->meleestate);
1307: }
1308: }
1309:
1310: //===========================================================================
1311: //
1312: // A_NoGravity
1313: //
1314: //===========================================================================
1315:
1316: void A_NoGravity(mobj_t *actor)
1317: {
1318: actor->flags |= MF_NOGRAVITY;
1319: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.