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/maps/titlemap.wad b/maps/titlemap.wad index 5a63358..d1db4cb 100644 Binary files a/maps/titlemap.wad and b/maps/titlemap.wad differ 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/modeldef.flak b/modeldef.flak index 2cd675d..26fb610 100644 --- a/modeldef.flak +++ b/modeldef.flak @@ -26,10 +26,10 @@ Model "FlakSlug" Path "models" Model 0 "flakslugm_d.3d" Skin 0 "jflakslugel1.png" - Scale 0.048 0.048 0.04 + Scale 0.048 0.04 0.04 AngleOffset 180 PitchOffset 90 - PITCHFROMMOMENTUM + USEACTORPITCH FrameIndex FSLG A 0 0 } diff --git a/sndinfo.txt b/sndinfo.txt index 92965c6..457ed91 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 @@ -108,6 +110,7 @@ misc/chat2 newbeep misc/teleport resp2a misc/ut_keg utsuperh misc/ut_heal uthealth +$volume misc/ut_heal 0.7 // a bit too loud otherwise misc/ut_shard shardpck misc/ut_armor armorut belt/pickup beltsnd diff --git a/zscript/biorifle.zsc b/zscript/biorifle.zsc index 6ac6e70..86c96d6 100644 --- a/zscript/biorifle.zsc +++ b/zscript/biorifle.zsc @@ -412,8 +412,8 @@ Class BioGel : Actor s.args[3] = int(s.args[3]*Scale.x); invoker.deadtimer = -2; if ( invoker.atline ) invoker.atline.RemoteActivate(target,invoker.atside,SPAC_Impact,pos); - UTMainHandler.DoBlast(self,Min(250,int(Scale.x*75)),20000*Scale.x); - A_Explode(int(Random[GES](18,26)*Scale.x),Min(250,int(Scale.x*75))); + UTMainHandler.DoBlast(self,Min(175,int(Scale.x*50)),20000*Scale.x); + A_Explode(int(Random[GES](18,26)*Scale.x),Min(175,int(Scale.x*50))); A_PlaySound("ges/explode",CHAN_VOICE); int numpt = Min(300,int(Scale.x*30))+Random[GES](-10,10); for ( int i=0; i 0 ) + { + double MagnitudeVel = Vel.length(); + SeekingDir = (SeekingDir*0.5*MagnitudeVel+Vel).unit(); + Vel = MagnitudeVel * SeekingDir; + invoker.Acceleration = 25 * SeekingDir; + } + } + } States { Spawn: RCKT B 1 { A_SetRoll(roll+30,SPF_INTERPOLATE); + if ( invoker.ticcnt++ > 3 ) + { + invoker.ticcnt = 0; + A_RocketSeek(); + } + vel += invoker.Acceleration/TICRATE; + if ( vel.length() > 45. ) vel = Vel.unit()*45.; Vector3 dir = vel.unit(); if ( waterlevel <= 0 ) vel = dir*min(vel.length()+1,32); A_SetAngle(atan2(dir.y,dir.x),SPF_INTERPOLATE); A_SetPitch(asin(-dir.z),SPF_INTERPOLATE); - if ( tracer ) A_SeekerMissile(0,2,SMF_PRECISE); for ( int i=0; i<3; i++ ) { let s = Spawn("UTSmoke",pos); @@ -179,7 +205,7 @@ Class UTRocket : Actor } Wait; Death: - TNT1 A 0 A_RocketExplode(Random[Eightball](90,120),220); + TNT1 A 0 A_RocketExplode(Random[Eightball](90,120),160); SSMX ABCDEFGHIJ 2 Bright; Stop; } @@ -233,7 +259,7 @@ Class UTGrenade : UTRocket } Goto Spawn; Death: - TNT1 A 0 A_RocketExplode(Random[Eightball](100,150),200); + TNT1 A 0 A_RocketExplode(Random[Eightball](100,150),140); Goto Super::Death+1; } } diff --git a/zscript/flakcannon.zsc b/zscript/flakcannon.zsc index 1838e40..4ac6de6 100644 --- a/zscript/flakcannon.zsc +++ b/zscript/flakcannon.zsc @@ -29,13 +29,17 @@ Class FlakAmmo : Ammo Default { Tag "Flak Shells"; - Inventory.PickupMessage "You picked up 10 Flak Shells."; + Inventory.PickupMessage "You picked up %d Flak Shells."; Inventory.Amount 10; Inventory.MaxAmount 50; Ammo.BackpackAmount 20; Ammo.BackpackMaxAmount 100; Ammo.DropAmount 5; } + override String PickupMessage() + { + return String.Format(pickupmsg,Amount); + } States { Spawn: @@ -52,6 +56,7 @@ Class FlakAmmo2 : FlakAmmo Inventory.PickupMessage "You picked up a Flak Shell."; Inventory.Amount 1; Ammo.DropAmount 1; + +INVENTORY.IGNORESKILL; } States { @@ -143,10 +148,10 @@ Class FlakChunk : Actor DamageType 'Shredded'; BounceType "Doom"; BounceFactor 0.8; + WallBounceFactor 0.8; PROJECTILE; +USEBOUNCESTATE; -BOUNCEAUTOOFF; - +BOUNCEAUTOOFFFLOORONLY; +CANBOUNCEWATER; +SKYEXPLODE; Scale 0.3; @@ -225,9 +230,10 @@ Class FlakChunk : Actor invoker.rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); invoker.pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); invoker.yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed); - vel = (vel.unit()+(FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4))).unit()*vel.length(); + vel = (vel.unit()+(FRandom[Flak](-0.2,0.2),FRandom[Flak](-0.2,0.2),FRandom[Flak](-0.2,0.2))).unit()*vel.length(); A_PlaySound("flak/bounce",volume:0.3); A_AlertMonsters(); + bBOUNCEAUTOOFFFLOORONLY = true; if ( vel.length() < 4.0 ) ExplodeMissile(); } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) @@ -383,12 +389,12 @@ Class FlakSlug : Actor { bForceXYBillboard = true; A_SetRenderStyle(1.0,STYLE_Add); - A_SprayDecal("RocketBlast",150); + A_SprayDecal("RocketBlast",50); A_NoGravity(); A_SetScale(1.2); - UTMainHandler.DoBlast(self,150,75000); - A_Explode(Random[Flak](70,80),150); - A_QuakeEx(4,4,4,8,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:150,rollIntensity:0.2); + UTMainHandler.DoBlast(self,120,75000); + A_Explode(Random[Flak](70,80),120); + A_QuakeEx(4,4,4,8,0,170,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollIntensity:0.2); A_PlaySound("flak/explode",CHAN_VOICE); A_AlertMonsters(); if ( !Tracer ) Spawn("SlugSmoke",pos); diff --git a/zscript/healitems.zsc b/zscript/healitems.zsc index 08df1b9..ab7369d 100644 --- a/zscript/healitems.zsc +++ b/zscript/healitems.zsc @@ -28,7 +28,6 @@ Class UTHealthBox : Health replaces Medikit Tag "Health Box"; Inventory.Amount 50; Inventory.PickupMessage "You picked up a Health Box."; - Health.LowMessage 25,"You picked up a Health Box that you REALLY need!"; Inventory.PickupSound "misc/ut_heal"; } States diff --git a/zscript/minigun.zsc b/zscript/minigun.zsc index 8be71a9..1bb5340 100644 --- a/zscript/minigun.zsc +++ b/zscript/minigun.zsc @@ -30,13 +30,17 @@ Class MiniAmmo : Ammo Default { Tag "Large Bullets"; - Inventory.PickupMessage "You picked up 50 bullets."; + Inventory.PickupMessage "You picked up %d bullets."; Inventory.Amount 50; Inventory.MaxAmount 200; Ammo.BackpackAmount 100; Ammo.BackpackMaxAmount 400; Ammo.DropAmount 20; } + override String PickupMessage() + { + return String.Format(pickupmsg,Amount); + } States { Spawn: @@ -102,7 +106,7 @@ Class Minigun : UTWeapon A_Overlay(-2,"MuzzleFlash",true); A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true); A_OverlayRenderstyle(-2,STYLE_Add); - if ( (alt && (invoker.bcnt++ < 3)) || (invoker.bcnt++ < 5) ) return; + if ( (alt && (invoker.bcnt++ < 2)) || (invoker.bcnt++ < 4) ) return; invoker.bcnt = 0; if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; invoker.FireEffect(); diff --git a/zscript/powerups.zsc b/zscript/powerups.zsc index cc366eb..f22ee84 100644 --- a/zscript/powerups.zsc +++ b/zscript/powerups.zsc @@ -52,13 +52,18 @@ Class DamageAmplifier : Powerup Powerup.Color "EE00FF", 0.15; } + override void BeginPlay() + { + Super.BeginPlay(); + if ( deathmatch ) EffectTics /= 2; + } + override void InitEffect() { Super.InitEffect(); l = Spawn("DamageAmpLight",Owner.pos); l.target = Owner; l.master = self; - if ( deathmatch ) EffectTics /= 2; } override void DoEffect() @@ -197,11 +202,16 @@ Class PowerUTInvisibility : PowerInvisibility { Default { - Powerup.Duration -80; + Powerup.Duration -100; Powerup.Strength 90; Powerup.Mode "Additive"; Powerup.Color "FFFFFF", 0.1; } + override void BeginPlay() + { + Super.BeginPlay(); + if ( deathmatch ) EffectTics /= 2; + } override void EndEffect() { Super.EndEffect(); diff --git a/zscript/ripper.zsc b/zscript/ripper.zsc index 4db9ed3..06620a9 100644 --- a/zscript/ripper.zsc +++ b/zscript/ripper.zsc @@ -58,7 +58,7 @@ Class Razor2 : Actor Radius 2; Height 2; Speed 40; // should be 26 but it looks way too slow - DamageFunction Random[Ripper](30,40); + DamageFunction (Random[Ripper](30,40)*((DamageType=='Decapitated')?3.5:1.0)); DamageType 'Ripper'; Obituary "%k ripped a chunk of meat out of %o with the Ripper."; BounceType "Doom"; @@ -84,12 +84,11 @@ Class Razor2 : Actor } override int SpecialMissileHit( Actor victim ) { - if ( pos.z > victim.pos.z+victim.height*0.8 ) DamageType = 'Decapitated'; + if ( pos.z > victim.pos.z+victim.height*0.75 ) DamageType = 'Decapitated'; return -1; } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) { - if ( pos.z > target.pos.z+target.height*0.8 ) damage *= 2; if ( !target.bNOBLOOD ) { target.SpawnBlood(pos,AngleTo(target),damage); @@ -202,9 +201,9 @@ Class Razor2Alt : Razor2 Spawn("Razor2AltLight",pos); A_AlertMonsters(); A_SprayDecal("RazorBlast",20); - UTMainHandler.DoBlast(self,120,87000); - A_Explode(Random[Ripper](30,50),180,damagetype:'RipperAltDeath'); - A_QuakeEx(3,3,3,10,0,180,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollIntensity:0.1); + UTMainHandler.DoBlast(self,90,87000); + A_Explode(Random[Ripper](30,50),90,damagetype:'RipperAltDeath'); + A_QuakeEx(3,3,3,10,0,140,"",QF_RELATIVE|QF_SCALEDOWN,falloff:90,rollIntensity:0.1); int numpt = Random[Ripper](10,20); Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); for ( int i=0; i= 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); + player.jumptics = 0; + 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 ) + { + player.turnticks--; + Angle += (180./TURN180_TICKS); + } + else Angle += cmd.yaw*(360./65536.); + player.onground = (pos.z <= floorz) || bOnMobj || bMBFBouncer || (player.cheats & CF_NOCLIP2); + double friction = FrictionToUnreal(); + double fs = TweakSpeeds(1.0,0.0); + if ( !doomspeed.GetBool() ) + { + if ( cmd.buttons&BT_SPEED ) fs *= walkfactor; + } + 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); + Vector2 dodge = (0,0); + int fm = cmd.forwardmove; + int sm = cmd.sidemove; + if ( fm ) + { + int clk = abs(gametic-last_fm_tap); + if ( (clk < 8) && (last_fm*fm == 0) && (last_tap_fm*fm>0) ) + dodge += RotateVector((fm,0),angle).unit(); + if ( !last_fm && (last_jump_held < gametic-1) ) + { + last_fm_tap = gametic; + last_tap_fm = fm; + } + } + last_fm = fm; + if ( sm ) + { + int clk = abs(gametic-last_sm_tap); + if ( (clk < 8) && (last_sm*sm == 0) && (last_tap_sm*sm>0) ) + dodge += RotateVector((0,-sm),angle).unit(); + if ( !last_sm && (last_jump_held < gametic-1) ) + { + last_sm_tap = gametic; + last_tap_sm = sm; + } + } + last_sm = sm; + if ( player.onground ) + { + if ( !bNoGravity && !waterlevel && (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; + if ( !(player.cheats&CF_PREDICTING) ) + A_PlaySound("*jump",CHAN_BODY); + if ( player.cheats & CF_REVERTPLEASE ) + { + player.cheats &= ~CF_REVERTPLEASE; + player.camera = player.mo; + } + player.vel *= 0; + } + else + { + 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(); + if ( acceleration.length() <= double.epsilon ) + { + 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; + } + else + { + Vector2 acceldir = acceleration.unit(); + acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); + vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * friction/TICRATE; + } + vel.xy = vel.xy + acceleration/TICRATE; + 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; + 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; + Vector2 dir = (0,0); + if ( vel.xy.length() > double.epsilon ) dir = vel.xy.unit(); + if ( acceleration.length() <= double.epsilon ) + { + Vector2 oldvel = vel.xy; + vel.xy = vel.xy - (2 * dir) * vel.xy.length() * fluidfriction/TICRATE; + if ( oldvel dot vel.xy < 0.0 ) vel.xy *= 0; + } + else + { + Vector2 acceldir = acceleration.unit(); + acceleration = acceldir * Min(acceleration.length(), accelrate/TICRATE); + vel.xy = vel.xy - (dir - acceldir) * vel.xy.length() * fluidfriction/TICRATE; + } + acceleration *= doomaircontrol.GetBool()?level.aircontrol:utaircontrol; + vel.xy = vel.xy + acceleration/TICRATE; + if ( vel.length() > terminalvelocity/TICRATE ) vel = vel.unit()*(terminalvelocity/TICRATE); + player.vel *= 0; + } + else + { + // swimming uses standard physics, otherwise things break + double forwardmove, sidemove; + double bobfactor; + double friction, movefactor; + double fm, sm; + [friction, movefactor] = GetFriction(); + bobfactor = (friction= 2 ) Vel.z = 4*Speed; + else if ( bNoGravity ) Vel.z = 3.; + else if ( level.IsJumpingAllowed() && player.onground && (player.jumpTics == 0) && (last_jump_held < gametic-1) ) + { + double jumpvelz = JumpZ; + double jumpfac = 0; + for ( let p = Inv; p != null; p = p.Inv ) + { + let pp = PowerHighJump(p); + if ( !pp ) continue; + double f = pp.Strength; + if ( f > jumpfac ) jumpfac = f; + } + if ( jumpfac > 0 ) jumpvelz *= jumpfac; + Vel.z += jumpvelz; + bOnMobj = false; + player.jumpTics = -1; + if ( !(player.cheats&CF_PREDICTING) ) + A_PlaySound("*jump",CHAN_BODY); + } + last_jump_held = gametic; + } + if ( !player.onground || player.jumptics ) + last_jump_held = gametic; + } } // Random Spawner that passes through dropped status to items @@ -206,6 +450,7 @@ Class RandomSpawner2 : RandomSpawner Class UTWeapon : Weapon { int DropAmmo; + bool bExtraPickup; Property DropAmmo: DropAmmo; @@ -252,6 +497,79 @@ Class UTWeapon : Weapon A_ClearRefire(); } + override bool HandlePickup( Inventory item ) + { + if (item.GetClass() == GetClass()) + { + if ( Weapon(item).PickupForAmmo(self) ) + item.bPickupGood = true; + if ( (MaxAmount > 1) || bALWAYSPICKUP ) + return Inventory.HandlePickup(item); + return true; + } + return false; + } + override bool ShouldStay() + { + if ( ((multiplayer && (!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && !bDropped ) + return (!bExtraPickup && !bALWAYSPICKUP); + return false; + } + override bool TryPickup( in out Actor toucher ) + { + if ( !bExtraPickup ) bExtraPickup = ((MaxAmount > 1) && (toucher.CountInv(GetClass()) < MaxAmount)); + return Super.TryPickup(toucher); + } + + // Whole chain of function rewrites because of some stupid hardcoded deathmatch ammo multiplier + override bool TryPickupRestricted( in out Actor toucher ) + { + if ( ShouldStay() ) return false; + bExtraPickup = false; + bool gaveSome = !!(NonIdioticAddAmmo(toucher,AmmoType1,AmmoGive1)); + gaveSome |= !!(NonIdioticAddAmmo(toucher,AmmoType2,AmmoGive2)); + if ( gaveSome ) GoAwayAndDie(); + return gaveSome; + } + override void AttachToOwner( Actor other ) + { + bExtraPickup = false; + Inventory.AttachToOwner(other); + Ammo1 = NonIdioticAddAmmo(Owner,AmmoType1,AmmoGive1); + Ammo2 = NonIdioticAddAmmo(Owner,AmmoType2,AmmoGive2); + SisterWeapon = AddWeapon(SisterWeaponType); + if ( Owner.player ) + { + if ( !Owner.player.GetNeverSwitch() && !bNo_Auto_Switch ) + Owner.player.PendingWeapon = self; + if ( Owner.player.mo == players[consoleplayer].camera ) + StatusBar.ReceivedWeapon(self); + } + GivenAsMorphWeapon = false; + } + + // rewrite of AddAmmo without stupid hardcoded 2.5x ammo multiplier + protected Ammo NonIdioticAddAmmo( Actor other, Class ammotype, int amount ) + { + if ( !ammotype ) return null; + Ammo ammoitem; + if ( !bIgnoreSkill ) amount = int(amount*G_SkillPropertyFloat(SKILLP_AmmoFactor)); + ammoitem = Ammo(other.FindInventory(ammotype)); + if ( !ammoitem ) + { + ammoitem = Ammo(Spawn(ammotype)); + ammoitem.Amount = min(amount,ammoitem.MaxAmount); + ammoitem.AttachToOwner(other); + } + else if ( ammoitem.Amount < ammoitem.MaxAmount ) + { + ammoitem.Amount += amount; + if ( ammoitem.Amount > ammoitem.MaxAmount ) + ammoitem.Amount = ammoitem.MaxAmount; + } + return ammoitem; + } + Default { Weapon.BobStyle "Smooth"; @@ -817,6 +1135,7 @@ Class UTMainHandler : StaticEventHandler { ui TextureID tex; Array flashes; + transient CVar nobosstelefrag; override void WorldLoaded( WorldEvent e ) { @@ -833,23 +1152,27 @@ 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(); + CVar protomenu = CVar.GetCVar('flak_protomenu',players[consoleplayer]); + if ( !protomenu ) return; // this can happen + int proto = protomenu.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"); } } @@ -908,7 +1231,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()); diff --git a/zscript/warheadlauncher.zsc b/zscript/warheadlauncher.zsc index 6ff2efa..534a8f4 100644 --- a/zscript/warheadlauncher.zsc +++ b/zscript/warheadlauncher.zsc @@ -11,6 +11,7 @@ Class WarheadAmmo : Ammo Ammo.BackpackMaxAmount 3; Ammo.DropAmount 1; Inventory.RespawnTics 2100; + +INVENTORY.IGNORESKILL; } States { @@ -717,6 +718,7 @@ Class WarheadLauncher : UTWeapon replaces BFG9000 Weapon.AmmoGive 1; Inventory.RespawnTics 2100; +INVENTORY.ALWAYSPICKUP; + +INVENTORY.IGNORESKILL; +WEAPON.NOAUTOFIRE; UTWeapon.DropAmmo 1; }