From 1b7a288bf52ad93b6f630d4e0b38f12aa73e4345 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Sat, 18 Aug 2018 15:20:02 +0200 Subject: [PATCH] Fully implemented UT-style player movement (optional). "Disable boss telefragging" now toggleable. Menu background now displays whenever the menu is open, rather than just on the title screen. Now it matches the expected UT behaviour. --- cvarinfo.txt | 53 ++++++----- menudef.txt | 8 ++ sndinfo.txt | 6 +- zscript/utcommon.zsc | 210 +++++++++++++++++++++++++++++++------------ 4 files changed, 195 insertions(+), 82 deletions(-) diff --git a/cvarinfo.txt b/cvarinfo.txt index 12949f1..754624b 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -1,24 +1,29 @@ -user int flak_protomenu = 0; -user bool flak_showmenu = true; -server bool flak_pulsereload = false; -server bool flak_enforcerreload = false; -user bool flak_redeemerreadout = true; -user int flak_colorprefs = 2; -user color flak_colorcustom = "00 80 ff"; -user int flak_opacity = 15; // UT's opacity is 1 <-> 16 in steps of 1 (default 15) - // 16 means fully opaque, everything else is just additive with gradually lowering alpha - // status is never fully opaque (clamped under 16) - // currently selected weapon and numbers are fully opaque until 8 opacity (their opacity is bumped by 7 basically) -user bool flak_showweapons = true; // if disabled, frags and ammo are shown centered, with a gap for armor and health -user bool flak_showstatus = true; // if disabled armor and health show on the top right (or center between frags and ammo if weapon display is disabled) -user bool flak_showammo = true; -user bool flak_showfrags = true; -user bool flak_showinfo = true; -user float flak_hudsize = 1.0; // 0.2 <-> 1.0 in steps of 0.2 (default 1.0) -user float flak_weaponsize = 0.8; // 0.2 <-> 1.0 in steps of 0.2 (default 0.8) -user float flak_statussize = 1.0; // 0.5 <-> 1.5 in steps of 0.1 (default 1.0) -user bool flak_footsteps = true; -server bool flak_translocator = false; -user bool flak_noswitchdeemer = true; // don't switch to redeemer when out of ammo -user bool flak_deemershader = false; -server bool flak_classicsshock = false; // classic enhanced shock rifle (no altfire, beams don't have splash damage) +user int flak_protomenu = 0; // version of main menu (0: final, 1: 22x betas, 2: same as 1, but with extended menu music) +user bool flak_showmenu = true; // show the UT main menu background whenever the menu is open +server bool flak_pulsereload = false; // pulsegun can reload (features unused animation from early versions) +server bool flak_enforcerreload = false; // enforcer can reload +user bool flak_redeemerreadout = true; // enable target readout, may cause slowdowns on weak CPUs +user int flak_colorprefs = 2; // 0: team color, 1: player color, 2: custom color +user color flak_colorcustom = "00 80 ff"; // custom hud color +user int flak_opacity = 15; // UT's opacity is 1 <-> 16 in steps of 1 (default 15) + // 16 means fully opaque, everything else is just additive with gradually lowering alpha + // status is never fully opaque (clamped under 16) + // currently selected weapon and numbers are fully opaque until 8 opacity (their opacity is bumped by 7 basically) +user bool flak_showweapons = true; // if disabled, frags and ammo are shown centered, with a gap for armor and health +user bool flak_showstatus = true; // if disabled armor and health show on the top right (or center between frags and ammo if weapon display is disabled) +user bool flak_showammo = true; // show ammo counters +user bool flak_showfrags = true; // show kill/frag count +user bool flak_showinfo = true; // show name of aimed at player in mp (and their health if in coop or same team) +user float flak_hudsize = 1.0; // 0.2 <-> 1.0 in steps of 0.2 (default 1.0) +user float flak_weaponsize = 0.8; // 0.2 <-> 1.0 in steps of 0.2 (default 0.8) +user float flak_statussize = 1.0; // 0.5 <-> 1.5 in steps of 0.1 (default 1.0) +user bool flak_footsteps = true; // players make footstep sounds +server bool flak_translocator = false; // translocator is enabled (hello, sequence breaking) +user bool flak_noswitchdeemer = true; // don't switch to redeemer when out of ammo +user bool flak_deemershader = false; // fancy blur/grain/tint shader +server bool flak_classicsshock = false; // classic enhanced shock rifle (no altfire, beams don't have splash damage) +server bool flak_utmovement = false; // emulate UE1's air/ground movement physics +server bool flak_doomspeed = false; // keep Doomguy run speed when using UT movement +server bool flak_doomaircontrol = false; // keep Doom's limited air control when using UT movement +server bool flak_nobosstelefrag = false; // disable telefragging of boss monsters (useful when translocator is enabled) +server bool flak_nowalkdrop = false; // don't drop off ledges while holding walk key (glitchy) diff --git a/menudef.txt b/menudef.txt index 4e2d10d..e445485 100644 --- a/menudef.txt +++ b/menudef.txt @@ -27,9 +27,17 @@ OptionMenu "UTOptionMenu" Option "No Redeemer Autoswitch", "flak_noswitchdeemer", "YesNo" Option "Classic Enh. Shock Rifle", "flak_classicsshock", "YesNo" StaticText " " + StaticText "Translocator (Potentially Game-Breaking)", "Gold" + Option "Prevent Boss Telefrag", "flak_nobosstelefrag", "YesNo" Option "Enable Translocator", "flak_translocator", "YesNo" Command "Apply Changes", "event refreshtrans" StaticText " " + StaticText "Player Options", "Gold" + Option "Enable UT Movement", "flak_utmovement", "YesNo" + Option "Doom Player Speed", "flak_doomspeed", "YesNo", "flak_utmovement" + Option "Doom Air Control", "flak_doomaircontrol", "YesNo", "flak_utmovement" + Option "Walk Disables Dropoff (Glitchy)", "flak_nowalkdrop", "YesNo", "flak_utmovement" + StaticText " " StaticText "HUD Options", "Gold" Option "Show Weapon Bar", "flak_showweapons", "YesNo" Option "Show Status Doll", "flak_showstatus", "YesNo" diff --git a/sndinfo.txt b/sndinfo.txt index 92965c6..620e361 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -33,7 +33,8 @@ $playeralias player male *pain75 ut/malepain2 $playeralias player male *pain50 ut/malepain3 $playeralias player male *pain25 ut/malepain4 $playeralias player male *grunt ut/malegrunt -$playeralias player male *land ut/land +$playeralias player male *land DSEMPTY +$playeralias player male *uland ut/land $playeralias player male *jump ut/malejump $playeralias player male *usefail ut/malehump $playeralias player male *surface ut/malesurface @@ -74,7 +75,8 @@ $playeralias player female *pain75 ut/femalepain2 $playeralias player female *pain50 ut/femalepain3 $playeralias player female *pain25 ut/femalepain4 $playeralias player female *grunt ut/femalegrunt -$playeralias player female *land ut/land +$playeralias player female *land DSEMPTY +$playeralias player female *uland ut/land $playeralias player female *jump ut/femalejump $playeralias player female *usefail ut/femalegrunt $playeralias player female *surface ut/femalesurf diff --git a/zscript/utcommon.zsc b/zscript/utcommon.zsc index 128ce7e..e4a51a3 100644 --- a/zscript/utcommon.zsc +++ b/zscript/utcommon.zsc @@ -2,16 +2,26 @@ Class UTPlayer : DoomPlayer { bool lastground; double lastvelz, prevvelz; - transient CVar footsteps; + transient CVar footsteps, utmovement, doomspeed, doomaircontrol, nowalkdrop; Vector2 acceleration; + Vector3 acceleration3; + int last_fm_tap, last_sm_tap; + int last_fm, last_sm; + + const groundspeed = 400.; + const accelrate = 2048.; + const walkfactor = 0.3; + const utaircontrol = 0.35; + const groundspeed_doomish = 600.; Default { Player.StartItem "Enforcer"; Player.StartItem "ImpactHammer"; Player.StartItem "MiniAmmo", 30; - Player.DamageScreenColor "FF 00 00", 1.0; + Player.DamageScreenColor "FF 00 00"; Player.ViewHeight 46; + Player.GruntSpeed 20; } // Have to modify the give cheat to handle UT armor @@ -171,23 +181,48 @@ Class UTPlayer : DoomPlayer if ( !footsteps ) footsteps = CVar.GetCVar('flak_footsteps',players[consoleplayer]); if ( !footsteps.GetBool() ) return; double ang = level.time/(20*TICRATE/35.)*360.; - if ( (abs(sin(ang)) >= 1.0) && player.onground && (player.cmd.forwardmove || player.cmd.sidemove) && (waterlevel < 3) ) + bool forcefootstep = false; + if ( player.onground && !bNoGravity && !lastground && (waterlevel < 3) ) { - if ( (waterlevel > 0) || GetFloorTerrain().IsLiquid && !bOnMobj ) A_PlaySound("ut/playerfootstepwet",CHAN_5,abs(vel.xy.length())*0.03); - else A_PlaySound("ut/playerfootstep",CHAN_5,abs(vel.xy.length())*0.03); + if ( lastvelz < -4 ) + { + double vol = clamp((-lastvelz-4)*0.05,0.01,1.0); + if ( ((waterlevel > 0) || GetFloorTerrain().IsLiquid) && !bOnMobj ) A_PlaySound("ut/wetsplash",CHAN_AUTO,vol); + else A_PlaySound("*uland",CHAN_AUTO,vol); + } + else forcefootstep = true; } - if ( player.onground && !bNoGravity && !lastground && (lastvelz < -4) && (lastvelz >= -8) && (waterlevel < 3) ) + if ( forcefootstep || ((abs(sin(ang)) >= 1.0) && player.onground && (player.cmd.forwardmove || player.cmd.sidemove) && (waterlevel < 3)) ) { - if ( ((waterlevel > 0) || GetFloorTerrain().IsLiquid) && !bOnMobj ) A_PlaySound("ut/wetsplash",CHAN_AUTO,abs(lastvelz*0.03)); - else A_PlaySound("*land",CHAN_AUTO,abs(lastvelz*0.03)); + double vol = abs(vel.xy.length())*0.03; + if ( forcefootstep ) vol = clamp(-lastvelz*0.05,0.01,1.0); + if ( (waterlevel > 0) || GetFloorTerrain().IsLiquid && !bOnMobj ) A_PlaySound("ut/playerfootstepwet",CHAN_5,vol); + else A_PlaySound("ut/playerfootstep",CHAN_5,vol); } lastground = player.onground; lastvelz = prevvelz; prevvelz = vel.z; } + double FrictionToUnreal() + { + double fin = GetFriction(); + if ( fin >= 1.0 ) return 0.0; + return 734.2969*fin*fin-1485.0868*fin+750.7899; + } + override void MovePlayer() { + if ( !utmovement ) utmovement = CVar.GetCVar('flak_utmovement'); + if ( !doomspeed ) doomspeed = CVar.GetCVar('flak_doomspeed'); + if ( !doomaircontrol ) doomaircontrol = CVar.GetCVar('flak_doomaircontrol'); + if ( !nowalkdrop ) nowalkdrop = CVar.GetCVar('flak_nowalkdrop'); + bNODROPOFF = false; + if ( !utmovement.GetBool() ) + { + Super.MovePlayer(); + return; + } UserCmd cmd = player.cmd; if ( player.turnticks ) { @@ -196,74 +231,95 @@ Class UTPlayer : DoomPlayer } else Angle += cmd.yaw*(360./65536.); player.onground = (pos.z <= floorz) || bOnMobj || bMBFBouncer || (player.cheats & CF_NOCLIP2); - double friction, movefactor; - double forwardmove, sidemove; - double fm, sm; - double bobfactor; - [friction, movefactor] = GetFriction(); - bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR; - if ( !player.onground && !bNoGravity && !waterlevel ) + double friction = FrictionToUnreal(); + double fs = TweakSpeeds(1.0,0.0); + if ( !doomspeed.GetBool() ) { - // TODO replicate Unreal air control - movefactor *= level.aircontrol; - bobfactor *= level.aircontrol; + if ( cmd.buttons&BT_SPEED ) fs *= walkfactor; } - fm = cmd.forwardmove; - sm = cmd.sidemove; - [fm, sm] = TweakSpeeds (fm, sm); - fm *= Speed / 256; - sm *= Speed / 256; - if ( CanCrouch() && player.crouchfactor != 1 ) - { - fm *= player.crouchfactor; - sm *= player.crouchfactor; - bobfactor *= player.crouchfactor; - } - forwardmove = fm*movefactor*(35/TICRATE); - sidemove = sm*movefactor*(35/TICRATE); - if ( forwardmove ) Bob(Angle,cmd.forwardmove*bobfactor/256.,true); - if ( sidemove ) Bob(Angle-90,cmd.sidemove*bobfactor/256.,false); + else fs *= max(abs(cmd.forwardmove/12800.),abs(cmd.sidemove/10240.)); + if ( CanCrouch() && (player.crouchfactor != -1) ) fs *= player.crouchfactor; + acceleration = rotatevector((cmd.forwardmove,-cmd.sidemove),angle); if ( player.onground ) { - // Hook in Unreal physics (code totally not shamelessly copied from any source code leaks no sir) - // TODO find a way to properly "convert" Doom friction values into Unreal friction values (where default ground friction is 8) + if ( nowalkdrop.GetBool() ) + bNODROPOFF = ((acceleration.length() > double.epsilon) && (cmd.buttons&BT_SPEED)); + // Hook in Unreal physics Vector2 dir = (0,0); if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit(); - acceleration = rotatevector((cmd.forwardmove,-cmd.sidemove),angle); if ( acceleration.length() <= double.epsilon ) { Vector2 oldvel = vel.xy; - vel.xy = vel.xy - (2 * dir) * vel.xy.length() * (1./TICRATE) * friction; + vel.xy = vel.xy - (2 * dir) * vel.xy.length() * friction/TICRATE; if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0; } else { Vector2 acceldir = acceleration.unit(); - acceleration = acceldir * Min(acceleration.length(), 2048./TICRATE); - vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * (1./TICRATE) * friction; + acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); + vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * friction/TICRATE; } vel.xy = vel.xy + acceleration * (1./TICRATE); - double maxvel = 400./TICRATE; - if ( CanCrouch() && player.crouchfactor != 1 ) - maxvel *= player.crouchfactor; - if ( cmd.buttons&BT_SPEED ) - maxvel *= 0.35; + double maxvel; + if ( doomspeed.GetBool() ) maxvel = (groundspeed_doomish*fs)/TICRATE; + else maxvel = (groundspeed*fs)/TICRATE; + double doomfriction = clamp(GetFriction()/ORIG_FRICTION,0.0,1.0); + maxvel *= doomfriction; if ( vel.xy.length() > maxvel ) vel.xy = vel.xy.unit()*maxvel; - double b = vel.x*cos(angle)+vel.y*sin(angle); - Bob(Angle,b/256.,true); - b = vel.x*cos(angle-90)+vel.y*sin(angle-90); - Bob(Angle-90,b/256.,false); if ( !(player.cheats & CF_PREDICTING) ) { if ( acceleration.length() <= double.epsilon ) PlayIdle(); else PlayRunning(); } + player.vel = vel.xy; + } + else if ( !bNoGravity && !waterlevel ) + { + // air acceleration when falling + float maxaccel = accelrate/TICRATE; + if ( vel.xy.length() < (40./TICRATE) ) + maxaccel += (40.-vel.xy.length())/TICRATE; + if ( acceleration.length() > maxaccel ) + acceleration = acceleration.unit()*maxaccel; + acceleration *= doomaircontrol.GetBool()?level.aircontrol:0.35; + vel.xy += acceleration/TICRATE; + player.vel *= 0; } else { - // TODO replicate Unreal air friction - if ( forwardmove ) ForwardThrust(forwardmove,Angle); - if ( sidemove ) Thrust(sidemove,Angle-90); + // swimming uses standard physics, otherwise things break + double forwardmove, sidemove; + double bobfactor; + double friction, movefactor; + double fm, sm; + [friction, movefactor] = GetFriction(); + bobfactor = (friction 1) && (last_fm*fm>0) ) + dodge += RotateVector((fm,0),angle).unit(); + last_fm_tap = gametic; + last_fm = fm; + } + if ( sm ) + { + int clk = abs(gametic-last_sm_tap); + if ( (clk < 5) && (clk > 1) && (last_sm*sm>0) ) + dodge += RotateVector((0,-sm),angle).unit(); + last_sm_tap = gametic; + last_sm = sm; + } + if ( dodge.length() > 0 ) + { + if ( doomspeed.GetBool() ) vel += dodge.unit()*(groundspeed_doomish*1.5)/TICRATE; + else vel += dodge.unit()*(groundspeed*1.5)/TICRATE; + vel.z += jumpz*0.5; + bOnMobj = false; + player.jumpTics = -1; + if ( !(player.cheats&CF_PREDICTING) ) + A_PlaySound("*jump",CHAN_BODY); + } + } + Super.CheckJump(); + } } // Random Spawner that passes through dropped status to items @@ -904,6 +999,7 @@ Class UTMainHandler : StaticEventHandler { ui TextureID tex; Array flashes; + transient CVar nobosstelefrag; override void WorldLoaded( WorldEvent e ) { @@ -920,23 +1016,25 @@ Class UTMainHandler : StaticEventHandler override void WorldThingSpawned( WorldEvent e ) { - if ( e.Thing.bBOSS ) e.Thing.bNOTELEFRAG = true; + if ( !nobosstelefrag ) nobosstelefrag = CVar.GetCVar('flak_nobosstelefrag'); + if ( nobosstelefrag.GetBool() && e.Thing.bBOSS ) e.Thing.bNOTELEFRAG = true; } ui void StartMenu() { - if ( gamestate != GS_TITLELEVEL ) return; int proto = CVar.GetCVar('flak_protomenu',players[consoleplayer]).GetInt(); if ( proto ) { + tex = TexMan.CheckForTexture("protobg",TexMan.Type_Any); + if ( gamestate != GS_TITLELEVEL ) return; if ( proto > 1 ) S_ChangeMusic("menu2"); else S_ChangeMusic("xyzdMenu"); - tex = TexMan.CheckForTexture("protobg",TexMan.Type_Any); } else { - S_ChangeMusic("utmenu23"); tex = TexMan.CheckForTexture("finalbg",TexMan.Type_Any); + if ( gamestate != GS_TITLELEVEL ) return; + S_ChangeMusic("utmenu23"); } } @@ -995,7 +1093,7 @@ Class UTMainHandler : StaticEventHandler override void RenderOverlay( RenderEvent e ) { - if ( gamestate != GS_TITLELEVEL ) return; + if ( !menuactive ) return; if ( tex.IsNull() || !tex.IsValid() ) return; if ( !CVar.GetCVar('flak_showmenu',players[consoleplayer]).GetBool() ) return; Screen.Dim("Black",1.0,0,0,Screen.GetWidth(),Screen.GetHeight());