diff --git a/Readme.md b/Readme.md index c152429..8356b41 100644 --- a/Readme.md +++ b/Readme.md @@ -3,7 +3,7 @@ The Unreal 1 counterpart to Doom Tournament. Adds Unreal 1 weapons and items (including dummied out stuff and others). -This mod requires GZDoom g4.3pre-64-g37fa2e1b6 or later, and runs on top of +This mod requires GZDoom g4.3pre-79-gbcef44051 or later, and runs on top of Doom Tournament (currently the devel branch is required). ## Currently Implemented @@ -19,6 +19,9 @@ Doom Tournament (currently the devel branch is required). - Single rocket mode for Eightball - "Hold up to 2 seconds" feature from Unreal Bible - Flak Cannon (slot 6) (replaces rocket launcher) + - Razorjack (slot 7) (replaces chaingun) + - Razorjack hold fire to increase blade speed (from Unreal Bible) + - Make Razorjack altfire actually seek where player is aiming (toggleable) - SMP 7243 (slot 0) (replaces bfg9000) - Backpack (replaces backpack, identical to Doom Tournament version) - Unreal 1 HUD @@ -52,7 +55,6 @@ Doom Tournament (currently the devel branch is required). ## In progress - - Razorjack (slot 7) (replaces chaingun) - GES Bio Rifle (slot 8) (replaces plasma rifle) - Rifle (slot 9) (replaces plasma rifle) - Minigun (slot 0) (replaces chaingun) @@ -60,13 +62,11 @@ Doom Tournament (currently the devel branch is required). ## Planned - Unreal Bible & prototype build behaviour restoration - - Razorjack hold fire to increase blade speed - Rifle restored rapid fire - Rifle restored flashlight - Biorifle "Hold up to 2 seconds" feature from Unreal Bible - QOL improvements - - Make Razorjack altfire actually seek where player is aiming - Biorifle splashes like UT (toggleable) - Stunner (slot 4) (replaces chainsaw) diff --git a/cvarinfo.txt b/cvarinfo.txt index 4760a3d..492ffc7 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -37,7 +37,7 @@ server bool sting_riflel = false; // old rifle flashlight // you know... a scope server bool sting_razor = false; // razorjack blade charging // hold primary fire to increase the - // spin up to 3x + // spin up to 3 levels server bool sting_flamet = false; // use flamethrower model based on old // design and texture rather than the // modern redesign @@ -84,3 +84,6 @@ server bool sting_ehold = false; // eightball can be held fully loaded // for up to 2 seconds server bool sting_bhold = false; // biorifle can be held fully loaded // for up to 2 seconds +server bool sting_razoraim = false; // razorjack alt follows aim instead of + // being steered by player rotation +server bool sting_biosplash = false; // biorifle alt splashes like in ut diff --git a/language.txt b/language.txt index 5e77188..42bc022 100644 --- a/language.txt +++ b/language.txt @@ -235,6 +235,8 @@ STING_MSENTRY = "Enable new Minigun Sentry"; STING_DUBIOUS = "Enable Demolisher, Razorclaw and Autocannon"; STING_QOPTS = "Convenience features"; STING_AUTOSCUBA = "Automatic SCUBA Gear toggling"; +STING_RAZORAIM = "Razorjack altfire follows the crosshair"; +STING_BIOSPLASH = "Biorifle altfire splashes like in UT"; STING_MCREDS = "Unreal Credits"; STING_CDR = "Doomreal"; STING_CLEAD = "Development Lead:"; @@ -463,6 +465,8 @@ STING_MSENTRY = "Habilitar nueva Torreta"; STING_DUBIOUS = "Habilitar Demoledor, Garra y Autocañón"; STING_QOPTS = "Características de comodidad"; STING_AUTOSCUBA = "Uso automático de Kit de Buceo"; +STING_RAZORAIM = "El fuego alt. del Razorjack sigue el punto de mira"; +STING_BIOSPLASH = "El fuego alt. del Biorifle salpica como en UT"; STING_MCREDS = "Créditos de Unreal"; STING_CDR = "Doomreal"; STING_CLEAD = "Desarrolladora Jefe:"; diff --git a/menudef.txt b/menudef.txt index 97e7471..509e5fb 100644 --- a/menudef.txt +++ b/menudef.txt @@ -49,6 +49,8 @@ OptionMenu "UnrealOptionMenu" StaticText " " StaticText "$STING_QOPTS", "Gold" Option "$STING_AUTOSCUBA", "sting_autoscuba", "YesNo" + Option "$STING_RAZORAIM", "sting_razoraim", "YesNo" + Option "$STING_BIOSPLASH", "sting_biosplash", "YesNo" } AddOptionMenu "OptionsMenu" diff --git a/modeldef.razorjack b/modeldef.razorjack index ccb2e6c..cb97647 100644 --- a/modeldef.razorjack +++ b/modeldef.razorjack @@ -3,13 +3,48 @@ Model "RazorAmmo" Path "models" Model 0 "RazorAmmoMesh_d.3d" Skin 0 "JPickup21.png" - ZOffset 8 + ZOffset 5 Scale 0.1 0.1 0.12 FrameIndex BHOP A 0 0 FrameIndex BHOP B 0 1 } +Model "RazorBlade" +{ + Path "models" + Model 0 "razorb_d.3d" + SurfaceSkin 0 1 "JRazor1.png" + USEACTORPITCH + USEACTORROLL + ROTATING + AngleOffset 90 + Scale 0.08 0.08 0.096 + + Rotation-Speed 15 + FrameIndex RAZB A 0 0 + Rotation-Speed 25 + FrameIndex RAZB B 0 0 + Rotation-Speed 35 + FrameIndex RAZB C 0 0 + Rotation-Speed 45 + FrameIndex RAZB D 0 0 +} + +Model "RazorBladeTrail" +{ + Path "models" + Model 0 "razorb_d.3d" + SurfaceSkin 0 0 "FireEffect54.png" + DONTCULLBACKFACES + USEACTORPITCH + USEACTORROLL + AngleOffset 90 + Scale 0.08 0.08 0.096 + + FrameIndex RAZB A 0 0 +} + Model "Razorjack" { Path "models" @@ -26,3 +61,124 @@ Model "Razorjack" ROTATING FrameIndex RZRP A 1 0 } + +Model "Razorjack" +{ + Path "models" + Model 0 "Razor_d.3d" + Skin 0 "JRazor1.png" + Scale 0.1 -0.1 0.1 + //Offset 0 -18.7 -8 + Offset 0 -10 -4.5 + AngleOffset -90 + RollOffset -11.25 + + // Select + FrameIndex RZRS A 0 0 + FrameIndex RZRS B 0 1 + FrameIndex RZRS C 0 2 + FrameIndex RZRS D 0 3 + FrameIndex RZRS E 0 4 + FrameIndex RZRS F 0 5 + FrameIndex RZRS G 0 6 + FrameIndex RZRS H 0 7 + FrameIndex RZRS I 0 8 + FrameIndex RZRS J 0 9 + FrameIndex RZRS K 0 10 + FrameIndex RZRS L 0 11 + FrameIndex RZRS M 0 12 + FrameIndex RZRS N 0 13 + FrameIndex RZRS O 0 14 + FrameIndex RZRS P 0 15 + FrameIndex RZRS Q 0 16 + FrameIndex RZRS R 0 17 + FrameIndex RZRS S 0 18 + FrameIndex RZRS T 0 19 + FrameIndex RZRS U 0 20 + FrameIndex RZRS V 0 21 + FrameIndex RZRS W 0 22 + FrameIndex RZRS X 0 23 + FrameIndex RZRS Y 0 24 + FrameIndex RZRS Z 0 25 + FrameIndex RZS2 A 0 26 + FrameIndex RZS2 B 0 27 + FrameIndex RZS2 C 0 28 + FrameIndex RZS2 D 0 29 + // Fire + FrameIndex RZRF A 0 30 + FrameIndex RZRF B 0 31 + FrameIndex RZRF C 0 32 + FrameIndex RZRF D 0 33 + FrameIndex RZRF E 0 34 + FrameIndex RZRF F 0 35 + // Load + FrameIndex RZRF G 0 36 + FrameIndex RZRF H 0 37 + FrameIndex RZRF I 0 38 + FrameIndex RZRF J 0 39 + // Idle + FrameIndex RZRI A 0 40 + FrameIndex RZRI B 0 41 + FrameIndex RZRI C 0 42 + FrameIndex RZRI D 0 43 + FrameIndex RZRI E 0 44 + FrameIndex RZRI F 0 45 + FrameIndex RZRI G 0 46 + FrameIndex RZRI H 0 47 + FrameIndex RZRI I 0 48 + FrameIndex RZRI J 0 49 + FrameIndex RZRI K 0 50 + FrameIndex RZRI L 0 51 + FrameIndex RZRI M 0 52 + FrameIndex RZRI N 0 53 + FrameIndex RZRI O 0 54 + FrameIndex RZRI P 0 55 + FrameIndex RZRI Q 0 56 + FrameIndex RZRI R 0 57 + FrameIndex RZRI S 0 58 + FrameIndex RZRI T 0 59 + FrameIndex RZRI U 0 60 + FrameIndex RZRI V 0 61 + FrameIndex RZRI W 0 62 + FrameIndex RZRI X 0 63 + FrameIndex RZRI Y 0 64 + FrameIndex RZRI Z 0 65 + FrameIndex RZI2 A 0 66 + FrameIndex RZI2 B 0 67 + FrameIndex RZI2 C 0 68 + FrameIndex RZI2 D 0 69 + FrameIndex RZI2 E 0 70 + // AltFire1 + FrameIndex RZRA A 0 71 + FrameIndex RZRA B 0 72 + FrameIndex RZRA C 0 73 + FrameIndex RZRA D 0 74 + FrameIndex RZRA E 0 75 + FrameIndex RZRA F 0 76 + FrameIndex RZRA G 0 77 + FrameIndex RZRA H 0 78 + FrameIndex RZRA I 0 79 + FrameIndex RZRA J 0 80 + FrameIndex RZRA K 0 81 + FrameIndex RZRA L 0 82 + // AltFire2 + FrameIndex RZRA M 0 83 + FrameIndex RZRA N 0 84 + FrameIndex RZRA O 0 85 + FrameIndex RZRA P 0 86 + FrameIndex RZRA Q 0 87 + // AltFire3 + FrameIndex RZRA R 0 88 + FrameIndex RZRA S 0 89 + FrameIndex RZRA T 0 90 + FrameIndex RZRA U 0 91 + // Down + FrameIndex RZRD A 0 92 + FrameIndex RZRD B 0 93 + FrameIndex RZRD C 0 94 + FrameIndex RZRD D 0 95 + FrameIndex RZRD E 0 96 + FrameIndex RZRD F 0 97 + FrameIndex RZRD G 0 98 + FrameIndex RZRD H 0 99 +} diff --git a/models/FireEffect54.png b/models/FireEffect54.png new file mode 100644 index 0000000..d73bbee Binary files /dev/null and b/models/FireEffect54.png differ diff --git a/sndinfo.txt b/sndinfo.txt index 7163cff..75a6666 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -174,6 +174,8 @@ stinger/flesh chunkhit flak/click click +eightball/fly brocket + asmd/vapour vapour dampener/on dampsnd diff --git a/zscript/asmd.zsc b/zscript/asmd.zsc index e2833ce..333f063 100644 --- a/zscript/asmd.zsc +++ b/zscript/asmd.zsc @@ -361,10 +361,31 @@ Class ASMDBall : Actor if ( BlockingLine ) HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit(); else if ( BlockingFloor ) { - HitNormal = BlockingFloor.floorplane.Normal; + // find closest 3d floor for its normal + F3DFloor ff = null; + for ( int i=0; i1.5); Actor r; diff --git a/zscript/automag.zsc b/zscript/automag.zsc index cb1ba98..f4c6c96 100644 --- a/zscript/automag.zsc +++ b/zscript/automag.zsc @@ -196,8 +196,16 @@ Class Automag : UnrealWeapon else if ( d.HitType != TRACE_HitNone ) { Vector3 hitnormal = -d.HitDir; - if ( d.HitType == TRACE_HitFloor ) hitnormal = d.HitSector.floorplane.Normal; - else if ( d.HitType == TRACE_HitCeiling ) hitnormal = d.HitSector.ceilingplane.Normal; + if ( d.HitType == TRACE_HitFloor ) + { + if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal; + else hitnormal = d.HitSector.floorplane.Normal; + } + else if ( d.HitType == TRACE_HitCeiling ) + { + if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal; + else hitnormal = d.HitSector.ceilingplane.Normal; + } else if ( d.HitType == TRACE_HitWall ) { hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit(); diff --git a/zscript/dispersionpistol.zsc b/zscript/dispersionpistol.zsc index baf85a6..dc65784 100644 --- a/zscript/dispersionpistol.zsc +++ b/zscript/dispersionpistol.zsc @@ -570,7 +570,7 @@ Class DispersionPistol : UnrealWeapon A_WeaponOffset(0,32); invoker.bCharging = false; if ( self is 'UTPlayer' ) - UTPlayer(self).PlayAttacking(); + UTPlayer(self).PlayAttacking3(); DefaultAmmo(weap.Ammo1).rechargephase = 0; A_PlaySound("dpistol/fire",CHAN_WEAPON,Dampener.Active(self)?.4:1.); double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50); diff --git a/zscript/miscitems.zsc b/zscript/miscitems.zsc index 6e96b6e..32580d2 100644 --- a/zscript/miscitems.zsc +++ b/zscript/miscitems.zsc @@ -1444,7 +1444,28 @@ Class SentryItem : UnrealInventory if ( Owner ) Owner.RemoveInventory(self); else { - // TODO replace + let r = Spawn("Berserk",pos,ALLOW_REPLACE); + r.spawnangle = spawnangle; + r.spawnpoint = spawnpoint; + r.angle = angle; + r.pitch = pitch; + r.roll = roll; + r.special = special; + r.args[0] = args[0]; + r.args[1] = args[1]; + r.args[2] = args[2]; + r.args[3] = args[3]; + r.args[4] = args[4]; + r.ChangeTid(tid); + r.SpawnFlags = SpawnFlags&~MTF_SECRET; + r.HandleSpawnFlags(); + r.SpawnFlags = SpawnFlags; + r.bCountSecret = SpawnFlags&MTF_SECRET; + r.vel = vel; + r.master = master; + r.target = target; + r.tracer = tracer; + r.bDropped = bDropped; } Destroy(); } diff --git a/zscript/olsmp.zsc b/zscript/olsmp.zsc index 2467b7b..a867a72 100644 --- a/zscript/olsmp.zsc +++ b/zscript/olsmp.zsc @@ -38,13 +38,9 @@ Class OLSMPAmmo : Ammo r.target = target; r.tracer = tracer; r.bDropped = bDropped; - Destroy(); - } - else - { - Owner.RemoveInventory(self); - Destroy(); } + else Owner.RemoveInventory(self); + Destroy(); } Default { @@ -187,8 +183,16 @@ Class OLSMP : UnrealWeapon else if ( d.HitType != TRACE_HitNone ) { Vector3 hitnormal = -d.HitDir; - if ( d.HitType == TRACE_HitFloor ) hitnormal = d.HitSector.floorplane.Normal; - else if ( d.HitType == TRACE_HitCeiling ) hitnormal = d.HitSector.ceilingplane.Normal; + if ( d.HitType == TRACE_HitFloor ) + { + if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal; + else hitnormal = d.HitSector.floorplane.Normal; + } + else if ( d.HitType == TRACE_HitCeiling ) + { + if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal; + else hitnormal = d.HitSector.ceilingplane.Normal; + } else if ( d.HitType == TRACE_HitWall ) { hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit(); diff --git a/zscript/razorjack.zsc b/zscript/razorjack.zsc index a7fd4b2..51ea4eb 100644 --- a/zscript/razorjack.zsc +++ b/zscript/razorjack.zsc @@ -26,19 +26,222 @@ Class RazorAmmo : Ammo Class RazorBlade : Actor { + Vector3 gvel, accel; + double oldgangle, gangle, oldgpitch, gpitch; + + Default + { + Radius 2; + Height 2; + Speed 25; + DamageFunction (int((30+special1*5)*((DamageType=='Decapitated')?3.5:1.0))); + DamageType 'Shredded'; + Obituary "$O_RAZORJACK"; + BounceType "Hexen"; + ReactionTime 5; + BounceFactor 1.0; + WallBounceFactor 1.0; + PROJECTILE; + +USEBOUNCESTATE; + +SKYEXPLODE; + +CANBOUNCEWATER; + +NODAMAGETHRUST; + +DONTBOUNCEONSHOOTABLES; + +ROLLSPRITE; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + let t = Spawn("RazorBladeTrail",pos); + t.target = self; + frame = special1; + if ( special1 > 0 ) + { + vel *= 1.+.06+special1; + A_PlaySound("ripper/hum",CHAN_VOICE,1.0,true,3.0,pitch:3.125+special1*.2); + } + else A_PlaySound("ripper/hum",CHAN_VOICE,1.0,true,3.0,pitch:3.125); + Vector3 dir = vel.unit(); + A_SetAngle(atan2(dir.y,dir.x)); + A_SetPitch(asin(-dir.z)); + frame = 0; + gvel = vel; + oldgangle = gangle = angle; + oldgpitch = gpitch = pitch; + } + override int SpecialMissileHit( Actor victim ) + { + if ( pos.z > victim.pos.z+victim.height*0.81 ) DamageType = 'Decapitated'; + return -1; + } + override int DoSpecialDamage( Actor target, int damage, Name damagetype ) + { + if ( !target.bNOBLOOD ) + { + target.SpawnBlood(pos,AngleTo(target),damage); + A_PlaySound("ripper/flesh"); + A_AlertMonsters(); + } + UTMainHandler.DoKnockback(target,vel.unit(),15000); + return damage; + } + void A_RazorAltOrient() + { + if ( !bAMBUSH || !target || !target.player || (target.Health <= 0) ) return; + if ( sting_razoraim ) + { + FLineTraceData d; + target.LineTrace(target.angle,10000,target.pitch,0,target.player.viewheight,data:d); + Vector3 SeekingDir = level.Vec3Diff(pos,d.HitLocation).unit(); + double MagnitudeVel = Vel.length(); + SeekingDir = (SeekingDir*0.1*MagnitudeVel+Vel).unit(); + vel = MagnitudeVel * SeekingDir; + accel = SeekingDir * 25.; + vel += accel/TICRATE; + vel = vel.unit()*clamp(MagnitudeVel,10,15); + } + else + { + double dangle, dpitch; + dangle = deltaangle(oldgangle,target.angle); + dpitch = deltaangle(oldgpitch,target.pitch); + gangle += dangle; + gpitch += dpitch; + vel += (cos(gangle)*cos(gpitch),sin(gangle)*cos(gpitch),-sin(gpitch))*15./TICRATE; + double spd = vel.length(); + vel = vel*clamp(spd,10,15)/spd; + gvel = vel; + oldgangle = target.angle; + oldgpitch = target.pitch; + } + Vector3 dir = vel.unit(); + A_SetAngle(atan2(dir.y,dir.x)); + A_SetPitch(asin(-dir.z)); + } + action void A_RazorHit() + { + A_PlaySound("ripper/hit"); + A_AlertMonsters(); + A_SprayDecal("WallCrack",-20); + int numpt = Random[Ripper](5,10); + Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); + for ( int i=0; i 2))) ) - Use(false); + if ( (oldwaterlevel < 2) && (owner.waterlevel > 2) ) + { + if ( sting_autoscuba && !bActive ) Use(false); + oldwaterlevel = owner.waterlevel; + } + else if ( (oldwaterlevel > 2) && (owner.waterlevel < 2) ) + { + if ( sting_autoscuba && bActive ) Use(false); + oldwaterlevel = owner.waterlevel; + } if ( bActive && !tracer ) { tracer = Spawn("SCUBASound",Owner.pos);