mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 17:22:12 +00:00
* All Flicky A_ functions ported.
* Corrected MT_EGGSHIELD spawning a flicky. * New compared to the Lua implementation: Flickies turn around when they hit walls!
This commit is contained in:
parent
bf8bff82ba
commit
d3a70eb1db
6 changed files with 374 additions and 4 deletions
|
@ -1937,6 +1937,15 @@ static actionpointer_t actionpointers[] =
|
|||
{{A_NapalmScatter}, "A_NAPALMSCATTER"},
|
||||
{{A_SpawnFreshCopy}, "A_SPAWNFRESHCOPY"},
|
||||
{{A_FlickySpawn}, "A_FLICKYSPAWN"},
|
||||
{{A_FlickyAim}, "A_FLICKYAIM"},
|
||||
{{A_FlickyFly}, "A_FLICKYFLY"},
|
||||
{{A_FlickySoar}, "A_FLICKYSOAR"},
|
||||
{{A_FlickyCoast}, "A_FLICKYCOAST"},
|
||||
{{A_FlickyHop}, "A_FLICKYHOP"},
|
||||
{{A_FlickyFlounder}, "A_FLICKYFLOUNDER"},
|
||||
{{A_FlickyCheck}, "A_FLICKYCHECK"},
|
||||
{{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"},
|
||||
{{A_FlickyFlutter}, "A_FLICKYFLUTTER"},
|
||||
|
||||
{{NULL}, "NONE"},
|
||||
|
||||
|
|
|
@ -3602,7 +3602,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_s3k7b, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_XPLD_FLICKY, // deathstate
|
||||
S_XPLD1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_wbreak, // deathsound
|
||||
3, // speed
|
||||
|
|
|
@ -215,6 +215,15 @@ void A_BrakLobShot();
|
|||
void A_NapalmScatter();
|
||||
void A_SpawnFreshCopy();
|
||||
void A_FlickySpawn();
|
||||
void A_FlickyAim();
|
||||
void A_FlickyFly();
|
||||
void A_FlickySoar();
|
||||
void A_FlickyCoast();
|
||||
void A_FlickyHop();
|
||||
void A_FlickyFlounder();
|
||||
void A_FlickyCheck();
|
||||
void A_FlickyHeightCheck();
|
||||
void A_FlickyFlutter();
|
||||
|
||||
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
||||
#define NUMMOBJFREESLOTS 256
|
||||
|
|
352
src/p_enemy.c
352
src/p_enemy.c
|
@ -243,6 +243,15 @@ void A_BrakLobShot(mobj_t *actor);
|
|||
void A_NapalmScatter(mobj_t *actor);
|
||||
void A_SpawnFreshCopy(mobj_t *actor);
|
||||
void A_FlickySpawn(mobj_t *actor);
|
||||
void A_FlickyAim(mobj_t *actor);
|
||||
void A_FlickyFly(mobj_t *actor);
|
||||
void A_FlickySoar(mobj_t *actor);
|
||||
void A_FlickyCoast(mobj_t *actor);
|
||||
void A_FlickyHop(mobj_t *actor);
|
||||
void A_FlickyFlounder(mobj_t *actor);
|
||||
void A_FlickyCheck(mobj_t *actor);
|
||||
void A_FlickyHeightCheck(mobj_t *actor);
|
||||
void A_FlickyFlutter(mobj_t *actor);
|
||||
|
||||
//
|
||||
// ENEMY THINKING
|
||||
|
@ -10339,7 +10348,6 @@ void A_SpawnFreshCopy(mobj_t *actor)
|
|||
}
|
||||
|
||||
// Internal Flicky spawning function.
|
||||
|
||||
mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers)
|
||||
{
|
||||
mobj_t *flicky;
|
||||
|
@ -10371,9 +10379,13 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz
|
|||
flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype);
|
||||
flicky->angle = actor->angle;
|
||||
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
|
||||
|
||||
P_SetObjectMomZ(flicky, momz, false);
|
||||
flicky->movedir = P_RandomChance(FRACUNIT/2) ? -1 : 1;
|
||||
flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1);
|
||||
flicky->fuse = P_RandomRange(595, 700); // originally 300, 350
|
||||
flicky->threshold = 0;
|
||||
|
||||
if (lookforplayers)
|
||||
P_LookForPlayers(flicky, true, false, 0);
|
||||
|
@ -10406,3 +10418,339 @@ void A_FlickySpawn(mobj_t *actor)
|
|||
|
||||
P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true);
|
||||
}
|
||||
|
||||
#define FLICKYHITWALL if (actor->momx == actor->momy && actor->momy == 0) actor->threshold = 1;
|
||||
|
||||
// Internal Flicky bubbling function.
|
||||
void P_InternalFlickyBubble(mobj_t *actor)
|
||||
{
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
mobj_t *overlay;
|
||||
|
||||
if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer)
|
||||
return;
|
||||
|
||||
overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
|
||||
P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate);
|
||||
P_SetTarget(&actor->tracer, overlay);
|
||||
P_SetTarget(&overlay->target, actor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!actor->tracer || P_MobjWasRemoved(actor->tracer))
|
||||
return;
|
||||
|
||||
P_RemoveMobj(actor->tracer);
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
}
|
||||
|
||||
// Function: A_FlickyAim
|
||||
//
|
||||
// Description: Flicky aiming function.
|
||||
//
|
||||
// var1 = how far around the target (in angle constants) the flicky should look
|
||||
// var2 = distance from target to aim for
|
||||
//
|
||||
void A_FlickyAim(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyAim", actor))
|
||||
return;
|
||||
#endif
|
||||
P_InternalFlickyBubble(actor);
|
||||
P_InstaThrust(actor, 0, 0);
|
||||
|
||||
if (!actor->target)
|
||||
{
|
||||
P_LookForPlayers(actor, true, false, 0);
|
||||
actor->angle = P_RandomKey(36)*ANG10;
|
||||
return;
|
||||
}
|
||||
|
||||
if (actor->fuse > 2*TICRATE)
|
||||
{
|
||||
angle_t posvar;
|
||||
fixed_t chasevar, chasex, chasey;
|
||||
|
||||
if (actor->threshold)
|
||||
{
|
||||
actor->movedir *= -1;
|
||||
actor->threshold = 0;
|
||||
}
|
||||
|
||||
posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2;
|
||||
|
||||
chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar);
|
||||
chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar);
|
||||
|
||||
if (P_AproxDistance(chasex - actor->x, chasey - actor->y))
|
||||
actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey);
|
||||
}
|
||||
else if (actor->threshold)
|
||||
{
|
||||
actor->angle += ANGLE_180;
|
||||
actor->threshold = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Internal Flicky flying function. Also usuable as an underwater swim thrust.
|
||||
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez)
|
||||
{
|
||||
angle_t vertangle;
|
||||
|
||||
flyspeed = FixedMul(flyspeed, actor->scale);
|
||||
actor->flags |= MF_NOGRAVITY;
|
||||
|
||||
FLICKYHITWALL
|
||||
|
||||
var1 = ANG30;
|
||||
var2 = 32*FRACUNIT;
|
||||
A_FlickyAim(actor);
|
||||
|
||||
chasez *= 8;
|
||||
if (!actor->target || !(actor->fuse > 2*TICRATE))
|
||||
chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT);
|
||||
else
|
||||
{
|
||||
fixed_t add = actor->target->z + (actor->target->height - actor->height)/2;
|
||||
if (add > (actor->ceilingz - 24*actor->scale - actor->height))
|
||||
add = actor->ceilingz - 24*actor->scale - actor->height;
|
||||
else if (add < (actor->floorz + 24*actor->scale))
|
||||
add = actor->floorz + 24*actor->scale;
|
||||
chasez += add;
|
||||
}
|
||||
|
||||
if (!targetdist)
|
||||
targetdist = 16*FRACUNIT; //Default!
|
||||
|
||||
if (abs(chasez - actor->z) > targetdist)
|
||||
targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
|
||||
|
||||
vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed));
|
||||
actor->momz = FixedMul(FINESINE(vertangle), flyspeed);
|
||||
}
|
||||
|
||||
// Function: A_FlickyFly
|
||||
//
|
||||
// Description: Flicky flying function.
|
||||
//
|
||||
// var1 = how fast to fly
|
||||
// var2 = how far ahead the target should be considered
|
||||
//
|
||||
void A_FlickyFly(mobj_t *actor)
|
||||
{
|
||||
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
|
||||
//INT32 locvar1 = var1;
|
||||
//INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyFly", actor))
|
||||
return;
|
||||
#endif
|
||||
P_InternalFlickyFly(actor, var1, var2,
|
||||
FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK)
|
||||
);
|
||||
}
|
||||
|
||||
// Function: A_FlickySoar
|
||||
//
|
||||
// Description: Flicky soaring function - specific to puffin.
|
||||
//
|
||||
// var1 = how fast to fly
|
||||
// var2 = how far ahead the target should be considered
|
||||
//
|
||||
void A_FlickySoar(mobj_t *actor)
|
||||
{
|
||||
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
|
||||
//INT32 locvar1 = var1;
|
||||
//INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickySoar", actor))
|
||||
return;
|
||||
#endif
|
||||
P_InternalFlickyFly(actor, var1, var2,
|
||||
2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK)))
|
||||
);
|
||||
|
||||
if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_NULL)//SPR_FLKJ)
|
||||
actor->frame = 3;
|
||||
}
|
||||
|
||||
//Function: A_FlickyCoast
|
||||
//
|
||||
// Description: Flicky swim-coasting function.
|
||||
//
|
||||
// var1 = speed to change state upon reaching
|
||||
// var2 = state to change to upon slowing down
|
||||
// the spawnstate of the mobj = state to change to when above water
|
||||
//
|
||||
void A_FlickyCoast(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyCoast", actor))
|
||||
return;
|
||||
#endif
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
FLICKYHITWALL
|
||||
|
||||
actor->momx = (11*actor->momx)/12;
|
||||
actor->momy = (11*actor->momy)/12;
|
||||
actor->momz = (11*actor->momz)/12;
|
||||
|
||||
if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1)
|
||||
P_SetMobjState(actor, locvar2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
actor->flags &= ~MF_NOGRAVITY;
|
||||
P_SetMobjState(actor, mobjinfo[actor->type].spawnstate);
|
||||
}
|
||||
|
||||
// Internal Flicky hopping function.
|
||||
void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle)
|
||||
{
|
||||
if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
|
||||
|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
|
||||
{
|
||||
if (momz)
|
||||
{
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
|
||||
P_SetObjectMomZ(actor, momz, false);
|
||||
}
|
||||
P_InstaThrust(actor, angle, FixedMul(momh, actor->scale));
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_FlickyHop
|
||||
//
|
||||
// Description: Flicky hopping function.
|
||||
//
|
||||
// var1 = vertical thrust
|
||||
// var2 = horizontal thrust
|
||||
//
|
||||
void A_FlickyHop(mobj_t *actor)
|
||||
{
|
||||
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyHop instead.
|
||||
//INT32 locvar1 = var1;
|
||||
//INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyHop", actor))
|
||||
return;
|
||||
#endif
|
||||
P_InternalFlickyHop(actor, var1, var2, actor->angle);
|
||||
}
|
||||
|
||||
// Function: A_FlickyFlounder
|
||||
//
|
||||
// Description: Flicky floundering function.
|
||||
//
|
||||
// var1 = intended vertical thrust
|
||||
// var2 = intended horizontal thrust
|
||||
//
|
||||
void A_FlickyFlounder(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
angle_t hopangle;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyFlounder", actor))
|
||||
return;
|
||||
#endif
|
||||
locvar1 *= (P_RandomKey(2) + 1);
|
||||
locvar2 *= (P_RandomKey(2) + 1);
|
||||
hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2);
|
||||
P_InternalFlickyHop(actor, locvar1, locvar2, hopangle);
|
||||
}
|
||||
|
||||
// Function: A_FlickyCheck
|
||||
//
|
||||
// Description: Flicky airtime check function.
|
||||
//
|
||||
// var1 = state to change to upon touching the floor
|
||||
// var2 = state to change to upon falling
|
||||
// the meleestate of the mobj = state to change to when underwater
|
||||
//
|
||||
void A_FlickyCheck(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyCheck", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
FLICKYHITWALL
|
||||
|
||||
if (locvar2 && P_MobjFlip(actor)*actor->momz < 1)
|
||||
P_SetMobjState(actor, locvar2);
|
||||
else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
|
||||
|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
|
||||
P_SetMobjState(actor, locvar1);
|
||||
else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER))
|
||||
P_SetMobjState(actor, mobjinfo[actor->type].meleestate);
|
||||
P_InternalFlickyBubble(actor);
|
||||
}
|
||||
|
||||
// Function: A_FlickyHeightCheck
|
||||
//
|
||||
// Description: Flicky height check function.
|
||||
//
|
||||
// var1 = state to change to when falling below height relative to target
|
||||
// var2 = height relative to target to change state at
|
||||
//
|
||||
void A_FlickyHeightCheck(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyHeightCheck", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
FLICKYHITWALL
|
||||
|
||||
if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1
|
||||
&& ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2)
|
||||
|| (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz)))
|
||||
P_SetMobjState(actor, locvar1);
|
||||
P_InternalFlickyBubble(actor);
|
||||
}
|
||||
|
||||
// Function: A_FlickyFlutter
|
||||
//
|
||||
// Description: Flicky fluttering function - specific to chicken.
|
||||
//
|
||||
// var1 = state to change to upon touching the floor
|
||||
// var2 = state to change to upon falling
|
||||
// the meleestate of the mobj = state to change to when underwater
|
||||
//
|
||||
void A_FlickyFlutter(mobj_t *actor)
|
||||
{
|
||||
// We're not setting up locvars here - it passes var1 and var2 through to A_FlickyCheck instead.
|
||||
//INT32 locvar1 = var1;
|
||||
//INT32 locvar2 = var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlickyFlutter", actor))
|
||||
return;
|
||||
#endif
|
||||
A_FlickyCheck(actor);
|
||||
|
||||
var1 = ANG30;
|
||||
var2 = 32*FRACUNIT;
|
||||
A_FlickyAim(actor);
|
||||
|
||||
P_InstaThrust(actor, actor->angle, 2*actor->scale);
|
||||
if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2)
|
||||
actor->momz = -P_MobjFlip(actor)*actor->scale/2;
|
||||
}
|
||||
|
||||
#undef FLICKYHITWALL
|
|
@ -296,6 +296,9 @@ void P_NewChaseDir(mobj_t *actor);
|
|||
boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist);
|
||||
|
||||
mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers);
|
||||
void P_InternalFlickyBubble(mobj_t *actor);
|
||||
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez);
|
||||
void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle);
|
||||
|
||||
//
|
||||
// P_MAP
|
||||
|
|
|
@ -7213,10 +7213,11 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
y = mobj->y + FixedMul(FINECOSINE(fa),ns);
|
||||
|
||||
mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE);
|
||||
P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP);
|
||||
P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn
|
||||
ns = 4 * FRACUNIT;
|
||||
mo2->momx = FixedMul(FINESINE(fa),ns);
|
||||
mo2->momy = FixedMul(FINECOSINE(fa),ns);
|
||||
mo2->angle = fa << ANGLETOFINESHIFT;
|
||||
|
||||
if (P_RandomChance(FRACUNIT/4)) // I filled a spreadsheet trying to get the equivalent chance to the original P_RandomByte hack!
|
||||
S_StartSound(mo2, mobj->info->deathsound);
|
||||
|
|
Loading…
Reference in a new issue