Release Candidate 3:

- Fix inventory items not removing themselves when fully drained and no more
  copies are held.
- Fixed Minigun playing the unwind animation on player death.
- Fixed main hand Automag still firing when out of ammo dual wielding.
- Corrected name clash between two explosion sounds.
- Fixed suits still protecting from elemental damage when depleted.
- Add option to wear all suits simultaneously.
- Stunner now consumes Stinger ammo to recharge, this is more in line with the
  Unreal Bible.
- Max damage per explosion capped to 100 for Stinger. Prevents ludicrous
  map-clearing explosions with an amplified asmd combo.
- Shoot-through lines can now be activated by hitscan/beam weapons thanks to
  new DT "bullet trail" feature. No more softlocks in custom maps.
- Added option to make Peacemaker missiles not seek owner and allies.
- Peacemaker missiles start seeking targets much earlier, making it more viable
  indoors.
- Autocannon has had its damage increased again.
- Adjusted swingers for many weapons to feel a bit more natural. Still far from
  perfect.
- Reverted changes to Flamethrower projectile density, and simply made it have
  less dynamic lights.
- Adjustments to armors. Suit elemental resistances now take priority (as
  intended). [please redownload your DT devbuild for full effect]
- Added ring effect for 6-rocket tight wad. Completely forgot this was a thing.
- Fixed flashlight not clearing its dynlights when depleted and still having
  copies.
This commit is contained in:
Marisa the Magician 2019-10-10 08:32:36 +02:00
commit c6a81479ca
29 changed files with 218 additions and 74 deletions

View file

@ -513,7 +513,10 @@ Class ASMDBeam : Actor
if ( isFrozen() || !moving ) return;
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.ShootThroughList.Clear();
t.Trace(pos,cursector,tracedir,1000,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )

View file

@ -174,7 +174,7 @@ Class Automag : UnrealWeapon
else A_Overlay(-3,"LeftMuzzleFlash");
A_OverlayFlags(-3,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-3,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[Automag](0.5,0.2),FRandom[Automag](-0.3,0.2)),2,0,1,SWING_Spring,0,2);
UTMainHandler.DoSwing(self,(FRandom[Automag](0.5,0.2),FRandom[Automag](-0.3,0.2)),2,0.5,1,SWING_Spring,0,2);
}
else
{
@ -195,6 +195,7 @@ Class Automag : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,int((invoker.Amount+alt)**2));
if ( d.HitType == TRACE_HitActor )
{
int dmg = 17;
@ -375,9 +376,10 @@ Class Automag : UnrealWeapon
TNT1 A 1
{
A_CheckReload();
int flags = (invoker.clipcount<=0)?WRF_NOFIRE:0;
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) player.SetPSprite(PSP_WEAPON,ResolveState("Reload"));
else if ( ((invoker.clipcount < invoker.default.clipcount) || (invoker.slaveclipcount < invoker.default.slaveclipcount)) && (invoker.Ammo1.Amount > 0) ) A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(WRF_ALLOWZOOM);
else if ( ((invoker.clipcount < invoker.default.clipcount) || (invoker.slaveclipcount < invoker.default.slaveclipcount)) && (invoker.Ammo1.Amount > 0) ) A_WeaponReady(flags|WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(flags|WRF_ALLOWZOOM);
if ( !invoker.slaveactive && (CountInv("Automag") > 1) )
{
invoker.slavespin = invoker.slavereload = invoker.slaverefire = 0;

View file

@ -238,6 +238,7 @@ Class Betamag : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,int((invoker.Amount+alt)**2));
if ( d.HitType == TRACE_HitActor )
{
int dmg = 14;
@ -484,14 +485,14 @@ Class Betamag : UnrealWeapon
{
A_Overlay(-9999,null);
invoker.slavewhip = true;
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.5,-0.4),FRandom[Betamag](0.2,0.3)),4,0,8,SWING_Spring,5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.5,-0.4),FRandom[Betamag](0.2,0.3)),4,0.3,8,SWING_Spring,5);
}
AUTW ABCDE 2;
AUTW F 0
{
if ( self is 'UTPlayer' ) UTPlayer(self).PlayAttacking3();
A_PlaySound("betamag/whip",CHAN_ITEM);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.3,-0.2),FRandom[Betamag](-0.8,-0.5)),2,0,8,SWING_Spring,2,0.5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](-0.3,-0.2),FRandom[Betamag](-0.8,-0.5)),7,-1,8,SWING_Spring,2,0.5);
}
AUTW FGHIJ 2;
AUTW K 0
@ -515,7 +516,7 @@ Class Betamag : UnrealWeapon
if ( !((invoker.Ammo1.Amount<=0) && (player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK))) && !(player.cmd.buttons&BT_RELOAD) ) return ResolveState("LeftIdle");
invoker.slavewhip = false;
A_Overlay(-9998,null);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.4,0.5),FRandom[Betamag](0.2,0.3)),4,0,8,SWING_Spring,5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.4,0.5),FRandom[Betamag](0.2,0.3)),4,0.3,8,SWING_Spring,5);
return ResolveState(null);
}
2UTW ABCDE 2;
@ -523,7 +524,7 @@ Class Betamag : UnrealWeapon
{
if ( self is 'UTPlayer' ) UTPlayer(self).PlayAttacking3();
A_PlaySound("betamag/whip",CHAN_7);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.2,0.3),FRandom[Betamag](-0.8,-0.5)),2,0,8,SWING_Spring,2,0.5);
UTMainHandler.DoSwing(self,(FRandom[Betamag](0.2,0.3),FRandom[Betamag](-0.8,-0.5)),7,-1,8,SWING_Spring,2,0.5);
}
2UTW FGHIJ 2;
2UTW K 0

View file

@ -186,6 +186,7 @@ Class HitListEntry
Class BigTracer : LineTracer
{
Actor ignoreme;
Array<Line> ShootThroughList;
Array<HitListEntry> hitlist;
double penetration; // please don't laugh
@ -213,6 +214,7 @@ Class BigTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -308,7 +310,7 @@ Class BigGun : UnrealWeapon
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
A_QuakeEx(2,2,2,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollintensity:0.12);
for ( int i=0; i<6; i++ )
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.04,-0.2),FRandom[BigGun](-0.2,0.2)),FRandom[BigGun](6,9),FRandom[BigGun](-0.2,0.8),Random[BigGun](2,4),SWING_Spring,Random[BigGun](3,6),FRandom[BigGun](1.5,2.3));
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.04,-0.2),FRandom[BigGun](-0.2,0.2)),FRandom[BigGun](6,9),FRandom[BigGun](-2,-3),Random[BigGun](2,4),SWING_Spring,Random[BigGun](3,4),FRandom[BigGun](1.5,2.3));
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
vel -= x*(player.onground?9.5:2.5);
@ -321,7 +323,16 @@ Class BigGun : UnrealWeapon
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.penetration = 200.;
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,level.PointInSector(origin.xy),dir,10000.,0);
for ( int i=0; i<invoker.t.ShootThroughList.Size(); i++ )
invoker.t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
for ( int i=5; i<invoker.t.Results.Distance; i+=10 )
{
if ( !Random[Boolet](0,bAlt?3:2) ) continue;
let b = Actor.Spawn("UTBubble",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](0.4,0.6);
}
for ( int i=0; i<invoker.t.hitlist.Size(); i++ )
{
let l = invoker.t.hitlist[i];
@ -462,7 +473,7 @@ Class BigGun : UnrealWeapon
BIGT BCDEFGHIJKLMNOP 2;
BIGT Q 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0.5,6,SWING_Spring,2,1.5);
}
BIGT RSTUVWXY 2;
Goto Idle;
@ -514,12 +525,12 @@ Class BigGun : UnrealWeapon
{
A_ClearRefire();
A_Overlay(-9999,"Null");
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.7,0.3),FRandom[BigGun](0.4,0.3)),3,0,10,SWING_Spring,70,0.8);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.7,0.3),FRandom[BigGun](0.4,0.3)),3,0.2,10,SWING_Spring,70,0.8);
}
BIGR ABCDEFGHIJKL 2;
BIGR M 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.3,0.4),FRandom[BigGun](0.6,0.8)),6,0,3,SWING_Spring,2,3);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.3,0.4),FRandom[BigGun](0.6,0.8)),6,-1,3,SWING_Spring,2,3);
invoker.clipout = true;
A_QuakeEx(2,2,2,5,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollintensity:0.18);
A_PlaySound("big/punch",CHAN_WEAPON,Dampener.Active(self)?.3:1.);
@ -529,7 +540,7 @@ Class BigGun : UnrealWeapon
BIR2 ABCDEF 2;
BIR2 G 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](0.3,0.5)),6,0,3,SWING_Spring,2,3);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](0.3,0.5)),6,-1,3,SWING_Spring,2,3);
invoker.clipout = false;
let aadd = min(invoker.ammo1.amount,invoker.default.clipcount-invoker.clipcount);
invoker.clipcount += aadd;
@ -542,15 +553,19 @@ Class BigGun : UnrealWeapon
BIR2 M 2
{
invoker.PlayUpSound(self);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),3,0.5,7,SWING_Spring,3,1.5);
}
BIR2 NOP 2;
BIR2 Q 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](-0.8,-1.2)),3,0,6,SWING_Spring,2,1.5);
UTMainHandler.DoSwing(self,(FRandom[BigGun](0.2,0.3),FRandom[BigGun](-0.8,-1.2)),3,-0.5,7,SWING_Spring,3,1.5);
}
BIR2 RSTUVWXYZ[\] 2;
BIR3 ABCDEF 2;
BIR3 A 2
{
UTMainHandler.DoSwing(self,(FRandom[BigGun](-0.3,-0.2),FRandom[BigGun](0.4,0.5)),2,-0.5,3,SWING_Spring,1,2.);
}
BIR3 BCDEF 2;
Goto Idle;
Deselect:
BIGD A 1

View file

@ -187,12 +187,12 @@ Class Bonesaw : UnrealWeapon
{
A_Overlay(-9999,"Null");
A_PlaySound("bonesaw/claw",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](-0.2,-0.3)),4,0,8,SWING_Spring,5,0.7);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](-0.2,-0.3)),4,0.2,8,SWING_Spring,2,2.);
}
CSWA ABC 2;
CSWA D 0
{
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](0.8,0.5)),2,0,8,SWING_Spring,2,1.2);
UTMainHandler.DoSwing(self,(FRandom[Bonesaw](-0.1,0.1),FRandom[Bonesaw](0.8,0.5)),6,-1,8,SWING_Spring,2,1.2);
}
CSWA DEF 1;
CSWA G 0 A_Clamp();

View file

@ -541,7 +541,7 @@ Class DispersionPistol : UnrealWeapon
}
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3),FRandom[DPistol](-0.1,0.3)),2,-0.3,3,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3),FRandom[DPistol](-0.1,0.3)),2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
@ -614,7 +614,7 @@ Class DispersionPistol : UnrealWeapon
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
double ss = 0.5+invoker.chargesize*0.3;
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3)*ss,FRandom[DPistol](-0.1,0.3))*ss,2,-0.3,3,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[DPistol](-0.1,-0.3)*ss,FRandom[DPistol](-0.1,0.3))*ss,2+invoker.upgradelevel*0.5,-0.3,3,SWING_Spring,0,3+invoker.upgradelevel);
if ( !Dampener.Active(self) ) A_AlertMonsters();
int qs = int(1+invoker.chargesize*0.3);
A_QuakeEx(qs,qs,qs,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
@ -850,7 +850,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease2:
#### # 3 A_DispAltFire();
DPF2 ABC 6;
DPF2 ABC 8;
DPI2 A 3;
Goto Idle;
AltFire3:
@ -858,7 +858,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease3:
#### # 3 A_DispAltFire();
DPF3 ABC 6;
DPF3 ABC 9;
DPI3 A 3;
Goto Idle;
AltFire4:
@ -866,7 +866,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease4:
#### # 3 A_DispAltFire();
DPF4 ABC 6;
DPF4 ABC 10;
DPI4 A 3;
Goto Idle;
AltFire5:
@ -874,7 +874,7 @@ Class DispersionPistol : UnrealWeapon
Wait;
AltRelease5:
#### # 3 A_DispAltFire();
DPF5 ABC 6;
DPF5 ABC 12;
DPI5 A 3;
Goto Idle;
Upgrade:

View file

@ -384,7 +384,7 @@ Class FlameGun : UnrealWeapon
for ( int i=0; i<(bAlt?1:3); i++ )
{
a = FRandom[FlameGun](0,360);
s = FRandom[FlameGun](0,bAlt?0.:.15);
s = FRandom[FlameGun](0,bAlt?0.:.06);
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);

View file

@ -37,7 +37,7 @@ Class SMiniShell : FastProjectile
{
Obituary "$O_SMINI";
DamageType 'Shot';
DamageFunction 300;
DamageFunction 400;
Radius 4;
Height 4;
Speed 200;
@ -71,7 +71,7 @@ Class SMiniShell : FastProjectile
A_AlertMonsters();
A_SetRenderStyle(1.0,STYLE_Add);
A_NoGravity();
A_Explode(150,120,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded');
A_Explode(200,120,XF_HURTSOURCE|XF_EXPLICITDAMAGETYPE,damagetype:'exploded');
A_QuakeEx(4,4,4,10,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:120,rollintensity:0.2);
A_PlaySound("smini/explode",CHAN_VOICE,pitch:FRandom[SMini](0.8,1.2));
A_SprayDecal("SmallRocketBlast");
@ -214,7 +214,7 @@ Class SMiniGun : UnrealWeapon
for ( int i=0; i<(bAlt?4:1); i++ )
{
if ( bAlt && !weap.DepleteAmmo(weap.bAltFire,true,1) ) break;
UTMainHandler.DoSwing(self,basedir+(FRandom[SMini](-0.04,0.04),FRandom[SMini](-0.04,0.04)),FRandom[SMini](3,4),FRandom[SMini](-0.2,0.8),Random[SMini](2,4),SWING_Spring,Random[SMini](3,6),FRandom[SMini](1.5,2.3));
UTMainHandler.DoSwing(self,basedir+(FRandom[SMini](-0.04,0.04),FRandom[SMini](-0.04,0.04)),FRandom[SMini](6,8),FRandom[SMini](-1,-2),Random[SMini](3,4),SWING_Spring,Random[SMini](3,4),FRandom[SMini](2.2,3.5));
int pos = bAlt?i:invoker.special1;
origin = level.Vec3Offset(origin,x*(!(pos%2)?-1.5:1.5)+y*(pos<2?1.5:-1.5));
double a = FRandom[Minigun](0,360), s = FRandom[Minigun](0,bAlt?0.12:0.03);

View file

@ -125,6 +125,7 @@ Class ImpalerBoltTracer : LineTracer
{
Actor ignoreme;
Array<HitListEntry> hitlist;
Array<Line> ShootThroughList;
override ETraceStatus TraceCallback()
{
@ -145,6 +146,7 @@ Class ImpalerBoltTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -167,7 +169,10 @@ Class ImpalerBurstBolt : Actor
t.hitlist.Clear();
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
t.ShootThroughList.Clear();
t.Trace(pos,CurSector,x,11.125,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
for ( int i=0; i<t.hitlist.Size(); i++ )
{
UTMainHandler.DoKnockback(t.hitlist[i].hitactor,t.hitlist[i].x,6000);
@ -307,7 +312,10 @@ Class ImpalerBolt : Actor
t.HitList.Clear();
if ( bHITOWNER ) t.ignoreme = null;
else t.ignoreme = target;
t.ShootThroughList.Clear();
t.Trace(pos,cursector,x,beamsize,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
for ( int i=0; i<t.HitList.Size(); i++ )
{
if ( !(GetAge()%15) )

View file

@ -1365,13 +1365,24 @@ Class UFlashlight : UnrealInventory
Owner.A_PlaySound("lite/off",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_FLASHLIGHT"));
if ( Amount <= 0 ) DepleteOrDestroy();
else
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
}
}
}
override void DetachFromOwner()
{
Super.DetachFromOwner();
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
Super.DetachFromOwner();
}
override void OwnerDied()
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
Super.OwnerDied();
}
override void Travelled()
{
@ -1413,6 +1424,11 @@ Class USearchlight : UFlashlight
Owner.A_PlaySound("lite/off",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_SEARCHLIGHT"));
if ( Amount <= 0 ) DepleteOrDestroy();
else
{
if ( lt[0] ) lt[0].Destroy();
if ( lt[1] ) lt[1].Destroy();
}
}
}
override void SetupLights()

View file

@ -230,7 +230,7 @@ Class UFlame : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( waterlevel <= 0 )
if ( (waterlevel <= 0) && Random[FlameT](0,1) )
{
let l = Spawn("UFlameLight",pos);
l.target = self;
@ -262,18 +262,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*2;
s.alpha *= alpha*4;
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+60*int(0.4-alpha);
double rad = 60+120*int(0.2-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*5));
int amt = max(1,int(alpha*10));
OnFire.Apply(t,master,amt);
}
}
@ -283,7 +283,7 @@ Class UFlame : Actor
Speed 20;
Radius 4;
Height 4;
Alpha 0.4;
Alpha 0.2;
Scale 0.1;
+NOBLOCKMAP;
+NOGRAVITY;
@ -304,7 +304,7 @@ Class UFlame : Actor
{
A_Flame();
A_SetScale(scale.x*1.01+0.04);
A_FadeOut(0.01);
A_FadeOut(0.005);
}
Stop;
}
@ -886,7 +886,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);
@ -904,7 +904,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

@ -165,6 +165,7 @@ Class OLSMP : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,alt?6:4);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 17;

View file

@ -105,6 +105,7 @@ Class PeaceRocket : Actor
while ( bi.Next() )
{
if ( !bi.Thing || (!bi.Thing.bISMONSTER && !bi.Thing.player) || (bi.Thing.Health <= 0) || (Distance3D(bi.Thing) > 500) || !CheckSight(bi.Thing) ) continue;
if ( sting_peacehome && ((bi.Thing == target) || (target && target.IsFriend(bi.Thing))) ) continue;
double dist = Distance3D(bi.Thing);
if ( dist > mindist ) break;
tracer = bi.Thing;
@ -185,6 +186,8 @@ Class PeaceRocket : Actor
A_CheckForTargets();
A_CountDown();
}
// early check
if ( GetAge() == 5 ) A_CheckForTargets();
}
Wait;
Death:

View file

@ -92,6 +92,7 @@ Class QCasing : UCasing
Class QuadshotTracer : LineTracer
{
Actor ignoreme;
Array<Line> ShootThroughList;
Array<HitListEntry> hitlist;
override ETraceStatus TraceCallback()
@ -123,6 +124,7 @@ Class QuadshotTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -184,8 +186,16 @@ Class QuadShot : UnrealWeapon
return ClipOut?-1:ClipCount, -1, (ClipCount<2), false;
}
action void ProcessTraceHit( QuadshotTracer t )
action void ProcessTraceHit( QuadshotTracer t, Vector3 origin, Vector3 dir, int bc = 1 )
{
for ( int i=0; i<invoker.t.ShootThroughList.Size(); i++ )
invoker.t.ShootThroughList[i].Activate(self,0,SPAC_PCross);
for ( int i=5; i<invoker.t.Results.Distance; i+=10 )
{
if ( !Random[Boolet](0,4*bc) ) continue;
let b = Actor.Spawn("UTBubble",level.Vec3Offset(origin,dir*i));
b.Scale *= FRandom[Boolet](0.4,0.6);
}
for ( int i=0; i<t.HitList.Size(); i++ )
{
int dmg = 12;
@ -258,7 +268,7 @@ Class QuadShot : UnrealWeapon
for ( int i=0; i<invoker.clipcount; i++ )
{
for ( int i=0; i<3; i++ )
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,4),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](3,4),SWING_Spring,Random[Quadshot](1,6),FRandom[Quadshot](0.8,1.4));
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](6,8),FRandom[Quadshot](-1.,-1.5),Random[Quadshot](6,8),SWING_Spring,0,FRandom[Quadshot](1.8,2.4));
for ( int i=0; i<10; i++ )
{
a = FRandom[Quadshot](0,360);
@ -267,8 +277,9 @@ Class QuadShot : UnrealWeapon
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,CurSector,dir,10000,0);
ProcessTraceHit(invoker.t);
ProcessTraceHit(invoker.t,origin,dir,int(spread));
}
}
vel += (0,0,(0.3+0.3*spread))-x*(1.5+1.1*spread);
@ -279,7 +290,7 @@ Class QuadShot : UnrealWeapon
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
A_PlaySound("quadshot/fire",CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
for ( int i=0; i<3; i++ )
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](2,3),FRandom[Quadshot](-0.2,0.5),Random[Quadshot](2,3),SWING_Spring,Random[Quadshot](0,3),FRandom[Quadshot](0.8,1.4));
UTMainHandler.DoSwing(self,(FRandom[Quadshot](-0.04,-0.2),FRandom[Quadshot](-0.2,0.2)),FRandom[Quadshot](5,7),FRandom[Quadshot](-1,-1.5),Random[Quadshot](3,6),SWING_Spring,0,FRandom[Quadshot](1.8,2.4));
for ( int i=0; i<10; i++ )
{
a = FRandom[Quadshot](0,360);
@ -288,8 +299,9 @@ Class QuadShot : UnrealWeapon
if ( !invoker.t ) invoker.t = new("QuadshotTracer");
invoker.t.ignoreme = self;
invoker.t.hitlist.Clear();
invoker.t.ShootThroughList.Clear();
invoker.t.Trace(origin,CurSector,dir,10000,0);
ProcessTraceHit(invoker.t);
ProcessTraceHit(invoker.t,origin,dir);
}
vel += (0,0,0.3)-x*1.5;
invoker.clipcount--;

View file

@ -146,7 +146,9 @@ Class URifle : UnrealWeapon
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x);
if ( !zoomed ) origin = level.Vec3Offset(origin,y*3-z*2);
FLineTraceData d;
LineTrace(angle,10000,BulletSlope(),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
double pt = BulletSlope();
LineTrace(angle,10000,pt,TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,(cos(angle)*cos(pt),sin(angle)*cos(pt),-sin(pt)),10000,alt?3:1);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 45;

View file

@ -275,7 +275,7 @@ Class TarydiumDebuff : Thinker
{
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 = int(amount); // in Unreal this was capped to 10, which would make it deal barely any damage
b.special1 = int(min(amount,100)); // 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
}

View file

@ -18,7 +18,13 @@ Class StunnerAmmo : Ammo
if ( rechargephase < 7 ) return;
rechargespeed = max(2.,.2*Amount);
rechargephase = 0;
Amount = min(Amount+1,MaxAmount);
if ( Amount >= MaxAmount ) return;
let sting = Owner.FindInventory("StingerAmmo");
if ( sting && (sting.Amount > 0) )
{
sting.Amount--;
Amount++;
}
}
override bool TryPickup( in out Actor toucher )
{
@ -72,6 +78,7 @@ Class StunLight : PaletteLight
Class StunTracer : LineTracer
{
Actor owner, ignore;
Array<Line> ShootThroughList;
override ETraceStatus TraceCallback()
{
@ -85,6 +92,7 @@ Class StunTracer : LineTracer
{
if ( !Results.HitLine.sidedef[1] || (Results.HitLine.Flags&(Line.ML_BlockHitscan|Line.ML_BlockEverything)) )
return TRACE_Stop;
ShootThroughList.Push(Results.HitLine);
return TRACE_Skip;
}
return TRACE_Stop;
@ -117,7 +125,10 @@ Class StunProj : Actor
}
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.ShootThroughList.Clear();
t.Trace(pos,cursector,tracedir,500,0);
for ( int i=0; i<t.ShootThroughList.Size(); i++ )
t.ShootThroughList[i].Activate(target,0,SPAC_PCross);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )

View file

@ -65,19 +65,20 @@ Class AsbestosSuit : UnrealArmor
Inventory.PickupSound "misc/suit";
Inventory.Icon "I_Suit";
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( (damageType == 'Fire') || (damageType == 'Ice') ) damage = newdamage = 0;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( passive && (Amount > 0) && ((damageType == 'Fire') || (damageType == 'Ice')) )
newdamage = 0;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("ToxinSuit");
if ( i ) other.RemoveInventory(i);
i = other.FindInventory("KevlarSuit");
if ( i ) other.RemoveInventory(i);
Super.AttachToOwner(other);
}
States
{
@ -101,14 +102,15 @@ Class ToxinSuit : UnrealArmor
Inventory.PickupSound "misc/suit";
Inventory.Icon "I_TSuit";
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
override void ModifyDamage( int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags )
{
if ( damageType == 'Slime' ) damage = newdamage = 0;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( passive && (Amount > 0) && ((damageType == 'Slime') || (damageType == 'Poison')) )
newdamage = 0;
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("AsbestosSuit");
if ( i ) other.RemoveInventory(i);
@ -140,6 +142,7 @@ Class KevlarSuit : UnrealArmor
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
if ( sting_allsuits ) return;
// remove other suits
Inventory i = other.FindInventory("AsbestosSuit");
if ( i ) other.RemoveInventory(i);
@ -163,9 +166,13 @@ Class ShieldBelt : UnrealArmor
Owner.A_PlaySound("belt/absorb",CHAN_7);
UTMainHandler.DoFlash(Owner,Color(80,255,224,0),5);
}
int oldamt = amount;
Super.AbsorbDamage(damage,damageType,newdamage);
if ( (oldamt > 0) && (amount <= 0) && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_SHIELDBELT"));
}
override void DepleteOrDestroy()
{
if ( (amount <= 0) && Owner.CheckLocalView() )
Console.Printf(StringTable.Localize("$D_SHIELDBELT"));
Super.DepleteOrDestroy();
}
Default
{
@ -202,11 +209,16 @@ Class PowerShield : UnrealArmor
Owner.A_PlaySound("belt/absorb",CHAN_7);
UTMainHandler.DoFlash(Owner,Color(80,224,0,255),5);
gothit = true;
damage = 0;
newdamage = 0;
}
int oldamt = amount;
amount = int.max; // blocks all damage
Super.AbsorbDamage(damage,damageType,newdamage);
amount = oldamt; // does not drain here
if ( damage > 0 ) newdamage = ApplyDamageFactors(GetClass(),damageType,damage,damage);
}
override void DepleteOrDestroy()
{
if ( (amount <= 0) && Owner.CheckLocalView() )
Console.Printf(StringTable.Localize("$D_POWERSHIELD"));
Super.DepleteOrDestroy();
}
override void Tick()
{
@ -218,11 +230,7 @@ Class PowerShield : UnrealArmor
gothit = false;
}
if ( !(level.maptime%15) && !sting_pshield ) amount--;
if ( amount <= 0 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_POWERSHIELD"));
DepleteOrDestroy();
}
if ( amount <= 0 ) DepleteOrDestroy();
}
Default
{

View file

@ -93,6 +93,7 @@ Class URocket : Actor
{
Vector3 InitialDir, Acceleration;
int ticcnt;
bool ringex;
Default
{
Obituary "$O_EIGHTBALL";
@ -152,6 +153,39 @@ Class URocket : Actor
s.vel = pvel;
s.scale *= FRandom[Eightball](0.9,2.7);
}
if ( !invoker.ringex ) return;
Actor r = Spawn("ASMDSBeamRing",pos);
Vector3 HitNormal = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
if ( BlockingLine ) HitNormal = (-BlockingLine.delta.y,BlockingLine.delta.x,0).unit();
else if ( BlockingFloor )
{
// find closest 3d floor for its normal
F3DFloor ff = null;
for ( int i=0; i<BlockingFloor.Get3DFloorCount(); i++ )
{
if ( !(BlockingFloor.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = BlockingFloor.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.top.Normal;
else HitNormal = BlockingFloor.floorplane.Normal;
r.SetOrigin(r.Vec3Offset(0,0,2),false);
}
else if ( BlockingCeiling )
{
// find closest 3d floor for its normal
F3DFloor ff = null;
for ( int i=0; i<BlockingCeiling.Get3DFloorCount(); i++ )
{
if ( !(BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(pos.xy) ~== ceilingz) ) continue;
ff = BlockingCeiling.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.bottom.Normal;
else HitNormal = BlockingCeiling.ceilingplane.Normal;
}
r.angle = atan2(HitNormal.y,HitNormal.x);
r.pitch = asin(-HitNormal.z);
}
action void A_RocketSeek()
{
@ -426,6 +460,8 @@ Class Eightball : UnrealWeapon
p.target = self;
p.tracer = invoker.LockedTarget;
a += step;
if ( !invoker.LockedTarget && (i==0) )
URocket(p).ringex = true;
}
}
else

View file

@ -47,12 +47,12 @@ Class UMinigun : UnrealWeapon
if ( alt )
{
A_QuakeEx(2,2,2,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.12);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.5,0,1,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.5,0,2,SWING_Spring,0,3);
}
else
{
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.3,0,1,SWING_Spring,0,3);
UTMainHandler.DoSwing(self,(FRandom[Minigun](-1,1),FRandom[Minigun](-1,1)),0.3,0,2,SWING_Spring,0,3);
}
let l = Spawn("MinigunLight",pos);
l.target = self;
@ -65,6 +65,7 @@ Class UMinigun : UnrealWeapon
Vector3 dir = (x2+y2*cos(a)*s+z2*sin(a)*s).unit();
FLineTraceData d;
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
UTBulletTrail.DoTrail(self,origin,dir,10000,alt?5:3);
if ( d.HitType == TRACE_HitActor )
{
int dmg = Random[Minigun](8,14); // fun fact: the Minigun is one of the few weapons that has actual RNG damage in Unreal
@ -183,7 +184,8 @@ Class UMinigun : UnrealWeapon
let weap = Weapon(invoker);
if ( !(player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK)) || (weap.Ammo1.Amount <= 0) )
{
player.SetPSprite(PSP_WEAPON,invoker.FindState("Release"));
A_StopSound(CHAN_WEAPON);
if ( Health > 0 ) player.SetPSprite(PSP_WEAPON,invoker.FindState("Release"));
return ResolveState("Null");
}
return ResolveState(null);

View file

@ -663,7 +663,7 @@ Class UnrealInventory : Inventory
{
Charge -= val;
if ( Charge > 0 ) return false;
if ( Amount > 1 )
if ( Amount >= 1 )
{
Amount--;
Charge = DefaultCharge;
@ -731,9 +731,15 @@ Class UnrealInventory : Inventory
}
override void DetachFromOwner()
{
Super.DetachFromOwner();
// deactivate
bActive = false;
Super.DetachFromOwner();
}
override void OwnerDied()
{
// deactivate
bActive = false;
Super.OwnerDied();
}
override void OnDrop( Actor dropper )
{

View file

@ -46,10 +46,15 @@ Class UInvisibility : UnrealInventory
DepleteOrDestroy();
}
}
override void OnDrop( Actor dropper )
override void DetachFromOwner()
{
Super.OnDrop(dropper);
dropper.TakeInventory("PowerUInvisibility",1);
Owner.TakeInventory("PowerUInvisibility",1);
Super.DetachFromOwner();
}
override void OwnerDied()
{
Owner.TakeInventory("PowerUInvisibility",1);
Super.OwnerDied();
}
override void PostBeginPlay()
{

View file

@ -120,6 +120,8 @@ Class UTranslocatorModule : Actor
{
SetOrigin(tracer.Vec2OffsetZ(0,0,pos.z),false);
vel.xy *= 0;
tracer = null;
bHITTRACER = false;
}
}
Stop;