Rocket Launcher has been added, and with that (and a couple more tweaks) this mod is ready for the public beta stage (as soon as coelckers/gzdoom#495 is merged).

This commit is contained in:
Marisa the Magician 2018-05-30 14:21:15 +02:00
commit 0a7587a19f
11 changed files with 316 additions and 39 deletions

View file

@ -27,10 +27,11 @@ Model "UTGrenade"
Path "models" Path "models"
Model 0 "UTRocket_d.3d" Model 0 "UTRocket_d.3d"
Skin 0 "JuRocket1.png" Skin 0 "JuRocket1.png"
Scale 0.07 0.0822 0.09864 Offset 0 0 1.4796
Scale 0.0822 0.0822 0.09864
USEACTORPITCH USEACTORPITCH
USEACTORROLL USEACTORROLL
AngleOffset -90 AngleOffset 90
FrameIndex RCKT A 0 0 FrameIndex RCKT A 0 0
} }
@ -39,10 +40,11 @@ Model "UTRocket"
Path "models" Path "models"
Model 0 "UTRocket_d.3d" Model 0 "UTRocket_d.3d"
Skin 0 "JuRocket1.png" Skin 0 "JuRocket1.png"
Scale 0.07 0.0822 0.09864 Offset 10.175 0 1.4796
Scale 0.0822 0.0822 0.09864
USEACTORPITCH USEACTORPITCH
USEACTORROLL USEACTORROLL
AngleOffset -90 AngleOffset 90
FrameIndex RCKT B 0 1 FrameIndex RCKT B 0 1
} }

View file

@ -38,14 +38,10 @@ Currently implemented:
- Jump Boots (radsuit, has "iron boots" powerup effect to compensate) - Jump Boots (radsuit, has "iron boots" powerup effect to compensate)
- Minigun (slot 7) - Minigun (slot 7)
- Sniper Rifle (slot 0) - Sniper Rifle (slot 0)
- Rocket Launcher (slot 9)
In progress: In progress:
- Rocket Launcher (slot 9)
Things to do eventually:
- Trim out unused animations.
- Add some more effects, maybe some nicer recoil on guns too. - Add some more effects, maybe some nicer recoil on guns too.
- Unreal 1 weapons? - General polishing and bugfixing.
- Think of what item(s) the jump boots can replace. - Trim out unused animations.

View file

@ -219,6 +219,7 @@ utrl/seeklock seeklock
utrl/seeklost seeklost utrl/seeklost seeklost
utrl/fly rcktfly1 utrl/fly rcktfly1
utrl/explode expl2 utrl/explode expl2
utrl/bounce hit1
sniper/select riflepck sniper/select riflepck
sniper/fire sniperf sniper/fire sniperf

Binary file not shown.

View file

@ -179,4 +179,6 @@ Sprite "EBLDG0",1,1{}
Sprite "EBLDH0",1,1{} Sprite "EBLDH0",1,1{}
Sprite "EBLDI0",1,1{} Sprite "EBLDI0",1,1{}
Sprite "EBLDJ0",1,1{} Sprite "EBLDJ0",1,1{}
Sprite "EBLDK0",1,1{} Sprite "EBLDK0",1,1{}
Graphic "XHAIRS99",16,16{}
Graphic "XHAIRB99",16,16{}

View file

@ -257,4 +257,4 @@ Sprite "BIMPA0",1,1{}
Sprite "BIMPB0",1,1{} Sprite "BIMPB0",1,1{}
Sprite "BIMPC0",1,1{} Sprite "BIMPC0",1,1{}
Sprite "BIMPD0",1,1{} Sprite "BIMPD0",1,1{}
Sprite "BIMPE0",1,1{} Sprite "BIMPE0",1,1{}

View file

@ -36,45 +36,236 @@ Class UTRocketAmmo2 : UTRocketAmmo
} }
} }
Class RocketLight : DynamicLight
{
Default
{
DynamicLight.Type "Point";
Args 255,224,128,32;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
}
}
Class UTRocketTrail : Actor
{
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
+FORCEXYBILLBOARD;
Scale 0.2;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
let l = Spawn("RocketLight",pos);
l.target = self;
}
override void Tick()
{
Super.Tick();
if ( !target || target.InStateSequence(target.CurState,target.FindState("Death")) )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
}
States
{
Spawn:
RFLA A -1 Bright;
Stop;
}
}
Class RocketExplLight : SlugLight
{
Default
{
Args 255,224,128,120;
}
}
Class UTRocket : Actor Class UTRocket : Actor
{ {
Default Default
{ {
Obituary "%o was smacked down by %k's Rocket Launcher."; Obituary "%o was smacked down by %k's Rocket Launcher.";
DamageFunction Random[Eightball](70,80);
DamageType 'RocketDeath';
Radius 2;
Height 0;
Speed 30;
PROJECTILE;
+SKYEXPLODE;
+SEEKERMISSILE;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
let l = Spawn("UTRocketTrail",pos);
l.target = self;
A_PlaySound("utrl/fly",CHAN_VOICE,1.0,true,2.5);
}
action void A_RocketExplode()
{
bFORCEXYBILLBOARD = true;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("RocketBlast",150);
A_NoGravity();
A_SetScale(0.75);
A_Explode(Random[Eightball](60,70),200);
A_QuakeEx(3,3,3,8,0,300,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
A_PlaySound("utrl/explode",CHAN_VOICE);
A_AlertMonsters();
Spawn("RocketExplLight",pos);
int numpt = Random[Eightball](15,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Eightball](-1,1),FRandom[Eightball](-1,1),FRandom[Eightball](-1,1)).unit()*FRandom[Eightball](1,4);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
}
numpt = Random[Eightball](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Eightball](-1,1),FRandom[Eightball](-1,1),FRandom[Eightball](-1,1)).unit()*FRandom[Eightball](2,8);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
numpt = Random[Eightball](25,50);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Eightball](-1,1),FRandom[Eightball](-1,1),FRandom[Eightball](-1,1)).unit()*FRandom[Eightball](4,12);
let s = Spawn("UTChip",pos);
s.vel = pvel;
}
} }
States States
{ {
Spawn: Spawn:
RCKT B 1; RCKT B 1
{
A_SetRoll(roll+30,SPF_INTERPOLATE);
Vector3 dir = vel.unit();
A_SetAngle(atan2(dir.y,dir.x),SPF_INTERPOLATE);
A_SetPitch(asin(-dir.z),SPF_INTERPOLATE);
if ( tracer ) A_SeekerMissile(0,2,SMF_PRECISE);
Spawn("UTSmoke",pos);
}
Wait; Wait;
Death:
TNT1 A 0 A_RocketExplode();
SEXP ABCDEFGHIJ 2 Bright;
Stop;
} }
} }
Class UTGrenade : Actor Class UTGrenade : UTRocket
{ {
double rollvel, pitchvel, anglevel;
Default Default
{ {
Obituary "%o was smacked down by %k's Rocket Launcher."; DamageFunction Random[Eightball](80,90);
DamageType 'GrenadeDeath';
-NOGRAVITY;
+USEBOUNCESTATE;
BounceType "Doom";
BounceFactor 0.75;
ReactionTime 85;
Speed 20;
}
override void PostBeginPlay()
{
Actor.PostBeginPlay();
rollvel = FRandom[Eightball](-8,8);
pitchvel = FRandom[Eightball](-8,8);
anglevel = FRandom[Eightball](-8,8);
ReactionTime += Random[Eightball](0,20);
} }
States States
{ {
Spawn: Spawn:
RCKT A 1; RCKT A 1
{
A_SetAngle(angle+anglevel,SPF_INTERPOLATE);
A_SetPitch(pitch+pitchvel,SPF_INTERPOLATE);
A_SetRoll(roll+rollvel,SPF_INTERPOLATE);
A_Countdown();
}
Wait; Wait;
Bounce:
RCKT A 0
{
A_PlaySound("utrl/bounce");
rollvel = FRandom[Eightball](-16,16);
pitchvel = FRandom[Eightball](-16,16);
anglevel = FRandom[Eightball](-16,16);
}
Goto Spawn;
} }
} }
Class UTRocketLauncher : UTWeapon Class UTRocketLauncher : UTWeapon
{ {
bool LockedOn;
Actor LockedTarget; Actor LockedTarget;
TextureID lockontex;
int locktics;
override void PostBeginPlay()
{
Super.PostBeginPlay();
lockontex = TexMan.CheckForTexture("Crosshr6",TexMan.Type_Any);
}
override void PostRender()
{
if ( LockedTarget ) Screen.DrawTexture(lockontex,false,(Screen.GetWidth()-16)*0.5,(Screen.GetHeight()-16)*0.5);
}
override void Tick()
{
Super.Tick();
if ( !Owner ) return;
if ( LockedOn && (!LockedTarget || (LockedTarget.Health <= 0) || LockedTarget.bKilled || LockedTarget.bCorpse || !LockedTarget.bShootable) )
{
LockedTarget = null;
LockedOn = false;
Owner.A_PlaySound("utrl/seeklost",CHAN_6);
}
if ( LockedTarget ) A_SetCrosshair(99);
else A_SetCrosshair(0);
}
// consumes 1 ammo // consumes 1 ammo
action void A_LoadRocket() action void A_LoadRocket( bool checktarget = true )
{ {
Weapon weap = Weapon(invoker); Weapon weap = Weapon(invoker);
if ( !weap ) return; if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return; if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return; if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
if ( weap.bAltFire )
{
invoker.LockedTarget = null;
invoker.LockedOn = false;
}
if ( checktarget && !weap.bAltFire ) A_CheckTarget();
} }
// refire that is ignored if there's no ammo // refire that is ignored if there's no ammo
@ -97,13 +288,90 @@ Class UTRocketLauncher : UTWeapon
UTMainHandler.DoFlash(self,Color(64,255,0,0),1); UTMainHandler.DoFlash(self,Color(64,255,0,0),1);
A_AlertMonsters(); A_AlertMonsters();
A_QuakeEx(2+num,2+num,2+num,6+num,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1+num*0.05); A_QuakeEx(2+num,2+num,2+num,6+num,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1+num*0.05);
// TODO Vector3 x, y, z, x2, y2, z2;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+6.0*y-6.0*z;
[x2, y2, z2] = Matrix4.GetAxes(BulletSlope(),angle,roll);
Actor p;
if ( weap.bAltFire )
{
// grenades
for ( int i=0; i<num; i++ )
{
a = FRandom[Eightball](0,360);
s = FRandom[Eightball](0,0.1);
Vector3 dir = (x2+cos(a)*y2*s+sin(a)*z2*s).unit();
p = Spawn("UTGrenade",origin);
p.vel = dir*p.speed*FRandom[Eightball](1.0,1.2);
p.vel.z += 5;
p.target = self;
}
}
else if ( num <= 1 )
{
// single rocket
p = Spawn("UTRocket",origin+cos(a)*y*s+sin(a)*z*s);
p.vel = (x2+cos(a)*y2*s*0.01+sin(a)*z2*s*0.01).unit()*p.speed;
p.target = self;
p.tracer = invoker.LockedTarget;
}
else if ( player.cmd.buttons&BT_ALTATTACK )
{
// rockets ("tight wad" as UT calls it)
double step = 360/num;
a = 90;
s = num?1.2:0.0;
for ( int i=0; i<num; i++ )
{
p = Spawn("UTRocket",origin+cos(a)*y*s+sin(a)*z*s);
p.vel = (x2+cos(a)*y2*s*0.01+sin(a)*z2*s*0.01).unit()*p.speed;
p.target = self;
p.tracer = invoker.LockedTarget;
a += step;
}
}
else
{
// rockets (wide spread)
double range = (num-1);
double step = range/(num-1);
s = -range*0.5;
for ( int i=0; i<num; i++ )
{
p = Spawn("UTRocket",origin+sin(s)*y*2);
p.vel = (x2+sin(s)*y2).unit()*p.speed;
p.target = self;
p.tracer = invoker.LockedTarget;
s += step;
}
}
} }
// lock-on check (TODO) // lock-on check
Actor CheckTarget() action void A_CheckTarget()
{ {
return null; let t = ThinkerIterator.Create("Actor");
Actor a;
double closest = double.max;
invoker.LockedTarget = null;
while ( a = Actor(t.Next()) )
{
if ( !a.bSHOOTABLE || (a.Health <= 0) || a.bKilled || a.bCorpse || (a == self) || isTeammate(a) || !CheckSight(a) ) continue;
Vector3 viewdir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
Vector3 reldir = level.Vec3Diff(Vec2OffsetZ(0,0,player.viewz),a.Vec2OffsetZ(0,0,a.pos.z+a.height*0.5));
double reldist = reldir.length();
if ( reldist > 2000 ) continue;
if ( reldir.unit() dot viewdir < 0.99 ) continue;
if ( reldist < closest )
{
closest = reldist;
invoker.LockedTarget = a;
}
}
if ( invoker.LockedTarget ) A_PlaySound("utrl/seeklock",CHAN_6);
else if ( invoker.LockedOn ) A_PlaySound("utrl/seeklost",CHAN_6);
if ( invoker.LockedTarget ) invoker.LockedOn = true;
} }
Default Default
@ -134,14 +402,26 @@ Class UTRocketLauncher : UTWeapon
Idle: Idle:
EBLI A 1 EBLI A 1
{ {
invoker.locktics = 0;
A_CheckReload(); A_CheckReload();
A_WeaponReady(); A_WeaponReady();
} }
EBLI A 1
{
A_CheckReload();
A_WeaponReady();
invoker.locktics++;
if ( invoker.locktics > 42 )
{
invoker.locktics = 0;
A_CheckTarget();
}
}
Wait; Wait;
Fire: Fire:
AltFire: AltFire:
// one is loaded already // one is loaded already
EBLI A 3 A_LoadRocket(); EBLI A 3 A_LoadRocket(false);
EBLI A 0 A_LoadedRefire(1); EBLI A 0 A_LoadedRefire(1);
Goto FireOne; Goto FireOne;
// load two // load two

View file

@ -68,10 +68,6 @@ Class ChunkLight : DynamicLight
DynamicLight.Type "Point"; DynamicLight.Type "Point";
Args 255,224,128,8; Args 255,224,128,8;
} }
override void PostBeginPlay()
{
Super.PostBeginPlay();
}
override void Tick() override void Tick()
{ {
Super.Tick(); Super.Tick();
@ -146,7 +142,7 @@ Class FlakChunk : Actor
{ {
Obituary "%o was ripped to shreds by %k's Flak Cannon."; Obituary "%o was ripped to shreds by %k's Flak Cannon.";
Radius 2; Radius 2;
Height 2; Height 0;
Speed 50; Speed 50;
DamageFunction Random[Flak](12,18); DamageFunction Random[Flak](12,18);
DamageType 'Shredded'; DamageType 'Shredded';
@ -365,13 +361,13 @@ Class FlakSlug : Actor
{ {
Obituary "%o was ripped to shreds by %k's Flak Cannon."; Obituary "%o was ripped to shreds by %k's Flak Cannon.";
DamageType 'FlakDeath'; DamageType 'FlakDeath';
Radius 4; DamageFunction Random[Flak](60,80);
Height 4; Radius 2;
Height 0;
Speed 40; Speed 40;
PROJECTILE; PROJECTILE;
-NOGRAVITY; -NOGRAVITY;
+SKYEXPLODE; +SKYEXPLODE;
+FORCERADIUSDMG;
+HITTRACER; +HITTRACER;
} }
override void PostBeginPlay() override void PostBeginPlay()
@ -398,7 +394,7 @@ Class FlakSlug : Actor
A_SprayDecal("RocketBlast",150); A_SprayDecal("RocketBlast",150);
A_NoGravity(); A_NoGravity();
A_SetScale(1.2); A_SetScale(1.2);
A_Explode(Random[Flak](60,80),150); A_Explode(Random[Flak](40,60),150);
A_QuakeEx(4,4,4,8,0,200,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2); A_QuakeEx(4,4,4,8,0,200,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
A_PlaySound("flak/explode",CHAN_VOICE); A_PlaySound("flak/explode",CHAN_VOICE);
A_AlertMonsters(); A_AlertMonsters();

View file

@ -98,8 +98,8 @@ Class PulseBall : Actor
PROJECTILE; PROJECTILE;
Scale 0.2; Scale 0.2;
Speed 30; Speed 30;
Radius 4; Radius 2;
Height 4; Height 0;
} }
override void PostBeginPlay() override void PostBeginPlay()
{ {

View file

@ -814,8 +814,8 @@ Class ShockBall : Actor
Obituary "%k inflicted mortal damage upon %o with the Shock Rifle"; Obituary "%k inflicted mortal damage upon %o with the Shock Rifle";
RenderStyle "Add"; RenderStyle "Add";
DamageType 'jolted'; DamageType 'jolted';
Radius 4; Radius 2;
Height 4; Height 0;
Scale 0.4; Scale 0.4;
Speed 20; Speed 20;
PROJECTILE; PROJECTILE;
@ -876,8 +876,8 @@ Class SuperShockBall : Actor
Obituary "%k electrified %o with the Enhanced Shock Rifle."; Obituary "%k electrified %o with the Enhanced Shock Rifle.";
RenderStyle "Add"; RenderStyle "Add";
DamageType 'jolted'; DamageType 'jolted';
Radius 4; Radius 2;
Height 4; Height 0;
Scale 0.5; Scale 0.5;
Speed 25; Speed 25;
PROJECTILE; PROJECTILE;

View file

@ -119,7 +119,7 @@ Class TranslocatorModule : Actor
Default Default
{ {
Radius 2; Radius 2;
Height 2; Height 0;
Speed 25; Speed 25;
PROJECTILE; PROJECTILE;
-NOGRAVITY; -NOGRAVITY;