diff --git a/Readme.md b/Readme.md index 8356b41..80dfb66 100644 --- a/Readme.md +++ b/Readme.md @@ -20,8 +20,11 @@ Doom Tournament (currently the devel branch is required). - "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) + - Hold fire to increase blade speed (from Unreal Bible) - Make Razorjack altfire actually seek where player is aiming (toggleable) + - GES Bio Rifle (slot 8) (replaces plasma rifle) + - "Hold up to 2 seconds" feature from Unreal Bible + - Biorifle splashes like UT (toggleable) - SMP 7243 (slot 0) (replaces bfg9000) - Backpack (replaces backpack, identical to Doom Tournament version) - Unreal 1 HUD @@ -55,7 +58,6 @@ Doom Tournament (currently the devel branch is required). ## In progress - - GES Bio Rifle (slot 8) (replaces plasma rifle) - Rifle (slot 9) (replaces plasma rifle) - Minigun (slot 0) (replaces chaingun) @@ -64,10 +66,6 @@ Doom Tournament (currently the devel branch is required). - Unreal Bible & prototype build behaviour restoration - Rifle restored rapid fire - Rifle restored flashlight - - Biorifle "Hold up to 2 seconds" feature from Unreal Bible - - - QOL improvements - - Biorifle splashes like UT (toggleable) - Stunner (slot 4) (replaces chainsaw) - Razorclaw (slot 1) (replaces chainsaw) diff --git a/modeldef.ubiorifle b/modeldef.ubiorifle index cf5f40a..63b41ce 100644 --- a/modeldef.ubiorifle +++ b/modeldef.ubiorifle @@ -58,6 +58,221 @@ Model "UBioAmmo2" FrameIndex BIOA K 0 10 FrameIndex BIOA L 0 11 } +Model "UBioGel" +{ + Path "models" + Model 0 "BioRGel_d.3d" + Skin 0 "Jflare.png" + Scale 0.12 0.1 0.1 + PitchOffset -90 + USEACTORPITCH + USEACTORROLL + + // Flying + FrameIndex GELF A 0 0 + FrameIndex GELF B 0 1 + FrameIndex GELF C 0 2 + FrameIndex GELF D 0 3 + FrameIndex GELF E 0 4 + FrameIndex GELF F 0 5 + FrameIndex GELF G 0 6 + FrameIndex GELF H 0 7 + FrameIndex GELF I 0 8 + FrameIndex GELF J 0 9 + FrameIndex GELF K 0 10 + FrameIndex GELF L 0 11 + FrameIndex GELF M 0 12 + // Hit + FrameIndex GELH A 0 14 + FrameIndex GELH B 0 15 + FrameIndex GELH C 0 16 + FrameIndex GELH D 0 17 + FrameIndex GELH E 0 18 + FrameIndex GELH F 0 19 + FrameIndex GELH G 0 20 + FrameIndex GELH H 0 21 + FrameIndex GELH I 0 22 + FrameIndex GELH J 0 23 + // Drip + FrameIndex GELD A 0 24 + FrameIndex GELD B 0 25 + FrameIndex GELD C 0 26 + FrameIndex GELD D 0 27 + FrameIndex GELD E 0 28 + FrameIndex GELD F 0 29 + FrameIndex GELD G 0 30 + FrameIndex GELD H 0 31 + FrameIndex GELD I 0 32 + FrameIndex GELD J 0 33 + FrameIndex GELD K 0 34 + FrameIndex GELD L 0 35 + FrameIndex GELD M 0 36 + // Slide + FrameIndex GELS A 0 37 + FrameIndex GELS B 0 38 + FrameIndex GELS C 0 39 + FrameIndex GELS D 0 40 + FrameIndex GELS E 0 41 + FrameIndex GELS F 0 42 + FrameIndex GELS G 0 43 + // Shrivel + FrameIndex GELX A 0 44 + FrameIndex GELX B 0 45 + FrameIndex GELX C 0 46 + FrameIndex GELX D 0 47 + FrameIndex GELX E 0 48 + FrameIndex GELX F 0 49 + FrameIndex GELX G 0 50 + FrameIndex GELX H 0 51 + FrameIndex GELX I 0 52 + FrameIndex GELX J 0 53 + FrameIndex GELX K 0 54 + FrameIndex GELX L 0 55 +} + +Model "UBioSplash" +{ + Path "models" + Model 0 "BioRGel_d.3d" + Skin 0 "Jflare.png" + Scale 0.12 0.1 0.1 + PitchOffset -90 + USEACTORPITCH + USEACTORROLL + + // Flying + FrameIndex GELF A 0 0 + FrameIndex GELF B 0 1 + FrameIndex GELF C 0 2 + FrameIndex GELF D 0 3 + FrameIndex GELF E 0 4 + FrameIndex GELF F 0 5 + FrameIndex GELF G 0 6 + FrameIndex GELF H 0 7 + FrameIndex GELF I 0 8 + FrameIndex GELF J 0 9 + FrameIndex GELF K 0 10 + FrameIndex GELF L 0 11 + FrameIndex GELF M 0 12 + // Hit + FrameIndex GELH A 0 14 + FrameIndex GELH B 0 15 + FrameIndex GELH C 0 16 + FrameIndex GELH D 0 17 + FrameIndex GELH E 0 18 + FrameIndex GELH F 0 19 + FrameIndex GELH G 0 20 + FrameIndex GELH H 0 21 + FrameIndex GELH I 0 22 + FrameIndex GELH J 0 23 + // Drip + FrameIndex GELD A 0 24 + FrameIndex GELD B 0 25 + FrameIndex GELD C 0 26 + FrameIndex GELD D 0 27 + FrameIndex GELD E 0 28 + FrameIndex GELD F 0 29 + FrameIndex GELD G 0 30 + FrameIndex GELD H 0 31 + FrameIndex GELD I 0 32 + FrameIndex GELD J 0 33 + FrameIndex GELD K 0 34 + FrameIndex GELD L 0 35 + FrameIndex GELD M 0 36 + // Slide + FrameIndex GELS A 0 37 + FrameIndex GELS B 0 38 + FrameIndex GELS C 0 39 + FrameIndex GELS D 0 40 + FrameIndex GELS E 0 41 + FrameIndex GELS F 0 42 + FrameIndex GELS G 0 43 + // Shrivel + FrameIndex GELX A 0 44 + FrameIndex GELX B 0 45 + FrameIndex GELX C 0 46 + FrameIndex GELX D 0 47 + FrameIndex GELX E 0 48 + FrameIndex GELX F 0 49 + FrameIndex GELX G 0 50 + FrameIndex GELX H 0 51 + FrameIndex GELX I 0 52 + FrameIndex GELX J 0 53 + FrameIndex GELX K 0 54 + FrameIndex GELX L 0 55 +} + +Model "UBioGlob" +{ + Path "models" + Model 0 "BioRGel_d.3d" + Skin 0 "Jflare.png" + Scale 0.12 0.1 0.1 + PitchOffset -90 + USEACTORPITCH + USEACTORROLL + + // Flying + FrameIndex GELF A 0 0 + FrameIndex GELF B 0 1 + FrameIndex GELF C 0 2 + FrameIndex GELF D 0 3 + FrameIndex GELF E 0 4 + FrameIndex GELF F 0 5 + FrameIndex GELF G 0 6 + FrameIndex GELF H 0 7 + FrameIndex GELF I 0 8 + FrameIndex GELF J 0 9 + FrameIndex GELF K 0 10 + FrameIndex GELF L 0 11 + FrameIndex GELF M 0 12 + // Hit + FrameIndex GELH A 0 14 + FrameIndex GELH B 0 15 + FrameIndex GELH C 0 16 + FrameIndex GELH D 0 17 + FrameIndex GELH E 0 18 + FrameIndex GELH F 0 19 + FrameIndex GELH G 0 20 + FrameIndex GELH H 0 21 + FrameIndex GELH I 0 22 + FrameIndex GELH J 0 23 + // Drip + FrameIndex GELD A 0 24 + FrameIndex GELD B 0 25 + FrameIndex GELD C 0 26 + FrameIndex GELD D 0 27 + FrameIndex GELD E 0 28 + FrameIndex GELD F 0 29 + FrameIndex GELD G 0 30 + FrameIndex GELD H 0 31 + FrameIndex GELD I 0 32 + FrameIndex GELD J 0 33 + FrameIndex GELD K 0 34 + FrameIndex GELD L 0 35 + FrameIndex GELD M 0 36 + // Slide + FrameIndex GELS A 0 37 + FrameIndex GELS B 0 38 + FrameIndex GELS C 0 39 + FrameIndex GELS D 0 40 + FrameIndex GELS E 0 41 + FrameIndex GELS F 0 42 + FrameIndex GELS G 0 43 + // Shrivel + FrameIndex GELX A 0 44 + FrameIndex GELX B 0 45 + FrameIndex GELX C 0 46 + FrameIndex GELX D 0 47 + FrameIndex GELX E 0 48 + FrameIndex GELX F 0 49 + FrameIndex GELX G 0 50 + FrameIndex GELX H 0 51 + FrameIndex GELX I 0 52 + FrameIndex GELX J 0 53 + FrameIndex GELX K 0 54 + FrameIndex GELX L 0 55 +} Model "UBioRifle" { @@ -74,3 +289,116 @@ Model "UBioRifle" ROTATING FrameIndex BIOP A 1 0 } + +Model "UBioRifle" +{ + Path "models" + Model 0 "BRifle_d.3d" + Skin 0 "JBrifle1.png" + Scale 0.2 -0.2 0.2 + AngleOffset -90 + Offset 7 -20 -11.5 + + // Select + FrameIndex BIOS A 0 0 + FrameIndex BIOS B 0 1 + FrameIndex BIOS C 0 2 + FrameIndex BIOS D 0 3 + FrameIndex BIOS E 0 4 + FrameIndex BIOS F 0 5 + FrameIndex BIOS G 0 6 + FrameIndex BIOS H 0 7 + FrameIndex BIOS I 0 8 + FrameIndex BIOS J 0 9 + FrameIndex BIOS K 0 10 + FrameIndex BIOS L 0 11 + FrameIndex BIOS M 0 12 + FrameIndex BIOS N 0 13 + FrameIndex BIOS O 0 14 + FrameIndex BIOS P 0 15 + FrameIndex BIOS Q 0 16 + FrameIndex BIOS R 0 17 + FrameIndex BIOS S 0 18 + FrameIndex BIOS T 0 19 + // Idle + FrameIndex BIOI A 0 20 + // Walk + FrameIndex BIOW A 0 21 + FrameIndex BIOW B 0 22 + FrameIndex BIOW C 0 23 + FrameIndex BIOW D 0 24 + FrameIndex BIOW E 0 25 + FrameIndex BIOW F 0 26 + FrameIndex BIOW G 0 27 + FrameIndex BIOW H 0 28 + FrameIndex BIOW I 0 29 + FrameIndex BIOW J 0 30 + FrameIndex BIOW K 0 31 + FrameIndex BIOW L 0 32 + FrameIndex BIOW M 0 33 + FrameIndex BIOW N 0 34 + FrameIndex BIOW O 0 35 + FrameIndex BIOW P 0 36 + FrameIndex BIOW Q 0 37 + FrameIndex BIOW R 0 38 + FrameIndex BIOW S 0 39 + FrameIndex BIOW T 0 40 + // Altfire + FrameIndex BIOA A 0 41 + FrameIndex BIOA B 0 42 + FrameIndex BIOA C 0 43 + FrameIndex BIOA D 0 44 + FrameIndex BIOA E 0 45 + FrameIndex BIOA F 0 46 + FrameIndex BIOA G 0 47 + FrameIndex BIOA H 0 48 + FrameIndex BIOA I 0 49 + FrameIndex BIOA J 0 50 + FrameIndex BIOA K 0 51 + FrameIndex BIOA L 0 52 + FrameIndex BIOA M 0 53 + FrameIndex BIOA N 0 54 + FrameIndex BIOA O 0 55 + FrameIndex BIOA P 0 56 + FrameIndex BIOA Q 0 57 + FrameIndex BIOA R 0 58 + FrameIndex BIOA S 0 59 + FrameIndex BIOA T 0 60 + FrameIndex BIOA U 0 61 + FrameIndex BIOA V 0 62 + FrameIndex BIOA W 0 63 + FrameIndex BIOA X 0 64 + FrameIndex BIOA Y 0 65 + FrameIndex BIOA Z 0 66 + FrameIndex BIA2 A 0 67 + FrameIndex BIA2 B 0 68 + FrameIndex BIA2 C 0 69 + FrameIndex BIA2 D 0 70 + // Fire + FrameIndex BIOF A 0 71 + FrameIndex BIOF B 0 72 + FrameIndex BIOF C 0 73 + FrameIndex BIOF D 0 74 + FrameIndex BIOF E 0 75 + FrameIndex BIOF F 0 76 + FrameIndex BIOF G 0 77 + FrameIndex BIOF H 0 78 + FrameIndex BIOF I 0 79 + FrameIndex BIOF J 0 80 + // Drip + FrameIndex BIOT A 0 81 + FrameIndex BIOT B 0 82 + FrameIndex BIOT C 0 83 + FrameIndex BIOT D 0 84 + FrameIndex BIOT E 0 85 + FrameIndex BIOT F 0 86 + FrameIndex BIOT G 0 87 + // Down + FrameIndex BIOD A 0 88 + FrameIndex BIOD B 0 90 + FrameIndex BIOD C 0 92 + FrameIndex BIOD D 0 94 + FrameIndex BIOD E 0 96 + FrameIndex BIOD F 0 98 + FrameIndex BIOD G 0 100 +} diff --git a/models/JBRifle1.png b/models/JBRifle1.png index cbb4ad9..6099bad 100644 Binary files a/models/JBRifle1.png and b/models/JBRifle1.png differ diff --git a/models/JBRifle1_.png b/models/JBRifle1_.png index cbb4ad9..6099bad 100644 Binary files a/models/JBRifle1_.png and b/models/JBRifle1_.png differ diff --git a/sndinfo.txt b/sndinfo.txt index 75a6666..1023093 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -178,6 +178,9 @@ eightball/fly brocket asmd/vapour vapour +ges/drip GelDrip +ges/load GelLoad + dampener/on dampsnd dampener/off dampndea diff --git a/zscript/ubiorifle.zsc b/zscript/ubiorifle.zsc index bd95d45..f40f5b0 100644 --- a/zscript/ubiorifle.zsc +++ b/zscript/ubiorifle.zsc @@ -42,18 +42,622 @@ Class UBioAmmo2 : UBioAmmo Class UBioGel : Actor { + Actor l, b; + enum EHitType + { + HIT_NONE, + HIT_WALL, + HIT_CEILING, + HIT_FLOOR + }; + int hittype; + int deadtimer, dttimer; + Line atline; + int atside; + int atpart; + int atplane; + Sector atsector; + double atz; + double rollvel, pitchvel, yawvel; + Vector3 normal; + Actor atbridge; + bool onbridge; + Vector3 atbridgeofs; + + override void PostBeginPlay() + { + Super.PostBeginPlay(); + vel.z += 3; + deadtimer = 105; + A_AttachLight('BioLight',DynamicLight.PointLight,"40FF80",int(8*scale.x),int(8*scale.x)); + rollvel = FRandom[GES](10,30)*RandomPick[GES](-1,1); + pitchvel = FRandom[GES](10,30)*RandomPick[GES](-1,1); + yawvel = FRandom[GES](10,30)*RandomPick[GES](-1,1); + } + override int SpecialMissileHit( Actor victim ) + { + if ( victim == b ) return 1; + if ( (victim is 'BioHitbox') && ((victim.target == master) || (victim.target.master == master)) ) return 1; + return -1; + } + override void Tick() + { + Super.Tick(); + if ( isFrozen() ) return; + if ( !bNOGRAVITY ) + { + roll += rollvel; + pitch += pitchvel; + pitch += yawvel; + if ( waterlevel > 0 ) + { + vel.xy *= 0.98; + rollvel *= 0.98; + pitchvel *= 0.98; + yawvel *= 0.98; + } + } + if ( deadtimer > -2 ) + { + if ( onbridge ) // attempt to follow the movement of the bridge (if it's moving) + { + if ( atbridge ) + { + if ( !Warp(atbridge,atbridgeofs.x,atbridgeofs.y,atbridgeofs.z,0,WARPF_ABSOLUTEOFFSET|WARPF_USECALLERANGLE|WARPF_COPYINTERPOLATION) ) + deadtimer = min(deadtimer,0); + } + else deadtimer = min(deadtimer,0); + } + if ( atline ) // attempt to follow the movement of the line + { + if ( atpart == 1 ) + { + if ( atline.flags&Line.ML_DONTPEGTOP ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(1)),true); + else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside?0:1].sector.GetPlaneTexZ(1)),true); + } + else if ( atpart == -1 ) + { + if ( atline.flags&Line.ML_DONTPEGBOTTOM ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(0)),true); + else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside?0:1].sector.GetPlaneTexZ(0)),true); + } + else if ( atline.flags&Line.ML_DONTPEGBOTTOM ) SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(0)),true); + else SetOrigin(Vec2OffsetZ(0,0,atz+atline.sidedef[atside].sector.GetPlaneTexZ(1)),true); + if ( (pos.z > ceilingz) || (pos.z < floorz) ) deadtimer = min(deadtimer,0); + } + else if ( atsector ) // attempt to follow the movement of the plane + { + SetOrigin(Vec2OffsetZ(0,0,atz+atsector.GetPlaneTexZ(atplane)),true); + if ( ceilingz-floorz <= 2 ) deadtimer = min(deadtimer,0); + } + } + if ( !InStateSequence(CurState,FindState("XDeath")) ) + { + int numpt; + if ( (!bNOGRAVITY && !Random[GES](0,2)) || !Random[GES](0,10) ) + { + numpt = Min(20,int(Scale.x*2))+Random[GES](-1,1); + for ( int i=0; i= pos.z-4*Scale.x)) ) deadtimer = 0; + } + if ( deadtimer-- <= 0 ) + { + deadtimer = -1; + SetStateLabel("XDeath"); + } + } + // align self to what surface was hit + // TODO handle plane collision within the very border between two + // sectors (most noticeable with moving 3d floors) + virtual void AlignSelf() + { + F3DFloor ff; + bINTERPOLATEANGLES = false; + bHITOWNER = true; + A_NoGravity(); + A_Stop(); + if ( bAMBUSH ) + { + SetStateLabel("XDeath"); + return; + } + A_SetSize(0.1,0); + if ( tracer && tracer.bACTLIKEBRIDGE ) + { + atbridge = tracer; + onbridge = true; + if ( (pos.x+radius) <= (atbridge.pos.x-atbridge.radius) ) + { + // west side + normal = (-1,0,0); + SetOrigin((atbridge.pos.x-atbridge.radius,pos.y,pos.z),false); + atbridgeofs = pos-atbridge.pos; + angle = 180; + pitch = 0; + roll = 180; // otherwise it slides upwards (UT changes roll like this too) + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_WALL; + } + else if ( (pos.x-radius) >= (atbridge.pos.x+atbridge.radius) ) + { + // east side + normal = (1,0,0); + SetOrigin((atbridge.pos.x+atbridge.radius,pos.y,pos.z),false); + atbridgeofs = pos-atbridge.pos; + angle = 0; + pitch = 0; + roll = 180; // otherwise it slides upwards (UT changes roll like this too) + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_WALL; + } + else if ( (pos.y+radius) <= (atbridge.pos.y-atbridge.radius) ) + { + // north side + normal = (0,-1,0); + SetOrigin((pos.x,atbridge.pos.y-atbridge.radius,pos.z),false); + atbridgeofs = pos-atbridge.pos; + angle = 270; + pitch = 0; + roll = 180; // otherwise it slides upwards (UT changes roll like this too) + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_WALL; + } + else if ( (pos.y-radius) >= (atbridge.pos.y+atbridge.radius) ) + { + // south side + normal = (0,1,0); + SetOrigin((pos.x,atbridge.pos.y+atbridge.radius,pos.z),false); + atbridgeofs = pos-atbridge.pos; + angle = 90; + pitch = 0; + roll = 180; // otherwise it slides upwards (UT changes roll like this too) + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_WALL; + } + else if ( pos.z >= (atbridge.pos.z+atbridge.height) ) + { + // top of actor + normal = (0,0,1); + SetOrigin((pos.x,pos.y,atbridge.pos.z+atbridge.height),false); + atbridgeofs = pos-atbridge.pos; + pitch = -90; + angle = 0; + roll = FRandom[GES](0,360); + hittype = HIT_FLOOR; + } + else if ( (pos.z+height) <= atbridge.pos.z ) + { + // bottom of actor + normal = (0,0,-1); + SetOrigin((pos.x,pos.y,atbridge.pos.z),false); + pitch = 90; + angle = 0; + roll = FRandom[GES](0,360); + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_CEILING; + } + else + { + // inside of actor, just shove to the top or bottom based on our Z velocity + if ( vel.z <= 0 ) + { + normal = (0,0,1); + SetOrigin((pos.x,pos.y,atbridge.pos.z+atbridge.height),false); + atbridgeofs = pos-atbridge.pos; + pitch = -90; + angle = 0; + roll = FRandom[GES](0,360); + hittype = HIT_FLOOR; + } + else + { + normal = (0,0,-1); + SetOrigin((pos.x,pos.y,atbridge.pos.z),false); + pitch = 90; + angle = 0; + roll = FRandom[GES](0,360); + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_CEILING; + } + } + } + else if ( BlockingFloor ) + { + // find closest 3d floor for its normal + for ( int i=0; i 0 ) hittype = HIT_FLOOR; + else if ( normal dot (0,0,-1) > 0.7 ) + hittype = HIT_CEILING; + else hittype = HIT_FLOOR; + } + else if ( BlockingLine ) + { + atline = BlockingLine; + normal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit(); + atside = 1; + if ( !BlockingLine.sidedef[1] || (CurSector == BlockingLine.frontsector) ) + { + atside = 0; + normal *= -1; + } + Vector3 orig = (BlockingLine.v1.p.x,BlockingLine.v1.p.y,0); + Vector3 onwall = pos-(normal dot (pos-orig))*normal; + SetOrigin(onwall+normal*0.5,false); + // attempt to guess line part (upper/mid/lower) + if ( !atline.sidedef[1] ) atpart = 0; // mid + else if ( atline.sidedef[atside?0:1].sector.ceilingplane.ZAtPoint(pos.xy) < pos.z ) atpart = 1; // upper + else if ( atline.sidedef[atside?0:1].sector.floorplane.ZAtPoint(pos.xy) > (pos.z+height) ) atpart = -1; // lower + else + { + atpart = 0; + // check if we're touching a 3d floor line + Sector backsector = atline.sidedef[atside?0:1].sector; + for ( int i=0; i (pos.z+height) ) continue; + if ( backsector.Get3DFloor(i).top.ZAtPoint(pos.xy) < pos.z ) continue; + ff = backsector.Get3DFloor(i); + break; + } + // attach to it + if ( ff ) + { + atline = ff.master; + atside = 0; + } + } + if ( atpart == 1 ) + { + if ( atline.flags&Line.ML_DONTPEGTOP ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(1); + else atz = pos.z-atline.sidedef[atside?0:1].sector.GetPlaneTexZ(1); + } + else if ( atpart == -1 ) + { + if ( atline.flags&Line.ML_DONTPEGBOTTOM ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(0); + else atz = pos.z-atline.sidedef[atside?0:1].sector.GetPlaneTexZ(0); + } + else if ( atline.flags&Line.ML_DONTPEGBOTTOM ) atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(0); + else atz = pos.z-atline.sidedef[atside].sector.GetPlaneTexZ(1); + angle = atan2(normal.y,normal.x); + pitch = 0; + roll = 180; // otherwise it slides upwards (UT changes roll like this too) + if ( waterlevel > 0 ) hittype = HIT_FLOOR; + else hittype = HIT_WALL; + } + else + { + SetStateLabel("XDeath"); + return; + } + b = Spawn("BioHitbox",pos); + b.target = self; + A_PlaySound("ges/hit"); + A_SprayDecal("BioSplat",-172); + int numpt = Min(100,int(Scale.x*10))+Random[GES](-5,5); + for ( int i=0; i 1) ) numsplash = int(4*Scale.x)-1; + } + override void Tick() + { + Super.Tick(); + if ( isFrozen() || !sting_biosplash ) return; + Vector3 ofs = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch)); + for ( int i=0; i<2; i++ ) + { + if ( numsplash-- <= 0 ) return; + Vector3 dir = (ofs+(FRandom[GES](-.8,.8),FRandom[GES](-.8,.8),FRandom[GES](-.8,.8))).unit(); + A_SetScale(scale.x-0.15); + A_AttachLight('BioLight',DynamicLight.PointLight,"40FF80",int(8*scale.x),int(8*scale.x)); + let d = Spawn("UBioSplash",pos+ofs*4); + d.target = target; + d.master = self; + d.scale *= FRandom[GES](0.5,0.7); + d.angle = atan2(dir.y,dir.x); + d.pitch = -asin(dir.z); + d.vel = (cos(d.angle)*cos(d.pitch),sin(d.angle)*cos(d.pitch),-sin(d.pitch))*d.speed*FRandom[GES](0.4,0.6); + d.vel.z -= 2; + } + } } Class UBioSplash : UBioGel { + override void AlignSelf() + { + Super.AlignSelf(); + if ( hittype == HIT_CEILING ) hittype = HIT_FLOOR; + } } Class UBioRifle : UnrealWeapon { + double chargesize, count; + bool bCharging; + + action void A_BioFire( bool bAlt = false ) + { + Weapon weap = Weapon(invoker); + if ( !weap ) return; + if ( !bAlt ) + { + if ( weap.Ammo1.Amount <= 0 ) return; + if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; + } + invoker.chargesize = min(invoker.chargesize,4.9); + if ( bAlt ) A_PlaySound("ges/fire",CHAN_WEAPON,Dampener.Active(self)?.17:1.,pitch:max(.5,1.35-invoker.chargesize/8.)); + else A_PlaySound("ges/fire",CHAN_WEAPON,Dampener.Active(self)?.17:1.); + invoker.FireEffect(); + UTMainHandler.DoFlash(self,Color(48,0,255,0),1); + A_AlertMonsters(); + if ( bAlt ) A_QuakeEx(1+int(0.5*invoker.chargesize),1+int(0.5*invoker.chargesize),1+int(0.5*invoker.chargesize),5+int(1.2*invoker.chargesize),0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05+0.01*invoker.chargesize); + else A_QuakeEx(1,1,1,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05); + Vector3 x, y, z; + double a, s; + [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); + Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+4*y-5*z); + Actor p; + if ( bAlt ) + { + p = Spawn("UBioGlob",origin); + p.A_SetScale(0.5+invoker.chargesize/3.5); + UTMainHandler.DoSwing(self,(FRandom[GES](-0.6,-1.3),FRandom[GES](-0.9,-0.2)),1+invoker.chargesize*0.3,-0.1,3,SWING_Spring,3,2); + } + else + { + p = Spawn("UBioGel",origin); + UTMainHandler.DoSwing(self,(FRandom[GES](-0.6,-1.3),FRandom[GES](-0.9,-0.2)),2,-0.5,2,SWING_Spring,2,2); + } + p.angle = angle; + p.pitch = BulletSlope(); + p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed; + p.target = self; + for ( int i=0; i<12; i++ ) + { + let s = Spawn("UTViewSmoke",origin); + UTViewSmoke(s).ofs = (10,4,-5); + s.scale *= 2.0; + s.target = self; + if ( Random[GES](0,1) ) s.SetShade("40FF60"); + else s.SetShade("60FF40"); + s.A_SetRenderStyle(0.5,STYLE_AddShaded); + UTViewSmoke(s).vvel += (FRandom[GES](0.8,1.6),FRandom[GES](-0.5,0.5),FRandom[GES](-0.5,0.5)); + } + } + action void A_ChargeUp() + { + let weap = Weapon(invoker); + if ( (invoker.chargesize < 4.9) && (weap.Ammo1.Amount > 0) ) + { + invoker.chargesize += 1./TICRATE; + invoker.count += 1./TICRATE; + if ( invoker.count > 1. ) + { + weap.DepleteAmmo(weap.bAltFire,true,1); + invoker.count = 0; + } + } + if ( !(player.cmd.buttons&BT_ALTATTACK) ) + player.SetPSPrite(PSP_WEAPON,invoker.FindState("AltRelease")); + } + action void A_BeginCharge() + { + let weap = Weapon(invoker); + invoker.bCharging = true; + weap.DepleteAmmo(weap.bAltFire,true,1); + invoker.count = invoker.chargesize = 0; + A_PlaySound("ges/load",CHAN_WEAPON,Dampener.Active(self)?.13:1.,true); + A_Overlay(-9999,"Dummy2"); + } + override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount ) + { + if ( bCharging ) return true; + return Super.CheckAmmo(fireMode,autoSwitch,requireAmmo,ammocount); + } Default { Tag "$T_BIORIFLE"; @@ -75,5 +679,74 @@ Class UBioRifle : UnrealWeapon Stop; BIOP B -1; Stop; + Select: + BIOS A 1 A_Raise(int.max); + Wait; + Ready: + BIOS ABCDEFGHIJKLMNOPQRST 1 A_WeaponReady(WRF_NOFIRE); + Goto Idle; + Dummy: + TNT1 A 1 + { + A_CheckReload(); + A_WeaponReady(); + // that's a long-ass if + if ( player.FindPSprite(PSP_WEAPON).CurState.InStateSequence(invoker.FindState("Idle")) && (player.cmd.forwardmove || player.cmd.sidemove) && (player.vel.length() > 0.5) ) + player.SetPSPrite(PSP_WEAPON,invoker.FindState("Sway")); + } + Wait; + Idle: + #### # 4 A_Overlay(-9999,"Dummy"); // little hackeroo to make this more responsive + BIOI A 1 A_Jump(80,"Drip"); + BIOI A -1; + Stop; + Sway: + #### # 3; + BIOW ABCDEFGHIJKLMNOPQRS 3 A_JumpIf((!player.cmd.forwardmove && !player.cmd.sidemove) || (player.vel.length() < 0.5),"Idle"); + Goto Sway+1; + Drip: + #### # 4; + BIOT ABC 6; + BIOT D 6 A_PlaySound("ges/drip",CHAN_ITEM,Dampener.Active(self)?.05:.5); + BIOT EFG 6; + BIOI A 4; + Goto Idle; + Fire: + BIOF A 0 + { + A_Overlay(-9999,"Null"); + A_BioFire(); + } + BIOF ABCDEFGHIJ 1; + Goto Idle; + Dummy2: + TNT1 A 1 A_ChargeUp(); + Wait; + AltFire: + #### # 2 A_BeginCharge(); + BIOA ABCDEFGHIJKLMNOPQRSTUVWXYZ 6; + BIA2 ABC 6; + BIA2 D 0 A_JumpIf(sting_bhold,1); + Goto AltRelease; + BIA2 D 3; + BIA2 CBA 6; + BIOA ZYXWVUT 6; + BIOA S 0; + Goto AltRelease; + AltRelease: + #### # 1 + { + A_Overlay(-9999,"Null"); + if ( self is 'UTPlayer' ) + UTPlayer(self).PlayAttacking3(); + A_BioFire(true); + } + BIOF ABCDEFGHIJ 2; + Goto Idle; + Deselect: + BIOD A 0 A_Overlay(-9999,"Null"); + BIOD ABCDEF 1; + BIOD G 1 A_Lower(int.max); + Wait; } } diff --git a/zscript/unrealcommon.zsc b/zscript/unrealcommon.zsc index d8e85e6..7b442eb 100644 --- a/zscript/unrealcommon.zsc +++ b/zscript/unrealcommon.zsc @@ -233,7 +233,8 @@ Class UPlayer : UTPlayer let psp = player.FindPSprite(PSP_WEAPON); if ( ((player.ReadyWeapon is 'UBioRifle') && (player.buttons&BT_ALTATTACK)) || (player.ReadyWeapon is 'Eightball') - || ((player.ReadyWeapon is 'DispersionPistol') && DispersionPistol(player.ReadyWeapon).bCharging) ) + || ((player.ReadyWeapon is 'DispersionPistol') && DispersionPistol(player.ReadyWeapon).bCharging) + || ((player.ReadyWeapon is 'UBioRifle') && UBioRifle(player.ReadyWeapon).bCharging) ) { if ( !InStateSequence(CurState,FindState("MissileRepStill")) ) SetStateLabel("MissileRepStill");