- [flak_m] Implement particle meshes.
- Append heal amount to health pickups (excl. superhealth).
- Armor Bonus item.
- Overhaul Stinger explosive charge behaviour, more in line with 0.83 and the novels.
- Fix: Dispersion Pistol should only have infinite ammo in deathmatch.
- Dispersion Pistol altfire always at level 0 if below 10 ammo.
- More Fireblaster tweaks and touches and whatnot. Now fires in 3 bursts of 3 projectiles. And there's more damage and whatnot, it should stop sucking.
- Capped fire effects for huge actors.
- Reduced flames per tic on Flamethrower, to see if this causes less performance issues. May roll back if this was a bad idea.
- Snuck in some longer versions of a couple player sounds.
- [oldsounds] Added higher quality dispersion pistol select sound.
This commit is contained in:
Marisa the Magician 2019-10-02 17:40:09 +02:00
commit 0cb76eb03a
30 changed files with 270 additions and 117 deletions

View file

@ -170,6 +170,29 @@ sometimes give you additional items like Flares, Seeds and other usables.
Identical to Doom Tournament. Identical to Doom Tournament.
## Minigun Sentry
A big, heavy turret that will gun down any enemies that stand in its view
range.
Unlike the Light Sentries this one has a much wider range of view and can be
resupplied with extra ammo. Conveniently, you can also recall it to put it back
in your inventory. While carried it will slowly repair any damage it has taken.
In deathmatch, the Sentry will "switch owners" to whoever last replenished it
with ammunition, like the Turrets in ChaosUT.
Note: This is an original item that mainly exists as a more polished take on
the previous one.
## Armor Bonus
There needed to be an equivalent to Doom Tournament's here. These stack up to
a total of 200. In addition, the more you have, the higher the percentage of
damage they will absorb.
They have the lowest priority, so all other armors will go down first.
# Prototype Items # Prototype Items
## Light & Dark Flares ## Light & Dark Flares
@ -188,21 +211,6 @@ carry and deploy, but once they're out in the field that's it. They will keep
going until they run out of ammo or battery, after which they will going until they run out of ammo or battery, after which they will
self-destruct. self-destruct.
## Minigun Sentry
A big, heavy turret that will gun down any enemies that stand in its view
range.
Unlike the Light Sentries this one has a much wider range of view and can be
resupplied with extra ammo. Conveniently, you can also recall it to put it back
in your inventory. While carried it will slowly repair any damage it has taken.
In deathmatch, the Sentry will "switch owners" to whoever last replenished it
with ammunition, like the Turrets in ChaosUT.
Note: This is an original item that mainly exists as a more polished take on
the previous one.
## Motion Detector ## Motion Detector
This pocket device will allow you to spot nearby enemies. In addition each one This pocket device will allow you to spot nearby enemies. In addition each one

View file

@ -846,6 +846,10 @@ HardwareShader Texture "models/FlametFX.png"
{ {
Shader "shaders/glsl/FlametFX.fp" Shader "shaders/glsl/FlametFX.fp"
} }
HardwareShader Texture "models/shield.png"
{
Shader "shaders/glsl/AmbientGlow.fp"
}
// PP shaders // PP shaders
HardwareShader PostProcess scene HardwareShader PostProcess scene
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

BIN
graphics/icons/I_Bonus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -786,3 +786,14 @@ Model "SCUBAGear"
FrameIndex SCUB A 0 0 FrameIndex SCUB A 0 0
} }
Model "UArmorBonus"
{
Path "models"
Model 0 "ubonus_d.3d"
Skin 0 "shield.png"
Scale 0.08 -0.08 0.096
AngleOffset 90
FrameIndex XANH A 0 0
}

BIN
models/shield.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
models/ubonus_a.3d Normal file

Binary file not shown.

BIN
models/ubonus_d.3d Normal file

Binary file not shown.

View file

@ -172,6 +172,11 @@ stinger/hit bladehit
stinger/hit2 ricochet stinger/hit2 ricochet
stinger/flesh chunkhit stinger/flesh chunkhit
$limit stinger/hit 16 $limit stinger/hit 16
stinger/explo1 stingex1
stinger/explo2 stingex2
stinger/explo3 stingex3
$random stinger/explode { stinger/explo1 stinger/explo2 stinger/explo3 }
$limit stinger/explode 16
flak/click click flak/click click
@ -318,8 +323,9 @@ flamegun/fire flamgfir
flamegun/end flamgend flamegun/end flamgend
flamegun/charge flamgabg flamegun/charge flamgabg
flamegun/alt flamgalt flamegun/alt flamgalt
flamegun/exp expl04 flamegun/exp expl2
$limit flamegun/exp 16 $limit flamegun/exp 16
flamegun/exp2 expl04
flamet/select flamtsel flamet/select flamtsel
flamet/idle flamtidl flamet/idle flamtidl

Binary file not shown.

Binary file not shown.

BIN
sounds/StingEx1.ogg Normal file

Binary file not shown.

BIN
sounds/StingEx2.ogg Normal file

Binary file not shown.

BIN
sounds/StingEx3.ogg Normal file

Binary file not shown.

BIN
sounds/expl2.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
sprites/TPNTA0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -503,7 +503,7 @@ Class DispersionPistol : UnrealWeapon
} }
else weap.Ammo1.Amount -= invoker.MainUse; else weap.Ammo1.Amount -= invoker.MainUse;
} }
DefaultAmmo(weap.Ammo1).rechargephase = ((weap.Ammo1.Amount>0)?0:30); DefaultAmmo(weap.Ammo1).rechargephase = (((weap.Ammo1.Amount>0)||!deathmatch)?0:30);
switch ( ulevel ) switch ( ulevel )
{ {
case 0: case 0:
@ -568,11 +568,12 @@ Class DispersionPistol : UnrealWeapon
invoker.bCharging = false; invoker.bCharging = false;
if ( self is 'UTPlayer' ) if ( self is 'UTPlayer' )
UTPlayer(self).PlayAttacking3(); UTPlayer(self).PlayAttacking3();
DefaultAmmo(weap.Ammo1).rechargephase = ((weap.Ammo1.Amount>0)?0:30); DefaultAmmo(weap.Ammo1).rechargephase = (((weap.Ammo1.Amount>0)||!deathmatch)?0:30);
A_PlaySound("dpistol/altfire",CHAN_WEAPON,Dampener.Active(self)?.4:1.); A_PlaySound("dpistol/altfire",CHAN_WEAPON,Dampener.Active(self)?.4:1.);
double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50); double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50);
invoker.FireEffect(); invoker.FireEffect();
int ulevel = sting_dpistol?0:invoker.upgradelevel; int ulevel = sting_dpistol?0:invoker.upgradelevel;
if ( weap.Ammo1.Amount < max(10,invoker.MainUse) ) ulevel = 0;
Class<Actor> proj, part; Class<Actor> proj, part;
switch ( ulevel ) switch ( ulevel )
{ {
@ -673,8 +674,10 @@ Class DispersionPistol : UnrealWeapon
if ( invoker.chargesize >= 5. ) return ResolveState(next); if ( invoker.chargesize >= 5. ) return ResolveState(next);
if ( !(sv_infiniteammo || (FindInventory('PowerInfiniteAmmo',true))) ) if ( !(sv_infiniteammo || (FindInventory('PowerInfiniteAmmo',true))) )
{ {
if ( weap.Ammo1.Amount < invoker.ChargeUse ) return ResolveState(next); int use = invoker.ChargeUse;
weap.Ammo1.Amount -= invoker.ChargeUse; if ( weap.Ammo1.Amount < max(10,invoker.ChargeUse) ) use = 1;
if ( weap.Ammo1.Amount < use ) return ResolveState(next);
weap.Ammo1.Amount -= use;
} }
return ResolveState(null); return ResolveState(null);
} }
@ -737,7 +740,7 @@ Class DispersionPistol : UnrealWeapon
{ {
A_CheckReload(); A_CheckReload();
let weap = Weapon(invoker); let weap = Weapon(invoker);
if ( weap && weap.Ammo1.Amount > 0 ) A_WeaponReady(); if ( weap && (weap.Ammo1.Amount > 0) ) A_WeaponReady();
else A_WeaponReady(WRF_NOFIRE); else A_WeaponReady(WRF_NOFIRE);
} }
TNT1 A 1 TNT1 A 1
@ -815,6 +818,10 @@ Class DispersionPistol : UnrealWeapon
#### # 0 #### # 0
{ {
invoker.chargesize = invoker.count = 0.; invoker.chargesize = invoker.count = 0.;
let weap = Weapon(invoker);
if ( weap.Ammo1.Amount < max(10,invoker.ChargeUse) )
weap.Ammo1.Amount--;
else weap.Ammo1.Amount -= invoker.ChargeUse;
invoker.bCharging = true; invoker.bCharging = true;
// need to make sure player does the repeat fire anim // need to make sure player does the repeat fire anim
if ( self is 'UPlayer' ) if ( self is 'UPlayer' )

View file

@ -43,7 +43,7 @@ Class UFireTrail : Actor
Class UFireball : Actor Class UFireball : Actor
{ {
Vector3 Acceleration; Vector3 Acceleration;
double spreadf; double spreadf, maxspeed;
int ns, nsp; int ns, nsp;
property SpreadFactor : spreadf; property SpreadFactor : spreadf;
@ -66,22 +66,24 @@ Class UFireball : Actor
UFireball.SpreadFactor 0.2; UFireball.SpreadFactor 0.2;
UFireball.NumSmokes 1; UFireball.NumSmokes 1;
UFireball.NumSparks 2; UFireball.NumSparks 2;
DeathSound "flamegun/exp";
} }
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();
maxspeed = 30.;
if ( bAMBUSH ) return; if ( bAMBUSH ) return;
let l = Spawn("UFireTrail",pos); let l = Spawn("UFireTrail",pos);
l.target = self; l.target = self;
Acceleration = vel.unit()*50; Acceleration = vel.unit()*50;
A_PlaySound("eightball/fly",CHAN_VOICE,1.0,true,3.,pitch:1.5); A_PlaySound("eightball/fly",CHAN_VOICE,.6,true,3.,pitch:1.5);
} }
action void A_Spread() action void A_Spread()
{ {
vel += invoker.Acceleration/TICRATE; vel += invoker.Acceleration/TICRATE;
vel += (FRandom[EWizFX](-1,1),FRandom[EWizFX](-1,1),FRandom[EWizFX](-1,1))*FRandom[EWizFX](.5,1.)*invoker.spreadf; vel += (FRandom[EWizFX](-1,1),FRandom[EWizFX](-1,1),FRandom[EWizFX](-1,1))*FRandom[EWizFX](.5,1.)*invoker.spreadf;
Vector3 dir = vel.unit(); Vector3 dir = vel.unit();
if ( vel.length() > 30. ) vel = dir*30.; if ( vel.length() > invoker.maxspeed ) vel = dir*invoker.maxspeed;
angle = atan2(dir.y,dir.x); angle = atan2(dir.y,dir.x);
pitch = asin(-dir.z); pitch = asin(-dir.z);
if ( waterlevel > 0 ) if ( waterlevel > 0 )
@ -102,6 +104,7 @@ Class UFireball : Actor
} }
for ( int i=0; i<invoker.ns; i++ ) for ( int i=0; i<invoker.ns; i++ )
{ {
if ( Random[FlameGun](0,2) ) continue;
let s = Spawn("UTSmoke",pos); let s = Spawn("UTSmoke",pos);
s.vel = (FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2)); s.vel = (FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2));
s.vel += vel*0.2; s.vel += vel*0.2;
@ -109,7 +112,7 @@ Class UFireball : Actor
} }
for ( int i=0; i<invoker.nsp; i++ ) for ( int i=0; i<invoker.nsp; i++ )
{ {
if ( Random[FlameGun](0,3) ) continue; if ( Random[FlameGun](0,6) ) continue;
let s = Spawn("UTSpark",pos); let s = Spawn("UTSpark",pos);
s.vel = (FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2)); s.vel = (FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2),FRandom[FlameGun](-0.2,0.2));
s.ClearBounce(); s.ClearBounce();
@ -128,10 +131,10 @@ Class UFireball : Actor
} }
else else
{ {
A_PlaySound("flamegun/exp",CHAN_VOICE,pitch:1.2);
Spawn("UFireLight",pos); Spawn("UFireLight",pos);
A_Explode(GetMissileDamage(0,0),60); A_Explode(GetMissileDamage(0,0),60);
UTMainHandler.DoBlast(self,60,9000); UTMainHandler.DoBlast(self,60,9000);
A_PlaySound(DeathSound,CHAN_VOICE,attenuation:1.5,pitch:FRandom[ExploS](0.8,1.2));
} }
A_SprayDecal("SmallRocketBlast"); A_SprayDecal("SmallRocketBlast");
Scale *= FRandom[ExploS](0.6,0.9); Scale *= FRandom[ExploS](0.6,0.9);
@ -164,10 +167,16 @@ Class UFireball : Actor
s.scale *= FRandom[ExploS](0.9,1.3); s.scale *= FRandom[ExploS](0.9,1.3);
} }
} }
override void Tick()
{
Super.Tick();
if ( !isFrozen() && InStateSequence(CurState,FindState("Spawn")) )
A_Spread();
}
States States
{ {
Spawn: Spawn:
FIRB ABCDEFGHIJK 1 Bright A_Spread(); FIRB ABCDEFGHIJK 2 Bright;
Loop; Loop;
Death: Death:
TNT1 A 0 A_FireballExplo(); TNT1 A 0 A_FireballExplo();
@ -183,10 +192,19 @@ Class UFireball2 : UFireball
Radius 8; Radius 8;
Height 8; Height 8;
DamageFunction 50; DamageFunction 50;
Speed 5; Speed 3;
Scale 1.5;
UFireball.SpreadFactor 0.35; UFireball.SpreadFactor 0.35;
UFireball.NumSmokes 2; UFireball.NumSmokes 6;
UFireball.NumSparks 4; UFireball.NumSparks 12;
DeathSound "flamegun/exp2";
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
Acceleration = vel.unit()*150;
maxspeed = 50.;
A_PlaySound("eightball/fly",CHAN_VOICE,1.,true,1.5,pitch:.85);
} }
action void A_FireballExplo2() action void A_FireballExplo2()
{ {
@ -235,9 +253,9 @@ Class UFireball2 : UFireball
if ( ff ) HitNormal = -ff.bottom.Normal; if ( ff ) HitNormal = -ff.bottom.Normal;
else HitNormal = BlockingCeiling.ceilingplane.Normal; else HitNormal = BlockingCeiling.ceilingplane.Normal;
} }
for ( int i=0; i<12; i++ ) for ( int i=0; i<20; i++ )
{ {
dir = (HitNormal*1.2+(FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1))).unit(); dir = (HitNormal*1.1+(FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1))).unit();
let s = Spawn("UFireballEmber",level.Vec3Offset(pos,HitNormal*2)); let s = Spawn("UFireballEmber",level.Vec3Offset(pos,HitNormal*2));
s.vel = dir*s.speed*FRandom[ExploS](0.6,1.8); s.vel = dir*s.speed*FRandom[ExploS](0.6,1.8);
s.angle = atan2(dir.y,dir.x); s.angle = atan2(dir.y,dir.x);
@ -266,6 +284,7 @@ Class UFireballEmber : UFireball
UFireball.SpreadFactor 0.5; UFireball.SpreadFactor 0.5;
UFireball.NumSmokes 1; UFireball.NumSmokes 1;
UFireball.NumSparks 1; UFireball.NumSparks 1;
DeathSound "";
} }
States States
{ {
@ -316,15 +335,22 @@ Class FlameGun : UnrealWeapon
UTMainHandler.DoSwing(self,(FRandom[FlameGun](-0.3,-0.2),FRandom[FlameGun](-0.2,0.2)),4,-1,3,SWING_Spring,2,2); UTMainHandler.DoSwing(self,(FRandom[FlameGun](-0.3,-0.2),FRandom[FlameGun](-0.2,0.2)),4,-1,3,SWING_Spring,2,2);
} }
if ( !Dampener.Active(self) ) A_AlertMonsters(); if ( !Dampener.Active(self) ) A_AlertMonsters();
Vector3 x, y, z; Vector3 x, y, z, x2, y2, z2, dir;
double a, s; double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-z); Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+3*y-z);
Actor p = Spawn(bAlt?"UFireball2":"UFireball",origin); [x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
p.angle = angle; for ( int i=0; i<(bAlt?1:3); i++ )
p.pitch = BulletSlope(); {
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed; a = FRandom[FlameGun](0,360);
p.target = self; s = FRandom[FlameGun](0,bAlt?0.:.15);
dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
let p = Spawn(bAlt?"UFireball2":"UFireball",origin);
p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z);
p.vel = dir*p.speed;
p.target = self;
}
int numpt = Random[FlameGun](10,15); int numpt = Random[FlameGun](10,15);
for ( int i=0; i<numpt; i++ ) for ( int i=0; i<numpt; i++ )
{ {
@ -380,33 +406,36 @@ Class FlameGun : UnrealWeapon
#### # 1 A_Overlay(-9999,"Null"); #### # 1 A_Overlay(-9999,"Null");
FGNF A 2 FGNF A 2
{ {
invoker.special1 = 0;
A_PlaySound("flamegun/start",CHAN_6,Dampener.Active(self)?.1:1.); A_PlaySound("flamegun/start",CHAN_6,Dampener.Active(self)?.1:1.);
if ( !Dampener.Active(self) ) A_AlertMonsters(); if ( !Dampener.Active(self) ) A_AlertMonsters();
} }
Hold: Hold:
FGNF B 1 A_FlameGunFire(); FGNF B 1 A_FlameGunFire();
FGNF CDEF 1; FGNF CDEFG 1;
FGNF G 0 FGNF H 0
{ {
if ( invoker.CheckAmmo(0,false,true) && (waterlevel < 2) ) invoker.special1++;
if ( invoker.CheckAmmo(0,false,true) && (waterlevel < 2) && (invoker.special1 < 3) )
A_Refire("Refire"); A_Refire("Refire");
} }
FGNF G 0 A_ClearRefire(); FGNF H 0 A_ClearRefire();
FGNF GHIJ 2; FGNF HIJ 2;
FGNT A 0 FGNT A 0
{ {
if ( invoker.CheckAmmo(0,false,true) && (waterlevel < 2) ) if ( invoker.CheckAmmo(0,false,true) && (waterlevel < 2) && (invoker.special1 < 3) )
A_Refire("Fire"); A_Refire("Fire");
} }
FGNT A 0 FGNT A 0
{ {
invoker.special1 = 0;
A_PlaySound("flamegun/end",CHAN_6,Dampener.Active(self)?.1:1.); A_PlaySound("flamegun/end",CHAN_6,Dampener.Active(self)?.1:1.);
A_ClearRefire(); A_ClearRefire();
} }
FGNT ABCDEFGHIJKLM 2; FGNT ABCDEFGHIJKLM 2;
Goto Idle; Goto Idle;
Refire: Refire:
FGNF G 2 A_PlaySound("flamegun/start",CHAN_6,Dampener.Active(self)?.1:1.); FGNF H 2 A_PlaySound("flamegun/start",CHAN_6,Dampener.Active(self)?.1:1.);
Goto Hold; Goto Hold;
AltFire: AltFire:
#### # 1 A_Overlay(-9999,"Null"); #### # 1 A_Overlay(-9999,"Null");

View file

@ -88,7 +88,7 @@ Class OnFire : Thinker
if ( level.maptime%5 ) return; if ( level.maptime%5 ) return;
int numpt = clamp(int(Random[FlameT](2,4)*amount*0.02),1,4); int numpt = clamp(int(Random[FlameT](2,4)*amount*0.02),1,4);
double mult = max(victim.radius,victim.height)/30.; double mult = max(victim.radius,victim.height)/30.;
numpt = int(max(1,numpt*mult**.5)); numpt = int(clamp(numpt*mult**.5,1,5));
for ( int i=0; i<numpt; i++ ) for ( int i=0; i<numpt; i++ )
{ {
Vector3 pos = victim.Vec3Offset(FRandom[FlameT](-victim.radius,victim.radius)*0.8,FRandom[FlameT](-victim.radius,victim.radius)*0.8,FRandom[FlameT](victim.height*0.2,victim.height*0.8)); Vector3 pos = victim.Vec3Offset(FRandom[FlameT](-victim.radius,victim.radius)*0.8,FRandom[FlameT](-victim.radius,victim.radius)*0.8,FRandom[FlameT](victim.height*0.2,victim.height*0.8));
@ -221,18 +221,18 @@ Class UFlame : Actor
let s = Spawn("UTSmoke",pos); let s = Spawn("UTSmoke",pos);
s.vel = (FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2)); s.vel = (FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2),FRandom[FlameT](-0.2,0.2));
s.vel += vel*0.3; s.vel += vel*0.3;
s.alpha *= alpha*4; s.alpha *= alpha*2;
s.scale *= 0.5+abs(scale.x)*(.5+GetAge()/6.); s.scale *= 0.5+abs(scale.x)*(.5+GetAge()/6.);
} }
if ( bAMBUSH ) return; if ( bAMBUSH ) return;
if ( Random[FlameT](0,int(20*((default.alpha+0.1)-alpha))) ) return; if ( Random[FlameT](0,int(20*((default.alpha+0.1)-alpha))) ) return;
double rad = 60+120*int(0.2-alpha); double rad = 60+60*int(0.4-alpha);
let bt = BlockThingsIterator.Create(self,rad); let bt = BlockThingsIterator.Create(self,rad);
while ( bt.Next() ) while ( bt.Next() )
{ {
let t = bt.Thing; let t = bt.Thing;
if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == tracer) || ((t == master) && (GetAge() < 6)) || (Distance3D(t) > rad+t.radius) ) continue; if ( !t || !t.bSHOOTABLE || (t.Health <= 0) || (t == tracer) || ((t == master) && (GetAge() < 6)) || (Distance3D(t) > rad+t.radius) ) continue;
int amt = max(1,int(alpha*10)); int amt = max(1,int(alpha*5));
OnFire.Apply(t,master,amt); OnFire.Apply(t,master,amt);
} }
} }
@ -242,7 +242,7 @@ Class UFlame : Actor
Speed 20; Speed 20;
Radius 4; Radius 4;
Height 4; Height 4;
Alpha 0.2; Alpha 0.4;
Scale 0.1; Scale 0.1;
+NOBLOCKMAP; +NOBLOCKMAP;
+NOGRAVITY; +NOGRAVITY;
@ -254,6 +254,7 @@ Class UFlame : Actor
+FORCEXYBILLBOARD; +FORCEXYBILLBOARD;
+DROPOFF; +DROPOFF;
+NOBLOCKMONST; +NOBLOCKMONST;
//+THRUIMPASSABLE; // gonna have to implement this
} }
States States
{ {
@ -261,8 +262,8 @@ Class UFlame : Actor
SEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright SEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright
{ {
A_Flame(); A_Flame();
A_SetScale(scale.x*1.08); A_SetScale(scale.x*1.01+0.04);
A_FadeOut(0.005); A_FadeOut(0.01);
} }
Stop; Stop;
} }
@ -803,7 +804,7 @@ Class UFlamethrower : UnrealWeapon
Vector3 x, y, z, x2, y2, z2; Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),15*x+2.3*y-2.7*z); Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),15*x+2.3*y-2.7*z);
for ( int i=0; i<2; i++ ) //for ( int i=0; i<2; i++ )
{ {
double a = FRandom[FlameT](0,360), s = FRandom[FlameT](0,.05); double a = FRandom[FlameT](0,360), s = FRandom[FlameT](0,.05);
[x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll); [x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
@ -821,7 +822,7 @@ Class UFlamethrower : UnrealWeapon
p.vel = vel*.5+(cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed*FRandom[FlameT](0.3,0.6); p.vel = vel*.5+(cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed*FRandom[FlameT](0.3,0.6);
p.vel.z -= 3; p.vel.z -= 3;
p.target = self; p.target = self;
continue; //continue;
} }
p.angle = atan2(dir.y,dir.x); p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z); p.pitch = asin(-dir.z);

View file

@ -173,9 +173,14 @@ Class TarydiumExplosion : Actor
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();
A_Explode(special1,int(90*scale.x)); A_Explode(max(10,special1),90+special1);
UTMainHandler.DoBlast(self,90*scale.x,90000); UTMainHandler.DoBlast(self,90+special1,900*special1);
A_PlaySound("flare/explode"); UTMainHandler.DoBlast(self,200+special1,200*special1); // hurtless secondary blast, so stuff that's pretty close by gets pushed away
// (just going off the novels here, it's supposed to be pretty strong)
A_QuakeEx(clamp(special1/6,2,9),clamp(special1/6,2,9),clamp(special1/6,2,9),10,0,300+special1*2,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200+special1*2,rollIntensity:0.12);
SetOrigin(Vec3Offset(0,0,16),false);
A_PlaySound("stinger/explode",CHAN_VOICE,pitch:FRandom[Stinger](0.8,1.5));
A_PlaySound("stinger/explode",CHAN_ITEM,pitch:FRandom[Stinger](0.8,1.5));
let l = Spawn("TarydiumExLight",pos); let l = Spawn("TarydiumExLight",pos);
l.args[3] = int(60*scale.x); l.args[3] = int(60*scale.x);
scale.x *= RandomPick[Stinger](-1,1); scale.x *= RandomPick[Stinger](-1,1);
@ -236,10 +241,10 @@ Class TDebuffLight : PointLightAttenuated
Destroy(); Destroy();
return; return;
} }
Args[0] = min(dbf.Amount,64); Args[0] = int(min(dbf.Amount,64));
Args[1] = min(dbf.Amount*3,192); Args[1] = int(min(dbf.Amount*3,192));
Args[2] = min(dbf.Amount*4,255); Args[2] = int(min(dbf.Amount*4,255));
Args[3] = int(max(dbf.victim.radius,dbf.victim.height))+60+min(dbf.amount/4,40); Args[3] = int(max(dbf.victim.radius,dbf.victim.height)+60+min(dbf.amount/4,40));
SetOrigin(dbf.Victim.Vec3Offset(0,0,dbf.Victim.Height/2),true); SetOrigin(dbf.Victim.Vec3Offset(0,0,dbf.Victim.Height/2),true);
} }
} }
@ -247,76 +252,78 @@ Class TDebuffLight : PointLightAttenuated
Class TarydiumDebuff : Thinker Class TarydiumDebuff : Thinker
{ {
Actor victim, instigator, lite; Actor victim, instigator, lite;
int amount; // accumulated damage for the explosion double amount; // accumulated damage for the explosion
Vector3 oldvel; Vector3 oldvel;
bool wasonair, reentrant; bool wasonair, exploding;
int explodetimer;
void UpdateEffect() void UpdateEffect()
{ {
if ( !victim ) if ( !victim ) return;
{
BlowUp();
return;
}
if ( !lite ) if ( !lite )
{ {
lite = Actor.Spawn("TDebuffLight",victim.pos); lite = Actor.Spawn("TDebuffLight",victim.pos);
TDebuffLight(lite).dbf = self; TDebuffLight(lite).dbf = self;
lite.Args[0] = min(Amount,64); lite.Args[0] = int(min(Amount,64));
lite.Args[1] = min(Amount*3,192); lite.Args[1] = int(min(Amount*3,192));
lite.Args[2] = min(Amount*4,255); lite.Args[2] = int(min(Amount*4,255));
lite.Args[3] = int(max(victim.radius,victim.height))+60+min(amount/4,40); lite.Args[3] = int(max(victim.radius,victim.height)+60+min(amount/4,40));
}
if ( Random[Stinger](0,amount) > 100 )
{
amount += 30;
BlowUp();
} }
} }
void BlowUp() void BlowUp()
{ {
reentrant = true; let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height)));
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(0,0,victim.default.height/2));
b.target = instigator; b.target = instigator;
b.special1 = amount; b.special1 = int(amount); // in Unreal this was capped to 10, which would make it deal barely any damage
b.scale *= 1.+min(1.5,amount*0.02); b.scale *= .8+min(1.,amount*0.01);
Destroy(); amount = amount*0.9-10; // in Unreal this falls off linearly 10 points at a time, which can take very long at full charge
}
override void OnDestroy()
{
if ( lite ) lite.Destroy();
Super.OnDestroy();
} }
override void Tick() override void Tick()
{ {
if ( !sting_stinger ) if ( !sting_stinger || !victim || (amount <= .4) )
{ {
Destroy(); Destroy();
return; return;
} }
if ( !victim || (victim.Health <= 0) ) if ( exploding )
{ {
explodetimer--;
if ( explodetimer > 0 ) return;
explodetimer = Random[Stinger](3,6);
BlowUp(); BlowUp();
return; return;
} }
if ( victim.Health <= 0 )
{
exploding = true;
return;
}
if ( victim.pos.z > victim.floorz ) wasonair = true; if ( victim.pos.z > victim.floorz ) wasonair = true;
else else
{ {
if ( wasonair && (oldvel.z < -20) ) if ( wasonair && (oldvel.z < -20) )
{ {
Amount += min(int(-oldvel.z),100); Amount += min(int(-oldvel.z),100);
BlowUp(); exploding = true;
return; return;
} }
wasonair = false; wasonair = false;
} }
oldvel = victim.vel; oldvel = victim.vel;
if ( !(level.maptime%20) ) amount *= 1.-.04/TICRATE;
UpdateEffect();
if ( amount <= .4 )
{ {
amount--; Destroy();
UpdateEffect(); return;
if ( amount <= 0 )
{
Destroy();
return;
}
} }
if ( level.maptime%3 ) return; if ( level.maptime%3 ) return;
int numpt = clamp(int(Random[Stinger](1,3)*amount*0.02),1,8); int numpt = clamp(int(Random[Stinger](1,3)*amount*0.02),1,8);
@ -340,7 +347,7 @@ Class TarydiumDebuff : Thinker
} }
} }
static void Apply( Actor victim, Actor instigator, int amount ) static void Apply( Actor victim, Actor instigator, double amount )
{ {
if ( !victim || (victim.Health <= 0) || !victim.bISMONSTER ) return; if ( !victim || (victim.Health <= 0) || !victim.bISMONSTER ) return;
if ( !sting_stinger ) return; if ( !sting_stinger ) return;
@ -446,7 +453,11 @@ Class StingerProjectile : Actor
target.SpawnBlood(pos,AngleTo(target),damage); target.SpawnBlood(pos,AngleTo(target),damage);
A_PlaySound("stinger/flesh"); A_PlaySound("stinger/flesh");
A_AlertMonsters(); A_AlertMonsters();
if ( sting_stinger ) TarydiumDebuff.Apply(target,self.target,damage/4); if ( sting_stinger )
{
TarydiumDebuff.Apply(target,self.target,10);
damage = 2;
}
} }
return damage; return damage;
} }

View file

@ -247,3 +247,32 @@ Class PowerShield : UnrealArmor
Stop; Stop;
} }
} }
Class UArmorBonus : UArmor
{
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
{
absorb = Clamp(Amount-50,25,100);
Super.AbsorbDamage(damage,damageType,newdamage);
}
Default
{
Tag "$T_ARMORBONUS";
+COUNTITEM;
+INVENTORY.ALWAYSPICKUP;
Inventory.Amount 5;
Inventory.MaxAmount 200;
Inventory.InterHubAmount 200;
UTArmor.ArmorAbsorption 25;
UnrealArmor.AbsorptionPriority 1;
Inventory.PickupMessage "$I_ARMORBONUS";
Inventory.PickupSound "misc/u1armor";
Inventory.Icon "I_Bonus";
}
States
{
Spawn:
XANH A -1;
Stop;
}
}

View file

@ -8,6 +8,10 @@ Class Bandages : Health
Inventory.PickupSound "misc/u1heal"; Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 700; Inventory.RespawnTics 700;
} }
override String PickupMessage()
{
return String.Format("%s +%d",PickupMsg,Amount);
}
States States
{ {
Spawn: Spawn:
@ -26,6 +30,10 @@ Class UHealth : Health
Inventory.PickupSound "misc/u1heal"; Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 700; Inventory.RespawnTics 700;
} }
override String PickupMessage()
{
return String.Format("%s +%d",PickupMsg,Amount);
}
States States
{ {
Spawn: Spawn:
@ -40,12 +48,15 @@ Class NaliFruit : Health
Default Default
{ {
Tag "$T_FRUIT"; Tag "$T_FRUIT";
Scale 0.05; Inventory.Amount 29;
Inventory.Amount 0;
Inventory.PickupMessage "$I_FRUIT"; Inventory.PickupMessage "$I_FRUIT";
Inventory.PickupSound "misc/u1heal"; Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 175; Inventory.RespawnTics 175;
} }
override String PickupMessage()
{
return String.Format("%s +%d",PickupMsg,Amount);
}
override bool TryPickup( in out Actor toucher ) override bool TryPickup( in out Actor toucher )
{ {
if ( Amount < 2 ) return false; if ( Amount < 2 ) return false;
@ -54,7 +65,7 @@ Class NaliFruit : Health
override void Tick() override void Tick()
{ {
Super.Tick(); Super.Tick();
if ( !InStateSequence(CurState,FindState("Spawn")) ) return; if ( !InStateSequence(CurState,FindState("Grow")) ) return;
if ( frame > 25 ) return; if ( frame > 25 ) return;
cnt++; cnt++;
if ( cnt < 300 ) return; if ( cnt < 300 ) return;
@ -63,8 +74,12 @@ Class NaliFruit : Health
States States
{ {
Spawn: Spawn:
FRUT A 0 NoDelay FRUT \[ 12;
Loop;
Grow:
FRUT A 0
{ {
A_SetScale(0.05);
invoker.Amount = 0; invoker.Amount = 0;
invoker.cnt = 0; invoker.cnt = 0;
} }
@ -76,8 +91,7 @@ Class NaliFruit : Health
A_SetTics(Random[Fruit](1,3)*35); A_SetTics(Random[Fruit](1,3)*35);
} }
FRUT BCDEFGHIJKLMNOPQRSTUVWXYZ 32; FRUT BCDEFGHIJKLMNOPQRSTUVWXYZ 32;
FRUT \[ 12; Goto Spawn;
Goto Spawn+29;
} }
} }
@ -163,6 +177,7 @@ Class SeedProj : Actor
if ( Scale.x <= 0.05 ) if ( Scale.x <= 0.05 )
{ {
let f = Spawn("NaliFruit",pos); let f = Spawn("NaliFruit",pos);
f.SetStateLabel("Grow");
f.angle = Random[Fruit](0,359); f.angle = Random[Fruit](0,359);
Destroy(); Destroy();
} }
@ -217,6 +232,7 @@ Class SuperHealth : Health
Inventory.PickupSound "misc/u1heal"; Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 3500; Inventory.RespawnTics 3500;
} }
// this one doesn't print the heal amount
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();

View file

@ -143,6 +143,7 @@ Class UPlayer : UTPlayer
if ( !(AllActorClasses[i].GetParentClass() is "UnrealArmor") ) continue; if ( !(AllActorClasses[i].GetParentClass() is "UnrealArmor") ) continue;
let item = Inventory(Spawn(AllActorClasses[i])); let item = Inventory(Spawn(AllActorClasses[i]));
item.ClearCounters(); // don't increase item counts item.ClearCounters(); // don't increase item counts
item.Amount = item.MaxAmount;
if ( !item.CallTryPickup(self) ) item.Destroy(); if ( !item.CallTryPickup(self) ) item.Destroy();
} }
if ( !giveall ) return; if ( !giveall ) return;
@ -761,8 +762,9 @@ Class UTeleportFog : Actor
override void PostBeginPlay() override void PostBeginPlay()
{ {
Super.PostBeginPlay(); Super.PostBeginPlay();
Spawn("UTTeleportLight",pos+(0,0,16)); Spawn("UTTeleportLight",Vec3Offset(0,0,16));
A_PlaySound ("misc/teleport"); A_PlaySound("misc/teleport",volume:.5);
Spawn("UTeleportParticles",Vec3Offset(0,0,16));
} }
States States
{ {
@ -772,6 +774,31 @@ Class UTeleportFog : Actor
} }
} }
Class UTeleportParticles : UTParticleMesh
{
Default
{
Tag "telepo;UTeleParticle";
Args 21;
ReactionTime 35;
XScale 0.06;
YScale 0.16;
}
}
Class UTeleParticle : UTMeshParticle
{
Default
{
Scale 0.2;
}
States
{
Spawn:
TPNT A -1 Bright;
Stop;
}
}
Class UnrealWeapon : UTWeapon Class UnrealWeapon : UTWeapon
{ {
override void FireEffect() override void FireEffect()
@ -892,9 +919,11 @@ Class UnrealMainHandler : EventHandler
TarydiumDebuff t; TarydiumDebuff t;
while ( t = TarydiumDebuff(ti.Next()) ) while ( t = TarydiumDebuff(ti.Next()) )
{ {
if ( (t.victim != e.Thing) || t.reentrant ) continue; // make sure to skip any debuffs that already blew up to prevent infinite recursion on chain reactions if ( (t.victim != e.Thing) || t.exploding ) continue; // make sure to skip any debuffs that already blew up to prevent infinite recursion on chain reactions
t.Amount += e.Damage/2; t.Amount += e.Damage;
t.BlowUp(); // stunner/asmd and others deal extra explosive charge
if ( e.DamageType == 'jolted' ) t.Amount += 50+e.Damage;
t.exploding = true;
break; break;
} }
} }
@ -1082,21 +1111,21 @@ Class UnrealMainHandler : EventHandler
else if ( e.Replacee == 'RadSuit' ) e.Replacement = 'UJumpBoots'; else if ( e.Replacee == 'RadSuit' ) e.Replacement = 'UJumpBoots';
else if ( e.Replacee == 'ArtiFly' ) e.Replacement = 'UJumpBoots'; else if ( e.Replacee == 'ArtiFly' ) e.Replacement = 'UJumpBoots';
else if ( (e.Replacee == 'Backpack') || (e.Replacee == 'BagOfHolding') ) e.Replacement = 'UnrealBackpack'; else if ( (e.Replacee == 'Backpack') || (e.Replacee == 'BagOfHolding') ) e.Replacement = 'UnrealBackpack';
else if ( (e.Replacee == 'ArmorBonus') || (e.Replacee == 'ArtiTimeBomb') ) e.Replacement = 'Flare'; else if ( (e.Replacee == 'ArmorBonus') || (e.Replacee == 'ArtiTimeBomb') )
{
if ( Random[Replacements](0,3) ) e.Replacement = 'UArmorBonus';
else e.Replacement = 'Flare';
}
else if ( (e.Replacee == 'HealthBonus') || (e.Replacee == 'CrystalVial') ) e.Replacement = 'Bandages'; else if ( (e.Replacee == 'HealthBonus') || (e.Replacee == 'CrystalVial') ) e.Replacement = 'Bandages';
else if ( (e.Replacee == 'GreenArmor') || (e.Replacee == 'Silvershield') ) e.Replacement = 'KevlarSuit'; else if ( (e.Replacee == 'GreenArmor') || (e.Replacee == 'Silvershield') ) e.Replacement = 'KevlarSuit';
else if ( (e.Replacee == 'BlueArmor') || (e.Replacee == 'EnchantedShield') ) e.Replacement = 'UArmor'; else if ( (e.Replacee == 'BlueArmor') || (e.Replacee == 'EnchantedShield') ) e.Replacement = 'UArmor';
else if ( e.Replacee == 'Stimpack' ) else if ( (e.Replacee == 'Stimpack') || (e.Replacee == 'ArtiHealth') )
{ {
if ( !Random[Replacements](0,2) ) e.Replacement = 'UHealth'; if ( Random[Replacements](0,1) ) e.Replacement = 'UHealth';
else if ( Random[Replacements](0,2) ) e.Replacement = 'NaliFruit';
else e.Replacement = 'Seeds'; else e.Replacement = 'Seeds';
} }
else if ( e.Replacee == 'Medikit' ) e.Replacement = 'UHealth'; else if ( e.Replacee == 'Medikit' ) e.Replacement = 'UHealth';
else if ( e.Replacee == 'ArtiHealth' )
{
if ( !Random[Replacements](0,2) ) e.Replacement = 'UHealth';
else e.Replacement = 'Seeds';
}
else if ( e.Replacee == 'ArtiTeleport' ) else if ( e.Replacee == 'ArtiTeleport' )
{ {
// I have no idea what to replace this with, so just have some random stuff // I have no idea what to replace this with, so just have some random stuff
@ -1121,7 +1150,7 @@ Class UnrealMainHandler : EventHandler
e.Replacement = 'VoiceBox'; e.Replacement = 'VoiceBox';
break; break;
case 6: case 6:
e.Replacement = 'SentryItem'; e.Replacement = 'SentryGunItem';
break; break;
case 7: case 7:
e.Replacement = 'Peacemaker'; e.Replacement = 'Peacemaker';

View file

@ -38,8 +38,8 @@ Class UnrealHUD : BaseStatusBar
// 0.83 HUD stuff // 0.83 HUD stuff
String OldAmmo[19]; String OldAmmo[19];
Class<Inventory> OldAmmoType[19]; Class<Inventory> OldAmmoType[19];
String OldArmor[6]; String OldArmor[7];
Class<Inventory> OldArmorType[6]; Class<Inventory> OldArmorType[7];
String OldKeys[7]; String OldKeys[7];
HUDFont mOldDigits, mOldDigitsSmall; HUDFont mOldDigits, mOldDigitsSmall;
Font OldLargeFont, OldSmallFont; Font OldLargeFont, OldSmallFont;
@ -134,12 +134,14 @@ Class UnrealHUD : BaseStatusBar
OldArmor[3] = "Tox083"; OldArmor[3] = "Tox083";
OldArmor[4] = "Belt083"; OldArmor[4] = "Belt083";
OldArmor[5] = "Pbelt083"; OldArmor[5] = "Pbelt083";
OldArmor[6] = "Bonus083";
OldArmorType[0] = "UArmor"; OldArmorType[0] = "UArmor";
OldArmorType[1] = "KevlarSuit"; OldArmorType[1] = "KevlarSuit";
OldArmorType[2] = "AsbestosSuit"; OldArmorType[2] = "AsbestosSuit";
OldArmorType[3] = "ToxinSuit"; OldArmorType[3] = "ToxinSuit";
OldArmorType[4] = "ShieldBelt"; OldArmorType[4] = "ShieldBelt";
OldArmorType[5] = "PowerShield"; OldArmorType[5] = "PowerShield";
OldArmorType[6] = "UArmorBonus";
OldKeys[0] = "Redk083"; OldKeys[0] = "Redk083";
OldKeys[1] = "Bluek083"; OldKeys[1] = "Bluek083";
OldKeys[2] = "Goldk083"; OldKeys[2] = "Goldk083";