- [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.
## 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
## 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
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
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"
}
HardwareShader Texture "models/shield.png"
{
Shader "shaders/glsl/AmbientGlow.fp"
}
// PP shaders
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
}
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/flesh chunkhit
$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
@ -318,8 +323,9 @@ flamegun/fire flamgfir
flamegun/end flamgend
flamegun/charge flamgabg
flamegun/alt flamgalt
flamegun/exp expl04
flamegun/exp expl2
$limit flamegun/exp 16
flamegun/exp2 expl04
flamet/select flamtsel
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;
}
DefaultAmmo(weap.Ammo1).rechargephase = ((weap.Ammo1.Amount>0)?0:30);
DefaultAmmo(weap.Ammo1).rechargephase = (((weap.Ammo1.Amount>0)||!deathmatch)?0:30);
switch ( ulevel )
{
case 0:
@ -568,11 +568,12 @@ Class DispersionPistol : UnrealWeapon
invoker.bCharging = false;
if ( self is 'UTPlayer' )
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.);
double mult = Amplifier.GetMult(self,int(invoker.ChargeSize*50)+50);
invoker.FireEffect();
int ulevel = sting_dpistol?0:invoker.upgradelevel;
if ( weap.Ammo1.Amount < max(10,invoker.MainUse) ) ulevel = 0;
Class<Actor> proj, part;
switch ( ulevel )
{
@ -673,8 +674,10 @@ Class DispersionPistol : UnrealWeapon
if ( invoker.chargesize >= 5. ) return ResolveState(next);
if ( !(sv_infiniteammo || (FindInventory('PowerInfiniteAmmo',true))) )
{
if ( weap.Ammo1.Amount < invoker.ChargeUse ) return ResolveState(next);
weap.Ammo1.Amount -= invoker.ChargeUse;
int use = 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);
}
@ -737,7 +740,7 @@ Class DispersionPistol : UnrealWeapon
{
A_CheckReload();
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);
}
TNT1 A 1
@ -815,6 +818,10 @@ Class DispersionPistol : UnrealWeapon
#### # 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;
// need to make sure player does the repeat fire anim
if ( self is 'UPlayer' )

View file

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

View file

@ -88,7 +88,7 @@ Class OnFire : Thinker
if ( level.maptime%5 ) return;
int numpt = clamp(int(Random[FlameT](2,4)*amount*0.02),1,4);
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++ )
{
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);
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.alpha *= alpha*4;
s.alpha *= alpha*2;
s.scale *= 0.5+abs(scale.x)*(.5+GetAge()/6.);
}
if ( bAMBUSH ) 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);
while ( bt.Next() )
{
let t = bt.Thing;
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);
}
}
@ -242,7 +242,7 @@ Class UFlame : Actor
Speed 20;
Radius 4;
Height 4;
Alpha 0.2;
Alpha 0.4;
Scale 0.1;
+NOBLOCKMAP;
+NOGRAVITY;
@ -254,6 +254,7 @@ Class UFlame : Actor
+FORCEXYBILLBOARD;
+DROPOFF;
+NOBLOCKMONST;
//+THRUIMPASSABLE; // gonna have to implement this
}
States
{
@ -261,8 +262,8 @@ Class UFlame : Actor
SEXP AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 1 Bright
{
A_Flame();
A_SetScale(scale.x*1.08);
A_FadeOut(0.005);
A_SetScale(scale.x*1.01+0.04);
A_FadeOut(0.01);
}
Stop;
}
@ -803,7 +804,7 @@ Class UFlamethrower : UnrealWeapon
Vector3 x, y, z, x2, y2, z2;
[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);
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);
[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.z -= 3;
p.target = self;
continue;
//continue;
}
p.angle = atan2(dir.y,dir.x);
p.pitch = asin(-dir.z);

View file

@ -173,9 +173,14 @@ Class TarydiumExplosion : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_Explode(special1,int(90*scale.x));
UTMainHandler.DoBlast(self,90*scale.x,90000);
A_PlaySound("flare/explode");
A_Explode(max(10,special1),90+special1);
UTMainHandler.DoBlast(self,90+special1,900*special1);
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);
l.args[3] = int(60*scale.x);
scale.x *= RandomPick[Stinger](-1,1);
@ -236,10 +241,10 @@ Class TDebuffLight : PointLightAttenuated
Destroy();
return;
}
Args[0] = min(dbf.Amount,64);
Args[1] = min(dbf.Amount*3,192);
Args[2] = min(dbf.Amount*4,255);
Args[3] = int(max(dbf.victim.radius,dbf.victim.height))+60+min(dbf.amount/4,40);
Args[0] = int(min(dbf.Amount,64));
Args[1] = int(min(dbf.Amount*3,192));
Args[2] = int(min(dbf.Amount*4,255));
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);
}
}
@ -247,76 +252,78 @@ Class TDebuffLight : PointLightAttenuated
Class TarydiumDebuff : Thinker
{
Actor victim, instigator, lite;
int amount; // accumulated damage for the explosion
double amount; // accumulated damage for the explosion
Vector3 oldvel;
bool wasonair, reentrant;
bool wasonair, exploding;
int explodetimer;
void UpdateEffect()
{
if ( !victim )
{
BlowUp();
return;
}
if ( !victim ) return;
if ( !lite )
{
lite = Actor.Spawn("TDebuffLight",victim.pos);
TDebuffLight(lite).dbf = self;
lite.Args[0] = min(Amount,64);
lite.Args[1] = min(Amount*3,192);
lite.Args[2] = min(Amount*4,255);
lite.Args[3] = int(max(victim.radius,victim.height))+60+min(amount/4,40);
}
if ( Random[Stinger](0,amount) > 100 )
{
amount += 30;
BlowUp();
lite.Args[0] = int(min(Amount,64));
lite.Args[1] = int(min(Amount*3,192));
lite.Args[2] = int(min(Amount*4,255));
lite.Args[3] = int(max(victim.radius,victim.height)+60+min(amount/4,40));
}
}
void BlowUp()
{
reentrant = true;
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(0,0,victim.default.height/2));
let b = victim.Spawn("TarydiumExplosion",victim.Vec3Offset(FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](-victim.radius,victim.radius),FRandom[Stinger](0,victim.height)));
b.target = instigator;
b.special1 = amount;
b.scale *= 1.+min(1.5,amount*0.02);
Destroy();
b.special1 = int(amount); // in Unreal this was capped to 10, which would make it deal barely any damage
b.scale *= .8+min(1.,amount*0.01);
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()
{
if ( !sting_stinger )
if ( !sting_stinger || !victim || (amount <= .4) )
{
Destroy();
return;
}
if ( !victim || (victim.Health <= 0) )
if ( exploding )
{
explodetimer--;
if ( explodetimer > 0 ) return;
explodetimer = Random[Stinger](3,6);
BlowUp();
return;
}
if ( victim.Health <= 0 )
{
exploding = true;
return;
}
if ( victim.pos.z > victim.floorz ) wasonair = true;
else
{
if ( wasonair && (oldvel.z < -20) )
{
Amount += min(int(-oldvel.z),100);
BlowUp();
exploding = true;
return;
}
wasonair = false;
}
oldvel = victim.vel;
if ( !(level.maptime%20) )
amount *= 1.-.04/TICRATE;
UpdateEffect();
if ( amount <= .4 )
{
amount--;
UpdateEffect();
if ( amount <= 0 )
{
Destroy();
return;
}
Destroy();
return;
}
if ( level.maptime%3 ) return;
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 ( !sting_stinger ) return;
@ -446,7 +453,11 @@ Class StingerProjectile : Actor
target.SpawnBlood(pos,AngleTo(target),damage);
A_PlaySound("stinger/flesh");
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;
}

View file

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

View file

@ -143,6 +143,7 @@ Class UPlayer : UTPlayer
if ( !(AllActorClasses[i].GetParentClass() is "UnrealArmor") ) continue;
let item = Inventory(Spawn(AllActorClasses[i]));
item.ClearCounters(); // don't increase item counts
item.Amount = item.MaxAmount;
if ( !item.CallTryPickup(self) ) item.Destroy();
}
if ( !giveall ) return;
@ -761,8 +762,9 @@ Class UTeleportFog : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
Spawn("UTTeleportLight",pos+(0,0,16));
A_PlaySound ("misc/teleport");
Spawn("UTTeleportLight",Vec3Offset(0,0,16));
A_PlaySound("misc/teleport",volume:.5);
Spawn("UTeleportParticles",Vec3Offset(0,0,16));
}
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
{
override void FireEffect()
@ -892,9 +919,11 @@ Class UnrealMainHandler : EventHandler
TarydiumDebuff t;
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
t.Amount += e.Damage/2;
t.BlowUp();
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;
// stunner/asmd and others deal extra explosive charge
if ( e.DamageType == 'jolted' ) t.Amount += 50+e.Damage;
t.exploding = true;
break;
}
}
@ -1082,21 +1111,21 @@ Class UnrealMainHandler : EventHandler
else if ( e.Replacee == 'RadSuit' ) 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 == '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 == 'GreenArmor') || (e.Replacee == 'Silvershield') ) e.Replacement = 'KevlarSuit';
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 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' )
{
// 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';
break;
case 6:
e.Replacement = 'SentryItem';
e.Replacement = 'SentryGunItem';
break;
case 7:
e.Replacement = 'Peacemaker';

View file

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