A_VileFire is an action that is used as the thinker for Brak Eggman's targeting reticule. It was originally used in Doom for the Archvile's fire attack, hence the name.
Similarly to A_CapeChase
, this action immediately sets the actor's position to be 24 fracunits in front of the actor's tracer, but only if the actor's target has a line of sight to the actor's tracer. When called every tic, this makes the actor follow its tracer. If Var1 is set to a valid sound number, that sound is played. If Var2's lower 16 bits are set to a valid Object type, a line consisting of Objects of that type is spawned between the actor and its target. The number of Objects in the line is set by Var2's upper 16 bits; if they are 0, it defaults to 8 Objects.
In the context of this action's usage as the thinker for Brak Eggman's targeting reticule, the actor is the targeting reticule, the target is Brak Eggman and the tracer is the player targeted by the attack. Thus, this action makes the targeting reticule follow the player as long as Brak Eggman has a line of sight to the player. The line of spawned Objects is used to indicate the line of sight.
Code – A_VileFire
|
|
// Function: A_VileFire
//
// Description: Kind of like A_CapeChase; keeps this object in front of its tracer, unless its target can't see it.
// Originally used by Archviles to keep their hellfire pillars on top of the player, hence the name (although it was just "A_Fire" there; added "Vile" to make it more specific).
// Added some functionality to optionally draw a line directly to the enemy doing the targetting. Y'know, to hammer things in a bit.
//
// var1 = sound to play
// var2:
// Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all)
// Upper 16 bits = # to spawn (default is 8)
//
void A_VileFire(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
mobj_t *dest;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_VileFire", actor))
return;
#endif
dest = actor->tracer;
if (!dest)
return;
// don't move it if the vile lost sight
if (!P_CheckSight(actor->target, dest))
return;
// keep to same scale and gravity as tracer ALWAYS
actor->destscale = dest->scale;
P_SetScale(actor, actor->destscale);
if (dest->eflags & MFE_VERTICALFLIP)
{
actor->eflags |= MFE_VERTICALFLIP;
actor->flags2 |= MF2_OBJECTFLIP;
}
else
{
actor->eflags &= ~MFE_VERTICALFLIP;
actor->flags2 &= ~MF2_OBJECTFLIP;
}
P_UnsetThingPosition(actor);
actor->x = dest->x + P_ReturnThrustX(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale));
actor->y = dest->y + P_ReturnThrustY(actor, dest->angle, FixedMul(24*FRACUNIT, actor->scale));
actor->z = dest->z + ((actor->eflags & MFE_VERTICALFLIP) ? dest->height-actor->height : 0);
P_SetThingPosition(actor);
// Play sound, if one's specified
if (locvar1 > 0 && locvar1 < NUMSFX)
S_StartSound(actor, (sfxenum_t)locvar1);
// Now draw the line to the actor's target
if (locvar2 & 0xFFFF)
{
mobjtype_t lineMobj;
UINT16 numLineMobjs;
fixed_t distX;
fixed_t distY;
fixed_t distZ;
UINT16 i;
lineMobj = (mobjtype_t)(locvar2 & 0xFFFF);
numLineMobjs = (UINT16)(locvar2 >> 16);
if (numLineMobjs == 0) {
numLineMobjs = 8;
}
// Get distance for each step
distX = (actor->target->x - actor->x) / numLineMobjs;
distY = (actor->target->y - actor->y) / numLineMobjs;
distZ = ((actor->target->z + FixedMul(actor->target->height/2, actor->target->scale)) - (actor->z + FixedMul(actor->height/2, actor->scale))) / numLineMobjs;
for (i = 1; i <= numLineMobjs; i++)
{
P_SpawnMobj(actor->x + (distX * i), actor->y + (distY * i), actor->z + (distZ * i) + FixedMul(actor->height/2, actor->scale), lineMobj);
}
}
}
|
|