|
This article or section is outdated and has not been fully updated to reflect the current version of SRB2.
Please help the Wiki by correcting or removing any misinformation, as well as adding any new information to the page.
|
|
To do Update for 2.2.0:
- Var1 has a new option to be documented
- Egg Mobile doesn't actually use this for attacking anymore, only for flying away from the player after being hit
|
A_SkullAttack is the standard attack of the Lost Souls from Doom, repurposed for use in SRB2. If a target is in range, the Object plays its ActiveSound
and flies like a missile in a direction relative to it, depending on the value of Var1. If Var1 is 0, it will charge directly at the target; if set to 1, it dashes away from the target; if set to 2, it strafes relative to the target (randomly chooses between left or right). Var2 determines whether the actor will fly both vertically and horizontally (Var2 = 0), or just horizontally (Var2 = 1).
Unlike with actions such as A_Chase
, A_SkullAttack
doesn't need to be called repeatedly for most purposes – it gives the actor MF2_SKULLFLY
, preventing the momentum given (a fixed speed of 20 fracunits/tic) from being lost until the actor crashes into an Object or wall (removing MF2_SKULLFLY
), and allowing the actor to bounce off any floor/ceiling it hits. Exclusively for the Egg Mobile and custom Objects with MF_BOSS
, the actor additionally spawns ghosts of itself.
Note: The Egg Mobile interprets this slightly differently, charging directly at the target, and dashing through them. This only works for the Egg Mobile, and should not be confused with the action's normal effect. Objects that desire this behavior should either replace the Egg Mobile Object itself, or toggle the flag MF_NOCLIPTHING
(which will prevent it from ceasing the attack before colliding with the target, but, since it removes most collision checks against other Things, will also have its own side effects).
Code – A_SkullAttack
|
|
// Function: A_SkullAttack
//
// Description: Fly at the player like a missile.
//
// var1:
// 0 - Fly at the player
// 1 - Fly away from the player
// 2 - Strafe in relation to the player
// 3 - Dynamic mode - don't get too close to walls
// var2:
// 0 - Fly horizontally and vertically
// 1 - Fly horizontal-only (momz = 0)
//
#define SKULLSPEED (20*FRACUNIT)
void A_SkullAttack(mobj_t *actor)
{
mobj_t *dest;
angle_t an;
INT32 dist;
INT32 speed;
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SkullAttack", actor))
return;
#endif
if (!actor->target)
return;
speed = FixedMul(SKULLSPEED, actor->scale);
dest = actor->target;
actor->flags2 |= MF2_SKULLFLY;
if (actor->info->activesound)
S_StartSound(actor, actor->info->activesound);
A_FaceTarget(actor);
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
if (locvar1 == 1)
actor->angle += ANGLE_180;
else if (locvar1 == 2)
actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90;
else if (locvar1 == 3)
{
statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate;
UINT32 oldflags = mobjinfo[MT_NULL].flags;
fixed_t oldradius = mobjinfo[MT_NULL].radius;
fixed_t oldheight = mobjinfo[MT_NULL].height;
mobj_t *check;
INT32 i, j;
static INT32 k;/* static for (at least) GCC 9.1 weirdness */
boolean allow;
angle_t testang = 0;
mobjinfo[MT_NULL].spawnstate = S_INVISIBLE;
mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP;
mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius;
mobjinfo[MT_NULL].height = mobjinfo[actor->type].height;
if (P_RandomChance(FRACUNIT/2)) // port priority 1?
{
i = 9;
j = 27;
}
else
{
i = 27;
j = 9;
}
#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\
testang = actor->angle + ((i+(q))*ANG10);\
allow = (P_TryMove(check,\
P_ReturnThrustX(check, testang, dist + 2*actor->radius),\
P_ReturnThrustY(check, testang, dist + 2*actor->radius),\
true));\
P_RemoveMobj(check);\
if (allow)\
break;
if (P_RandomChance(FRACUNIT/2)) // port priority 2?
{
for (k = 0; k < 9; k++)
{
dostuff(i+k)
dostuff(i-k)
dostuff(j+k)
dostuff(j-k)
}
}
else
{
for (k = 0; k < 9; k++)
{
dostuff(i-k)
dostuff(i+k)
dostuff(j-k)
dostuff(j+k)
}
}
actor->angle = testang;
#undef dostuff
mobjinfo[MT_NULL].spawnstate = oldspawnstate;
mobjinfo[MT_NULL].flags = oldflags;
mobjinfo[MT_NULL].radius = oldradius;
mobjinfo[MT_NULL].height = oldheight;
}
an = actor->angle >> ANGLETOFINESHIFT;
actor->momx = FixedMul(speed, FINECOSINE(an));
actor->momy = FixedMul(speed, FINESINE(an));
dist = dist / speed;
if (dist < 1)
dist = 1;
actor->momz = (dest->z + (dest->height>>1) - actor->z) / dist;
if (locvar1 == 1)
actor->momz = -actor->momz;
if (locvar2 == 1)
actor->momz = 0;
}
|
|