Oh boy, here comes another big one.

Notable changes since last commit are the full implementation of the automag and asmd.
Also the Translator is now fully functional.
Fonts have been restructured to a neater format.
There have also been other random changes I don't have the time to document in detail.
This commit is contained in:
Marisa the Magician 2019-08-31 03:14:20 +02:00
commit 01249eb43f
1892 changed files with 5151 additions and 416 deletions

View file

@ -104,12 +104,538 @@ Class ASMDAmmo2 : ASMDAmmo
}
}
Class ASMD : UTWeapon
Class ASMDLight : EnforcerLight
{
override void PlayUpSound( Actor origin )
Default
{
origin.A_PlaySound(upsound,CHAN_WEAPON,Dampener.Active(origin)?.1:1.);
Args 64,32,255,70;
}
}
Class ASMDBeamRing : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
Radius 0.1;
Height 0;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() ) return;
A_FadeOut(0.05,0);
}
States
{
Spawn:
RNGX ABCDEF 4 Bright;
Stop;
}
}
Class ASMDSBeamRing : ASMDBeamRing {}
Class ASMDBlastRing : ASMDBeamRing
{
override void Tick()
{
Actor.Tick();
if ( isFrozen() ) return;
A_FadeOut(0.028,0);
}
States
{
Spawn:
RNGX ABCDEF 7 Bright;
Stop;
}
}
Class ASMDRingTrail : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+INTERPOLATEANGLES;
Radius 0.1;
Height 0;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() ) return;
A_FadeOut(0.05,0);
}
States
{
Spawn:
RNGX ABCDEF 4 Bright;
Stop;
}
}
Class ASMDBeamLight : PaletteLight
{
Default
{
Tag "Blue2";
Args 0,0,0,50;
ReactionTime 30;
}
}
Class ASMDSBeamLight : PaletteLight
{
Default
{
Tag "Ampd";
Args 0,0,0,50;
ReactionTime 30;
}
}
Class ASMDBlastLight : PaletteLight
{
Default
{
Tag "Purple";
ReactionTime 40;
Args 0,0,0,300;
}
}
Class ASMDSpark : Actor
{
Default
{
RenderStyle "Add";
Radius 2;
Height 2;
+NOBLOCKMAP;
+NOGRAVITY;
+MISSILE;
+FORCEXYBILLBOARD;
+THRUACTORS;
+ROLLSPRITE;
+ROLLCENTER;
+NOTELEPORT;
+DONTSPLASH;
+CANBOUNCEWATER;
-BOUNCEAUTOOFF;
BounceType "Hexen";
BounceFactor 1.0;
WallBounceFactor 1.0;
Scale 0.1;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
roll = FRandom[ASMD](0,360);
}
States
{
Spawn:
AFLA A 1 Bright
{
A_FadeOut(FRandom[ASMD](0.0,0.1));
vel *= 0.98;
}
Wait;
}
}
Class ViewASMDSpark : ShockSpark
{
Vector3 ofs, vvel;
override void PostBeginPlay()
{
Actor.PostBeginPlay();
scale *= FRandom[Puff](0.4,0.9);
alpha *= FRandom[Puff](0.5,2.0);
roll = FRandom[ASMD](0,360);
}
override void Tick()
{
Actor.Tick();
if ( !target || !target.player )
{
Destroy();
return;
}
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(target.pitch,target.angle,target.roll);
Vector3 origin = x*ofs.x+y*ofs.y+z*ofs.z+(0,0,target.player.viewz);
SetOrigin(target.Vec2OffsetZ(origin.x,origin.y,origin.z),true);
bInvisible = (players[consoleplayer].camera != target);
if ( isFrozen() ) return;
ofs += vvel;
vvel *= 0.9;
scale *= 0.8;
if ( scale.x <= 0.01 ) Destroy();
}
States
{
Spawn:
AFLA A 1 Bright A_FadeOut(FRandom[ASMD](0.0,0.1));
Wait;
}
}
Class ASMDHitbox : ShockHitbox
{
Default
{
Health 1;
+SHOOTABLE;
+NOBLOOD;
}
override void Die( Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath )
{
if ( target && target.InStateSequence(target.CurState,target.FindState("Spawn")) )
{
target.bAMBUSH = true;
target.ExplodeMissile();
}
Super.Die(source,inflictor,dmgflags,MeansOfDeath);
}
}
Class ASMDBall : Actor
{
Actor b;
double mult;
double startangle, startpitch;
override int SpecialMissileHit( Actor victim )
{
if ( victim == b ) return 1;
return -1;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
b = Spawn("ASMDHitbox",pos);
b.target = self;
startpitch = pitch;
startangle = angle;
}
action void A_BallExplode()
{
if ( bAMBUSH ) return;
pitch = invoker.startpitch;
angle = invoker.startangle;
roll = 0;
UTMainHandler.DoBlast(self,70,70000);
int dmg = int(55*(1+invoker.mult));
A_Explode(dmg,70);
A_SprayDecal("ShockMarkBig",16);
Actor r;
if ( dmg > 60 )
{
SetStateLabel("AmpDeath");
A_SetScale(0.7);
let l = Spawn("ASMDSBeamLight",pos);
l.Args[3] = 120;
r = Spawn("ASMDSBeamRing",pos);
}
else
{
A_SetScale(1.3);
let l = Spawn("ASMDBeamLight",pos);
l.Args[3] = 120;
r = Spawn("ASMDBeamRing",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 )
{
HitNormal = BlockingFloor.floorplane.Normal;
r.SetOrigin(r.Vec3Offset(0,0,2),false);
}
else if ( BlockingCeiling ) HitNormal = BlockingCeiling.ceilingplane.Normal;
r.angle = atan2(HitNormal.y,HitNormal.x);
r.pitch = asin(-HitNormal.z);
r.scale *= 1.5;
A_PlaySound("shock/hit",CHAN_VOICE);
A_PlaySound("shock/ball",CHAN_WEAPON,pitch:FRandom[ASMD](0.5,1.5));
A_QuakeEx(4,4,4,30,0,200,"",QF_RELATIVE|QF_SCALEDOWN,falloff:70,rollIntensity:0.15);
A_AlertMonsters();
int numpt = Random[ASMD](50,100);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](2,6);
let s = Spawn("ASMDSpark",pos);
s.vel = pvel;
}
}
action void A_BallSpin()
{
for ( int i=0; i<6; i++ )
{
Vector3 x, y, z;
[x,y,z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
double a = FRandom[ASMD](0,360), s = FRandom[ASMD](0,0.15);
Vector3 dir;
switch (i)
{
case 0:
dir = (x+y*cos(a)*s+z*sin(a)*s).unit();
break;
case 1:
dir = (y+x*cos(a)*s+z*sin(a)*s).unit();
break;
case 2:
dir = (-x+y*cos(a)*s+z*sin(a)*s).unit();
break;
case 3:
dir = (-y+x*cos(a)*s+z*sin(a)*s).unit();
break;
case 4:
dir = (z+x*cos(a)*s+y*sin(a)*s).unit();
break;
case 5:
dir = (-z+x*cos(a)*s+y*sin(a)*s).unit();
break;
}
let p = Spawn("ASMDSpark",level.Vec3Offset(pos,-vel));
p.vel = vel*0.5+dir*FRandom[ASMD](1,3);
}
pitch += 7.12;
angle += 5.25;
roll += 9.96;
}
Default
{
Obituary "$O_ASMD";
RenderStyle "Add";
DamageType 'jolted';
Radius 4;
Height 4;
Speed 20;
PROJECTILE;
+FORCEXYBILLBOARD;
+SKYEXPLODE;
+EXPLODEONWATER;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+INTERPOLATEANGLES;
}
States
{
Spawn:
TAZB A 1 Bright A_BallSpin();
Wait;
Death:
TNT1 A 0 A_BallExplode();
AEXP ABCDEF 3 Bright;
Stop;
AmpDeath:
SSMX ABCDEFGHIJ 2 Bright;
Stop;
SuperDeath:
PSMX ABCDEFGHIJ 2 Bright;
Stop;
}
}
Class ASMDBeam : Actor
{
ShockBeamTracer t;
Vector3 tracedir;
bool moving;
double totaldist;
Default
{
Obituary "$O_ASMD";
DamageType 'jolted';
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 1.8;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+NOTELEPORT;
+FORCEXYBILLBOARD;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
t = new("ShockBeamTracer");
t.owner = target;
t.ignore = self;
moving = true;
}
override void Tick()
{
Super.Tick();
if ( isFrozen() || !moving ) return;
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
t.Trace(pos,cursector,tracedir,1000,0);
totaldist += t.Results.Distance;
// spawn particles
for ( int i=10; i<t.Results.Distance; i+=80 )
Spawn("ASMDBeamLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
for ( int i=0; i<t.Results.Distance; i+=4 )
{
Vector3 pofs = tracedir*FRandom[ASMD](0,2)+(FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5),FRandom[ASMD](-.5,.5));
let s = Spawn("ASMDSpark",Vec3Offset(tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z));
s.scale *= 0.2;
s.vel = (FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3),FRandom[ASMD](-.3,.3));
}
for ( int i=10; i<t.Results.Distance; i+=20 )
{
let s = Spawn("ASMDRingTrail",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
s.angle = angle;
s.pitch = pitch;
}
if ( totaldist >= 10000.0 )
{
// reposition and explode on air
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
double mult = Amplifier.GetMult(target,100);
BeamExplode(mult>1.5);
Actor r;
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
else r = Spawn("ASMDBeamRing",pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
}
else if ( t.Results.HitType == TRACE_HitNone )
{
// reposition
SetOrigin(t.Results.HitPos+t.Results.HitVector,false);
angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
pitch = asin(-t.Results.HitVector.z);
}
else if ( t.Results.HitType == TRACE_HitActor )
{
// reposition and explode on actor
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
double mult = Amplifier.GetMult(target,100);
Actor r;
if ( t.Results.HitActor is 'ASMDHitbox' )
{
BeamExplode(true);
if ( target )
{
target.TakeInventory('ASMDAmmo',2);
UTMainHandler.DoSwing(target,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),10,-2,3,SWING_Spring,3,6);
}
let b = t.Results.HitActor.target;
b.pitch = 90;
b.angle = 0;
b.roll = 0;
UTMainHandler.DoBlast(b,240,140000);
b.A_Explode(int(55*3.9*mult),240);
b.A_SprayDecal("BigShockMark1",100);
b.A_SprayDecal("SBigShockMark2",100);
b.SetStateLabel("SuperDeath");
b.A_SetScale(1.8);
let l = Spawn("ASMDBlastLight",pos);
let r = Spawn("ASMDBlastRing",b.pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
A_PlaySound("shock/blast",CHAN_WEAPON,attenuation:0.5,pitch:0.6);
int numpt = Random[ASMD](200,300);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](1,32);
let s = Spawn("ASMDSpark",b.pos);
s.vel = pvel;
}
}
else
{
BeamExplode(mult>1.5);
t.Results.HitActor.DamageMobj(self,target,int(35*mult),'jolted',DMG_USEANGLE,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
UTMainHandler.DoKnockback(t.Results.HitActor,t.Results.HitVector,60000);
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
else r = Spawn("ASMDBeamRing",pos);
r.angle = atan2(t.Results.HitVector.y,t.Results.HitVector.x);
r.pitch = asin(-t.Results.HitVector.z);
}
}
else
{
// reposition and explode on wall
SetOrigin(t.Results.HitPos-t.Results.HitVector*4,false);
A_SprayDecal("ShockMark",16);
moving = false;
Vector3 HitNormal = t.Results.HitVector;
if ( t.Results.HitType == TRACE_HitWall )
{
t.Results.HitLine.RemoteActivate(target,t.Results.Side,SPAC_Impact,pos);
// calculate normal
HitNormal = (-t.Results.HitLine.delta.y,t.Results.HitLine.delta.x,0).unit();
if ( t.Results.Side == 0 ) HitNormal *= -1;
}
else if ( t.Results.HitType == TRACE_HitFloor )
HitNormal = t.Results.HitSector.floorplane.Normal;
else if ( t.Results.HitType == TRACE_HitCeiling )
HitNormal = t.Results.HitSector.ceilingplane.Normal;
double mult = Amplifier.GetMult(target,100);
BeamExplode(mult>1.5);
Actor r;
if ( mult > 1.5 ) r = Spawn("ASMDSBeamRing",pos);
else r = Spawn("ASMDBeamRing",pos);
r.angle = atan2(HitNormal.y,HitNormal.x);
r.pitch = asin(-HitNormal.z);
}
}
void BeamExplode( bool amped = false )
{
moving = false;
if ( amped )
{
Scale *= 0.3;
SetStateLabel("AmpExplode");
Spawn("ASMDSBeamLight",pos);
}
else
{
SetStateLabel("Explode");
Spawn("ASMDBeamLight",pos);
}
A_QuakeEx(2,2,2,5,0,120,"",QF_RELATIVE|QF_SCALEDOWN,falloff:60,rollIntensity:0.1);
A_PlaySound("shock/hit",CHAN_VOICE);
A_AlertMonsters();
int numpt = Random[ASMD](20,50);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](2,6);
let s = Spawn("ASMDSpark",pos);
s.vel = pvel;
}
}
States
{
Spawn:
TNT1 A -1;
Stop;
Explode:
AEXP ABCDEF 3 Bright;
Stop;
AmpExplode:
SSMX ABCDEFGHIJ 2 Bright;
Stop;
}
}
Class ASMD : UnrealWeapon
{
action void A_ShockFire()
{
Weapon weap = Weapon(invoker);
@ -118,10 +644,28 @@ Class ASMD : UTWeapon
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/fire",CHAN_WEAPON,Dampener.Active(self)?.2:1.);
invoker.FireEffect();
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
UTMainHandler.DoSwing(self,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),2,-0.3,3,SWING_Spring,0,4);
if ( !Dampener.Active(self) ) A_AlertMonsters();A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10*x+2.9*y-2.5*z;
Actor p = Spawn("ASMDBeam",origin);
p.angle = angle;
p.pitch = BulletSlope();
p.target = self;
int numpt = Random[ASMD](20,40);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("ViewASMDSpark",origin);
ViewASMDSpark(s).ofs = (10,2.9,-2.5);
s.target = self;
ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
}
}
action void A_ShockAlt()
{
@ -130,11 +674,32 @@ Class ASMD : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/altfire",CHAN_WEAPON,Dampener.Active(self)?.2:1.);
double mult = Amplifier.GetMult(self,80);
invoker.FireEffect();
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
UTMainHandler.DoFlash(self,Color(80,64,32,255),1);
UTMainHandler.DoSwing(self,(FRandom[ASMD](-0.1,-0.6),FRandom[ASMD](-0.1,0.5)),3,-0.4,3,SWING_Spring,0,4);
if ( !Dampener.Active(self) ) A_AlertMonsters();A_AlertMonsters();
A_QuakeEx(2,2,2,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(1,1,1,8,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10*x+2.9*y-2.5*z;
Actor p = Spawn("ASMDBall",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;
ASMDBall(p).mult = mult-1;
int numpt = Random[ASMD](20,40);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("ViewASMDSpark",origin);
ViewASMDSpark(s).ofs = (10,2.9,-2.5);
s.target = self;
ViewASMDSpark(s).vvel += (FRandom[ASMD](0.5,2.0),FRandom[ASMD](-1.5,1.5),FRandom[ASMD](-1.5,1.5));
}
}
Default
{
@ -168,13 +733,13 @@ Class ASMD : UTWeapon
{
A_CheckReload();
A_WeaponReady();
// that's a mouthful
// that's a long-ass if
if ( player.FindPSprite(PSP_WEAPON).CurState.InStateSequence(invoker.FindState("Idle")) && (player.cmd.forwardmove || player.cmd.sidemove) && (player.vel.length() > 0.5) )
player.SetPSPrite(PSP_WEAPON,invoker.FindState("Sway"));
}
Wait;
Vapour:
#### # 2 A_Overlay(-9999,"Dummy");
#### # 8 A_Overlay(-9999,"Dummy");
ASMI A 6
{
A_PlaySound("asmd/vapour",CHAN_6,0.5);
@ -213,10 +778,8 @@ Class ASMD : UTWeapon
A_ShockFire();
A_Overlay(-9999,"Null");
}
ASMF ABCDEFGH 2;
ASMF I 5;
ASMI A 0 A_Refire();
ASMI A 0 A_Jump(48,"Vapour");
ASMF ABCDEFGH 3;
ASMF H 0 A_Jump(48,"Vapour");
Goto Idle;
AltFire:
#### # 1
@ -224,10 +787,8 @@ Class ASMD : UTWeapon
A_ShockAlt();
A_Overlay(-9999,"Null");
}
ASMA ABCDFGHI 2;
ASMA J 1;
ASMA J 0 A_Refire();
ASMI A 0 A_Jump(48,"Vapour");
ASMA ABCDFGHIJ 2;
ASMA J 0 A_Jump(48,"Vapour");
Goto Idle;
Deselect:
ASMD A 1 A_Overlay(-9999,"Null");
@ -237,5 +798,12 @@ Class ASMD : UTWeapon
Select:
ASMS A 1 A_Raise(int.max);
Wait;
Flash:
ASFF A 2 Bright
{
let l = Spawn("ASMDLight",pos);
l.target = self;
}
Stop;
}
}

View file

@ -1,7 +1,563 @@
Class UClip : UMiniAmmo
{
Default
{
Tag "$T_CLIP";
Inventory.PickupMessage "$I_CLIP";
Inventory.Amount 20;
Ammo.DropAmount 5;
}
States
{
Spawn:
UCLP A -1;
Stop;
}
}
Class UCasing : UTCasing
{
}
Class Automag : UTWeapon
Class Automag : UnrealWeapon
{
int ClipCount, SlaveClipCount;
bool SlaveActive, SlaveDown, SlaveReload, SlaveAltFire, SlaveSpin;
int SlaveRefire;
double AltAccuracy;
property ClipCount : ClipCount;
property SlaveClipCount : SlaveClipCount;
override bool HandlePickup( Inventory item )
{
if ( sting_automags && (item.GetClass() == GetClass()) )
{
SetTag(StringTable.Localize("$T_AUTOMAG2"));
return Super.HandlePickup(item);
}
return Super.HandlePickup(item);
}
override Inventory CreateTossable( int amt )
{
Inventory inv = Super.CreateTossable(amt);
if ( inv )
{
SetTag(StringTable.Localize("$T_AUTOMAG"));
inv.SetTag(StringTable.Localize("$T_AUTOMAG"));
if ( Owner && (Owner.player.ReadyWeapon == self) )
{
// delete the slave overlay
PSprite psp;
for ( psp = Owner.player.psprites; psp; psp = psp.next )
{
if ( (psp.Caller == self) && ((psp.id == 2) || (psp.id == -9998)) ) psp.Destroy();
slaveactive = false;
slavedown = false;
}
}
}
return inv;
}
action void A_AutomagRefire( statelabel flash = null, bool slave = false )
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( invoker.altaccuracy < 0.2 ) invoker.altaccuracy += 0.05;
if ( slave )
{
if ( invoker.slaveclipcount < 5 ) A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.35);
if ( (invoker.slaveclipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
invoker.slaverefire = 0;
return;
}
bool pending = (player.PendingWeapon != WP_NOCHANGE) && (player.WeaponState & WF_REFIRESWITCHOK);
if ( (player.cmd.buttons&BT_ATTACK) && !invoker.slavealtfire && !pending && (player.health > 0) )
{
invoker.slaverefire++;
if ( player.ReadyWeapon.CheckAmmo(Weapon.PrimaryFire,true) )
player.setpsprite(2,flash?ResolveState(flash):ResolveState("LeftHold"));
}
else if ( (player.cmd.buttons&BT_ALTATTACK) && invoker.slavealtfire && !pending && (player.health > 0) )
{
invoker.slaverefire++;
if ( player.ReadyWeapon.CheckAmmo(Weapon.AltFire,true) )
player.setpsprite(2,flash?ResolveState(flash):ResolveState("LeftAltHold"));
}
else
{
invoker.slaverefire = 0;
player.ReadyWeapon.CheckAmmo(invoker.slavealtfire?Weapon.AltFire:Weapon.PrimaryFire,true);
}
}
else
{
if ( invoker.clipcount < 5 ) A_PlaySound("automag/click",CHAN_ITEM,!Dampener.Active(self)?1.:.35);
if ( (invoker.clipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
A_ClearRefire();
return;
}
A_Refire(flash);
}
}
action void A_LeftWeaponReady()
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( player.cmd.buttons&BT_ATTACK && !player.ReadyWeapon.bAltFire )
{
if ( (invoker.slaveclipcount <= 0) && (weap.Ammo1.Amount > 0) )
{
player.setpsprite(2,ResolveState("LeftReload"));
return;
}
invoker.slaverefire = 0;
invoker.slavealtfire = false;
player.setpsprite(2,ResolveState("LeftFire"));
}
else if ( player.cmd.buttons&BT_ALTATTACK && player.ReadyWeapon.bAltFire )
{
if ( (invoker.slaveclipcount <= 0) && (weap.Ammo1.Amount > 0) )
{
player.setpsprite(2,ResolveState("LeftReload"));
return;
}
invoker.slaverefire = 0;
invoker.slavealtfire = true;
player.setpsprite(2,ResolveState("LeftAltFire"));
}
}
action void A_AutomagFire( bool alt = false, bool slave = false )
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
if ( slave ) invoker.slaveclipcount--;
else invoker.clipcount--;
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,255,128,0),1);
A_PlaySound("automag/fire",slave?CHAN_6:CHAN_WEAPON,!Dampener.Active(self)?1.:.2);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.08);
if ( slave )
{
if ( alt ) A_Overlay(-3,"LeftAltMuzzleFlash");
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);
}
else
{
if ( alt ) A_Overlay(-2,"AltMuzzleFlash");
else A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
UTMainHandler.DoSwing(self,(FRandom[Automag](-0.2,-0.5),FRandom[Automag](-0.3,0.2)),2,0,1,SWING_Spring,0,2);
}
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = Vec2OffsetZ(0,0,player.viewz)+10.0*x;
int ydir = slave?-1:1;
if ( alt ) origin = origin-z*3.0+ydir*y*1.0;
else origin = origin-z*1.0+ydir*y*4.0;
double a = FRandom[Automag](0,360), s = FRandom[Automag](0,alt?invoker.altaccuracy:0.01);
[x2, y2, z2] = dt_CoordUtil.GetAxes(BulletSlope(),angle,roll);
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);
if ( d.HitType == TRACE_HitActor )
{
int dmg = 17;
dmg = d.HitActor.DamageMobj(invoker,self,dmg,'shot',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
double mm = 3000;
if ( FRandom[Automag](0,1) < 0.2 ) mm *= 5;
UTMainHandler.DoKnockback(d.HitActor,d.HitDir,mm);
if ( d.HitActor.bNOBLOOD )
{
let p = Spawn("BulletImpact",d.HitLocation);
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
p.pitch = asin(d.HitDir.z);
}
else
{
d.HitActor.TraceBleed(dmg,self);
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
}
}
else if ( d.HitType != TRACE_HitNone )
{
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor ) hitnormal = d.HitSector.floorplane.Normal;
else if ( d.HitType == TRACE_HitCeiling ) hitnormal = d.HitSector.ceilingplane.Normal;
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("BulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
}
for ( int i=0; i<3; i++ )
{
let s = Spawn("UTViewSmoke",origin);
if ( alt ) UTViewSmoke(s).ofs = (10,ydir,-3);
else UTViewSmoke(s).ofs = (10,4*ydir,-1);
s.target = self;
s.alpha *= 0.5;
}
origin += x*8.0+ydir*y*6.0-z*2.0;
let c = Spawn("UCasing",origin);
c.vel = x*FRandom[Junk](-1.5,1.5)+y*ydir*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
}
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
if ( Amount > 1 ) return StringTable.Localize("$O_AUTOMAG2");
return StringTable.Localize("$O_AUTOMAG");
}
override void Travelled()
{
Super.Travelled();
slaveactive = false;
}
override void OwnerDied()
{
Super.OwnerDied();
slaverefire = 0;
}
override void Tick()
{
Super.Tick();
if ( sting_automags && (MaxAmount <= 1) ) MaxAmount = 2;
else if ( !sting_automags && (MaxAmount > 1) ) MaxAmount = 1;
if ( !Owner || sting_automags || (Amount <= 1) ) return;
// no dual wielding
if ( Owner.player.ReadyWeapon == self )
{
// delete the slave overlay
PSprite psp;
for ( psp = Owner.player.psprites; psp; psp = psp.next )
{
if ( (psp.Caller == self) && ((psp.id == 2) || (psp.id == -9998)) ) psp.Destroy();
slaveactive = false;
slavedown = false;
}
}
Amount = 1;
}
Default
{
Tag "$T_AUTOMAG";
Inventory.Icon "I_ClipAm";
Inventory.PickupMessage "$I_AUTOMAG";
Inventory.MaxAmount 1;
Inventory.InterHubAmount 2;
Weapon.UpSound "automag/select";
Weapon.SlotNumber 2;
Weapon.SelectionOrder 2;
Weapon.AmmoType "UMiniAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "UMiniAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 30;
Weapon.Kickback 180;
UTWeapon.DropAmmo 10;
Automag.ClipCount 20;
Automag.SlaveClipCount 20;
}
States
{
Spawn:
AUTP A -1;
Stop;
AUTP B -1;
Stop;
Select:
AUTS A 1 A_Raise(int.max);
Ready:
AUTS A 0
{
invoker.slavedown = false;
if ( !invoker.slaveactive && (CountInv("Automag") > 1) )
A_Overlay(2,"LeftReady");
}
AUTS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_WeaponReady(WRF_NOFIRE);
AUS2 ABCD 1 A_WeaponReady(WRF_NOFIRE);
Idle:
AUTI A 0 A_Overlay(-9999,"Dummy");
AUTI AB 30;
AUTI A 0 A_Jump(50,"Twiddle");
Goto Idle+1;
LeftReady:
2UTS A 0
{
A_PlaySound("automag/select",CHAN_6,!Dampener.Active(self)?1.:.1);
invoker.slaveactive = true;
}
2UTS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1 A_JumpIf(invoker.slavedown,"LeftDeselect");
2US2 ABCD 1 A_JumpIf(invoker.slavedown,"LeftDeselect");
LeftIdle:
2UTI A 0 A_Overlay(-9998,"LeftDummy");
2UTI AB 30;
2UTI A 0 A_Jump(50,"LeftTwiddle");
Goto LeftIdle+1;
Twiddle:
AUTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto Idle+1;
LeftTwiddle:
2UTT ABCDEFGHIJKLMNOPQRSTUVWXY 2;
Goto LeftIdle+1;
Dummy:
TNT1 A 1
{
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) A_Overlay(PSP_WEAPON,"Reload");
else if ( ((invoker.clipcount < min(20,invoker.Ammo1.Amount)) || (invoker.slaveclipcount < min(20,invoker.Ammo1.Amount))) ) A_WeaponReady(WRF_ALLOWRELOAD|WRF_ALLOWZOOM);
else A_WeaponReady(WRF_ALLOWZOOM);
if ( !invoker.slaveactive && (CountInv("Automag") > 1) ) A_Overlay(2,"LeftReady");
}
Wait;
LeftDummy:
TNT1 A 1
{
if ( health <= 0 )
{
invoker.slaveactive = false;
A_Overlay(2,"LeftDeselect");
}
else if ( invoker.slavereload ) A_Overlay(2,"LeftReload");
else if ( invoker.slavedown ) A_Overlay(2,"LeftDeselect");
else if ( invoker.slavespin ) A_Overlay(2,"LeftZoom");
else A_LeftWeaponReady();
}
Wait;
Fire:
AUTF A 1 A_Overlay(-9999,null);
AUTF BCD 1;
Hold:
AUTF E 2 A_AutomagFire();
AUTF FG 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
AUTF H 2 A_AutomagFire();
AUTF IJ 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
AUTF K 2 A_AutomagFire();
AUTF LM 2;
AUTF N 0 A_AutomagRefire(1);
Goto Release;
AUTF NN 2;
Goto Hold;
Release:
AUTF NN 2;
AUTF OPQRST 1;
AUTI A 0;
Goto Idle;
LeftFire:
2UTI A 5 A_Overlay(-9998,null);
2UTI A 0 A_AutomagRefire(1,true);
Goto LeftIdle;
LeftHold:
2UTF ABCD 1;
2UTF E 2 A_AutomagFire(false,true);
2UTF FG 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
2UTF H 2 A_AutomagFire(false,true);
2UTF IJ 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
2UTF K 2 A_AutomagFire(false,true);
2UTF LM 2;
2UTF N 0 A_AutomagRefire(1,true);
Goto LeftRelease;
2UTF NN 2;
Goto LeftHold+4;
LeftRelease:
2UTF NN 2;
2UTF OPQRST 1;
2UTI A 0;
Goto LeftIdle;
AltFire:
AUTA A 0
{
invoker.altaccuracy = 0.08;
A_Overlay(-9999,null);
}
AUTA ABCDEFGHIJ 1;
AltHold:
AUTA K 2 A_AutomagFire(true);
AUTA LM 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
AUTA N 2 A_AutomagFire(true);
AUTA OP 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
AUTA Q 2 A_AutomagFire(true);
AUTA RS 2;
AUTA T 0 A_AutomagRefire(1);
Goto AltRelease;
AUTA T 1;
Goto AltHold;
AltRelease:
AUTA TUVWXYZ 1;
AUA2 ABCD 1;
Goto Idle;
LeftAltFire:
2UTI A 5 A_Overlay(-9998,null);
2UTI A 0 A_AutomagRefire(1,true);
LeftAltHold:
2UTA ABCDEFGHIJ 1;
2UTA K 2 A_AutomagFire(true,true);
2UTA LM 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
2UTA N 2 A_AutomagFire(true,true);
2UTA OP 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
2UTA Q 2 A_AutomagFire(true,true);
2UTA RS 2;
2UTA T 0 A_AutomagRefire(1,true);
Goto LeftAltRelease;
2UTA T 1;
Goto LeftAltHold+10;
LeftAltRelease:
2UTA TUVWXYZ 1;
2UA2 ABCD 1;
Goto LeftIdle;
Reload:
AUTR A 0
{
invoker.slavereload = ((player.cmd.buttons&BT_RELOAD)&&invoker.slaveactive&&(invoker.slaveclipcount < min(20,invoker.Ammo1.Amount)))||(invoker.slaveclipcount <= 0);
return A_JumpIf(invoker.clipcount>=min(20,invoker.Ammo1.Amount),"Idle");
}
AUTR A 0
{
invoker.clipcount = Min(20,invoker.Ammo1.Amount);
A_Overlay(-9999,null);
A_WeaponOffset(0,32); // fix sudden psprite lowering
A_PlaySound("automag/click",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
}
AUTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
AUTD ABCD 1;
AUTD E 30
{
A_PlaySound("automag/reload",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
if ( self is 'UTPlayer' )
UTPlayer(self).PlayReloading();
}
AUTS A 0 A_PlaySound("automag/select",CHAN_WEAPON,!Dampener.Active(self)?1.:.1);
Goto Ready;
LeftReload:
2UTR A 0
{
invoker.slaveclipcount = Min(20,invoker.Ammo1.Amount);
invoker.slavereload = false;
A_Overlay(-9998,null);
A_PlaySound("automag/click",CHAN_6,!Dampener.Active(self)?1.:.1);
}
2UTR ABCDEFGHIJKLMNOPQRSTUVWXY 1;
2UTD ABCD 1;
2UTD E 30
{
A_PlaySound("automag/reload",CHAN_6,!Dampener.Active(self)?1.:.1);
if ( self is 'UTPlayer' )
UTPlayer(self).PlayReloading();
}
2UTS A 0 A_PlaySound("automag/select",CHAN_6,!Dampener.Active(self)?1.:.1);
Goto LeftReady;
Zoom:
AUT2 A 1
{
A_Overlay(-9999,null);
invoker.slavespin = true;
}
AUT2 BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
AUT3 AB 1;
ZoomLoop:
AUT3 CDEFGH 1;
AUT3 I 0 A_JumpIf(player.cmd.buttons&BT_ZOOM,"ZoomLoop1");
AUT3 IJKLMNOPQRS 1;
Goto Idle;
ZoomLoop1:
AUT3 I 1;
AUT3 C 0;
Goto ZoomLoop;
LeftZoom:
2UT2 A 1
{
A_Overlay(-9998,null);
invoker.slavespin = false;
}
2UT2 BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
2UT3 AB 1;
LeftZoomLoop:
2UT3 CDEFGH 1;
2UT3 I 0 A_JumpIf(player.cmd.buttons&BT_ZOOM,"LeftZoomLoop1");
2UT3 IJKLMNOPQRS 1;
Goto LeftIdle;
LeftZoomLoop1:
2UT3 I 1;
2UT3 C 0;
Goto LeftZoomLoop;
Deselect:
AUTI A 1 { invoker.slavedown = true; }
AUTD A 0 A_Overlay(-9999,null);
AUTD A 0 A_JumpIf(invoker.slaveactive,"Deselect");
AUTD ABCD 1;
AUTD E 1 A_Lower(int.max);
Wait;
LeftDeselect:
2UTD A 0
{
A_Overlay(-9998,null);
invoker.slaveactive = false;
}
2UTD ABCD 1;
2UTD E 0;
Stop;
MuzzleFlash:
AMUZ A 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
AltMuzzleFlash:
AMUZ B 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftMuzzleFlash:
AMUZ C 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
LeftAltMuzzleFlash:
AMUZ D 2 Bright
{
let l = Spawn("EnforcerLight",pos);
l.target = self;
}
Stop;
}
}

View file

@ -1,3 +1,3 @@
Class Betamag : UTWeapon
Class Betamag : UnrealWeapon
{
}

View file

@ -6,6 +6,6 @@ Class BigAmmo2 : BigAmmo
{
}
Class BigGun : UTWeapon
Class BigGun : UnrealWeapon
{
}

View file

@ -1,3 +1,3 @@
Class Bonesaw : UTWeapon
Class Bonesaw : UnrealWeapon
{
}

View file

@ -1,11 +1,522 @@
Class WeaponPowerUp : Inventory
{
Default
{
Tag "$T_WPOWERUP";
Inventory.PickupMessage "$I_WPOWERUP";
Inventory.PickupSound "misc/p_pkup";
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
}
override bool TryPickup( in out Actor toucher )
{
if ( !toucher.FindInventory("DispersionPistol") ) return false;
let damo = DispersionAmmo(toucher.FindInventory("DispersionAmmo"));
if ( damo )
{
damo.BackpackMaxAmount = damo.MaxAmount = min(90,damo.MaxAmount+10);
damo.Amount = min(damo.MaxAmount,damo.Amount+10);
}
let dpis = DispersionPistol(toucher.FindInventory("DispersionPistol"));
if ( dpis && (dpis.upgradelevel < 4) )
{
if ( toucher.player && (toucher.player.ReadyWeapon == dpis) && (toucher.player.PendingWeapon == WP_NOCHANGE) )
{
dpis.upgradelevel++;
let psp = toucher.player.FindPSprite(PSP_Weapon);
psp.SetState(dpis.FindState("Upgrade"));
}
else
{
dpis.pendingupgrade = true;
ScriptUtil.SetWeapon(toucher,"DispersionPistol");
}
}
GoAwayAndDie();
return true;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("WeaponPowerUpX",pos);
tracer.angle = angle;
tracer.target = self;
}
States
{
Spawn:
WPOW A -1;
Stop;
}
}
Class WeaponPowerUpX : ASMDAmmoX
{
States
{
Spawn:
WPOW ABCDEFGHIJKLMNOPQRST 3 Bright;
Loop;
}
}
Class DispersionAmmo : Ammo
{
double rechargephase, rechargespeed;
Default
{
Inventory.Icon "I_Disper";
Inventory.Amount 10;
Inventory.MaxAmount 50;
Ammo.BackpackAmount 0;
Ammo.BackpackMaxAmount 50;
}
override void Tick()
{
Super.Tick();
if ( !Owner ) return;
if ( Amount < 10 ) rechargespeed = 1.1;
else rechargespeed = 0.11*Amount;
rechargephase += 1./rechargespeed;
if ( rechargephase < 35 ) return;
rechargephase = 0;
Amount = min(Amount+1,MaxAmount);
}
}
Class DispersionPistol : UTWeapon
Class DispLight1 : EnforcerLight
{
Default
{
args 96,64,255,80;
}
}
Class DispLight2 : EnforcerLight
{
Default
{
args 64,255,96,80;
}
}
Class DispLight3 : EnforcerLight
{
Default
{
args 255,255,96,80;
}
}
Class DispLight4 : EnforcerLight
{
Default
{
args 255,160,64,80;
}
}
Class DispLight5 : EnforcerLight
{
Default
{
args 255,96,64,80;
}
}
Class DispersionPistol : UnrealWeapon
{
int upgradelevel;
bool pendingupgrade;
double chargesize, count;
bool bCharging;
override void Tick()
{
Super.Tick();
if ( sting_dpistol ) AmmoUse2 = 1;
else AmmoUse2 = AmmoUse1/2;
}
action void A_DispFire()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
DispersionAmmo(weap.Ammo1).rechargephase = 0;
A_PlaySound("dpistol/fire",CHAN_WEAPON,Dampener.Active(self)?.4:1.,pitch:1.2);
double mult = Amplifier.GetMult(self,80);
invoker.FireEffect();
switch ( invoker.upgradelevel )
{
case 0:
UTMainHandler.DoFlash(self,Color(80,96,64,255),1);
A_Overlay(PSP_FLASH,"Flash1");
break;
case 1:
UTMainHandler.DoFlash(self,Color(80,64,255,96),1);
A_Overlay(PSP_FLASH,"Flash2");
break;
case 2:
UTMainHandler.DoFlash(self,Color(80,255,255,96),1);
A_Overlay(PSP_FLASH,"Flash3");
break;
case 3:
UTMainHandler.DoFlash(self,Color(80,255,160,64),1);
A_Overlay(PSP_FLASH,"Flash4");
break;
default:
UTMainHandler.DoFlash(self,Color(80,255,96,64),1);
A_Overlay(PSP_FLASH,"Flash5");
break;
}
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);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(2,2,2,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
}
action void A_DispAltFire()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
A_WeaponOffset(0,32);
invoker.bCharging = false;
if ( self is 'UTPlayer' )
UTPlayer(self).PlayAttacking();
DispersionAmmo(weap.Ammo1).rechargephase = 0;
A_PlaySound("dpistol/fire",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;
switch ( ulevel )
{
case 0:
UTMainHandler.DoFlash(self,Color(80,96,64,255),1);
A_Overlay(PSP_FLASH,"Flash1");
break;
case 1:
UTMainHandler.DoFlash(self,Color(80,64,255,96),1);
A_Overlay(PSP_FLASH,"Flash2");
break;
case 2:
UTMainHandler.DoFlash(self,Color(80,255,255,96),1);
A_Overlay(PSP_FLASH,"Flash3");
break;
case 3:
UTMainHandler.DoFlash(self,Color(80,255,160,64),1);
A_Overlay(PSP_FLASH,"Flash4");
break;
default:
UTMainHandler.DoFlash(self,Color(80,255,96,64),1);
A_Overlay(PSP_FLASH,"Flash5");
break;
}
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);
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);
}
action bool A_DispCharge()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return false;
DispersionAmmo(weap.Ammo1).rechargephase = 0;
UTMainHandler.DoSwing(self,(FRandom[DPistol](-1,1),FRandom[DPistol](-1,1)),0.02*invoker.chargesize,0,2,SWING_Spring);
A_WeaponOffset(FRandom[DPistol](-1,1)*1.2*invoker.chargesize,32+FRandom[DPistol](-1,1)*1.2*invoker.chargesize);
if ( !Dampener.Active(self) ) A_AlertMonsters();
invoker.chargesize += (2.-invoker.upgradelevel*0.15)/35.;
invoker.count += 1./35.;
if ( invoker.count < 0.3 ) return false;
invoker.count = 0;
weap.DepleteAmmo(weap.bAltFire,true,1);
if ( (weap.Ammo1.Amount <= 0) || (invoker.chargesize >= 5.) )
return true;
return false;
}
override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount )
{
if ( bCharging ) return true;
return Super.CheckAmmo(fireMode,autoSwitch,requireAmmo,ammocount);
}
Default
{
Tag "$T_DPISTOL";
Inventory.PickupMessage "$I_DPISTOL";
Weapon.UpSound "dpistol/select";
Weapon.SlotNumber 1;
Weapon.SelectionOrder 1;
Weapon.AmmoType "DispersionAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "DispersionAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 50;
UTWeapon.DropAmmo 25;
+WEAPON.WIMPY_WEAPON;
}
States
{
Spawn:
DPIP A -1;
Stop;
DPIP B -1;
Stop;
Ready:
DPS1 A 0
{
if ( invoker.upgradelevel == 0 ) return ResolveState("Ready1");
else if ( invoker.upgradelevel == 1 ) return ResolveState("Ready2");
else if ( invoker.upgradelevel == 2 ) return ResolveState("Ready3");
else if ( invoker.upgradelevel == 3 ) return ResolveState("Ready4");
return ResolveState("Ready5");
}
Ready1:
DPS1 ABCDEFGHIJK 2;
DPI1 A 5;
Goto Idle;
Ready2:
DPS2 ABCDEFGHIJK 2;
DPI2 A 5;
Goto Idle;
Ready3:
DPS3 ABCDEFGHIJK 2;
DPI3 A 5;
Goto Idle;
Ready4:
DPS4 ABCDEFGHIJK 2;
DPI4 A 5;
Goto Idle;
Ready5:
DPS5 ABCDEFGHIJK 2;
DPI5 A 5;
Goto Idle;
Dummy:
TNT1 A 1
{
A_CheckReload();
A_WeaponReady();
}
Wait;
Idle:
#### # 0
{
if ( invoker.pendingupgrade )
{
invoker.pendingupgrade = false;
invoker.upgradelevel++;
return ResolveState("Upgrade");
}
A_Overlay(-9999,"Dummy");
if ( invoker.upgradelevel == 0 ) return ResolveState("Idle1");
else if ( invoker.upgradelevel == 1 ) return ResolveState("Idle2");
else if ( invoker.upgradelevel == 2 ) return ResolveState("Idle3");
else if ( invoker.upgradelevel == 3 ) return ResolveState("Idle4");
return ResolveState("Idle5");
}
Idle1:
DPI1 AB 30;
Goto Idle1;
Idle2:
DPI2 AB 30;
Goto Idle2;
Idle3:
DPI3 AB 30;
Goto Idle3;
Idle4:
DPI4 AB 30;
Goto Idle4;
Idle5:
DPI5 AB 30;
Goto Idle5;
Fire:
#### # 0
{
A_Overlay(-9999,"Null");
if ( invoker.upgradelevel == 0 ) return ResolveState("Fire1");
else if ( invoker.upgradelevel == 1 ) return ResolveState("Fire2");
else if ( invoker.upgradelevel == 2 ) return ResolveState("Fire3");
else if ( invoker.upgradelevel == 3 ) return ResolveState("Fire4");
return ResolveState("Fire5");
}
Fire1:
#### # 3 A_DispFire();
DPF1 ABC 5;
DPI1 A 5 A_Refire("Fire1");
Goto Idle;
Fire2:
#### # 3 A_DispFire();
DPF2 ABC 5;
DPI2 A 5 A_Refire("Fire2");
Goto Idle;
Fire3:
#### # 3 A_DispFire();
DPF3 ABC 5;
DPI3 A 5 A_Refire("Fire3");
Goto Idle;
Fire4:
#### # 3 A_DispFire();
DPF4 ABC 5;
DPI4 A 5 A_Refire("Fire4");
Goto Idle;
Fire5:
#### # 3 A_DispFire();
DPF5 ABC 5;
DPI5 A 5 A_Refire("Fire5");
Goto Idle;
AltFire:
#### # 0
{
invoker.chargesize = invoker.count = 0.;
invoker.bCharging = true;
// need to make sure player does the repeat fire anim
if ( self is 'UPlayer' )
UPlayer(self).PlayAttacking();
A_PlaySound("dpistol/charge",CHAN_WEAPON,Dampener.Active(self)?.4:1.);
A_Overlay(-9999,"Null");
if ( invoker.upgradelevel == 0 ) return ResolveState("AltFire1");
else if ( invoker.upgradelevel == 1 ) return ResolveState("AltFire2");
else if ( invoker.upgradelevel == 2 ) return ResolveState("AltFire3");
else if ( invoker.upgradelevel == 3 ) return ResolveState("AltFire4");
return ResolveState("AltFire5");
}
AltFire1:
#### # 1 A_JumpIf(A_DispCharge(),2);
#### # 0 A_ReFire("AltFire1");
AltRelease1:
#### # 3 A_DispAltFire();
DPF1 ABC 8;
DPI1 A 6;
Goto Idle;
AltFire2:
#### # 1 A_JumpIf(A_DispCharge(),2);
#### # 0 A_ReFire("AltFire2");
AltRelease2:
#### # 3 A_DispAltFire();
DPF2 ABC 8;
DPI2 A 6;
Goto Idle;
AltFire3:
#### # 1 A_JumpIf(A_DispCharge(),2);
#### # 0 A_ReFire("AltFire3");
AltRelease3:
#### # 3 A_DispAltFire();
DPF3 ABC 8;
DPI3 A 6;
Goto Idle;
AltFire4:
#### # 1 A_JumpIf(A_DispCharge(),2);
#### # 0 A_ReFire("AltFire4");
AltRelease4:
#### # 3 A_DispAltFire();
DPF4 ABC 8;
DPI4 A 6;
Goto Idle;
AltFire5:
#### # 1 A_JumpIf(A_DispCharge(),2);
#### # 0 A_ReFire("AltFire5");
AltRelease5:
#### # 3 A_DispAltFire();
DPF5 ABC 8;
DPI5 A 6;
Goto Idle;
Upgrade:
#### # 0
{
A_Overlay(-9999,"Null");
invoker.AmmoUse1 = min(6,invoker.upgradelevel+1);
if ( invoker.upgradelevel == 0 ) return ResolveState("Idle");
else if ( invoker.upgradelevel == 1 ) return ResolveState("Upgrade1");
else if ( invoker.upgradelevel == 2 ) return ResolveState("Upgrade2");
else if ( invoker.upgradelevel == 3 ) return ResolveState("Upgrade3");
return ResolveState("Upgrade4");
}
Upgrade1:
#### # 0 A_PlaySound("dpistol/up1",CHAN_6,Dampener.Active(self)?.2:1.);
DPU1 ABCD 9;
DPI2 A 4;
Goto Idle;
Upgrade2:
#### # 0 A_PlaySound("dpistol/up2",CHAN_6,Dampener.Active(self)?.2:1.);
DPU2 ABCDEFGHI 9;
DPI3 A 4;
Goto Idle;
Upgrade3:
#### # 0 A_PlaySound("dpistol/up3",CHAN_6,Dampener.Active(self)?.2:1.);
DPU3 ABCDEFGHI 9;
DPI4 A 4;
Goto Idle;
Upgrade4:
#### # 0 A_PlaySound("dpistol/up4",CHAN_6,Dampener.Active(self)?.2:1.);
DPU4 ABCDEFGHI 9;
DPI5 A 4;
Goto Idle;
Select:
DPS1 A 1 A_Raise(int.max);
Wait;
Deselect:
#### # 0
{
A_Overlay(-9999,"Null");
if ( invoker.upgradelevel == 0 ) return ResolveState("Deselect1");
else if ( invoker.upgradelevel == 1 ) return ResolveState("Deselect2");
else if ( invoker.upgradelevel == 2 ) return ResolveState("Deselect3");
else if ( invoker.upgradelevel == 3 ) return ResolveState("Deselect4");
return ResolveState("Deselect5");
}
Deselect1:
DPD1 ABCDE 2;
DPD1 E 1 A_Lower(int.max);
Wait;
Deselect2:
DPD2 ABCDE 2;
DPD2 E 1 A_Lower(int.max);
Wait;
Deselect3:
DPD3 ABCDE 2;
DPD3 E 1 A_Lower(int.max);
Wait;
Deselect4:
DPD4 ABCDE 2;
DPD4 E 1 A_Lower(int.max);
Wait;
Deselect5:
DPD5 ABCDE 2;
DPD5 E 1 A_Lower(int.max);
Wait;
Flash1:
DPFF A 2 Bright
{
let l = Spawn("DispLight1",pos);
l.target = self;
}
Stop;
Flash2:
DPFF B 2 Bright
{
let l = Spawn("DispLight2",pos);
l.target = self;
}
Stop;
Flash3:
DPFF C 2 Bright
{
let l = Spawn("DispLight3",pos);
l.target = self;
}
Stop;
Flash4:
DPFF D 2 Bright
{
let l = Spawn("DispLight4",pos);
l.target = self;
}
Stop;
Flash5:
DPFF E 2 Bright
{
let l = Spawn("DispLight5",pos);
l.target = self;
}
Stop;
}
}

View file

@ -1,3 +1,3 @@
Class FlameGun : UTWeapon
Class FlameGun : UnrealWeapon
{
}

View file

@ -2,6 +2,6 @@ Class SMiniAmmo : Ammo
{
}
Class SMiniGun : UTWeapon
Class SMiniGun : UnrealWeapon
{
}

View file

@ -5,10 +5,6 @@ Class ImpalerAmmo2 : ImpalerAmmo
{
}
Class ImpalerCharge : Ammo
{
}
Class Impaler : UTWeapon
Class Impaler : UnrealWeapon
{
}

View file

@ -128,48 +128,49 @@ Class UnrealBackpack : BackpackItem replaces Backpack
Class UTranslator : UnrealInventory
{
bool bCurrentlyActivated, bNewMessage, bNotNewMessage, bShowHint;
bool bNewMessage, bNotNewMessage;
string NewMessage, Hint;
ui TextureID thud;
ui Font tfnt;
ui void DrawTranslator( Vector2 scalev, double ClipX, double ClipY )
{
if ( thud.IsNull() ) thud = TexMan.CheckForTexture("TranHUD3",TexMan.Type_Any);
if ( !tfnt ) tfnt = Font.FindFont('UTahoma10');
double CurX, CurY;
CurX = ClipX/2-128;
CurY = ClipY/2-68;
Screen.DrawTexture(thud,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
String ttxt;
if ( bShowHint && (Hint.length() > 0) ) ttxt = String.Format("%s: %s",StringTable.Localize("$TR_HINT"),Hint);
else if ( NewMessage.length() > 0 ) ttxt = NewMessage;
else ttxt = StringTable.Localize("$TR_NOMSG");
BrokenLines lines = tfnt.BreakLines(ttxt,220);
int th = tfnt.GetHeight();
CurX += 20;
CurY += 18;
for ( int i=0; i<lines.Count() && i<(110/th); i++ )
{
Screen.DrawText(tfnt,Font.CR_GREEN,CurX,CurY,lines.StringAt(i),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += th-1;
}
}
Array<String> OldMessages, OldHints;
override void Travelled()
{
Super.Travelled();
NewMessage = Hint = "";
OldMessages.Clear();
OldHints.Clear();
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
bActive = bCurrentlyActivated = !bCurrentlyActivated;
if ( !bActive ) bShowHint = bNewMessage = bNotNewmessage = false;
if ( Owner.player == players[consoleplayer] )
Menu.SetMenu('TranslatorMenu');
bNewMessage = bNotNewmessage = false;
return false;
}
void AddMessage( String msg, String hnt )
{
int found = -1;
for ( int i=0; i<OldMessages.Size(); i++ )
{
if ( OldMessages[i] != msg ) continue;
found = i;
}
if ( found != -1 )
{
OldMessages.Delete(found);
OldHints.Delete(found);
}
if ( (NewMessage != msg) && (NewMessage.Length() > 0) )
{
OldMessages.Push(NewMessage);
OldHints.Push(Hint);
}
NewMessage = msg;
Hint = hnt;
}
Default
{
Tag "$T_TRANSLATOR";
@ -177,6 +178,83 @@ Class UTranslator : UnrealInventory
Inventory.Icon "I_Tran";
Inventory.MaxAmount 1;
}
States
{
Spawn:
TRNS A -1;
Stop;
}
}
// To be placed by mappers
// Uses two UDMF-settable user strings
// AMBUSH: only triggered by script activation, not touch
Class TranslatorEvent : Actor
{
String user_message, user_hint;
Array<Actor> Touchers;
Default
{
Radius 40;
Height 80;
+SPECIAL;
+NOGRAVITY;
+INVISIBLE;
}
virtual void TriggerMessage( Actor who )
{
if ( special1 > gametic ) return;
let Translator = UTranslator(who.FindInventory("UTranslator"));
if ( !Translator ) return;
special1 = gametic+8;
if ( who.CheckLocalView() )
{
if ( special2 ) Console.Printf(StringTable.Localize("$TR_MSG"));
else Console.Printf(StringTable.Localize("$TR_NEWMSG"));
S_Sound("translator/event",CHAN_VOICE|CHAN_UI);
}
Translator.AddMessage(user_message,user_hint);
if ( special2 ) Translator.bNotNewMessage = true;
else Translator.bNewMessage = true;
special2 = 1;
}
// GZDoom doesn't have Touch/UnTouch like UE1 so I have to improvise
override void Tick()
{
Super.Tick();
for ( int i=0; i<Touchers.Size(); i++ )
{
bool deletthis = false;
if ( Touchers[i].pos.x+Touchers[i].radius < pos.x-radius ) deletthis = true;
if ( Touchers[i].pos.x-Touchers[i].radius > pos.x+radius ) deletthis = true;
if ( Touchers[i].pos.y+Touchers[i].radius < pos.y-radius ) deletthis = true;
if ( Touchers[i].pos.y-Touchers[i].radius > pos.y+radius ) deletthis = true;
if ( Touchers[i].pos.z+Touchers[i].height < pos.z ) deletthis = true;
if ( Touchers[i].pos.z > pos.z+height ) deletthis = true;
if ( !deletthis ) continue;
Touchers.Delete(i);
i--;
}
}
override void Touch( Actor toucher )
{
if ( bAMBUSH || !toucher || !toucher.player ) return;
for ( int i=0; i<Touchers.Size(); i++ ) if ( Touchers[i] == toucher ) return;
Touchers.Push(toucher);
TriggerMessage(toucher);
}
override void Activate( Actor activator )
{
if ( !activator || !activator.player ) return;
TriggerMessage(activator);
}
States
{
Spawn:
SMSG A -1;
Stop;
}
}
Class VoiceBox : UnrealInventory
@ -188,7 +266,7 @@ Class VoiceBox : UnrealInventory
Tag "$T_VOICEBOX";
Inventory.PickupMessage "$I_VOICEBOX";
Inventory.Icon "I_VoiceB";
Inventory.MaxAmount 5;
Inventory.MaxAmount 3;
UnrealInventory.Charge 600;
}
override void Tick()
@ -209,18 +287,18 @@ Class VoiceBox : UnrealInventory
override bool Use( bool pickup )
{
if ( pickup || bActive ) return false;
bActive = true;
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz);
origin = level.Vec3Offset(origin,x*20.-z*8.);
box = Spawn("VoiceBoxActive",origin);
box.ReactionTime = Charge;
box.vel = x*12.;
box.vel.z += 3.;
box.vel = x*9.;
box.vel.z += 1.;
box.target = Owner;
box.angle = Owner.angle;
box.pitch = Owner.pitch;
bActive = true;
return false;
}
States
@ -266,13 +344,15 @@ Class VoiceBoxHitbox : Actor
Class VoiceBoxActive : Actor
{
Actor b;
bool alreadyhit;
double desiredangle, anglevel, oldangle;
override void PostBeginPlay()
{
Super.PostBeginPlay();
b = Spawn("VoiceBoxHitbox",pos);
b.master = self;
desiredangle = FRandom[Junk](0,360);
anglevel = FRandom[Junk](5,15);
}
action void A_VoiceBoxPlay()
{
@ -292,19 +372,30 @@ Class VoiceBoxActive : Actor
if ( invoker.b ) invoker.b.A_AlertMonsters(0,AMF_TARGETEMITTER);
for ( int i=0; i<10; i++ ) if ( !Random[Voicebox](0,30) ) A_PlaySound(BattleSounds[i],CHAN_AUTO,FRandom[Voicebox](0.5,1.0));
}
override void Tick()
{
oldangle = angle;
Super.Tick();
if ( deltaangle(angle,desiredangle) ~== 0 ) angle = desiredangle;
else angle += clamp(deltaangle(angle,desiredangle),-anglevel,anglevel);
}
Default
{
Radius 6;
Height 6;
PROJECTILE;
-NOGRAVITY;
+USEBOUNCESTATE;
+SKYEXPLODE;
+MOVEWITHSECTOR;
+CANBOUNCEWATER;
+BOUNCEAUTOOFF;
+BOUNCEAUTOOFFFLOORONLY;
+USEBOUNCESTATE;
+INTERPOLATEANGLES;
BounceType "Hexen";
BounceFactor 0.3;
WallBounceFactor 0.3;
BounceFactor 0.5;
BounceSound "transloc/bounce";
WallBounceFactor 0.5;
Gravity 0.35;
ReactionTime 200;
}
@ -314,23 +405,14 @@ Class VoiceBoxActive : Actor
VBOX A -1;
Stop;
Bounce:
VBOX A 0
{
if ( alreadyhit )
{
ClearBounce();
ExplodeMissile();
}
else
{
A_SetPitch(0);
A_PlaySound("transloc/bounce");
if ( BlockingFloor ) alreadyhit = true;
}
}
VBOX A 0 { angle = invoker.oldangle; }
Goto Spawn;
Death:
VBOX A 30;
VBOX A 30
{
invoker.anglevel *= 0;
A_PlaySound("voice/activate");
}
VBOX ABCDEFGHIJ 1
{
A_VoiceBoxPlay();
@ -339,13 +421,280 @@ Class VoiceBoxActive : Actor
}
Goto Death+1;
Death2:
TNT1 A 1 A_Log("// TODO explosion");
VBOX A 0
{
if ( invoker.b ) invoker.b.Destroy();
A_PlaySound("flare/explode",CHAN_VOICE);
A_NoGravity();
A_Stop();
A_SetRenderStyle(1.,STYLE_Add);
SetZ(pos.z+16);
Spawn("FlareXLight",pos);
bMOVEWITHSECTOR = false;
bFORCEXYBILLBOARD = true;
A_SetScale(FRandomPick[ExploS](-1.5,1.5),FRandomPick[ExploS](-1.5,1.5));
return A_Jump(256,"Explo1","Explo2","Explo3","Explo4","Explo5");
}
Explo1:
EXP1 ABCDEFGH 3 Bright;
Stop;
Explo2:
EXP2 ABCDEFGH 3 Bright;
Stop;
Explo3:
EXP3 ABCDEFGH 3 Bright;
Stop;
Explo4:
EXP4 ABCDEFGH 3 Bright;
Stop;
Explo5:
EXP5 ABCDEFGH 3 Bright;
Stop;
}
}
Class Flare : UnrealInventory
{
Default
{
Tag "$T_FLARES";
Inventory.PickupMessage "$I_FLARES";
Inventory.Icon "I_Flare";
Inventory.MaxAmount 20;
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),x*10.-z*8.);
let a = Spawn("FlareThrown",origin);
a.target = Owner;
a.angle = Owner.angle;
a.pitch = Owner.pitch;
a.vel += x*a.speed;
return true;
}
States
{
Spawn:
FLAR A -1;
Stop;
}
}
Class FlareThrown : Actor
{
double pitchvel, anglevel, rollvel;
double desiredangle;
bool rotatetodesired;
double lastpitch, lastangle, lastroll;
Actor b;
Default
{
Radius 6;
Height 6;
+NOBLOCKMAP;
+MISSILE;
+MOVEWITHSECTOR;
+THRUACTORS;
+USEBOUNCESTATE;
+INTERPOLATEANGLES;
+BOUNCEAUTOOFF;
+BOUNCEAUTOOFFFLOORONLY;
+NOTELEPORT;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
DamageType "Exploded";
Speed 12;
VSpeed 2;
Mass 1;
Gravity 0.35;
BounceType "Hexen";
WallBounceFactor 0.6;
BounceFactor 0.6;
ReactionTime 350;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
pitchvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
rollvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
}
override void Tick()
{
lastpitch = pitch;
lastangle = angle;
lastroll = roll;
Super.Tick();
if ( rotatetodesired )
{
if ( deltaangle(pitch,0) ~== 0 ) pitch = 0;
else pitch += clamp(deltaangle(pitch,0),-pitchvel,pitchvel);
if ( deltaangle(angle,desiredangle) ~== 0 ) angle = desiredangle;
else angle += clamp(deltaangle(angle,desiredangle),-anglevel,anglevel);
if ( deltaangle(roll,0) ~== 0 ) roll = 0;
else roll += clamp(deltaangle(roll,0),-rollvel,rollvel);
}
else
{
angle += anglevel;
pitch += pitchvel;
roll += rollvel;
}
if ( ReactionTime <= 0 ) return;
if ( GetAge() < 9 ) return;
if ( waterlevel > 0 )
{
if ( tracer ) tracer.Destroy();
if ( b ) b.Destroy();
A_StopSound(CHAN_VOICE);
ReactionTime = 0;
return;
}
if ( !b )
{
A_PlaySound("flare/on");
A_PlaySound("flare/loop",CHAN_VOICE,.5,true);
tracer = Spawn("FlareThrownX",pos);
tracer.angle = angle;
tracer.pitch = pitch;
tracer.target = self;
b = Spawn("FlareHitbox",pos);
b.master = self;
}
b.A_AlertMonsters(0,AMF_TARGETEMITTER);
ReactionTime--;
}
States
{
Spawn:
FLAR A -1;
Stop;
Bounce:
FLAR A 0
{
pitch = lastpitch;
angle = lastangle;
roll = lastroll;
rotatetodesired = true;
desiredangle = FRandom[Junk](0,360);
pitchvel = abs(pitchvel)*0.75;
anglevel = abs(anglevel)*0.75;
rollvel = abs(rollvel)*0.75;
}
Goto Spawn;
Death:
FLAR A 0 { anglevel *= 0; }
FLAR A 1
{
if ( waterlevel > 0 )
{
if ( tracer ) tracer.Destroy();
if ( b ) b.Destroy();
A_StopSound(CHAN_VOICE);
return ResolveState("Fizz");
}
return A_JumpIf(ReactionTime<=0,1);
}
Wait;
FLAR A 0
{
if ( tracer ) tracer.Destroy();
if ( b ) b.Destroy();
if ( waterlevel > 0 )
{
return ResolveState("Fizz");
}
A_StopSound(CHAN_VOICE);
A_PlaySound("flare/explode");
A_Explode(50,50);
A_NoGravity();
A_Stop();
A_SetRenderStyle(1.,STYLE_Add);
SetZ(pos.z+9);
Spawn("FlareXLight",pos);
bMOVEWITHSECTOR = false;
bFORCEXYBILLBOARD = true;
A_SetScale(FRandomPick[ExploS](-1.5,1.5),FRandomPick[ExploS](-1.5,1.5));
return A_Jump(256,"Explo1","Explo2","Explo3","Explo4","Explo5");
}
Explo1:
EXP1 ABCDEFGH 3 Bright;
Stop;
Explo2:
EXP2 ABCDEFGH 3 Bright;
Stop;
Explo3:
EXP3 ABCDEFGH 3 Bright;
Stop;
Explo4:
EXP4 ABCDEFGH 3 Bright;
Stop;
Explo5:
EXP5 ABCDEFGH 3 Bright;
Stop;
Fizz:
FLAR A 1
{
special1++;
if ( special1 > 150 ) A_FadeOut();
}
Wait;
}
}
Class FlareXLight : PaletteLight
{
Default
{
ReactionTime 25;
Args 0,0,0,80;
}
}
Class FlareHitbox : VoiceBoxHitbox
{
Default
{
Tag "$T_FLARES";
Radius 4;
Height 6;
Health 1;
}
}
Class FlareThrownX : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+INTERPOLATEANGLES;
Radius 0.1;
Height 0;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
angle = target.angle;
pitch = target.pitch;
}
States
{
Spawn:
FLAR A -1 Bright;
Stop;
}
}
Class LightFlare : UnrealInventory
@ -379,6 +728,7 @@ Class Dampener : UnrealInventory
{
Owner.A_PlaySound("dampener/off",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_DAMPENER"));
if ( Amount <= 0 ) DepleteOrDestroy();
}
}
Default
@ -386,7 +736,7 @@ Class Dampener : UnrealInventory
Tag "$T_DAMPENER";
Inventory.PickupMessage "$I_DAMPENER";
Inventory.Icon "I_Dampen";
Inventory.MaxAmount 5;
Inventory.MaxAmount 3;
UnrealInventory.Charge 1000;
}
States
@ -450,28 +800,8 @@ Class Forcefield : UnrealInventory
}
}
Class ForcefieldX : Actor
Class ForcefieldX : AsmdAmmoX
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
Radius 0.1;
Height 0;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
Warp(target,flags:WARPF_COPYINTERPOLATION|WARPF_NOCHECKPOSITION);
bInvisible = target.bInvisible||!target.InStateSequence(target.CurState,target.FindState("Spawn"));
}
States
{
Spawn:
@ -514,6 +844,7 @@ Class ForceFieldLight : DynamicLight
Class ForcefieldEffect : Actor
{
double nvol;
int lct;
Default
{
@ -544,13 +875,14 @@ Class ForcefieldEffect : Actor
A_PlaySound("ffield/active",CHAN_VOICE,0.6,true);
let tracer = Spawn("ForceFieldLight",pos);
tracer.target = self;
lct = 24;
}
States
{
Spawn:
FFLD ABCDEFGHI 3 Bright;
FFLD J 700 Bright;
FFLD J 35 Bright
FFLD ABCDEFGHIJ 3 Bright;
#### # 700 Bright;
#### # 35 Bright
{
A_UnsetShootable();
A_UnsetSolid();

View file

@ -2,6 +2,6 @@ Class FlameAmmo : Ammo
{
}
Class UFlamethrower : UTWeapon
Class UFlamethrower : UnrealWeapon
{
}

View file

@ -2,6 +2,6 @@ Class PeaceAmmo : Ammo
{
}
Class Peacemaker : UTWeapon
Class Peacemaker : UnrealWeapon
{
}

View file

@ -6,6 +6,6 @@ Class UShells2 : UShells
{
}
Class QuadShot : UTWeapon
Class QuadShot : UnrealWeapon
{
}

View file

@ -2,6 +2,6 @@ Class RazorAmmo : Ammo
{
}
Class Razorjack : UTWeapon
Class Razorjack : UnrealWeapon
{
}

View file

@ -6,6 +6,6 @@ Class URifleAmmo2 : URifleAmmo
{
}
Class URifle : UTWeapon
Class URifle : UnrealWeapon
{
}

View file

@ -39,6 +39,16 @@ Class StingerAmmo2 : StingerAmmo
}
}
Class StingerBurstLight : PaletteLight
{
Default
{
Tag "Blue3";
Args 0,0,0,30;
ReactionTime 10;
}
}
Class StingerProjectile : Actor
{
Default
@ -74,6 +84,7 @@ Class StingerProjectile : Actor
if ( !Random[Stinger](0,2) ) A_PlaySound("stinger/hit2",CHAN_BODY,0.5,pitch:FRandom[Stinger](0.5,1.5));
else A_PlaySound("stinger/hit",CHAN_BODY,0.6);
A_AlertMonsters();
Spawn("StingerBurstLight",pos);
}
TPRJ BCDEFG 2 Bright;
Stop;
@ -83,8 +94,18 @@ Class StingerProjectile : Actor
}
}
Class Stinger : UTWeapon
Class StingerLight : EnforcerLight
{
Default
{
args 64,128,255,80;
}
}
Class Stinger : UnrealWeapon
{
int flashnum;
Default
{
Tag "$T_STINGER";
@ -99,10 +120,6 @@ Class Stinger : UTWeapon
Weapon.AmmoGive 40;
UTWeapon.DropAmmo 20;
}
override void PlayUpSound( Actor origin )
{
origin.A_PlaySound(upsound,CHAN_WEAPON,Dampener.Active(origin)?.1:1.);
}
action void A_StingerFire( bool hold = false )
{
Weapon weap = Weapon(invoker);
@ -121,13 +138,14 @@ Class Stinger : UTWeapon
}
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.1,-0.2),FRandom[Stinger](-0.1,0.1)),4,-1.5,2,SWING_Spring,2,2);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+8.0*y-9.0*z;
Vector3 origin = (pos.x,pos.y,player.viewz)+5.0*x+8.0*y-8.0*z;
Actor p = Spawn("StingerProjectile",origin);
p.angle = angle;
p.pitch = BulletSlope();
@ -143,13 +161,14 @@ Class Stinger : UTWeapon
A_Overlay(PSP_FLASH,"MFlash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(16,0,64,255),1);
UTMainHandler.DoSwing(self,(FRandom[Stinger](-0.3,-0.8),FRandom[Stinger](-0.4,0.4)),4,-1,3,SWING_Spring,3,5);
if ( !Dampener.Active(self) ) A_AlertMonsters();
A_QuakeEx(1,1,1,4,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
[x, y, z] = dt_Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = (pos.x,pos.y,player.viewz)+10.0*x+8.0*y-9.0*z;
Vector3 origin = (pos.x,pos.y,player.viewz)+5.0*x+8.0*y-8.0*z;
[x, y, z] = dt_Matrix4.GetAxes(BulletSlope(),angle,roll);
Actor p;
double a, s;
@ -193,7 +212,11 @@ Class Stinger : UTWeapon
STNI A 3;
STNI A 0 A_Refire(1);
Goto Idle;
STNI A 0 A_PlaySound("stinger/hold",CHAN_WEAPON,Dampener.Active(self)?.1:1.,true);
STNI A 0
{
A_PlaySound("stinger/hold",CHAN_WEAPON,Dampener.Active(self)?.1:1.,true);
invoker.flashnum = Random[Stinger](0,3);
}
Hold:
STNH A 1
{
@ -201,6 +224,7 @@ Class Stinger : UTWeapon
if ( self is 'UPlayer' )
UPlayer(self).PlayAttacking();
A_StingerFire(true);
invoker.flashnum = (invoker.flashnum+1)%4;
}
STNH BCDEFG 1;
STNH A 0 A_Refire();
@ -212,14 +236,51 @@ Class Stinger : UTWeapon
STNI A 35; // yes, 1 second cooldown
Goto Idle;
Deselect:
STND ABCDEFGHIJK 1;
STND ACEGIK 1;
STND K 1 A_Lower(int.max);
Wait;
MFlash:
STFF A 2 Bright
{
let l = Spawn("StingerLight",pos);
l.target = self;
}
Stop;
MFlashHold:
TNT1 A 0 A_JumpIf(invoker.flashnum==0,7);
TNT1 A 0 A_JumpIf(invoker.flashnum==1,4);
TNT1 A 0 A_JumpIf(invoker.flashnum==2,4);
TNT1 A 0 A_JumpIf(invoker.flashnum==3,1);
Stop;
STFF A 2 Bright
{
let l = Spawn("StingerLight",pos);
l.target = self;
}
Stop;
STFF B 2 Bright
{
let l = Spawn("StingerLight",pos);
l.target = self;
}
Stop;
STFF C 2 Bright
{
let l = Spawn("StingerLight",pos);
l.target = self;
}
Stop;
STFF D 2 Bright
{
let l = Spawn("StingerLight",pos);
l.target = self;
}
Stop;
/*MFlash:
STFF ABC 2 Bright;
Stop;
MFlashHold:
STFH ABCDEFG 1 Bright;
Stop;
Stop;*/
}
}

View file

@ -2,6 +2,6 @@ Class StunnerAmmo : Ammo
{
}
Class Stunner : UTWeapon
Class Stunner : UnrealWeapon
{
}

View file

@ -10,12 +10,6 @@ Class UnrealArmor : UTArmor
UnrealArmor.AbsorptionPriority 0;
}
override void AbsorbDamage( int damage, Name damageType, out int newdamage )
{
Console.Printf("%s absorbs %d",GetTag(),damage);
Super.AbsorbDamage(damage,damageType,newdamage);
}
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
@ -222,7 +216,7 @@ Class PowerShield : UnrealArmor
amount--;
gothit = false;
}
if ( !(level.maptime%15) ) amount--;
if ( !(level.maptime%15) && !sting_pshield ) amount--;
if ( amount <= 0 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_POWERSHIELD"));

View file

@ -1,7 +1,10 @@
Class UBioAmmo : Ammo
{
}
Class UBioRifle : UTWeapon
Class UBioAmmo2 : UBioAmmo
{
}
Class UBioRifle : UnrealWeapon
{
}

View file

@ -5,6 +5,6 @@ Class URocketAmmo2 : URocketAmmo
{
}
Class Eightball : UTWeapon
Class Eightball : UnrealWeapon
{
}

View file

@ -42,12 +42,8 @@ Class UFlakAmmo : UFlakBox
}
}
Class UFlakCannon : UTWeapon
Class UFlakCannon : UnrealWeapon
{
override void PlayUpSound( Actor origin )
{
origin.A_PlaySound(upsound,CHAN_WEAPON,Dampener.Active(origin)?.1:1.);
}
action void A_Loading( bool first = false )
{
if ( first ) A_PlaySound("flak/load",CHAN_WEAPON,Dampener.Active(self)?.1:1.);
@ -63,6 +59,7 @@ Class UFlakCannon : UTWeapon
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(48,255,96,0),1);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.3,-0.8),FRandom[Flak](-0.5,0.5)),4,-1.5,2,SWING_Spring,2,2);
if ( !Dampener.Active(self) ) A_AlertMonsters();
@ -75,9 +72,10 @@ Class UFlakCannon : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("flak/altfire",CHAN_WEAPON,Dampener.Active(self)?.2:1.);
A_Overlay(PSP_FLASH,"AltFlash");
A_Overlay(PSP_FLASH,"Flash");
A_OverlayFlags(PSP_FLASH,PSPF_RenderStyle,true);
A_OverlayRenderstyle(PSP_FLASH,STYLE_Add);
invoker.FireEffect();
UTMainHandler.DoFlash(self,Color(32,255,96,0),1);
UTMainHandler.DoSwing(self,(FRandom[Flak](-0.4,-0.8),FRandom[Flak](0.4,0.8)),4,-1,3,SWING_Spring,3,5);
if ( !Dampener.Active(self) ) A_AlertMonsters();
@ -147,10 +145,17 @@ Class UFlakCannon : UTWeapon
FLD2 F 1 A_Lower(int.max);
Wait;
Flash:
FMUZ A 3 Bright
{
let l = Spawn("FlakLight",pos);
l.target = self;
}
Stop;
/*Flash:
FLFF ABCDEFGHIJ 1 Bright;
Stop;
AltFlash:
FLFA ABCDEF 1 Bright;
Stop;
Stop;*/
}
}

View file

@ -1,19 +1,242 @@
Class Bandages : Health
{
Default
{
Tag "$T_BANDAGES";
Inventory.Amount 5;
Inventory.PickupMessage "$I_BANDAGES";
Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 700;
}
States
{
Spawn:
BAND A -1;
Stop;
}
}
Class UHealth : Health
{
Default
{
Tag "$T_HEALTH";
Inventory.Amount 20;
Inventory.PickupMessage "$I_HEALTH";
Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 700;
}
States
{
Spawn:
HLTH A -1;
Stop;
}
}
Class NaliFruit : Health
{
int cnt;
Default
{
Tag "$T_FRUIT";
Scale 0.05;
Inventory.Amount 0;
Inventory.PickupMessage "$I_FRUIT";
Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 175;
}
override bool TryPickup( in out Actor toucher )
{
if ( Amount < 2 ) return false;
return Super.TryPickup(toucher);
}
override void Tick()
{
Super.Tick();
if ( !InStateSequence(CurState,FindState("Spawn")) ) return;
if ( frame > 25 ) return;
cnt++;
if ( cnt < 300 ) return;
if ( !(cnt%17) ) Amount = min(29,Amount+1);
}
States
{
Spawn:
FRUT A 0 NoDelay
{
invoker.Amount = 0;
invoker.cnt = 0;
}
FRUT A 1 A_SetScale(Scale.x+1./35.);
FRUT A 0 A_JumpIf(Scale.x<1.0,"Spawn");
FRUT A 35
{
A_SetScale(1.);
A_SetTics(Random[Fruit](1,3)*35);
}
FRUT BCDEFGHIJKLMNOPQRSTUVWXYZ 32;
FRUT \[ 12;
Goto Spawn+29;
}
}
Class SeedProj : Actor
{
double pitchvel, anglevel, rollvel;
double desiredangle;
bool rotatetodesired;
double lastpitch, lastangle, lastroll;
Default
{
Radius 6;
Height 6;
+NOBLOCKMAP;
+MISSILE;
+MOVEWITHSECTOR;
+THRUACTORS;
+USEBOUNCESTATE;
+INTERPOLATEANGLES;
+NOTELEPORT;
+BOUNCEAUTOOFF;
+BOUNCEAUTOOFFFLOORONLY;
Speed 5;
VSpeed 2;
Mass 1;
Gravity 0.35;
BounceType "Hexen";
WallBounceFactor 0.6;
BounceFactor 0.6;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
pitchvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
anglevel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
rollvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1);
}
override void Tick()
{
lastpitch = pitch;
lastangle = angle;
lastroll = roll;
Super.Tick();
if ( rotatetodesired )
{
if ( deltaangle(pitch,0) ~== 0 ) pitch = 0;
else pitch += clamp(deltaangle(pitch,0),-pitchvel,pitchvel);
if ( deltaangle(angle,desiredangle) ~== 0 ) angle = desiredangle;
else angle += clamp(deltaangle(angle,desiredangle),-anglevel,anglevel);
if ( deltaangle(roll,0) ~== 0 ) roll = 0;
else roll += clamp(deltaangle(roll,0),-rollvel,rollvel);
}
else
{
angle += anglevel;
pitch += pitchvel;
roll += rollvel;
}
}
States
{
Spawn:
SEED A -1;
Stop;
Bounce:
SEED A 0
{
pitch = lastpitch;
angle = lastangle;
roll = lastroll;
rotatetodesired = true;
desiredangle = FRandom[Junk](0,360);
pitchvel = abs(pitchvel)*0.75;
anglevel = abs(anglevel)*0.75;
rollvel = abs(rollvel)*0.75;
}
Goto Spawn;
Death:
SEED A 20 { anglevel *= 0; }
SEED A 1
{
A_SetScale(Scale.x-1./35.);
if ( Scale.x <= 0.05 )
{
let f = Spawn("NaliFruit",pos);
f.angle = Random[Fruit](0,359);
Destroy();
}
}
Wait;
}
}
Class Seeds : UnrealInventory
{
Default
{
Tag "$T_SEEDS";
Inventory.PickupMessage "$I_SEEDS";
Inventory.Icon "I_Seed";
Inventory.MaxAmount 20;
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll);
Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),x*10.-z*8.);
let a = Spawn("SeedProj",origin);
a.target = Owner;
a.angle = Owner.angle;
a.pitch = Owner.pitch;
a.vel += x*a.speed;
return true;
}
States
{
Spawn:
SEED A -1;
Stop;
}
}
Class SuperHealth : Health
{
Default
{
Tag "$T_SHEALTH";
+COUNTITEM;
+INVENTORY.AUTOACTIVATE;
+INVENTORY.ALWAYSPICKUP;
+INVENTORY.FANCYPICKUPSOUND;
Inventory.Amount 100;
Inventory.MaxAmount 200;
Inventory.PickupMessage "$I_SHEALTH";
Inventory.PickupSound "misc/u1heal";
Inventory.RespawnTics 3500;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("SuperHealthX",pos);
tracer.angle = angle;
tracer.target = self;
}
States
{
Spawn:
SHTH A -1;
Stop;
}
}
Class SuperHealthX : AsmdAmmoX
{
States
{
Spawn:
SHTH A -1 Bright;
Stop;
}
}

View file

@ -1,7 +1,21 @@
Class UMiniAmmo : Ammo
{
Default
{
Tag "$T_MINIAMMO";
Inventory.PickupMessage "";
Inventory.Amount 50;
Inventory.MaxAmount 200;
Ammo.BackpackAmount 100;
Ammo.BackpackMaxAmount 400;
Ammo.DropAmount 20;
}
override String PickupMessage()
{
return String.Format("%s%d%s",StringTable.Localize("$I_MINIAMMOL"),Amount,StringTable.Localize("$I_MINIAMMOR"));
}
}
Class UMinigun : UTWeapon
Class UMinigun : UnrealWeapon
{
}

View file

@ -5,6 +5,7 @@ Class UPlayer : UTPlayer
Player.StartItem "Automag";
Player.StartItem "DispersionPistol";
Player.StartItem "UMiniAmmo", 30;
Player.StartItem "DispersionAmmo", 50;
}
// Have to modify the give cheat to handle UT armor
@ -163,14 +164,22 @@ Class UPlayer : UTPlayer
if ( (player && (player.mo == self)) && (player.crouchdir == -1) ) return;
// check weapon type
let psp = player.FindPSprite(PSP_WEAPON);
if ( (player.ReadyWeapon is 'Stinger') && psp
&& psp.CurState.InStateSequence(player.ReadyWeapon.FindState("Hold")) )
if ( ((player.ReadyWeapon is 'Stinger') && psp
&& psp.CurState.InStateSequence(player.ReadyWeapon.FindState("Hold")))
|| ((player.ReadyWeapon is 'DispersionPistol') && DispersionPistol(player.ReadyWeapon).bCharging) )
{
if ( !InStateSequence(CurState,FindState("MissileRep")) )
SetStateLabel("MissileRep");
}
else SetStateLabel("Missile");
}
override void PlayFootstep( double vol )
{
let boot = UJumpBoots(FindInventory("UJumpBoots"));
if ( boot && boot.bActive ) A_PlaySound("u1/metalfootstep",CHAN_5,min(1.,vol*2));
else A_PlaySound("ut/playerfootstep",CHAN_5,vol);
}
}
Class UFemaleArmGibber : UTGibber
@ -391,7 +400,7 @@ Class UPlayerMale : UPlayer
{
Default
{
Player.SoundClass "umale";
Player.SoundClass "umale1";
UTPlayer.VoiceType VOICE_MaleOne;
}
@ -459,6 +468,7 @@ Class UPlayerMale2 : UPlayerMale
{
Default
{
Player.SoundClass "umale2";
Player.DisplayName "$N_MALE2";
Player.Portrait "";
-NOMENU;
@ -468,6 +478,7 @@ Class UPlayerMale3 : UPlayerMale
{
Default
{
Player.SoundClass "umale3";
Player.DisplayName "$N_MALE3";
Player.Portrait "";
UTPlayer.VoiceType VOICE_MaleTwo;
@ -488,7 +499,7 @@ Class UnrealInventory : Inventory
// Drawstuffs over HUD
virtual ui void PostRender( double lbottom ) {}
bool DrainCharge( int val )
virtual bool DrainCharge( int val )
{
Charge -= val;
if ( Charge > 0 ) return false;
@ -499,7 +510,6 @@ Class UnrealInventory : Inventory
bActive = false;
return true;
}
DepleteOrDestroy();
return true;
}
override void AttachToOwner( Actor other )
@ -573,6 +583,20 @@ Class UTeleportFog : Actor
}
}
Class UnrealWeapon : UTWeapon
{
override void FireEffect()
{
Super.FireEffect();
let invis = UInvisibility(Owner.FindInventory("UInvisibility"));
if ( invis && invis.bActive ) invis.special1 = -1;
}
override void PlayUpSound( Actor origin )
{
origin.A_PlaySound(upsound,CHAN_WEAPON,Dampener.Active(origin)?.1:1.);
}
}
Class UnrealStaticHandler : StaticEventHandler
{
ui TextureID tex[6];
@ -708,33 +732,19 @@ Class UnrealMainHandler : EventHandler
}
else if ( (e.Replacee == 'RocketLauncher') || (e.Replacee == 'PhoenixRod') )
{
switch ( Random[Replacements](0,2) )
if ( !Random[Replacements](0,3) )
{
case 0:
e.Replacement = 'FlameGun';
break;
case 1:
e.Replacement = 'UFlakCannon';
break;
case 2:
e.Replacement = 'Eightball';
break;
if ( !Random[Replacements](0,2) ) e.Replacement = 'UFlamethrower';
else e.Replacement = 'FlameGun';
}
else if ( Random[Replacements](0,1) ) e.Replacement = 'UFlakCannon';
else e.Replacement = 'Eightball';
}
else if ( (e.Replacee == 'PlasmaRifle') || (e.Replacee == 'SkullRod') )
{
switch ( Random[Replacements](0,2) )
{
case 0:
e.Replacement = 'UFlamethrower';
break;
case 1:
e.Replacement = 'URifle';
break;
case 2:
e.Replacement = 'UBioRifle';
break;
}
if ( !Random[Replacements](0,3) ) e.Replacement = 'Impaler';
else if ( Random[Replacements](0,1) ) e.Replacement = 'URifle';
else e.Replacement = 'UBioRifle';
}
else if ( (e.Replacee == 'BFG9000') || (e.Replacee == 'Mace') )
{
@ -786,7 +796,8 @@ Class UnrealMainHandler : EventHandler
}
else if ( (e.Replacee == 'RocketAmmo') || (e.Replacee == 'PhoenixRodAmmo') || (e.Replacee == 'MaceAmmo') )
{
if ( Random[Replacements](0,1) )
if ( !Random[Replacements](0,4) ) e.Replacement = 'FlameAmmo';
else if ( Random[Replacements](0,1) )
{
if ( !Random[Replacements](0,3) ) e.Replacement = 'UFlakBox';
else e.Replacement = 'UFlakAmmo';
@ -799,17 +810,23 @@ Class UnrealMainHandler : EventHandler
}
else if ( (e.Replacee == 'RocketBox') || (e.Replacee == 'PhoenixRodHefty') || (e.Replacee == 'MaceHefty') )
{
if ( Random[Replacements](0,1) ) e.Replacement = 'UFlakBox';
if ( !Random[Replacements](0,3) ) e.Replacement = 'FlameAmmo';
else if ( Random[Replacements](0,1) ) e.Replacement = 'UFlakBox';
else e.Replacement = 'URocketAmmo';
}
else if ( (e.Replacee == 'Cell') || (e.Replacee == 'SkullRodAmmo') )
{
if ( !Random[Replacements](0,4) ) e.Replacement = 'BigAmmo2';
else if ( Random[Replacements](0,1) )
else if ( !Random[Replacements](0,3) )
{
if ( !Random[Replacements](0,3) ) e.Replacement = 'ImpalerAmmo';
else e.Replacement = 'ImpalerAmmo2';
}
else if ( Random[Replacements](0,1) )
{
if ( !Random[Replacements](0,3) ) e.Replacement = 'UBioAmmo';
else e.Replacement = 'UBioAmmo2';
}
else
{
if ( !Random[Replacements](0,3) ) e.Replacement = 'URifleAmmo';
@ -819,7 +836,8 @@ Class UnrealMainHandler : EventHandler
else if ( (e.Replacee == 'CellPack') || (e.Replacee == 'SkullRodHefty') )
{
if ( !Random[Replacements](0,4) ) e.Replacement = 'BigAmmo';
else if ( Random[Replacements](0,1) ) e.Replacement = 'ImpalerAmmo';
else if ( !Random[Replacements](0,3) ) e.Replacement = 'ImpalerAmmo';
else if ( Random[Replacements](0,1) ) e.Replacement = 'UBioAmmo';
else e.Replacement = 'URifleAmmo';
}
else if ( (e.Replacee == 'InvulnerabilitySphere') || (e.Replacee == 'ArtiInvulnerability') ) e.Replacement = 'PowerShield';
@ -922,17 +940,25 @@ Class UnrealMainHandler : EventHandler
override void PlayerEntered( PlayerEvent e )
{
if ( flak_translocator )
{
players[e.playernumber].mo.TakeInventory("Translocator",1);
if ( sting_telegun )
players[e.playernumber].mo.GiveInventory("UTranslocator",1);
if ( sting_flares )
{
players[e.playernumber].mo.GiveInventory("LightFlare",1);
players[e.playernumber].mo.GiveInventory("DarkFlare",1);
}
}
override void PlayerRespawned( PlayerEvent e )
{
if ( flak_translocator )
{
players[e.playernumber].mo.TakeInventory("Translocator",1);
if ( sting_telegun )
players[e.playernumber].mo.GiveInventory("UTranslocator",1);
if ( sting_flares )
{
players[e.playernumber].mo.GiveInventory("LightFlare",1);
players[e.playernumber].mo.GiveInventory("DarkFlare",1);
}
}
override void NetworkProcess( ConsoleEvent e )
@ -944,6 +970,12 @@ Class UnrealMainHandler : EventHandler
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] )
{
players[i].mo.TakeInventory("Translocator",1);
}
}
if ( sting_telegun )
{
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] )
{
players[i].mo.GiveInventory("UTranslocator",1);
}
}
@ -954,6 +986,36 @@ Class UnrealMainHandler : EventHandler
players[i].mo.TakeInventory("UTranslocator",1);
}
}
if ( sting_flares )
{
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] )
{
players[i].mo.GiveInventory("LightFlare",1);
players[i].mo.GiveInventory("DarkFlare",1);
}
}
else
{
for ( int i=0; i<MAXPLAYERS; i++ ) if ( playeringame[i] )
{
players[i].mo.TakeInventory("LightFlare",1);
players[i].mo.TakeInventory("DarkFlare",1);
}
}
}
}
override void WorldLoaded( WorldEvent e )
{
// More "authentic" Unreal flavor of these edits
if ( (level.GetChecksum() ~== "959A613006CC3AA912C4A22908B7566A") || (level.GetChecksum() ~== "0EADB2F82732A968B8513E4DC6138439") )
{
S_ChangeMusic("Cyrene");
TextureID sky95 = TexMan.CheckForTexture("95Bg",TexMan.Type_Any);
level.ChangeSky(sky95,sky95);
level.ReplaceTextures("rClfFlr0","C_flr19",0);
level.ReplaceTextures("rClfBas0","C_wal19k",0);
level.ReplaceTextures("uAlnWl2b","C_WAL19A",0);
level.ReplaceTextures("xAlnWl2b","C_WAL19F",0);
}
}
}

View file

@ -16,18 +16,21 @@ Class UnrealHUD : BaseStatusBar
int lastseentic, Count;
// Fonts
Font LargeFont, LargeRedFont, MedFont, WhiteFont, TinyFont, TinyWhiteFont, TinyRedFont;
Font LargeFont, LargeRedFont, UBigFont, MedFont, WhiteFont, TinyFont, TinyWhiteFont, TinyRedFont;
HUDFont mMapFont;
// Common Textures
TextureID HalfHud, HudLine, HudAmmo, IconHeal, IconSkul, IconSel, IconBase, KeyIcons[7];
// These can't be used yet
/*String PickupMsg;
// messaging stuff
String PickupMsg;
int PickupMsgTic;
String ShortMsg[4];
int ShortMsgTic[4];
int ShortMsgCol[4];*/
int ShortMsgCol[4];
String MidPrintStr;
int MidPrintTic;
bool MidPrintLarge;
// 0.83 HUD stuff
String OldAmmo[18];
@ -36,10 +39,14 @@ Class UnrealHUD : BaseStatusBar
Class<Inventory> OldArmorType[6];
String OldKeys[7];
HUDFont mOldDigits;
Font OldLargeFont, OldSmallFont;
// Translations
int RedIcon;
// Translator menu interaction
transient bool bTranslatorActive;
override void Init()
{
Super.Init();
@ -51,14 +58,14 @@ Class UnrealHUD : BaseStatusBar
GreenColor = "00 FF 00";
BlackColor = "00 00 00";
DrawColor = "FF FF FF";
LargeFont = Font.FindFont('ULargeFont');
LargeRedFont = Font.FindFont('ULargeRedFont');
MedFont = Font.FindFont('UMedFont');
WhiteFont = Font.FindFont('UWhiteFont');
TinyFont = Font.FindFont('UTinyFont');
TinyWhiteFont = Font.FindFont('UTinyWhiteFont');
TinyRedFont = Font.FindFont('UTinyRedFont');
mMapFont = HUDFont.Create(WhiteFont);
LargeFont = Font.GetFont('ULargeFont');
LargeRedFont = Font.GetFont('ULargeRedFont');
UBigFont = Font.GetFont('UBigFont');
MedFont = Font.GetFont('UMedFont');
WhiteFont = Font.GetFont('UWhiteFont');
TinyFont = Font.GetFont('UTinyFont');
TinyWhiteFont = Font.GetFont('UTinyWhiteFont');
TinyRedFont = Font.GetFont('UTinyRedFont');
HalfHud = TexMan.CheckForTexture("HalfHud",TexMan.Type_Any);
HudLine = TexMan.CheckForTexture("HudLine",TexMan.Type_Any);
HudAmmo = TexMan.CheckForTexture("HudAmmo",TexMan.Type_Any);
@ -74,7 +81,10 @@ Class UnrealHUD : BaseStatusBar
KeyIcons[4] = TexMan.CheckForTexture("I_SkullB",TexMan.Type_Any);
KeyIcons[5] = TexMan.CheckForTexture("I_SkullY",TexMan.Type_Any);
KeyIcons[6] = TexMan.CheckForTexture("I_KeyG",TexMan.Type_Any);
mOldDigits = HUDFont.Create(Font.FindFont('U083Digits'),26,Mono_CellLeft);
mOldDigits = HUDFont.Create(Font.GetFont('U083Digits'),26,Mono_CellLeft);
mMapFont = HUDFont.Create(WhiteFont);
OldLargeFont = Font.GetFont('UOldLargeFont');
OldSmallFont = Font.GetFont('UOldSmallFont');
OldAmmo[0] = "Disp083";
OldAmmo[1] = "Clip083";
OldAmmo[2] = "Tary083";
@ -137,8 +147,13 @@ Class UnrealHUD : BaseStatusBar
Super.Draw(state,TicFrac);
FracTic = TicFrac;
HudMode = CVar.GetCVar('stinger_hudmode',players[consoleplayer]).GetInt();
scalev.x = scalev.y = Max(0,CVar.GetCVar('stinger_hudscale',players[consoleplayer]).GetInt());
if ( scalev.x == 0 ) scalev.x = scalev.y = max(1,min(Screen.GetWidth()/640.,Screen.GetHeight()/480.));
scalev.x = scalev.y = CVar.GetCVar('hud_scale',players[consoleplayer]).GetInt();
if ( scalev.x == 0 ) scalev.x = scalev.y = max(1,min(Screen.GetWidth()/640.,Screen.GetHeight()/480.)); // the typical behavior is scaling to 640x400 but we're expecting 4:3 here
else if ( scalev.x < 0 )
{
scalev.x = CleanXFac_1;
scalev.y = CleanYFac_1;
}
ClipX = Screen.GetWidth()/scalev.x;
ClipY = Screen.GetHeight()/scalev.y;
CurX = 0;
@ -149,21 +164,22 @@ Class UnrealHUD : BaseStatusBar
UnrealInventory(i).PreRender(lbottom);
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
UTWeapon(CPlayer.ReadyWeapon).PreRender(lbottom);
if ( state == HUD_StatusBar )
{
BeginStatusBar();
DrawUnrealBar();
}
else if ( state == HUD_Fullscreen )
if ( state == HUD_Fullscreen )
{
BeginHUD();
DrawUnrealHUD();
}
else if ( state == HUD_StatusBar )
{
BeginStatusBar();
DrawUnrealBar();
}
for ( Inventory i=CPlayer.mo.inv; i; i=i.inv )
if ( i is 'UnrealInventory' )
UnrealInventory(i).PostRender(lbottom);
if ( CPlayer.ReadyWeapon is 'UTWeapon' )
UTWeapon(CPlayer.ReadyWeapon).PostRender(lbottom);
DrawIdentifyInfo(state);
DrawMessages(state);
}
@ -360,11 +376,7 @@ Class UnrealHUD : BaseStatusBar
}
}
// draw translator
if ( translator )
{
if ( translator.bCurrentlyActivated ) translator.DrawTranslator(scalev,ClipX,ClipY);
else bFlashTranslator = (translator.bNewMessage || translator.bNotNewMessage);
}
if ( translator ) bFlashTranslator = (translator.bNewMessage || translator.bNotNewMessage);
// draw the inventory bar
if ( (HUDMode == 5) || !SelectedItem ) return;
Count++;
@ -375,7 +387,7 @@ Class UnrealHUD : BaseStatusBar
DrawHudIcon(x,y,Prev,bRed);
if ( Prev.MaxAmount > 1 ) DrawNumberOf(Prev,x,y);
}
bRed = ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bActive) || (SelectedItem is 'Powerup') || ((SelectedItem is 'UTranslator') && bFlashTranslator);
bRed = ((SelectedItem is 'UnrealInventory') && UnrealInventory(SelectedItem).bActive) || (SelectedItem is 'Powerup') || ((SelectedItem is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4))));
if ( !Next && !Prev && !bDrawOne ) DrawHudIcon(x+64,y,SelectedItem,bRed);
else DrawHudIcon(x+32,y,SelectedItem,bRed);
CurX = x+32;
@ -485,7 +497,7 @@ Class UnrealHUD : BaseStatusBar
Screen.DrawTexture(HudLine,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_WindowRightF,Min(28.*(CPlayer.mo.Health/double(CPlayer.mo.SpawnHealth())),28.));
}
private void DrawIdentifyInfo()
private void DrawIdentifyInfo( int state )
{
double lalpha = 2.0-((gametic+fractic)-lastseentic)/Thinker.TICRATE;
if ( !lastseen || (lalpha <= 0) ) return;
@ -496,14 +508,15 @@ Class UnrealHUD : BaseStatusBar
cl1 = String.Format("Dark%s",cl2);
}
String tname = String.Format("\c[%s]%s:\c[%s] %s",cl1,StringTable.Localize("$M_NAME"),cl2,lastseen.player.GetUserName());
CurX = (ClipX-WhiteFont.StringWidth(tname))/2;
let fnt = (state==HUD_Fullscreen)?WhiteFont:OldSmallFont;
CurX = (ClipX-fnt.StringWidth(tname))/2;
CurY = ClipY-54;
Screen.DrawText(WhiteFont,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
Screen.DrawText(fnt,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
if ( !deathmatch || (lastseen.IsTeammate(CPlayer.mo)) )
{
CurY += 1.2*WhiteFont.GetHeight();
CurY += 1.2*fnt.GetHeight();
tname = String.Format("\c[%s]%s:\c[%s] %d",cl1,StringTable.Localize("$M_HEALTH"),cl2,lastseen.Health);
Screen.DrawText(WhiteFont,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
Screen.DrawText(fnt,Font.CR_UNTRANSLATED,CurX,CurY,tname,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,lalpha/2.);
}
}
@ -530,9 +543,27 @@ Class UnrealHUD : BaseStatusBar
private void DrawUnrealHUD()
{
if ( HudMode == 5 )
if ( HudMode >= 5 )
{
DrawInventory(ClipX-96,0);
// minimal hud
int ArmorAmount = 0;
for ( Inventory Inv=CPlayer.mo.Inv; Inv; Inv=Inv.Inv )
{
if ( !(Inv is 'UTArmor') ) continue;
ArmorAmount += Inv.Amount;
}
int AmmoAmount1 = 0, AmmoAmount2 = 0;
Ammo amo1, amo2;
[amo1, amo2] = GetCurrentAmmo();
if ( amo1 )
{
AmmoAmount1 = amo1.Amount;
if ( amo2 ) AmmoAmount2 = amo2.Amount;
}
String str;
if ( amo1 && amo2 && (amo2 != amo1) ) str = String.Format(StringTable.Localize("$S_MINHUD2"),CPlayer.Health,(deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount,AmmoAmount2,AmmoAmount1);
else str = String.Format(StringTable.Localize("$S_MINHUD"),CPlayer.Health,(deathmatch||teamplay)?CPlayer.fragcount:CPlayer.killcount,AmmoAmount1);
Screen.DrawText(OldSmallFont,Font.CR_WHITE,(Screen.GetWidth()-OldSmallFont.StringWidth(str)*CleanXFac_1)/2,CleanYFac_1,str,DTA_CleanNoMove_1,true);
return;
}
if ( ClipX < 320 ) HudMode = 4;
@ -566,14 +597,32 @@ Class UnrealHUD : BaseStatusBar
else if ( HudMode == 3 ) DrawKeys(deathmatch?32:0,ClipY-48,true);
else if ( HudMode == 4 ) DrawKeys(deathmatch?32:0,ClipY-16,true);
}
// Display Identification Info
DrawIdentifyInfo();
}
private void DrawUnrealBar()
{
// 0.83 status bar, just for funsies
DrawImage("Bar083",(0,336),DI_ITEM_OFFSETS);
// extra widescreen filler
bool first = true;
double base = -128;
double rx, dummy;
do
{
[rx, dummy, dummy] = StatusBarToRealCoords(base,0,HorizontalResolution);
DrawImage(first?"BarL083":"BarM083",(base,336),DI_ITEM_OFFSETS);
first = false;
base -= 128;
} while ( rx >= -128 );
first = true;
base = 640;
do
{
[rx, dummy, dummy] = StatusBarToRealCoords(base,0,HorizontalResolution);
DrawImage(first?"BarR083":"BarM083",(base,336),DI_ITEM_OFFSETS);
first = false;
base += 128;
} while ( rx < Screen.GetWidth() );
static const float slotofs[] = {525, 84, 128, 173, 216, 259, 349, 392, 436, 481};
static const float keyofs[] = {187, 211, 235, 379, 403, 427};
for ( int i=0; i<10; i++ )
@ -626,23 +675,13 @@ Class UnrealHUD : BaseStatusBar
if ( HudMode > 5 ) return;
// Draw frags in DM
if ( deathmatch ) DrawFragCount(ClipX-32,0);
// Need to draw the inventory bar (and translator)
// Need to draw the inventory bar
DrawInventory(ClipX-(deathmatch?128:96),0,false,true);
// Display Identification Info
DrawIdentifyInfo();
}
override void Tick()
{
Super.Tick();
// prune expired short messages
/*for ( int i=0; i<3; i++ )
{
if ( (gametic-ShortMsgTic[i]) < 70 ) continue;
ShortMsg[i] = ShortMsg[i+1];
ShortMsgTic[i] = ShortMsgTic[i+1];
ShortMsgCol[i] = ShortMsgCol[i+1];
}*/
CPlayer.inventorytics = 0;
vtracer.ignore = CPlayer.mo;
vtracer.trace(CPlayer.mo.Vec2OffsetZ(0,0,CPlayer.viewz),CPlayer.mo.CurSector,(cos(CPlayer.mo.angle)*cos(CPlayer.mo.pitch),sin(CPlayer.mo.angle)*cos(CPlayer.mo.pitch),-sin(CPlayer.mo.pitch)),1000,0);
@ -651,16 +690,17 @@ Class UnrealHUD : BaseStatusBar
lastseentic = gametic;
}
// all of this requires features that are not available yet
/*override void NewGame()
{
PickupMsg = "";
}
override void FlushNotify()
{
for ( int i=0; i<4; i++ )
{
ShortMsg[i] = "";
ShortMsgTic[i] = int.min;
}
PickupMsg = "";
PickupMsgTic = int.min;
MidPrintStr = "";
MidPrintTic = int.min;
}
override bool ProcessNotify( EPrintLevel printlevel, String outline )
@ -669,7 +709,7 @@ Class UnrealHUD : BaseStatusBar
{
// set pickup message
PickupMsg = outline;
PickupMsgTic = gametic;
PickupMsgTic = gametic+50;
return true;
}
else
@ -685,7 +725,26 @@ Class UnrealHUD : BaseStatusBar
else if ( (printlevel == PRINT_CHAT) || (printlevel == PRINT_TEAMCHAT) ) ShortMsgCol[0] = Font.CR_GREEN;
else ShortMsgCol[0] = Font.CR_WHITE;
ShortMsg[0] = outline;
ShortMsgTic[0] = gametic;
ShortMsgTic[0] = gametic+70;
return true;
}
return false;
}
override bool ProcessMidPrint( Font fnt, String msg, bool bold )
{
if ( !fnt || (fnt == SmallFont) || (fnt == OriginalSmallFont) || (fnt == NewSmallFont) )
{
MidPrintStr = msg;
MidPrintLarge = false;
MidPrintTic = gametic+70;
return true;
}
else if ( fnt == BigFont )
{
MidPrintStr = msg;
MidPrintLarge = true;
MidPrintTic = gametic+70;
return true;
}
return false;
@ -702,19 +761,24 @@ Class UnrealHUD : BaseStatusBar
fullstr.Remove(7,1);
Screen.DrawText(WhiteFont,Font.CR_GREEN,xpos,ypos,fullstr,DTA_CleanNoMove_1,true);
return true;
}*/
}
private void DrawMessages( int state )
{
// TODO add map intro text like in Unreal
/*double malpha = 2.0-((gametic+fractic)-PickupMsgTic)/Thinker.TICRATE;
int xpos, ypos;
if ( PickupMsg.Length() > 0 && (malpha > 0) )
if ( (MidPrintStr.Length() > 0) && (MidPrintTic > gametic) )
{
let mfnt = MidPrintLarge?UBigFont:WhiteFont;
xpos = (Screen.GetWidth()-mfnt.StringWidth(MidPrintStr)*CleanXFac_1)/2;
ypos = 96*CleanYFac_1;
Screen.DrawText(mfnt,Font.FindFontColor('UTHudText'),xpos,ypos,MidPrintStr,DTA_CleanNoMove_1,true,DTA_Alpha,clamp((MidPrintTic-gametic+fractic)*0.05,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
if ( PickupMsgTic > gametic )
{
xpos = (Screen.GetWidth()-WhiteFont.StringWidth(PickupMsg)*CleanXFac_1)/2;
if ( state == HUD_Statusbar ) ypos = GetTopOfStatusBar()-21*CleanYFac_1;
else ypos = Screen.GetHeight()-41*CleanYFac_1;
Screen.DrawText(WhiteFont,Font.CR_WHITE,xpos,ypos,PickupMsg,DTA_CleanNoMove_1,true,DTA_Alpha,min(1.,malpha),DTA_LegacyRenderStyle,STYLE_Add);
Screen.DrawText(WhiteFont,Font.CR_WHITE,xpos,ypos,PickupMsg,DTA_CleanNoMove_1,true,DTA_Alpha,clamp((PickupMsgTic-gametic+fractic)*0.05,0,1),DTA_LegacyRenderStyle,STYLE_Add);
}
// draw messages
xpos = 4*CleanXFac_1;
@ -722,21 +786,20 @@ Class UnrealHUD : BaseStatusBar
if ( (state == HUD_Fullscreen) && (HudMode < 2) && DrawArmor(0,0,false,true) ) ypos += int(32*scalev.y);
for ( int i=3; i>=0; i-- )
{
if ( (ShortMsg[i].Length() <= 0) || (gametic-ShortMsgTic[i] >= 70) ) continue;
if ( ShortMsgTic[i] < gametic ) continue;
let lines = WhiteFont.BreakLines(ShortMsg[i],CleanWidth_1/2);
for ( int j=0; j<lines.Count(); j++ )
{
Screen.DrawText(WhiteFont,ShortMsgCol[i],xpos,ypos,lines.StringAt(j),DTA_CleanNoMove_1,true);
ypos += (WhiteFont.GetHeight()+2)*CleanYFac_1;
}
}*/
}
}
override void DrawAutomapHUD( double ticFrac )
{
int crdefault = Font.CR_GREY;
int highlight = Font.CR_RED;
double cbottom = Screen.GetHeight()*0.99;
let scale = GetHUDScale();
double textdist = 8./scale.Y;
int height = WhiteFont.GetHeight();
@ -751,6 +814,7 @@ Class UnrealHUD : BaseStatusBar
double ltop = 0, rtop = 0;
if ( (HudMode < 6) && CPlayer.mo.InvSel )
rtop += (32*scalev.y)/scale.Y;
double cbottom = GetTopOfStatusBar()-textdist;
int protrusion = GetProtrusion(swidth/hres);
[tmp,tmp,hres] = StatusbarToRealCoords(0,0,protrusion);
width += int((swidth-hres)/scale.X);

View file

@ -51,16 +51,18 @@ Class ListMenuItemUnrealTextItem : ListMenuItemSelectable
override void Drawer( bool selected )
{
let tFont = generic_ui?NewSmallFont:mFont;
double basex = floor(0.5*(CleanWidth_1-tFont.StringWidth(StringTable.Localize(mText))));
String str = StringTable.Localize(mText);
let fnt = (generic_ui||!mFont.CanPrint(str))?NewSmallFont:mFont;
double basex = floor(0.5*(CleanWidth_1-fnt.StringWidth(str)));
double basey = floor(0.25*(CleanHeight_1-mSpacing*5));
Screen.DrawText(tFont,mColor,(basex+mXPos)*CleanXFac_1,(basey+mYpos)*CleanYFac_1,mText,DTA_CleanNoMove_1,true,DTA_Alpha,selected?1.0:0.5);
Screen.DrawText(fnt,(fnt==NewSmallFont)?Font.CR_GREEN:mColor,(basex+mXPos)*CleanXFac_1,(basey+mYpos)*CleanYFac_1,str,DTA_CleanNoMove_1,true,DTA_Alpha,selected?1.0:0.5);
}
override int GetWidth()
{
let tFont = generic_ui?NewSmallFont:mFont;
return max(1,tFont.StringWidth(StringTable.Localize(mText)));
String str = StringTable.Localize(mText);
let fnt = (generic_ui||!mFont.CanPrint(str))?NewSmallFont:mFont;
return max(1,fnt.StringWidth(StringTable.Localize(mText)));
}
override void DrawSelector( double xofs, double yofs, TextureID tex )
@ -97,14 +99,44 @@ Class OptionMenuItemHudType : OptionMenuItem
{
int xpos = indent + CursorSpace();
int ypos = y + OptionMenuSettings.mLinespacing*CleanYfac_1;
Screen.DrawFrame(xpos,ypos,64*CleanXFac_1,64*CleanYFac_1);
Screen.DrawTexture(tex[mCVar.GetInt()],false,xpos,ypos,DTA_CleanNoMove_1,true);
return -1;
}
}
// because I can't change the font color in mapinfo
// because I can't change the font or color in mapinfo
Class GreenMessageBox : MessageBoxMenu
{
override void Init( Menu parent, String message, int messagemode, bool playsound, Name cmd, voidptr native_handler )
{
Super.Init(parent,message,messagemode,playsound,cmd,native_handler);
Font NFont = Font.GetFont('UMedFont');
if ( !generic_ui )
{
if ( NFont && NFont.CanPrint(message) && NFont.CanPrint("$TXT_YES") && NFont.CanPrint("$TXT_NO") ) textFont = NFont;
else if ( OriginalSmallFont && OriginalSmallFont.CanPrint(message) && OriginalSmallFont.CanPrint("$TXT_YES") && OriginalSmallFont.CanPrint("$TXT_NO") ) textFont = OriginalSmallFont;
}
if ( !textFont )
{
arrowFont = textFont = NewSmallFont;
int factor = (CleanXfac+1)/2;
destWidth = screen.GetWidth()/factor;
destHeight = screen.GetHeight()/factor;
selector = "▶";
}
else
{
arrowFont = ConFont;
destWidth = CleanWidth;
destHeight = CleanHeight;
selector = "\xd";
}
int mr1 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_YES"));
int mr2 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_NO"));
mMouseRight = MAX(mr1,mr2);
mMessage = textFont.BreakLines(Stringtable.Localize(message),generic_ui?600:300);
}
override void Drawer ()
{
int i, y;
@ -133,3 +165,202 @@ Class GreenMessageBox : MessageBoxMenu
}
}
}
// Translator display as a menu, allows for more interactivity
// TODO:
// - additional mouse input options
// - support for extended menu graphic
Class TranslatorMenu : GenericMenu
{
bool bShowHint;
UTranslator trns;
TextureID thud, scroll[4];
Font tfnt, mfnt, pfnt;
BrokenLines lines;
int th, startline[0], maxlines[2], entry;
private void SetText( String txt )
{
String ttxt = (txt.Length()>0)?txt:StringTable.Localize("$TR_NOMSG");
tfnt = (!mfnt.CanPrint(ttxt))?NewSmallFont:mfnt;
lines = tfnt.BreakLines(ttxt,200);
th = tfnt.GetHeight();
startline[0] = 0;
startline[1] = 0;
maxlines[0] = 88/th;
}
override void Init( Menu parent )
{
Super.Init(parent);
trns = UTranslator(players[consoleplayer].mo.FindInventory('UTranslator'));
mfnt = Font.GetFont('UMedFont');
pfnt = Font.GetFont('UOldTinyFont');
if ( !trns || !trns.Owner || (trns.Owner.Health <= 0) )
{
// don't do anything, will get killed in the next tick
return;
}
MenuSound("menu/activate");
thud = TexMan.CheckForTexture("TranHUD3",TexMan.Type_Any);
scroll[0] = TexMan.CheckForTexture("VSldT",TexMan.Type_Any);
scroll[1] = TexMan.CheckForTexture("VSldM",TexMan.Type_Any);
scroll[2] = TexMan.CheckForTexture("VSldB",TexMan.Type_Any);
scroll[3] = TexMan.CheckForTexture("VSldO",TexMan.Type_Any);
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = true;
entry = 0;
SetText(StringTable.Localize(GetMessage(entry)));
}
private String GetMessage( int idx = 0 )
{
if ( idx == 0 ) return trns.NewMessage;
else return trns.OldMessages[trns.OldMessages.Size()-idx];
}
private String GetHint( int idx = 0 )
{
if ( idx == 0 ) return trns.Hint;
else return trns.OldHints[trns.OldHints.Size()-idx];
}
override void Ticker()
{
menuactive = OnNoPause; // don't pause game while translator is active
if ( trns && trns.Owner && (trns.Owner.Health > 0) ) return;
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = false;
Close();
}
override bool OnUIEvent( UIEvent ev )
{
switch ( ev.type )
{
case UIEvent.Type_WheelUp:
if ( startline[0] > 0 ) MenuSound("menu/cursor");
startline[0] = max(0,startline[0]-3);
return true;
case UIEvent.Type_WheelDown:
if ( startline[0] < max(0,lines.Count()-maxlines[0]) ) MenuSound("menu/cursor");
startline[0] = min(max(0,lines.Count()-maxlines[0]),startline[0]+3);
return true;
}
return Super.OnUIEvent(ev);
}
override bool MenuEvent( int mkey, bool fromcontroller )
{
switch( mkey )
{
case MKEY_Enter:
case MKEY_Back:
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = false;
MenuSound(GetCurrentMenu()?"menu/backup":"menu/clear");
Close();
return true;
case MKEY_Up:
if ( startline[0] > 0 ) MenuSound("menu/cursor");
startline[0] = max(0,startline[0]-1);
return true;
case MKEY_Down:
if ( startline[0] < max(0,lines.Count()-maxlines[0]) ) MenuSound("menu/cursor");
startline[0] = min(max(0,lines.Count()-maxlines[0]),startline[0]+1);
return true;
case MKEY_PageDown:
if ( trns && (GetHint(entry).length() > 0) )
{
MenuSound("menu/cursor");
bShowHint = true;
SetText(StringTable.Localize(GetHint(entry)));
}
return true;
case MKEY_PageUp:
if ( trns && bShowHint )
{
MenuSound("menu/cursor");
bShowHint = false;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
case MKEY_Left:
if ( trns && (entry < trns.OldMessages.Size()) )
{
MenuSound("menu/cursor");
bShowHint = false;
entry++;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
case MKEY_Right:
if ( trns && (entry > 0) )
{
MenuSound("menu/cursor");
bShowHint = false;
entry--;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
}
return false;
}
override void Drawer()
{
Super.Drawer();
if ( trns && trns.Owner && (trns.Owner.Health > 0) ) return;
double ClipX, ClipY, CurX, CurY;
if ( StatusBar is 'UnrealHUD' )
{
ClipX = UnrealHUD(StatusBar).ClipX;
ClipY = UnrealHUD(StatusBar).ClipY;
}
else
{
ClipX = CleanWidth_1;
ClipY = CleanHeight_1;
}
// The translator
CurX = ClipX/2-128;
CurY = ClipY/2-68;
Screen.DrawTexture(thud,false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// The message text
CurX += 22;
CurY += 22;
int l = startline[0];
for ( int i=0; i<maxlines[0]; i++ )
{
if ( l >= lines.Count() ) break;
Screen.DrawText(tfnt,Font.CR_UNTRANSLATED,CurX,CurY,lines.StringAt(l),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
l++;
CurY += th;
}
// Scrollbar
CurX = ClipX/2+100;
if ( lines.Count() > maxlines[0] )
{
CurY = ClipY/2-54;
Screen.DrawTexture(scroll[0],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 8;
for ( int i=0; i<10; i++ )
{
Screen.DrawTexture(scroll[1],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 8;
}
Screen.DrawTexture(scroll[2],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY = (ClipY/2-46) + ((startline[0]*72)/max(1,lines.Count()-maxlines[0]));
Screen.DrawTexture(scroll[3],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
if ( !bShowHint && (GetHint(entry).length() > 0) )
{
CurY = ClipY/2+40;
Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,">>",DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,(gametic%16)/16.);
}
CurX = ClipX/2-106;
CurY = ClipY/2+40;
if ( bShowHint ) Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,"<<",DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,(gametic%16)/16.);
else if ( trns.OldMessages.Size() > 0 ) Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,String.Format("%s %d / %d %s",(entry<trns.OldMessages.Size())?"<":" ",trns.OldMessages.Size()+1-entry,trns.OldMessages.Size()+1,(entry>0)?">":" "),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
}

View file

@ -1,18 +1,186 @@
Class UInvisibility : UnrealInventory
{
Default
{
Tag "$T_INVISIBILITY";
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+INVENTORY.ALWAYSPICKUP;
Inventory.Icon "I_Invis";
Inventory.PickupMessage "$I_INVISIBILITY";
Inventory.RespawnTics 3500;
Inventory.MaxAmount 2;
UnrealInventory.Charge 100;
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
bActive = !bActive;
if ( bActive )
{
Owner.A_PlaySound("uinvis/toggle",CHAN_ITEM);
Owner.GiveInventory("PowerUInvisibility",1);
}
else Owner.TakeInventory("PowerUInvisibility",1);
return false;
}
override void Tick()
{
Super.Tick();
if ( !bActive ) return;
if ( special1 == -1 )
{
Owner.TakeInventory("PowerUInvisibility",1);
special1 = 3;
}
else if ( special1 > 1 ) special1--;
else if ( special1 == 1 )
{
Owner.GiveInventory("PowerUInvisibility",1);
special1 = 0;
}
if ( !(level.maptime%35) && DrainCharge(1) )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_INVISIBILITY"));
Owner.TakeInventory("PowerUInvisibility",1);
DepleteOrDestroy();
}
}
override void OnDrop( Actor dropper )
{
Super.OnDrop(dropper);
dropper.TakeInventory("PowerUInvisibility",1);
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
tracer = Spawn("UInvisibilityX",pos);
tracer.angle = angle;
tracer.target = self;
}
States
{
Spawn:
INVS A -1;
Stop;
}
}
Class UInvisibilityX : AsmdAmmoX
{
States
{
Spawn:
INVS A -1 Bright;
Stop;
}
}
Class PowerUInvisibility : PowerInvisibility
{
Default
{
Powerup.Duration 0x7FFFFFFD;
Powerup.Strength 90;
Powerup.Mode "Additive";
}
}
Class Amplifier : UnrealInventory
{
static Amplifier Active( Actor Owner )
Default
{
Tag "$T_AMPLIFIER";
+COUNTITEM;
+INVENTORY.BIGPOWERUP;
+INVENTORY.ALWAYSPICKUP;
Inventory.Icon "I_Amp";
Inventory.PickupMessage "$I_AMPLIFIER";
Inventory.RespawnTics 3150;
Inventory.MaxAmount 2;
UnrealInventory.Charge 1000;
}
static double GetMult( Actor Owner, int val )
{
if ( !Owner ) return 1.;
let d = Amplifier(Owner.FindInventory("Amplifier"));
if ( d && d.bActive ) return d;
return null;
if ( !d || !d.bActive ) return 1.;
double Multiplier = max(1,4*(double(d.Charge-val)/d.DefaultCharge));
d.DrainCharge(val);
return Multiplier;
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
bActive = !bActive;
Owner.A_PlaySound("amplifier/set",CHAN_ITEM);
return false;
}
override void Tick()
{
Super.Tick();
if ( bActive && !tracer )
{
tracer = Spawn("AmpSound",Owner.pos);
tracer.target = Owner;
tracer.master = self;
}
else if ( !bActive && tracer ) tracer.Destroy();
if ( !bActive ) return;
if ( (Charge <= 0) || (!(level.maptime%35) && DrainCharge(2)) )
{
Owner.A_PlaySound("amplifier/set",CHAN_ITEM);
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_AMPLIFIER"));
if ( tracer ) tracer.Destroy();
DepleteOrDestroy();
}
}
States
{
Spawn:
AMPP A -1;
Stop;
}
}
Class AmpSound : Actor
{
Default
{
+NOBLOCKMAP;
+NOGRAVITY;
}
override void Tick()
{
Super.Tick();
if ( !target || !master )
{
Destroy();
return;
}
SetOrigin(target.pos,true);
if ( target.CheckLocalView() )
{
A_SoundVolume(CHAN_VOICE,0.0);
A_SoundVolume(CHAN_7,1.0);
}
else
{
A_SoundVolume(CHAN_VOICE,0.25);
A_SoundVolume(CHAN_7,0.0);
}
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_PlaySound("amplifier/act",CHAN_VOICE,0.25,true,1.5);
A_PlaySound("amplifier/act",CHAN_7,1.0,true,ATTN_NONE);
}
override void OnDestroy()
{
Super.OnDestroy();
A_StopSound(CHAN_VOICE);
A_StopSound(CHAN_7);
}
}
@ -21,22 +189,29 @@ Class UJumpBoots : UnrealInventory
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( (level.maptime > 0) || !InStateSequence(CurState,FindState("Spawn")) ) return;
// detect hurtfloors
// can't detect terraindef-based damage
// this is currently an engine limitation
bool foundslime = false;
bool foundlava = false;
bool foundswim = false;
for ( int i=0; i<level.Sectors.Size(); i++ )
{
Sector s = level.Sectors[i];
if ( s.MoreFlags&Sector.SECMF_UNDERWATER ) foundswim = true;
if ( !s.DamageInterval || !s.DamageAmount ) continue;
if ( s.DamageType == 'Slime' ) foundslime = true;
else if ( s.DamageType == 'Fire' ) foundlava = true;
}
// TODO replace self with asbestos/toxin suits
// TODO replace self with asbestos/toxin suits or scuba
}
}
Class MotionDetector : UnrealInventory
{
}
Class SCUBAGear : UnrealInventory
{
}

View file

@ -2,6 +2,6 @@ Class UTranslocatorAmmo : Ammo
{
}
Class UTranslocator : UTWeapon
Class UTranslocator : UnrealWeapon
{
}