* Bustable wallspikes.

* Improve the code for busting vertical spikes.
* Improve the frame arrangement for vertical spikes' spriteset. (Requires new patch.dta)
* Make all spikes consistently do damage with DMG_SPIKE.
* (unrelated) renamed "flame stomp" to "elemental stomp" in P_HitDeathMessages
This commit is contained in:
toasterbabe 2017-07-18 14:17:10 +01:00
parent 2330f1a9c9
commit ef4dc42c7c
6 changed files with 188 additions and 102 deletions

View file

@ -4681,6 +4681,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_WALLSPIKE5",
"S_WALLSPIKE6",
"S_WALLSPIKEBASE",
"S_WALLSPIKED1",
"S_WALLSPIKED2",
// Starpost
"S_STARPOST_IDLE",

View file

@ -1563,13 +1563,13 @@ state_t states[NUMSTATES] =
// Floor Spike
{SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended
{SPR_USPK, 5, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
{SPR_USPK, 4, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
{SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
{SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
{SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5}, // S_SPIKE4 -- Fully retracted
{SPR_USPK, 4, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
{SPR_USPK, 5, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
{SPR_USPK, 1,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
{SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
{SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
{SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
{SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
{SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
// Wall Spike
{SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2}, // S_WALLSPIKE1 -- Fully extended
@ -1579,6 +1579,8 @@ state_t states[NUMSTATES] =
{SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6}, // S_WALLSPIKE5
{SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1}, // S_WALLSPIKE6
{SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKEBASE -- Base
{SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED1 -- Busted spike particles
{SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED2
// Starpost
{SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE
@ -6003,9 +6005,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_s3k64, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
S_WALLSPIKED1, // deathstate
S_WALLSPIKED2, // xdeathstate
sfx_mspogo, // deathsound
2*TICRATE, // speed
16*FRACUNIT, // radius
14*FRACUNIT, // height

View file

@ -1784,6 +1784,8 @@ typedef enum state
S_WALLSPIKE5,
S_WALLSPIKE6,
S_WALLSPIKEBASE,
S_WALLSPIKED1,
S_WALLSPIKED2,
// Starpost
S_STARPOST_IDLE,

View file

@ -1665,7 +1665,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
if (damagetype == DMG_NUKE) // SH_ARMAGEDDON, armageddon shield
str = M_GetText("%s%s's armageddon blast %s %s.\n");
else if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && (inflictor->player->pflags & PF_SHIELDABILITY))
str = M_GetText("%s%s's flame stomp %s %s.\n");
str = M_GetText("%s%s's elemental stomp %s %s.\n");
else if (inflictor->player->powers[pw_invulnerability])
str = M_GetText("%s%s's invincibility aura %s %s.\n");
else if (inflictor->player->powers[pw_super])
@ -1719,6 +1719,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
break;
case MT_SPIKE:
case MT_WALLSPIKE:
str = M_GetText("%s was %s by spikes.\n");
break;
default:
@ -2395,7 +2396,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
else
{
P_SetObjectMomZ(target, 14*FRACUNIT, false);
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes
if (damagetype == DMG_SPIKE) // Spikes
S_StartSound(target, sfx_spkdth);
else
P_PlayDeathSound(target);
@ -2457,90 +2458,159 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
}
if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL)
if (target->type == MT_SPIKE && target->info->deathstate != S_NULL)
{
const fixed_t x=target->x,y=target->y,z=target->z;
const fixed_t scale=target->scale;
const boolean flip=(target->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP;
S_StartSound(target,target->info->deathsound);
const angle_t ang = ((inflictor) ? inflictor->angle : 0) + ANGLE_90;
const fixed_t scale = target->scale;
const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale);
const UINT16 flip = (target->eflags & MFE_VERTICALFLIP);
mobj_t *chunk;
fixed_t momz;
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
target->angle = inflictor->angle + ANGLE_90;
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
if (flip)
target->z -= FixedMul(12*FRACUNIT, target->scale);
else
target->z += FixedMul(12*FRACUNIT, target->scale);
P_SetThingPosition(target);
P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale));
target->momz = FixedMul(7*FRACUNIT, target->scale);
if (flip)
target->momz = -target->momz;
if (flip)
{
target = P_SpawnMobj(x,y,z-FixedMul(12*FRACUNIT, target->scale),MT_SPIKE);
target->eflags |= MFE_VERTICALFLIP;
}
else
target = P_SpawnMobj(x,y,z+FixedMul(12*FRACUNIT, target->scale),MT_SPIKE);
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
target->angle = inflictor->angle - ANGLE_90;
target->destscale = scale;
P_SetScale(target, scale);
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
P_SetThingPosition(target);
P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale));
target->momz = FixedMul(7*FRACUNIT, target->scale);
if (flip)
target->momz = -target->momz;
S_StartSound(target, target->info->deathsound);
if (target->info->xdeathstate != S_NULL)
{
target = P_SpawnMobj(x,y,z,MT_SPIKE);
momz = 6*scale;
if (flip)
target->eflags |= MFE_VERTICALFLIP;
P_SetMobjState(target, target->info->xdeathstate);
target->health = 0;
target->angle = inflictor->angle + ANGLE_90;
target->destscale = scale;
P_SetScale(target, scale);
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
P_SetThingPosition(target);
P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale));
target->momz = FixedMul(6*FRACUNIT, target->scale);
if (flip)
target->momz = -target->momz;
momz *= -1;
#define makechunk(angtweak, xmov, ymov) \
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE);\
chunk->eflags |= flip;\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = angtweak;\
chunk->destscale = scale;\
P_SetScale(chunk, scale);\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov;\
chunk->y += ymov;\
P_SetThingPosition(chunk);\
P_InstaThrust(chunk,chunk->angle, 4*scale);\
chunk->momz = momz
target = P_SpawnMobj(x,y,z,MT_SPIKE);
if (flip)
target->eflags |= MFE_VERTICALFLIP;
P_SetMobjState(target, target->info->xdeathstate);
target->health = 0;
target->angle = inflictor->angle - ANGLE_90;
target->destscale = scale;
P_SetScale(target, scale);
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
P_SetThingPosition(target);
P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale));
target->momz = FixedMul(6*FRACUNIT, target->scale);
if (flip)
target->momz = -target->momz;
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
makechunk(ang, xoffs, yoffs);
#undef makechunk
}
momz = 7*scale;
if (flip)
momz *= -1;
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE);
chunk->eflags |= flip;
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = ang + ANGLE_180;
chunk->destscale = scale;
P_SetScale(chunk, scale);
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x -= xoffs;
chunk->y -= yoffs;
if (flip)
chunk->z -= 12*scale;
else
chunk->z += 12*scale;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, chunk->angle, 2*scale);
chunk->momz = momz;
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
target->angle = ang;
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += xoffs;
target->y += yoffs;
target->z = chunk->z;
P_SetThingPosition(target);
P_InstaThrust(target, target->angle, 2*scale);
target->momz = momz;
}
else if (target->type == MT_WALLSPIKE && target->info->deathstate != S_NULL)
{
const angle_t ang = (/*(inflictor) ? inflictor->angle : */target->angle) + ANGLE_90;
const fixed_t scale = target->scale;
const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale), forwardxoffs = P_ReturnThrustX(target, target->angle, 7*scale), forwardyoffs = P_ReturnThrustY(target, target->angle, 7*scale);
const UINT16 flip = (target->eflags & MFE_VERTICALFLIP);
mobj_t *chunk;
boolean sprflip;
S_StartSound(target, target->info->deathsound);
if (!P_MobjWasRemoved(target->tracer))
P_RemoveMobj(target->tracer);
if (target->info->xdeathstate != S_NULL)
{
sprflip = P_RandomChance(FRACUNIT/2);
#define makechunk(angtweak, xmov, ymov) \
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE);\
chunk->eflags |= flip;\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = target->angle;\
chunk->destscale = scale;\
P_SetScale(chunk, scale);\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov - forwardxoffs;\
chunk->y += ymov - forwardyoffs;\
P_SetThingPosition(chunk);\
P_InstaThrust(chunk, angtweak, 4*scale);\
chunk->momz = P_RandomRange(5, 7)*scale;\
if (flip)\
chunk->momz *= -1;\
if (sprflip)\
chunk->frame |= FF_VERTICALFLIP
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
sprflip = !sprflip;
makechunk(ang, xoffs, yoffs);
#undef makechunk
}
sprflip = P_RandomChance(FRACUNIT/2);
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE);
chunk->eflags |= flip;
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = target->angle;
chunk->destscale = scale;
P_SetScale(chunk, scale);
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x += forwardxoffs - xoffs;
chunk->y += forwardyoffs - yoffs;
P_SetThingPosition(chunk);
P_InstaThrust(chunk, ang + ANGLE_180, 2*scale);
chunk->momz = P_RandomRange(5, 7)*scale;
if (flip)
chunk->momz *= -1;
if (sprflip)
chunk->frame |= FF_VERTICALFLIP;
P_SetMobjState(target, target->info->deathstate);
target->health = 0;
P_UnsetThingPosition(target);
target->flags = MF_NOCLIP;
target->x += forwardxoffs + xoffs;
target->y += forwardyoffs + yoffs;
P_SetThingPosition(target);
P_InstaThrust(target, ang, 2*scale);
target->momz = P_RandomRange(5, 7)*scale;
if (flip)
target->momz *= -1;
if (!sprflip)
target->frame |= FF_VERTICALFLIP;
}
else if (target->player)
{
@ -2876,7 +2946,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes
if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth);
else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
@ -2905,7 +2975,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes
if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth);
if (source && source->player && !player->powers[pw_super]) //don't score points against super players

View file

@ -439,7 +439,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Metal Sonic destroys tiny baby objects.
if (tmthing->type == MT_METALSONIC_RACE
&& (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) || thing->type == MT_SPIKE))
&& (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS)
|| (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)))
{
if ((thing->flags & (MF_ENEMY|MF_BOSS)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE)))
return true;
@ -451,12 +453,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->type == MT_SPIKE)
if (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)
{
mobjtype_t type = thing->type;
if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound);
for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext)
if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale))
if (thing->type == type && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y), thing->z - tmthing->z) < 56*thing->scale)//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(thing, tmthing, tmthing, 0);
}
else
@ -470,10 +474,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
// SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes.
if ((tmthing->player)
&& (((tmthing->player->charflags & SF_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE)
&& (thing->flags & (MF_MONITOR) || thing->type == MT_SPIKE))
&& (thing->flags & (MF_MONITOR)
|| (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)))
|| ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2))
&& (thing->type == MT_SPIKE))))
&& (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE))))
{
if ((thing->flags & (MF_MONITOR)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE)))
return true;
@ -485,12 +492,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->type == MT_SPIKE)
if (thing->type == MT_SPIKE
|| thing->type == MT_WALLSPIKE)
{
mobjtype_t type = thing->type;
if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound);
for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext)
if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale))
if (thing->type == type && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y), thing->z - tmthing->z) < 56*thing->scale)//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(thing, tmthing, tmthing, 0);
}
else
@ -937,12 +946,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && thing->eflags & MFE_VERTICALFLIP))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
}
else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && !(thing->eflags & MFE_VERTICALFLIP)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
}
else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?!
{
@ -951,12 +960,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP))
P_DamageMobj(tmthing, thing, thing, 1, 0);
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
}
else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP)))
P_DamageMobj(tmthing, thing, thing, 1, 0);
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
}
if (tmthing->type == MT_WALLSPIKE && tmthing->flags & MF_SOLID && thing->player) // wall spike impales player

View file

@ -2739,8 +2739,9 @@ static boolean P_ZMovement(mobj_t *mo)
return true;
break;
case MT_SPIKE:
case MT_WALLSPIKE:
// Dead spike particles disappear upon ground contact
if ((mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz) && mo->health <= 0)
if (!mo->health && (mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz))
{
P_RemoveMobj(mo);
return false;
@ -10148,7 +10149,7 @@ ML_NOCLIMB : Direction not controllable
// spawn base
{
const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so...
const fixed_t baseradius = mobj->radius - (mobj->scale/2); //FixedMul(FRACUNIT/2, mobj->scale);
const fixed_t baseradius = mobj->radius - mobj->scale;
mobj_t *base = P_SpawnMobj(
mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius),
mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius),