Fix UT player swimming physics.

This commit is contained in:
Marisa the Magician 2023-12-23 20:57:19 +01:00
commit 86e4571f7d

View file

@ -305,9 +305,9 @@ Class UTPlayer : DoomPlayer
if ( InStateSequence(CurState,FindState("See",true)) )
SetStateLabel("See2");
if ( !player || (player.mo != self) ) return;
if ( (waterlevel >= 2) && (lastwaterlevel < 2) )
if ( waterlevel && !lastwaterlevel )
PlaySplash(1.);
else if ( (waterlevel < 2) && (lastwaterlevel >= 2) )
else if ( !waterlevel && lastwaterlevel )
PlaySurface();
if ( (waterlevel >= 3) && !underwatersnd )
{
@ -522,7 +522,80 @@ Class UTPlayer : DoomPlayer
}
}
last_sm = sm;
if ( !bNoGravity && player.onground && (waterlevel < 3) )
if ( (bFly && bFlyCheat) || (player.cheats&CF_NOCLIP2) )
{
// fly cheat has infinite friction (player stops moving when movement keys are released)
Vector3 dir = (0,0,0);
if ( vel.length() > double.epsilon ) dir = vel.unit();
Vector3 x, y;
[x, y] = dt_Utility.GetAxes(angle,pitch,0);
acceleration3 = x*player.cmd.forwardmove+y*player.cmd.sidemove;
if ( player.cmd.buttons&BT_JUMP ) acceleration3.z = 0x500;
else if ( player.cmd.buttons&BT_CROUCH ) acceleration3.z = -0x500;
if ( acceleration3.length() <= double.epsilon ) vel *= 0;
else
{
Vector3 acceldir = acceleration3.unit();
acceleration3 = acceldir*Min(acceleration3.length(),accelrate/TICRATE);
vel = vel-(dir-acceldir)*vel.length();
}
vel = vel+acceleration3/TICRATE;
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
maxvel *= fs;
if ( vel.length() > maxvel ) vel = vel.unit()*maxvel;
player.vel *= .8;
player.jumptics = -2;
if ( !(player.cheats & CF_PREDICTING) ) PlayIdle();
}
else if ( (waterlevel || bNoGravity) && !player.GetClassicFlight() )
{
// swimming is pretty much like ground movement, but with much reduced friction and lower speed
friction *= fluidfriction/groundfriction;
Vector3 dir = (0,0,0);
if ( vel.length() > double.epsilon ) dir = vel.unit();
double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0);
Vector3 x, y;
[x, y] = dt_Utility.GetAxes(angle,pitch,0);
acceleration3 = x*player.cmd.forwardmove+y*player.cmd.sidemove;
if ( player.cmd.buttons&BT_JUMP ) acceleration3.z = 0x500;
else if ( player.cmd.buttons&BT_CROUCH ) acceleration3.z = -0x500;
if ( acceleration3.length() <= double.epsilon )
{
Vector3 oldvel = vel;
vel = vel-(2*dir)*vel.length()*friction/TICRATE;
if ( oldvel dot vel < 0.0 ) vel *= 0;
}
else
{
Vector3 acceldir = acceleration3.unit();
acceleration3 = acceldir*Min(acceleration3.length(),accelrate/TICRATE);
vel = vel-(dir-acceldir)*vel.length()*friction/TICRATE;
}
vel = vel+acceleration3/TICRATE;
double maxvel;
if ( bNoGravity ) // flying uses ground speed
{
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
}
else
{
if ( flak_doomspeed ) maxvel = swimspeed_doomish/TICRATE;
else maxvel = swimspeed/TICRATE;
}
maxvel *= fs*doomfriction;
if ( vel.length() > maxvel ) vel = vel.unit()*maxvel;
player.vel = player.vel*.8+vel.xy*.2;
player.jumptics = -2;
if ( !(player.cheats & CF_PREDICTING) )
{
if ( acceleration3.length() <= double.epsilon ) PlayIdle();
else PlayRunning();
}
}
else if ( player.onground )
{
if ( flak_tapdodge && (dodge.length() > 0) && !tempslide )
{
@ -586,7 +659,7 @@ Class UTPlayer : DoomPlayer
else player.vel = player.vel*.8+vel.xy*.2;
}
}
else if ( !bNoGravity && (waterlevel < 1) )
else
{
// air acceleration when falling
float maxaccel = accelrate/TICRATE;
@ -617,79 +690,6 @@ Class UTPlayer : DoomPlayer
player.jumptics = -2;
if ( !(player.cheats & CF_PREDICTING) ) PlayIdle();
}
else if ( (bFly && bFlyCheat) || (player.cheats&CF_NOCLIP2) )
{
// fly cheat has infinite friction (player stops moving when movement keys are released)
Vector3 dir = (0,0,0);
if ( vel.length() > double.epsilon ) dir = vel.unit();
Vector3 x, y;
[x, y] = dt_Utility.GetAxes(angle,pitch,0);
acceleration3 = x*player.cmd.forwardmove+y*player.cmd.sidemove;
if ( player.cmd.buttons&BT_JUMP ) acceleration3.z = 0x500;
else if ( player.cmd.buttons&BT_CROUCH ) acceleration3.z = -0x500;
if ( acceleration3.length() <= double.epsilon ) vel *= 0;
else
{
Vector3 acceldir = acceleration3.unit();
acceleration3 = acceldir*Min(acceleration3.length(),accelrate/TICRATE);
vel = vel-(dir-acceldir)*vel.length();
}
vel = vel+acceleration3/TICRATE;
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
maxvel *= fs;
if ( vel.length() > maxvel ) vel = vel.unit()*maxvel;
player.vel *= .8;
player.jumptics = -2;
if ( !(player.cheats & CF_PREDICTING) ) PlayIdle();
}
else
{
// swimming is pretty much like ground movement, but with much reduced friction and lower speed
friction *= fluidfriction/groundfriction;
Vector3 dir = (0,0,0);
if ( vel.length() > double.epsilon ) dir = vel.unit();
double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0);
Vector3 x, y;
[x, y] = dt_Utility.GetAxes(angle,pitch,0);
acceleration3 = x*player.cmd.forwardmove+y*player.cmd.sidemove;
if ( player.cmd.buttons&BT_JUMP ) acceleration3.z = 0x500;
else if ( player.cmd.buttons&BT_CROUCH ) acceleration3.z = -0x500;
if ( acceleration3.length() <= double.epsilon )
{
Vector3 oldvel = vel;
vel = vel-(2*dir)*vel.length()*friction/TICRATE;
if ( oldvel dot vel < 0.0 ) vel *= 0;
}
else
{
Vector3 acceldir = acceleration3.unit();
acceleration3 = acceldir*Min(acceleration3.length(),accelrate/TICRATE);
vel = vel-(dir-acceldir)*vel.length()*friction/TICRATE;
}
vel = vel+acceleration3/TICRATE;
double maxvel;
if ( waterlevel < 2 ) // flying uses ground speed
{
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
}
else
{
if ( flak_doomspeed ) maxvel = swimspeed_doomish/TICRATE;
else maxvel = swimspeed/TICRATE;
}
maxvel *= fs*doomfriction;
if ( vel.length() > maxvel ) vel = vel.unit()*maxvel;
player.vel = player.vel*.8+vel.xy*.2;
player.jumptics = -2;
if ( !(player.cheats & CF_PREDICTING) )
{
if ( acceleration3.length() <= double.epsilon ) PlayIdle();
else PlayRunning();
}
}
if ( player.cheats & CF_REVERTPLEASE )
{
player.cheats &= ~CF_REVERTPLEASE;
@ -765,40 +765,7 @@ Class UTPlayer : DoomPlayer
return;
// unreal physics while dead
double friction = FrictionToUnreal();
if ( !bNoGravity && player.onground && (waterlevel < 3) )
{
// Hook in Unreal physics
Vector2 dir = (0,0);
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0);
Vector2 oldvel = vel.xy;
vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE;
if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0;
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
maxvel *= doomfriction;
if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel;
player.vel *= 0;
}
else if ( !bNoGravity && (waterlevel < 1) )
{
// air acceleration when falling
Vector2 dir = (0,0);
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
// if new velocity is higher than ground speed, steer but don't increase it
if ( vel.xy.length() > maxvel )
{
double vsiz = vel.xy.length();
vel.xy = vel.xy.unit()*vsiz;
}
if ( vel.length() > terminalvelocity/TICRATE ) vel = vel.unit()*(terminalvelocity/TICRATE);
player.vel *= 0;
}
else
if ( waterlevel )
{
// swimming is pretty much like ground movement, but with much reduced friction and lower speed
friction *= fluidfriction/groundfriction;
@ -815,6 +782,61 @@ Class UTPlayer : DoomPlayer
if ( vel.length() > maxvel ) vel = vel.unit()*maxvel;
player.vel *= 0;
}
else if ( player.onground )
{
// Hook in Unreal physics
Vector2 dir = (0,0);
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0);
Vector2 oldvel = vel.xy;
vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE;
if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0;
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
maxvel *= doomfriction;
if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel;
player.vel *= 0;
}
else
{
// air acceleration when falling
Vector2 dir = (0,0);
if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit();
double maxvel;
if ( flak_doomspeed ) maxvel = groundspeed_doomish/TICRATE;
else maxvel = groundspeed/TICRATE;
// if new velocity is higher than ground speed, steer but don't increase it
if ( vel.xy.length() > maxvel )
{
double vsiz = vel.xy.length();
vel.xy = vel.xy.unit()*vsiz;
}
if ( vel.length() > terminalvelocity/TICRATE ) vel = vel.unit()*(terminalvelocity/TICRATE);
player.vel *= 0;
}
}
// backported from DEMOLITIONIST, needed to fix quirks in swimming behavior
override void FallAndSink( double grav, double oldfloorz )
{
if ( !flak_utmovement || !player || (player.mo != self) || (player.cheats&(CF_FROZEN|CF_TOTALLYFROZEN)) )
{
Super.FallAndSink(grav,oldfloorz);
return;
}
// do nothing if standing on ground or "floating"
if ( player.onground || bNOGRAVITY ) return;
// ensure we don't pass terminal velocity just from falling
if ( vel.z < -50 ) return;
// we don't care about "the doom way" here, gravity is
// ALWAYS in effect when not standing on solid ground
if ( waterlevel > 1 )
{
// UT buoyancy, reduces gravity in water by 99%
grav *= .01;
}
vel.z -= grav;
}
virtual void PlayFootstep( double vol )
@ -971,7 +993,7 @@ Class UTPlayer : DoomPlayer
|| InStateSequence(CurState,FindState("Turn")) )
SetStateLabel("See2");
}
else if ( !bNoGravity && (waterlevel < 1) && abs(pos.z-floorz) > maxstepheight )
else if ( !bNoGravity && (waterlevel < 1) && (abs(pos.z-floorz) > maxstepheight) )
{
// Falling
if ( InStateSequence(CurState,FindState("Spawn"))