Additional corpse hitbox features (zapping loop, land thumps, fall damage, etc.)

Corpse hitboxes and UT gibbing are enabled unconditionally for players.
Added enter/exit sounds for swimming.
This commit is contained in:
Marisa the Magician 2019-07-22 15:21:57 +02:00
commit 99edae06b9
6 changed files with 61 additions and 20 deletions

View file

@ -166,6 +166,7 @@ ut/bossfootstep bfootstp
ut/playerfootstepwet lsplash ut/playerfootstepwet lsplash
ut/wetsplash dsplash ut/wetsplash dsplash
ut/wetsurface wtrexit1
// everything else // everything else
@ -206,6 +207,7 @@ misc/gibp3 gibp4
misc/gibp4 gibp5 misc/gibp4 gibp5
misc/gibp5 gibp6 misc/gibp5 gibp6
$random misc/gibp { misc/gibp1 misc/gibp2 misc/gibp3 misc/gibp4 misc/gibp5 } $random misc/gibp { misc/gibp1 misc/gibp2 misc/gibp3 misc/gibp4 misc/gibp5 }
misc/corpsefall thump
impact/select imppick impact/select imppick
impact/pull impaltst impact/pull impaltst

BIN
sounds/Thump.ogg Normal file

Binary file not shown.

BIN
sounds/WtrExit1.ogg Normal file

Binary file not shown.

View file

@ -142,13 +142,6 @@ Class Razor2 : Actor
} }
Goto Spawn; Goto Spawn;
Death: Death:
TNT1 A 0
{
angle += 180;
pitch *= -1;
A_RazorHit();
}
XDeath:
TNT1 A 1 A_StopSound(CHAN_VOICE); TNT1 A 1 A_StopSound(CHAN_VOICE);
Stop; Stop;
} }

View file

@ -1,6 +1,7 @@
Class UTPlayer : DoomPlayer Class UTPlayer : DoomPlayer
{ {
bool lastground; bool lastground;
int lastwaterlevel;
int lastgroundtic; int lastgroundtic;
double lastvelz, prevvelz; double lastvelz, prevvelz;
transient CVar footsteps; transient CVar footsteps;
@ -14,6 +15,7 @@ Class UTPlayer : DoomPlayer
int tempslide; int tempslide;
double ssup; double ssup;
int corpsetime; int corpsetime;
bool headless, legless;
int dolltype, voicetype; int dolltype, voicetype;
@ -230,7 +232,7 @@ Class UTPlayer : DoomPlayer
bNOFRICTIONBOUNCE = false; bNOFRICTIONBOUNCE = false;
} }
if ( !footsteps ) footsteps = CVar.GetCVar('flak_footsteps',players[consoleplayer]); if ( !footsteps ) footsteps = CVar.GetCVar('flak_footsteps',players[consoleplayer]);
if ( !footsteps.GetBool() ) return; if ( !footsteps.GetBool() || (Health <= 0) ) return;
double ang = level.time/(20*TICRATE/35.)*360.; double ang = level.time/(20*TICRATE/35.)*360.;
bool forcefootstep = false; bool forcefootstep = false;
if ( player.onground && !bNoGravity && !lastground && (waterlevel < 2) ) if ( player.onground && !bNoGravity && !lastground && (waterlevel < 2) )
@ -241,9 +243,9 @@ Class UTPlayer : DoomPlayer
double vol = clamp((-lastvelz-8)*0.05,0.01,1.0); double vol = clamp((-lastvelz-8)*0.05,0.01,1.0);
if ( ((waterlevel > 0) || GetFloorTerrain().IsLiquid) && !bOnMobj ) A_PlaySound("ut/wetsplash",CHAN_AUTO,vol); if ( ((waterlevel > 0) || GetFloorTerrain().IsLiquid) && !bOnMobj ) A_PlaySound("ut/wetsplash",CHAN_AUTO,vol);
else A_PlaySound("*uland",CHAN_AUTO,vol); else A_PlaySound("*uland",CHAN_AUTO,vol);
PlayLanding();
} }
else forcefootstep = true; else forcefootstep = true;
if ( Health > 0 ) PlayLanding();
} }
if ( tempslide ) if ( tempslide )
{ {
@ -257,10 +259,14 @@ Class UTPlayer : DoomPlayer
if ( (waterlevel > 0) || GetFloorTerrain().IsLiquid && !bOnMobj ) A_PlaySound("ut/playerfootstepwet",CHAN_5,vol); if ( (waterlevel > 0) || GetFloorTerrain().IsLiquid && !bOnMobj ) A_PlaySound("ut/playerfootstepwet",CHAN_5,vol);
else PlayFootstep(vol); else PlayFootstep(vol);
} }
if ( (waterlevel >= 2) && (lastwaterlevel < 2) )
A_PlaySound("ut/wetsplash",CHAN_AUTO);
else if ( (waterlevel < 2) && (lastwaterlevel >= 2) )
A_PlaySound("ut/wetsurface",CHAN_AUTO);
lastground = player.onground; lastground = player.onground;
lastvelz = prevvelz; lastvelz = prevvelz;
prevvelz = vel.z; prevvelz = vel.z;
// TODO exit/entry sounds for water lastwaterlevel = waterlevel;
} }
double FrictionToUnreal() double FrictionToUnreal()
@ -873,6 +879,7 @@ Class UTPlayer : DoomPlayer
void A_HeadPop() void A_HeadPop()
{ {
headless = true;
Class<UTHead> hclass = "UTHeadMale"; Class<UTHead> hclass = "UTHeadMale";
if ( DollType == DOLL_Boss ) hclass = "UTHeadBoss"; if ( DollType == DOLL_Boss ) hclass = "UTHeadBoss";
else if ( DollType == DOLL_Female ) hclass = "UTHeadFemale"; else if ( DollType == DOLL_Female ) hclass = "UTHeadFemale";
@ -904,6 +911,13 @@ Class UTPlayer : DoomPlayer
if ( corpsetime > 350 ) A_FadeOut(0.03); if ( corpsetime > 350 ) A_FadeOut(0.03);
} }
override double GetDeathHeight()
{
// no height reduction while still being zapped
if ( DamageType == 'Zapped' ) return height;
return Super.GetDeathHeight();
}
States States
{ {
Spawn: Spawn:
@ -1019,7 +1033,8 @@ Class UTPlayer : DoomPlayer
PLD9 A 3 A_PlayerScream(); PLD9 A 3 A_PlayerScream();
PLD9 B 3 A_NoBlocking(); PLD9 B 3 A_NoBlocking();
PLD9 CDEFGHIJKLMNOPQRST 2; PLD9 CDEFGHIJKLMNOPQRST 2;
PD9B ABCDEFGHI 2; PD9B A 2 A_SetSize(-1,height*0.25); // reduce now
PD9B BCDEFGHI 2;
PD9B J 1 A_DMFade(); PD9B J 1 A_DMFade();
Wait; Wait;
Death8: Death8:
@ -1058,7 +1073,7 @@ Class UTPlayer : DoomPlayer
PLD1 M 1 A_DMFade(); PLD1 M 1 A_DMFade();
Wait; Wait;
XDeath: XDeath:
TNT1 A 1 TNT1 A 350
{ {
A_XScream(); A_XScream();
A_NoBlocking(); A_NoBlocking();
@ -1120,6 +1135,7 @@ Class UTPlayerTFemale : UTPlayer
void A_LegPop() void A_LegPop()
{ {
legless = true;
let a = Actor.Spawn("UTFemaleLegGibber",pos); let a = Actor.Spawn("UTFemaleLegGibber",pos);
a.vel = vel; a.vel = vel;
a.Scale = Scale; a.Scale = Scale;
@ -1154,7 +1170,8 @@ Class UTPlayerTFemale : UTPlayer
PLD9 A 3 A_PlayerScream(); PLD9 A 3 A_PlayerScream();
PLD9 B 3 A_NoBlocking(); PLD9 B 3 A_NoBlocking();
PLD9 CDEFGHIJKLMNOPQRST 2; PLD9 CDEFGHIJKLMNOPQRST 2;
PD9B ABCDEFGHIJ 2; PD9B A 2 A_SetSize(-1,height*0.25); // reduce now
PD9B BCDEFGHIJ 2;
PD9B K 1 A_DMFade(); PD9B K 1 A_DMFade();
Wait; Wait;
Death: Death:
@ -1923,6 +1940,8 @@ Class UTBlueKey : BlueCard
Class ShredCorpseHitbox : Actor Class ShredCorpseHitbox : Actor
{ {
int accdamage; int accdamage;
Vector3 lastvel;
bool wasonair;
Default Default
{ {
@ -1946,16 +1965,37 @@ Class ShredCorpseHitbox : Actor
override void Tick() override void Tick()
{ {
Super.Tick(); Super.Tick();
if ( !flak_corpsedamage || !target || (target.Health > 0) || target.InStateSequence(target.CurState,target.FindState("XDeath")) ) if ( (!(target is 'UTPlayer') && !flak_corpsedamage) || !target || (target.Health > 0) || target.InStateSequence(target.CurState,target.FindState("XDeath")) )
{ {
Destroy(); Destroy();
return; return;
} }
SetOrigin(target.pos,true); SetOrigin(target.pos,true);
A_SetSize(target.radius,target.height); A_SetSize(target.radius,target.height);
if ( target.pos.z > target.floorz ) wasonair = true;
else
{
if ( wasonair )
{
A_PlaySound("misc/corpsefall",CHAN_BODY,clamp(-lastvel.z*0.2,0.1,1.0));
if ( lastvel.z < -20 ) DamageMobj(null,null,int.max,'Falling');
}
wasonair = false;
}
lastvel = target.vel;
} }
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle ) override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{ {
if ( (target is 'UTPlayer') && (mod == 'Zapped') && (target.sprite == target.GetSpriteIndex('PLD9')) )
{
// keep the zapping action on
target.SetState(target.FindState("Death.Zapped")+Random[ZapMe](2,8));
damage /= 4;
// push the corpse
target.vel.xy += RotateVector((1,0),angle)*damage*0.1;
// keep it afloat
target.vel.z = max(0.1,target.vel.z+0.1);
}
accdamage -= damage; accdamage -= damage;
int gibhealth = (target.GibHealth==int.min)?-target.SpawnHealth():target.GibHealth; int gibhealth = (target.GibHealth==int.min)?-target.SpawnHealth():target.GibHealth;
if ( accdamage < gibhealth ) if ( accdamage < gibhealth )
@ -2613,7 +2653,7 @@ Class UTMainHandler : EventHandler
return; return;
} }
// attach damage accumulator for corpses // attach damage accumulator for corpses
if ( !flak_corpsedamage ) return; if ( !(e.Thing is 'UTPlayer') && !flak_corpsedamage ) return;
let a = Actor.Spawn("ShredCorpseHitbox",e.Thing.pos); let a = Actor.Spawn("ShredCorpseHitbox",e.Thing.pos);
a.target = e.Thing; a.target = e.Thing;
} }
@ -2644,7 +2684,9 @@ Class UTMainHandler : EventHandler
double dist = max(1,dir.length()); double dist = max(1,dir.length());
double damagescale = 1-max(0,(dist-a.radius)/ExplosionRadius); double damagescale = 1-max(0,(dist-a.radius)/ExplosionRadius);
dir = dir/dist; dir = dir/dist;
a.vel += dir*damagescale*(MomentumTransfer/(Thinker.TICRATE*a.mass)); if ( (a is 'ShredCorpseHitbox') && a.target )
a.target.vel += dir*damagescale*(MomentumTransfer/(Thinker.TICRATE*a.target.mass));
else a.vel += dir*damagescale*(MomentumTransfer/(Thinker.TICRATE*a.mass));
} }
} }
@ -2652,7 +2694,9 @@ Class UTMainHandler : EventHandler
static void DoKnockback( Actor Victim, Vector3 HitDirection, double MomentumTransfer ) static void DoKnockback( Actor Victim, Vector3 HitDirection, double MomentumTransfer )
{ {
if ( !Victim ) return; if ( !Victim ) return;
Victim.vel += HitDirection*(MomentumTransfer/(Thinker.TICRATE*Victim.Mass)); if ( (Victim is 'ShredCorpseHitbox') && Victim.target )
Victim.target.vel += HitDirection*(MomentumTransfer/(Thinker.TICRATE*Victim.target.Mass));
else Victim.vel += HitDirection*(MomentumTransfer/(Thinker.TICRATE*Victim.Mass));
} }
static void DoSwing( Actor target, Vector2 dir, double initial, double inc, int steps, int mode = 0, int delay = 0, double rmul = 1.0 ) static void DoSwing( Actor target, Vector2 dir, double initial, double inc, int steps, int mode = 0, int delay = 0, double rmul = 1.0 )

View file

@ -245,7 +245,7 @@ Class UTGibber : Actor
ang = FRandom[Blod](0,360); ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90); pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt)); dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.6+dir*FRandom[Blod](8.0,12.0); a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
} }
for ( int i=0; i<gibsize; i++ ) for ( int i=0; i<gibsize; i++ )
{ {
@ -309,7 +309,7 @@ Class UTFemaleLegGibber : UTGibber
ang = FRandom[Blod](0,360); ang = FRandom[Blod](0,360);
pt = FRandom[Blod](-90,90); pt = FRandom[Blod](-90,90);
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt)); dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.6+dir*FRandom[Blod](8.0,12.0); a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
} }
} }
for ( int i=0; i<gibsize; i++ ) for ( int i=0; i<gibsize; i++ )
@ -384,6 +384,8 @@ Class UTPlayerGibber : UTGibber
firstgib = true; firstgib = true;
for ( int i=0; i<11; i++ ) for ( int i=0; i<11; i++ )
{ {
if ( (i == 5) && UTPlayer(Gibbed).headless ) continue;
if ( ((i == 2) || (i == 6)) && UTPlayer(Gibbed).legless ) continue;
Actor a; Actor a;
if ( i < 6 ) if ( i < 6 )
{ {
@ -406,7 +408,7 @@ Class UTPlayerGibber : UTGibber
} }
} }
dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt)); dir = (cos(pt)*cos(ang),cos(pt)*sin(ang),sin(-pt));
a.vel = rvel*0.6+dir*FRandom[Blod](8.0,12.0); a.vel = rvel*0.6+dir*FRandom[Blod](3.0,6.0);
} }
} }
for ( int i=0; i<gibsize; i++ ) for ( int i=0; i<gibsize; i++ )