A_RemoteAction is an action which is used to make the actor tell a target Object to perform an action remotely. Var1 is used to select the target Object, with -1 referring to the actor's target, -2 to the actor's tracer, and all other numbers referring to an Object type to search for; in this case, the actor will choose the closest available Object of the selected type horizontally (Z positions are ignored). Var2 is used to specify the reference state that contains the action for the target Object to perform. The reference state is not actually executed, only the action is performed, so any attributes beside Var1 and Var2 are disregarded. The actor will temporarily make the selected Object its target when calling the reference state's action; the actor's original target (or lack of) will be restored afterwards.
Note that when Var1 is set to target or tracer when the actor does not have one, the reference state's action will not be used.
This action originates from the v1.09.4 modification ShufflarB2 and was added to SRB2 itself in v2.0.
Code – A_RemoteAction
// Function: A_RemoteAction
// Description: var1 is the remote object. var2 is the state reference for calling the action called on var1. var1 becomes the actor's target, the action (var2) is called on var1. actor's target is restored
// var1 = remote object (-2 uses tracer, -1 uses target)
// var2 = state reference for calling an action
void A_RemoteAction(mobj_t *actor)
INT32 locvar1 = var1;
INT32 locvar2 = var2;
mobj_t *originaltarget = actor->target; // Hold on to the target for later.
if (LUA_CallAction("A_RemoteAction", actor))
// If >=0, find the closest target.
if (locvar1 >= 0)
///* DO A_FINDTARGET STUFF *///
mobj_t *targetedmobj = NULL;
fixed_t dist1 = 0, dist2 = 0;
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1)
if (targetedmobj == NULL)
targetedmobj = mo2;
dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y);
dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y);
if ((locvar2 && dist1 < dist2) || (!locvar2 && dist1 > dist2))
targetedmobj = mo2;
dist2 = dist1;
CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Unable to find the specified object to target.\n");
return; // Oops, nothing found..
CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Found a target.\n");
///* END A_FINDTARGET STUFF *///
// If -2, use the tracer as the target
else if (locvar1 == -2)
// if -1 or anything else, just use the target.
// Steal the var1 and var2 from "locvar2"
var1 = states[locvar2].var1;
var2 = states[locvar2].var2;
astate = &states[locvar2];
CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n"
"var1 is %d\nvar2 is %d\n", actor->target, var1, var2);
P_SetTarget(&actor->target, originaltarget); // Restore the original target.