2 //**************************************************************************
4 //** a_action.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
19 // MACROS ------------------------------------------------------------------
21 // TYPES -------------------------------------------------------------------
23 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
25 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
27 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
29 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
30 extern fixed_t FloatBobOffsets[64];
32 // PUBLIC DATA DEFINITIONS -------------------------------------------------
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
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
105 // PRIVATE DATA DEFINITIONS ------------------------------------------------
107 // CODE --------------------------------------------------------------------
109 //--------------------------------------------------------------------------
111 // Environmental Action routines
113 //--------------------------------------------------------------------------
115 //==========================================================================
119 //==========================================================================
122 void A_DripBlood(mobj_t *actor)
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;
134 //============================================================================
138 //============================================================================
140 void A_PotteryExplode(mobj_t *actor)
145 for(i = (P_Random()&3)+3; i; i--)
147 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_POTTERYBIT1);
148 P_SetMobjState(mo, mo->info->spawnstate+(P_Random()%5));
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);
156 S_StartSound(mo, SFX_POTTERY_EXPLODE);
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]]);
169 //============================================================================
171 // A_PotteryChooseBit
173 //============================================================================
175 void A_PotteryChooseBit(mobj_t *actor)
177 P_SetMobjState(actor, actor->info->deathstate+(P_Random()%5)+1);
178 actor->tics = 256+(P_Random()<<1);
181 //============================================================================
185 //============================================================================
187 void A_PotteryCheck(mobj_t *actor)
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);
207 for(i = 0; i < MAXPLAYERS; i++)
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);
224 //============================================================================
228 //============================================================================
230 void A_CorpseBloodDrip(mobj_t *actor)
236 P_SpawnMobj(actor->x, actor->y, actor->z+actor->height/2,
240 //============================================================================
244 //============================================================================
246 void A_CorpseExplode(mobj_t *actor)
251 for(i = (P_Random()&3)+3; i; i--)
253 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT);
254 P_SetMobjState(mo, mo->info->spawnstate+(P_Random()%3));
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);
263 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT);
264 P_SetMobjState(mo, S_CORPSEBIT_4);
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);
275 //============================================================================
279 //============================================================================
281 void A_LeafSpawn(mobj_t *actor)
286 for(i = (P_Random()&3)+1; i; i--)
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));
293 P_ThrustMobj(mo, actor->angle, (P_Random()<<9)+3*FRACUNIT);
300 //============================================================================
304 //============================================================================
306 void A_LeafThrust(mobj_t *actor)
312 actor->momz += (P_Random()<<9)+FRACUNIT;
315 //============================================================================
319 //============================================================================
321 void A_LeafCheck(mobj_t *actor)
324 if(actor->special1 >= 20)
326 P_SetMobjState(actor, S_NULL);
331 if(!actor->momx && !actor->momy)
333 P_ThrustMobj(actor, actor->target->angle,
334 (P_Random()<<9)+FRACUNIT);
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;
345 #define ORBIT_RADIUS (15*FRACUNIT)
346 void GenerateOrbitTable(void)
350 for (angle=0; angle<256; angle++)
352 orbitTableX[angle] = FixedMul(ORBIT_RADIUS, finecosine[angle<<5]);
353 orbitTableY[angle] = FixedMul(ORBIT_RADIUS, finesine[angle<<5]);
356 printf("int orbitTableX[256]=\n{\n");
357 for (angle=0; angle<256; angle+=8)
359 printf("%d, %d, %d, %d, %d, %d, %d, %d,\n",
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]);
371 printf("int orbitTableY[256]=\n{\n");
372 for (angle=0; angle<256; angle+=8)
374 printf("%d, %d, %d, %d, %d, %d, %d, %d,\n",
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]);
390 // special1 true == removing from world
393 // target pointer to center mobj
394 // args[0] angle of ball
396 void A_BridgeOrbit(mobj_t *actor)
398 if (actor->target->special1)
400 P_SetMobjState(actor, S_NULL);
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;
409 void A_BridgeInit(mobj_t *actor)
412 mobj_t *ball1, *ball2, *ball3;
415 // GenerateOrbitTable();
420 startangle = P_Random();
423 // Spawn triad into world
424 ball1 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
425 ball1->args[0] = startangle;
426 ball1->target = actor;
428 ball2 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
429 ball2->args[0] = (startangle+85)&255;
430 ball2->target = actor;
432 ball3 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL);
433 ball3->args[0] = (startangle+170)&255;
434 ball3->target = actor;
436 A_BridgeOrbit(ball1);
437 A_BridgeOrbit(ball2);
438 A_BridgeOrbit(ball3);
441 void A_BridgeRemove(mobj_t *actor)
443 actor->special1 = true; // Removing the bridge
444 actor->flags &= ~MF_SOLID;
445 P_SetMobjState(actor, S_FREE_BRIDGE1);
449 //==========================================================================
453 //==========================================================================
456 void A_GhostOn(mobj_t *actor)
458 actor->flags |= MF_SHADOW;
462 //==========================================================================
466 //==========================================================================
469 void A_GhostOff(mobj_t *actor)
471 actor->flags &= ~MF_SHADOW;
475 //==========================================================================
479 //==========================================================================
481 void A_HideThing(mobj_t *actor)
483 actor->flags2 |= MF2_DONTDRAW;
486 //==========================================================================
490 //==========================================================================
492 void A_UnHideThing(mobj_t *actor)
494 actor->flags2 &= ~MF2_DONTDRAW;
497 //==========================================================================
501 //==========================================================================
503 void A_SetShootable(mobj_t *actor)
505 actor->flags2 &= ~MF2_NONSHOOTABLE;
506 actor->flags |= MF_SHOOTABLE;
509 //==========================================================================
513 //==========================================================================
515 void A_UnSetShootable(mobj_t *actor)
517 actor->flags2 |= MF2_NONSHOOTABLE;
518 actor->flags &= ~MF_SHOOTABLE;
521 //==========================================================================
525 //==========================================================================
527 void A_SetAltShadow(mobj_t *actor)
529 actor->flags &= ~MF_SHADOW;
530 actor->flags |= MF_ALTSHADOW;
533 //==========================================================================
537 //==========================================================================
540 void A_UnSetAltShadow(mobj_t *actor)
542 actor->flags &= ~MF_ALTSHADOW;
546 //--------------------------------------------------------------------------
548 // Sound Action Routines
550 //--------------------------------------------------------------------------
552 //==========================================================================
556 //==========================================================================
558 void A_ContMobjSound(mobj_t *actor)
563 S_StartSound(actor, SFX_SERPENTFX_CONTINUOUS);
565 case MT_HAMMER_MISSILE:
566 S_StartSound(actor, SFX_FIGHTER_HAMMER_CONTINUOUS);
569 S_StartSound(actor, SFX_EARTHQUAKE);
576 //==========================================================================
580 //==========================================================================
582 void A_ESound(mobj_t *mo)
595 S_StartSound(mo, sound);
600 //==========================================================================
601 // Summon Minotaur -- see p_enemy for variable descriptions
602 //==========================================================================
605 void A_Summon(mobj_t *actor)
610 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINOTAUR);
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;
621 memcpy((void *)mo->args, &leveltime, sizeof(leveltime));
622 master = (mobj_t *)actor->special1;
623 if (master->flags&MF_CORPSE)
625 mo->special1 = 0; // No master
629 mo->special1 = actor->special1; // Pointer to master (mobj_t *)
630 P_GivePower(master->player, pw_minotaur);
634 P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE);
635 S_StartSound(actor, SFX_MAULATOR_ACTIVE);
641 //==========================================================================
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
652 //==========================================================================
654 void A_FogSpawn(mobj_t *actor)
659 if (actor->special1-- > 0) return;
661 actor->special1 = actor->args[2]; // Reset frequency count
666 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHS);
669 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHM);
672 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHL);
678 delta = actor->args[1];
679 if (delta==0) delta=1;
680 mo->angle = actor->angle + (((P_Random()%delta)-(delta>>1))<<24);
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;
691 void A_FogMove(mobj_t *actor)
693 int speed = actor->args[0]<<FRACBITS;
697 if (!(actor->args[4])) return;
699 if (actor->args[3]-- <= 0)
701 P_SetMobjStateNF(actor, actor->info->deathstate);
705 if ((actor->args[3] % 4) == 0)
707 weaveindex = actor->special2;
708 actor->z += FloatBobOffsets[weaveindex]>>1;
709 actor->special2 = (weaveindex+1)&63;
712 angle = actor->angle>>ANGLETOFINESHIFT;
713 actor->momx = FixedMul(speed, finecosine[angle]);
714 actor->momy = FixedMul(speed, finesine[angle]);
717 //===========================================================================
721 //===========================================================================
723 void A_PoisonBagInit(mobj_t *actor)
727 mo = P_SpawnMobj(actor->x, actor->y, actor->z+28*FRACUNIT,
733 mo->momx = 1; // missile objects must move to impact other objects
734 mo->special1 = 24+(P_Random()&7);
736 mo->target = actor->target;
737 mo->radius = 20*FRACUNIT;
738 mo->height = 30*FRACUNIT;
739 mo->flags &= ~MF_NOCLIP;
742 //===========================================================================
746 //===========================================================================
748 void A_PoisonBagCheck(mobj_t *actor)
750 if(!--actor->special1)
752 P_SetMobjState(actor, S_POISONCLOUD_X1);
760 //===========================================================================
764 //===========================================================================
766 void A_PoisonBagDamage(mobj_t *actor)
770 extern void A_Explode(mobj_t *actor);
774 bobIndex = actor->special2;
775 actor->z += FloatBobOffsets[bobIndex]>>4;
776 actor->special2 = (bobIndex+1)&63;
779 //===========================================================================
783 //===========================================================================
785 void A_PoisonShroom(mobj_t *actor)
787 actor->tics = 128+(P_Random()<<1);
790 //===========================================================================
794 //===========================================================================
796 void A_CheckThrowBomb(mobj_t *actor)
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])
802 P_SetMobjState(actor, S_THROWINGBOMB7);
803 actor->z = actor->floorz;
805 actor->flags2 &= ~MF2_FLOORBOUNCE;
806 actor->flags &= ~MF_MISSILE;
810 P_SetMobjState(actor, actor->info->deathstate);
814 //===========================================================================
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
823 //===========================================================================
825 //===========================================================================
829 //===========================================================================
831 boolean A_LocalQuake(byte *args, mobj_t *actor)
833 mobj_t *focus, *target;
837 actor=actor; // suppress warning
839 // Find all quake foci
842 target = P_FindMobjFromTID(args[4], &lastfound);
845 focus = P_SpawnMobj(target->x,
847 target->z, MT_QUAKE_FOCUS);
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];
858 }while(target != NULL);
864 //===========================================================================
868 //===========================================================================
869 int localQuakeHappening[MAXPLAYERS];
871 void A_Quake(mobj_t *actor)
876 int richters = actor->args[0];
880 if (actor->args[1]-- > 0)
882 for (playnum=0; playnum < MAXPLAYERS; playnum++)
884 player = &players[playnum];
885 if (!playeringame[playnum]) continue;
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
893 localQuakeHappening[playnum] = richters;
895 // Check if in damage radius
896 if ((dist < actor->args[2]) &&
897 (victim->z <= victim->floorz))
901 P_DamageMobj(victim, NULL, NULL, HITDICE(1));
903 // Thrust player around
904 an = victim->angle + ANGLE_1*P_Random();
905 P_ThrustMobj(victim,an,richters<<(FRACBITS-1));
911 for (playnum=0; playnum < MAXPLAYERS; playnum++)
913 localQuakeHappening[playnum] = false;
915 P_SetMobjState(actor, S_NULL);
922 //===========================================================================
924 // Teleport other stuff
926 //===========================================================================
928 #define TELEPORT_LIFE 1
930 void A_TeloSpawnA(mobj_t *actor)
934 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX2);
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;
946 void A_TeloSpawnB(mobj_t *actor)
950 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX3);
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;
962 void A_TeloSpawnC(mobj_t *actor)
966 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX4);
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;
978 void A_TeloSpawnD(mobj_t *actor)
982 mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX5);
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;
994 void A_CheckTeleRing(mobj_t *actor)
996 if (actor->special1-- <= 0)
998 P_SetMobjState(actor, actor->info->deathstate);
1007 void P_SpawnDirt(mobj_t *actor, fixed_t radius)
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)
1041 mo = P_SpawnMobj(x,y,z,dtype);
1044 mo->momz = P_Random()<<10;
1051 //===========================================================================
1053 // Thrust floor stuff
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 //===========================================================================
1062 void A_ThrustInitUp(mobj_t *actor)
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;
1072 void A_ThrustInitDn(mobj_t *actor)
1075 actor->special2 = 5; // Raise speed
1076 actor->args[0] = 0; // Mark as down
1077 actor->floorclip = actor->info->height;
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;
1085 void A_ThrustRaise(mobj_t *actor)
1087 if (A_RaiseMobj(actor))
1088 { // Reached it's target height
1091 P_SetMobjStateNF(actor, S_BTHRUSTINIT2_1);
1093 P_SetMobjStateNF(actor, S_THRUSTINIT2_1);
1096 // Lose the dirt clump
1097 if ((actor->floorclip < actor->height) && actor->special1)
1099 P_RemoveMobj( (mobj_t *)actor->special1 );
1100 actor->special1 = 0;
1105 P_SpawnDirt(actor, actor->radius);
1106 actor->special2++; // Increase raise speed
1109 void A_ThrustLower(mobj_t *actor)
1111 if (A_SinkMobj(actor))
1115 P_SetMobjStateNF(actor, S_BTHRUSTINIT1_1);
1117 P_SetMobjStateNF(actor, S_THRUSTINIT1_1);
1121 void A_ThrustBlock(mobj_t *actor)
1123 actor->flags |= MF_SOLID;
1126 void A_ThrustImpale(mobj_t *actor)
1128 // Impale all shootables in radius
1129 PIT_ThrustSpike(actor);
1132 //===========================================================================
1134 // A_SoAExplode - Suit of Armor Explode
1136 //===========================================================================
1138 void A_SoAExplode(mobj_t *actor)
1143 for(i = 0; i < 10; i++)
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);
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);
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]]);
1165 S_StartSound(mo, SFX_SUITOFARMOR_BREAK);
1166 P_RemoveMobj(actor);
1169 //===========================================================================
1173 //===========================================================================
1175 void A_BellReset1(mobj_t *actor)
1177 actor->flags |= MF_NOGRAVITY;
1178 actor->height <<= 2;
1181 //===========================================================================
1185 //===========================================================================
1187 void A_BellReset2(mobj_t *actor)
1189 actor->flags |= MF_SHOOTABLE;
1190 actor->flags &= ~MF_CORPSE;
1195 //===========================================================================
1199 //===========================================================================
1201 void A_FlameCheck(mobj_t *actor)
1203 if(!actor->args[0]--) // Called every 8 tics
1205 P_SetMobjState(actor, S_NULL);
1210 //===========================================================================
1211 // Bat Spawner Variables
1212 // special1 frequency counter
1214 // args[0] frequency of spawn (1=fastest, 10=slowest)
1215 // args[1] spread angle (0..255)
1217 // args[3] duration of bats (in octics)
1218 // args[4] turn amount per move (in degrees)
1221 // special2 lifetime counter
1222 // args[4] turn amount per move (in degrees)
1223 //===========================================================================
1225 void A_BatSpawnInit(mobj_t *actor)
1227 actor->special1 = 0; // Frequency count
1230 void A_BatSpawn(mobj_t *actor)
1236 // Countdown until next spawn
1237 if (actor->special1-- > 0) return;
1238 actor->special1 = actor->args[0]; // Reset frequency count
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);
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
1254 void A_BatMove(mobj_t *actor)
1259 if (actor->special2 < 0)
1261 P_SetMobjState(actor, actor->info->deathstate);
1263 actor->special2 -= 2; // Called every 2 tics
1267 newangle = actor->angle + ANGLE_1*actor->args[4];
1271 newangle = actor->angle - ANGLE_1*actor->args[4];
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]);
1281 S_StartSound(actor, SFX_BAT_SCREAM);
1283 // Handle Z movement
1284 actor->z = actor->target->z + 2*FloatBobOffsets[actor->args[0]];
1285 actor->args[0] = (actor->args[0]+3)&63;
1288 //===========================================================================
1292 //===========================================================================
1294 void A_TreeDeath(mobj_t *actor)
1296 if(!(actor->flags2&MF2_FIREDAMAGE))
1298 actor->height <<= 2;
1299 actor->flags |= MF_SHOOTABLE;
1300 actor->flags &= ~(MF_CORPSE+MF_DROPOFF);
1306 P_SetMobjState(actor, actor->info->meleestate);
1310 //===========================================================================
1314 //===========================================================================
1316 void A_NoGravity(mobj_t *actor)
1318 actor->flags |= MF_NOGRAVITY;