Finished biorifle, began work on pulsegun.

Added some extra particle effects just for kicks.
Made various actors freeze-aware.
Tweaked a couple things here and there.
This commit is contained in:
Marisa the Magician 2018-05-17 02:17:10 +02:00
commit 73e8e8ada9
96 changed files with 1437 additions and 133 deletions

View file

@ -4,7 +4,6 @@ Class BioAmmo : Ammo
{
Tag "Biosludge Ammo";
Inventory.PickupMessage "You picked up the Biosludge Ammo.";
Inventory.PickupSound "ut/ammo";
Inventory.Amount 25;
Inventory.MaxAmount 100;
Ammo.BackpackAmount 50;
@ -21,10 +20,81 @@ Class BioAmmo : Ammo
Class BioHitbox : Actor
{
Default
{
Radius 2;
Height 2;
+SHOOTABLE;
+NOGRAVITY;
+NOCLIP;
+DONTSPLASH;
+NOBLOOD;
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
if ( inflictor == target ) return 0;
if ( target && !target.InStateSequence(target.CurState,target.ResolveState("XDeath")) )
{
target.bAMBUSH = true;
target.ExplodeMissile(null,inflictor);
}
return 0;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
SetOrigin(target.pos-(0,0,height*0.5),true);
}
}
Class BioLight : DynamicLight
{
Default
{
DynamicLight.Type "Point";
Args 64,255,48,8;
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
args[LIGHT_INTENSITY] = 8*target.Scale.x;
}
}
Class BioXLight : DynamicLight
{
double lifetime;
Default
{
DynamicLight.Type "Point";
Args 64,255,48,30;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
lifetime = 1.0;
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 64*lifetime;
args[LIGHT_GREEN] = 255*lifetime;
args[LIGHT_BLUE] = 48*lifetime;
lifetime -= 0.05;
if ( lifetime <= 0 ) Destroy();
}
}
Class BioGel : Actor
@ -41,35 +111,71 @@ Class BioGel : Actor
int deadtimer;
Line atline;
int atside;
int rollvel, pitchvel, yawvel;
override void PostBeginPlay()
{
Super.PostBeginPlay();
vel.z += 6;
deadtimer = -1;
l = Spawn("BioLight",pos);
l.target = self;
b = Spawn("BioHitbox",pos);
b.target = self;
rollvel = FRandom[GES](10,30)*RandomPick[GES](-1,1);
pitchvel = FRandom[GES](10,30)*RandomPick[GES](-1,1);
yawvel = FRandom[GES](10,30)*RandomPick[GES](-1,1);
}
action void A_SetToSlope( double dang, bool ceil = false )
override int SpecialMissileHit( Actor victim )
{
vector3 fnormal;
if ( ceil ) fnormal = invoker.CurSector.floorplane.Normal;
else fnormal = invoker.CurSector.ceilingplane.Normal;
vector2 fnormalp1 = ((fnormal.x != 0) || (fnormal.y != 0))?(fnormal.x,fnormal.y).Unit():(0,0);
vector2 fnormalp2 = ((fnormal.x,fnormal.y).Length(),fnormal.z);
double fang = atan2(fnormalp1.y,fnormalp1.x); // floor angle (not pitch!)
double fpitch = atan2(fnormalp2.x,fnormalp2.y); // floor pitch
double ddiff1 = cos(fang-(dang-90));
double ddiff2 = cos(fang-dang);
invoker.pitch = -fpitch*ddiff2;
invoker.roll = fpitch*ddiff1;
invoker.angle = dang;
if ( victim == b ) return 1;
if ( (victim is 'BioHitbox') && ((victim.target == master) || (victim.target.master == master)) ) return 1;
return -1;
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( !bNOGRAVITY )
{
A_SetRoll(roll+rollvel,SPF_INTERPOLATE);
A_SetPitch(pitch+pitchvel,SPF_INTERPOLATE);
A_SetPitch(pitch+yawvel,SPF_INTERPOLATE);
}
if ( !InStateSequence(CurState,FindState("XDeath")) && ((!bNOGRAVITY && !Random[GES](0,2)) || !Random[GES](0,10)) )
{
int numpt = Min(20,Scale.x*2)+Random[GES](-1,1);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[GES](-1,1),FRandom[GES](-1,1),FRandom[GES](-1,1)).unit()*FRandom[GES](1,3);
A_SpawnParticle("40FF30",SPF_FULLBRIGHT,Random[GES](30,60),FRandom[GES](1.2,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,-0.2,3.0);
}
}
if ( deadtimer <= -1 ) return;
let bi = BlockThingsIterator.Create(self,4*Scale.x);
while ( bi.Next() )
{
if ( !bi.Thing || !bi.Thing.bSHOOTABLE || (bi.Thing == b) || ((bi.Thing is 'BioHitbox') && ((bi.Thing.target.master == self) || (bi.Thing.target == master))) ) continue;
if ( (Distance2D(bi.Thing)-bi.Thing.radius <= 4*Scale.x) && ((bi.Thing.pos.z <= pos.z+4*Scale.x) && (bi.Thing.pos.z+bi.Thing.height >= pos.z-4*Scale.x)) ) deadtimer = 0;
}
if ( deadtimer-- <= 0 )
{
deadtimer = -1;
SetStateLabel("XDeath");
}
}
// align self to what surface was hit, currently does not support 3d floors + slopes properly
virtual void AlignSelf()
{
Vector3 normal;
FLineTraceData d;
A_NoGravity();
A_PlaySound("ges/hit");
A_Stop();
if ( bAMBUSH )
{
SetStateLabel("XDeath");
return;
}
Vector3 normal = (0,0,0);
FLineTraceData d;
A_SetSize(0.1,0);
if ( BlockingLine )
{
@ -84,7 +190,7 @@ Class BioGel : Actor
angle = atan2(normal.y,normal.x);
pitch = 0;
roll = 0;
LineTrace(angle+180,8,0,data:d);
LineTrace(angle+180,172,0,TRF_THRUACTORS,data:d);
SetOrigin(d.HitLocation+normal*0.5,false);
hittype = HIT_WALL;
}
@ -108,22 +214,55 @@ Class BioGel : Actor
hittype = HIT_CEILING;
else hittype = HIT_FLOOR;
}
else SetStateLabel("Crash");
else
{
SetStateLabel("XDeath");
return;
}
A_PlaySound("ges/hit");
A_SprayDecal("BioSplat",-172);
int numpt = Min(100,Scale.x*10)+Random[GES](-5,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (normal+(FRandom[GES](-.8,.8),FRandom[GES](-.8,.8),FRandom[GES](-.8,.8))).unit()*FRandom[GES](3,6);
A_SpawnParticle("40FF30",SPF_FULLBRIGHT,Random[GES](30,60),FRandom[GES](1.2,3.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,-0.2,3.0);
}
}
action void A_DropDrip()
{
// TODO
let d = Spawn("BioSplash",pos+cursector.ceilingplane.Normal*2*scale.x);
d.target = target;
d.angle = angle;
d.pitch = pitch;
d.roll = roll;
d.master = self;
d.scale = scale*0.5;
d.vel.z -= 6;
}
action void A_GelExplode()
{
A_NoGravity();
A_Stop();
if ( invoker.l ) invoker.l.Destroy();
if ( invoker.b ) invoker.b.Destroy();
let s = Spawn("BioXLight",pos);
s.args[3] *= Scale.x;
invoker.deadtimer = -1;
if ( invoker.atline ) invoker.atline.RemoteActivate(target,invoker.atside,SPAC_Impact,pos);
A_Explode(Random[GES](15,20)*Scale.x,Min(250,Scale.x*75));
A_Explode(Random[GES](15,25)*Scale.x,Min(250,Scale.x*25));
A_PlaySound("ges/explode",CHAN_VOICE);
// TODO particles
int numpt = Min(300,Scale.x*30)+Random[GES](-10,10);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[GES](-1,1),FRandom[GES](-1,1),FRandom[GES](-1,1)).unit()*FRandom[GES](3,12);
A_SpawnParticle("40FF30",SPF_FULLBRIGHT,Random[GES](30,60),FRandom[GES](2.4,6.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,-0.2,3.0);
}
Scale *= 0.5;
}
Default
{
Obituary "%o drank a glass of %k's dripping green load.";
DamageType 'Slime';
RenderStyle "Add";
Radius 4;
Height 4;
@ -133,6 +272,7 @@ Class BioGel : Actor
-NOGRAVITY;
+SKYEXPLODE;
+FORCERADIUSDMG;
+FORCEXYBILLBOARD;
}
States
{
@ -142,9 +282,10 @@ Class BioGel : Actor
Death:
GELH A 1 Bright AlignSelf();
GELH BCDEFGHIJ 1 Bright;
GELH J 0 Bright A_SetTics(Random[GES](10,30));
GELH J 1 Bright A_SetTics(Random[GES](10,30));
GELH J -1 Bright
{
invoker.deadtimer = Random[GES](250,300);
if ( invoker.hittype == HIT_WALL ) return ResolveState("Slide");
else if ( invoker.hittype == HIT_CEILING ) return ResolveState("Drip");
return ResolveState(null);
@ -154,15 +295,17 @@ Class BioGel : Actor
GELD ABCDEFGH 4 Bright;
GELD I 4 Bright A_DropDrip();
GELD JKLM 4 Bright;
GELD M -1 Bright;
Wait;
GELH J -1 Bright;
Stop;
Slide:
GELS ABCDEFG 3 Bright;
Wait;
GELS ABCDEF 3 Bright;
GELS G -1 Bright;
Stop;
Crash:
XDeath:
#### # 1 A_SetTics(Random[GES](1,3)); // TODO EXPLOSION
TNT1 A 1 A_GelExplode();
#### # 1 Bright A_SetTics(Random[GES](1,3));
GEX1 A 1 Bright A_GelExplode();
GEX1 BCDEFGHIJK 3 Bright;
Stop;
Shrivel:
GELX ABCDEFGHIJKL 1 Bright; // UNUSED
@ -172,10 +315,31 @@ Class BioGel : Actor
Class BioGlob : BioGel
{
int numsplash;
override void AlignSelf()
{
Super.AlignSelf();
// TODO splashes
if ( !bAMBUSH ) numsplash = 2*Scale.x-1;
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
Vector3 ofs = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
for ( int i=0; i<2; i++ )
{
if ( numsplash-- <= 0 ) return;
Vector3 dir = (ofs+(FRandom[GES](-.8,.8),FRandom[GES](-.8,.8),FRandom[GES](-.8,.8))).unit();
let d = Spawn("BioSplash",pos+ofs*4);
d.target = target;
d.master = self;
d.scale *= FRandom[GES](0.5,0.7);
d.angle = atan2(dir.y,dir.x);
d.pitch = -asin(dir.z);
d.vel = (cos(d.angle)*cos(d.pitch),sin(d.angle)*cos(d.pitch),-sin(d.pitch))*d.speed*FRandom[GES](0.25,0.35);
d.vel.z -= 3;
}
}
}
@ -190,10 +354,58 @@ Class BioSplash : BioGel
Class BioRifle : UTWeapon
{
double charge;
action void A_BioFire( bool alt = false )
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( !alt )
{
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
}
A_PlaySound("ges/fire",CHAN_WEAPON);
A_AlertMonsters();
if ( alt ) A_QuakeEx(1+0.5*invoker.charge,1+0.5*invoker.charge,1+0.5*invoker.charge,5+1.2*invoker.charge,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05+0.01*invoker.charge);
else A_QuakeEx(1,1,1,5,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+8.0*y-5.0*z;
Actor p;
if ( alt )
{
p = Spawn("BioGlob",origin);
p.A_SetScale(1+0.8*invoker.charge);
}
else p = Spawn("BioGel",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;
}
action void A_BeginCharge()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
invoker.charge = 0;
A_PlaySound("ges/charge",CHAN_WEAPON);
}
action void A_ChargeUp()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( invoker.charge >= 5.1 ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.charge = min(5.1,invoker.charge+0.5);
}
Default
{
Tag "GES Bio Rifle";
Inventory.PickupMessage "You got the GES BioRifle.";
Weapon.UpSound "ges/select";
Weapon.SlotNumber 3;
Weapon.AmmoType "BioAmmo";
Weapon.AmmoUse 1;
@ -211,16 +423,74 @@ Class BioRifle : UTWeapon
Ready:
BIOS ABCDEFGHIJKLMNOPQRSTUV 1;
Idle:
BIOI A 1 A_WeaponReady();
BIOI A 1
{
A_CheckReload();
A_WeaponReady();
}
Goto Idle;
Fire:
BIOF ABCDEFGHI 1;
BIOF A 1 A_BioFire();
BIOF BCDEFGHI 1;
Goto Idle;
AltFire:
BIOC ABCDEFGHIJKLMNOPQRSTUVWXYZ 1;
BIC2 ABCDE 1;
BIOM A 1;
BIOC A 4 A_BeginCharge();
BIOC B 5 A_ChargeUp();
BIOC CD 5;
BIOC E 0 A_Refire("AltFire2");
Goto AltRelease;
AltFire2:
BIOC E 5 A_ChargeUp();
BIOC FG 5;
BIOC H 0 A_Refire("AltFire3");
Goto AltRelease;
AltFire3:
BIOC H 5 A_ChargeUp();
BIOC IJ 5;
BIOC K 0 A_Refire("AltFire4");
Goto AltRelease;
AltFire4:
BIOC K 5 A_ChargeUp();
BIOC LM 5;
BIOC N 0 A_Refire("AltFire5");
Goto AltRelease;
AltFire5:
BIOC N 5 A_ChargeUp();
BIOC OP 5;
BIOC Q 0 A_Refire("AltFire6");
Goto AltRelease;
AltFire6:
BIOC Q 5 A_ChargeUp();
BIOC RS 5;
BIOC T 0 A_Refire("AltFire7");
Goto AltRelease;
AltFire7:
BIOC T 5 A_ChargeUp();
BIOC UV 5;
BIOC W 0 A_Refire("AltFire8");
Goto AltRelease;
AltFire8:
BIOC W 5 A_ChargeUp();
BIOC XY 5;
BIOC Z 0 A_Refire("AltFire9");
Goto AltRelease;
AltFire9:
BIOC Z 5 A_ChargeUp();
BIC2 AB 5;
BIC2 C 0 A_Refire("AltFire10");
Goto AltRelease;
AltFire10:
BIC2 C 5 A_ChargeUp();
BIC2 DE 5;
BIOM A 0 A_Refire("AltHeld");
Goto AltRelease;
AltHeld:
BIOM A 5 { invoker.charge = min(5.1,invoker.charge+0.1); }
BIOM A 0 A_Refire("AltHeld");
AltRelease:
BIOE A 1;
BIOF A 2 A_BioFire(true);
BIOF BCDEFGHI 2;
Goto Idle;
Select:
BIOS A 1 A_Raise(int.max);

View file

@ -4,7 +4,6 @@ Class FlakAmmo : Ammo
{
Tag "Flak Shells";
Inventory.PickupMessage "You picked up 10 Flak Shells.";
Inventory.PickupSound "ut/ammo";
Inventory.Amount 10;
Inventory.MaxAmount 50;
Ammo.BackpackAmount 50;
@ -41,7 +40,7 @@ Class ChunkLight : DynamicLight
Default
{
DynamicLight.Type "Point";
Args 255,224,8;
Args 255,224,128,8;
}
override void PostBeginPlay()
{
@ -55,6 +54,7 @@ Class ChunkLight : DynamicLight
Destroy();
return;
}
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 255*target.alpha;
args[LIGHT_GREEN] = 224*target.alpha;
args[LIGHT_BLUE] = 128*target.alpha;
@ -84,6 +84,7 @@ Class ChunkTrail : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
A_SpawnParticle("FFFF00",SPF_FULLBRIGHT,1,8,startalphaf:alpha);
A_SpawnParticle("E0A000",SPF_FULLBRIGHT,1,16,startalphaf:alpha*0.6);
A_SpawnParticle("804000",SPF_FULLBRIGHT,1,32,startalphaf:alpha*0.3);
@ -111,7 +112,7 @@ Class FlakChunk : Actor
{
Actor lasthit;
ChunkTrail trail;
double rollvel, pitchvel;
double rollvel, pitchvel, yawvel;
double lifetime, lifespeed;
int lifetics;
Default
@ -119,7 +120,7 @@ Class FlakChunk : Actor
Obituary "%o was ripped to shreds by %k's Flak Cannon.";
Radius 4;
Height 4;
Speed 80;
Speed 50;
DamageFunction Random[Flak](12,18);
DamageType 'Shredded';
BounceType "Doom";
@ -142,12 +143,15 @@ Class FlakChunk : Actor
trail.target = self;
trail.speed = 0.5;
rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1);
scale *= Frandom[Flak](0.8,1.2);
SetState(ResolveState("Spawn")+Random[Flak](0,3));
}
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
lifetics++;
if ( lifetics > 3 )
{
@ -160,15 +164,24 @@ Class FlakChunk : Actor
if ( InStateSequence(CurState,FindState("Death")) ) return;
A_SetRoll(roll+rollvel,SPF_INTERPOLATE);
A_SetPitch(pitch+pitchvel,SPF_INTERPOLATE);
A_SetAngle(angle+pitchvel,SPF_INTERPOLATE);
}
action void A_HandleBounce()
{
A_SprayDecal("WallCrack",-8);
int numpt = Random[Flak](8,12);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Flak](-1,1),FRandom[Flak](-1,1),FRandom[Flak](-1,1)).unit()*FRandom[Flak](2,4);
A_SpawnParticle("FFA000",SPF_FULLBRIGHT,Random[Flak](10,20),FRandom[Flak](1.2,3.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,3.0,-1,-0.25);
}
A_Gravity();
invoker.rollvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
invoker.pitchvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
invoker.yawvel = FRandom[Flak](50,100)*RandomPick[Flak](-1,1)*(vel.length()/speed);
vel = (vel.unit()+(FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4),FRandom[Flak](-0.4,0.4))).unit()*vel.length();
A_PlaySound("flak/bounce",volume:0.3);
A_AlertMonsters();
if ( vel.length() < 4.0 ) ExplodeMissile();
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
@ -177,6 +190,7 @@ Class FlakChunk : Actor
{
if ( target != lasthit ) target.SpawnBlood(pos,AngleTo(target),damage);
A_PlaySound("flak/meat",volume:0.3);
A_AlertMonsters();
}
lasthit = target;
return damage;
@ -249,6 +263,7 @@ Class SlugSmoke : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
lifetime += lifespeed;
if ( waterlevel <= 0 ) A_SpawnParticle("AAAAAA",0,50,16.0,velx:FRandom[Flak](-0.5,0.5),vely:FRandom[Flak](-0.5,0.5),velz:FRandom[Flak](-0.5,0.5),accelz:0.05,startalphaf:scale.x,sizestep:1.0);
scale.x = max(0,1-lifetime);
@ -278,6 +293,7 @@ Class SlugLight : DynamicLight
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 255*lifetime;
args[LIGHT_GREEN] = 224*lifetime;
args[LIGHT_BLUE] = 128*lifetime;
@ -320,6 +336,7 @@ Class FlakSlug : Actor
A_Explode(Random[Flak](60,80),150);
A_QuakeEx(4,4,4,8,0,200,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
A_PlaySound("flak/explode",CHAN_VOICE);
A_AlertMonsters();
if ( !Tracer ) Spawn("SlugSmoke",pos);
Spawn("SlugLight",pos);
Vector3 x, y, z;
@ -337,6 +354,12 @@ Class FlakSlug : Actor
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed*FRandom[Flak](0.5,1.5);
p.target = target;
}
int numpt = Random[Flak](40,80);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Flak](-1,1),FRandom[Flak](-1,1),FRandom[Flak](-1,1)).unit()*FRandom[Flak](2,4);
A_SpawnParticle("FFA000",SPF_FULLBRIGHT,Random[Flak](20,40),FRandom[Flak](4.8,7.2),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,3.0,-1,-0.25);
}
}
States
{
@ -356,6 +379,7 @@ Class FlakSlug : Actor
Class FlakLight : DynamicLight
{
int cnt;
Default
{
DynamicLight.Type "Point";
@ -376,57 +400,14 @@ Class FlakLight : DynamicLight
Destroy();
return;
}
SetOrigin(target.pos,true);
}
}
Class FlakMuzzle : Actor
{
Vector3 ofs;
override void PostBeginPlay()
{
Super.PostBeginPlay();
let l = Spawn("FlakLight",pos);
l.target = self;
if ( target ) ofs = target.Vec3To(self);
else ofs = (0,0,0);
}
override void Tick()
{
Super.Tick();
if ( !target )
{
Destroy();
return;
}
bInvisible = (target != players[consoleplayer].camera);
SetOrigin(target.Vec3Offset(ofs.x-target.vel.x,ofs.y-target.vel.y,ofs.z-target.vel.z),true);
}
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
Scale 0.08;
+NOGRAVITY;
+NOBLOCKMAP;
+DONTSPLASH;
}
States
{
Spawn:
FMUZ A 3 Bright;
Stop;
if ( target.player ) SetOrigin(target.pos+(0,0,target.player.viewheight),true);
else SetOrigin(target.pos,true);
if ( cnt++ > 2 ) Destroy();
}
}
Class FlakCannon : UTWeapon
{
action void A_Selecting()
{
A_PlaySound("flak/select",CHAN_WEAPON);
}
action void A_Loading( bool first = false )
{
if ( first ) A_PlaySound("flak/load",CHAN_WEAPON);
@ -439,13 +420,15 @@ Class FlakCannon : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("flak/fire",CHAN_WEAPON);
A_AlertMonsters();
A_QuakeEx(1,1,1,3,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+2.0*y-3.0*z;
let m = Spawn("FlakMuzzle",pos+(0,0,player.viewheight)+20.0*x+5.0*y-3.0*z);
m.target = self;
A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
[x, y, z] = Matrix4.GetAxes(BulletSlope(),angle,roll);
Actor p;
for ( int i=0; i<8; i++ )
@ -459,6 +442,12 @@ Class FlakCannon : UTWeapon
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
p.target = self;
}
int numpt = Random[Flak](20,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8))).unit()*FRandom[Flak](2,4);
A_SpawnParticle("FFA000",SPF_FULLBRIGHT,Random[Flak](10,20),FRandom[Flak](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,-0.1,3.0,-1,-0.25);
}
}
action void A_FireSlug()
{
@ -467,24 +456,33 @@ Class FlakCannon : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("flak/altfire",CHAN_WEAPON);
A_QuakeEx(2,2,2,10,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
A_AlertMonsters();
A_QuakeEx(2,2,2,6,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+2.0*y-3.0*z;
let m = Spawn("FlakMuzzle",pos+(0,0,player.viewheight)+20.0*x+5.0*y-3.0*z);
m.target = self;
A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
Actor p = Spawn("FlakSlug",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;
int numpt = Random[Flak](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8),FRandom[Flak](-.8,.8))).unit()*FRandom[Flak](2,4);
A_SpawnParticle("FFA000",SPF_FULLBRIGHT,Random[Flak](10,20),FRandom[Flak](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,-0.1,3.0,-1,-0.25);
}
}
Default
{
Tag "Flak Cannon";
Inventory.PickupMessage "You got the Flak Cannon.";
Weapon.UpSound "flak/select";
Weapon.SlotNumber 8;
Weapon.AmmoType "FlakAmmo";
Weapon.AmmoUse 1;
@ -500,8 +498,7 @@ Class FlakCannon : UTWeapon
FPCK B -1;
Stop;
Ready:
FLKS A 1 A_Selecting();
FLKS BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
FLKS ABCDEFGHIJKLMNOPQRSTUVWXYZ 1;
FKS2 ABC 1;
FLKL A 1 A_Loading(true);
FLKL BCDEFGHIJKLMNO 1;
@ -534,5 +531,12 @@ Class FlakCannon : UTWeapon
FLKD ABCDEFGHIJ 2;
FLKD J 1 A_Lower(int.max);
Wait;
MuzzleFlash:
FMUZ A 3 Bright
{
let l = Spawn("FlakLight",pos);
l.target = self;
}
Stop;
}
}

316
zscript/pulsegun.zsc Normal file
View file

@ -0,0 +1,316 @@
Class PulseAmmo : Ammo
{
Default
{
Tag "Pulse Cell";
Inventory.PickupMessage "You picked up a Pulse Cell.";
Inventory.Amount 25;
Inventory.MaxAmount 200;
Ammo.BackpackAmount 50;
Ammo.BackpackMaxAmount 400;
Ammo.DropAmount 25;
}
States
{
Spawn:
PAMO A -1;
Stop;
}
}
Class PulseBall : Actor
{
Default
{
RenderStyle "Add";
PROJECTILE;
Scale 0.2;
Speed 30;
}
override void PostBeginPlay()
{
A_PlaySound("pulse/fly",CHAN_BODY,0.8,true,8.0);
}
action void A_BallExp()
{
A_SetScale(0.45);
A_PlaySound("pulse/hit",CHAN_BODY);
}
States
{
Spawn:
PBAL ABCDE 1 Bright;
Loop;
Death:
TNT1 A 0 A_BallExp();
PBAL ABCDE 3 Bright;
Stop;
}
}
Class PulseBolt : Actor
{
}
Class StarterBolt : PulseBolt
{
}
Class PulseGun : UTWeapon
{
int clipcount;
double sangle;
StarterBolt beam;
Property ClipCount : clipcount;
action void A_Reloading()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
invoker.clipcount = Min(50,weap.Ammo1.Amount);
A_PlaySound("pulse/reload",CHAN_WEAPON);
}
action void A_DrainAmmo()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.clipcount--;
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+4.5*y-2.4*z;
int numpt = Random[Pulse](2,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5))).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("A0FFA0",SPF_FULLBRIGHT,Random[Pulse](10,20),FRandom[Pulse](1.2,2.4),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("60C040",SPF_FULLBRIGHT,Random[Pulse](15,25),FRandom[Pulse](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
action void A_PulseRefire( statelabel flash = null )
{
Weapon weap = Weapon(invoker);
if ( !weap || !player ) return;
if ( (invoker.clipcount <= 0) || (weap.Ammo1.Amount <= 0) )
{
A_ClearRefire();
if ( weap.bAltFire ) player.setpsprite(PSP_WEAPON,weap.FindState("AltRelease"));
else player.setpsprite(PSP_WEAPON,weap.FindState("Release"));
return;
}
A_Refire(flash);
}
action void A_PulseFire()
{
Weapon weap = Weapon(invoker);
if ( !weap ) return;
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.clipcount--;
A_AlertMonsters();
A_QuakeEx(1,1,1,2,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.05);
A_Overlay(-2,"MuzzleFlash");
A_OverlayFlags(-2,PSPF_RENDERSTYLE|PSPF_FORCESTYLE,true);
A_OverlayRenderstyle(-2,STYLE_Add);
Vector3 x, y, z;
double a;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+4.0*y-2.0*z;
origin += y*cos(invoker.sangle)*4.0+z*sin(invoker.sangle)*4.0;
invoker.sangle += 100;
Actor p = Spawn("PulseBall",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;
int numpt = Random[Pulse](2,5);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (x+(FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5),FRandom[Pulse](-.5,.5))).unit()*FRandom[Pulse](2,4);
A_SpawnParticle("A0FFA0",SPF_FULLBRIGHT,Random[Pulse](10,20),FRandom[Pulse](1.2,2.4),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-0.1);
A_SpawnParticle("60C040",SPF_FULLBRIGHT,Random[Pulse](15,25),FRandom[Pulse](2.4,3.6),0,origin.x-pos.x,origin.y-pos.y,origin.z-pos.z,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-0.1);
}
}
action void A_StartBeam()
{
A_PlaySound("pulse/bolt",CHAN_WEAPON,1.0,true);
invoker.beam = StarterBolt(Spawn("StarterBolt",pos));
invoker.beam.target = self;
}
action void A_StopBeam()
{
A_StopSound(CHAN_WEAPON);
if ( invoker.beam ) invoker.beam.Destroy();
}
Default
{
Tag "Pulse Gun";
Inventory.PickupMessage "You got a Pulse Gun";
Weapon.UpSound "pulse/select";
Weapon.SlotNumber 5;
Weapon.AmmoType "PulseAmmo";
Weapon.AmmoUse 1;
Weapon.AmmoType2 "PulseAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 60;
PulseGun.ClipCount 50;
}
States
{
Spawn:
PGNP A -1;
Stop;
PGNP B -1;
Stop;
Ready:
PGNS ABCDEFGHIJKLMNOPQRSTUVW 1;
Idle:
PGNI A 1
{
A_CheckReload();
if ( (invoker.clipcount <= 0) && (invoker.Ammo1.Amount > 0) ) return A_Jump(255,"Reload");
A_WeaponReady(WRF_ALLOWRELOAD);
return A_JumpIf(!Random[Pulse](0,300),1);
}
Wait;
PGNI ABCDEFGHIJKLMNOPQRSTUVWXYZ 1
{
A_CheckReload();
A_WeaponReady(WRF_ALLOWRELOAD);
}
Goto Idle;
Fire:
PGNI A 0 A_PlaySound("pulse/fire",CHAN_WEAPON,1.0,true);
Hold:
PGNF A 1 A_PulseFire();
PGNF B 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF C 1 A_PulseFire();
PGNF D 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF E 1 A_PulseFire();
PGNF F 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF G 1 A_PulseFire();
PGNF H 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF I 1 A_PulseFire();
PGNF J 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF K 1 A_PulseFire();
PGNF L 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF M 1 A_PulseFire();
PGNF N 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF O 1 A_PulseFire();
PGNF P 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF Q 1 A_PulseFire();
PGNF R 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF S 1 A_PulseFire();
PGNF T 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF U 1 A_PulseFire();
PGNF V 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF W 1 A_PulseFire();
PGNF X 1;
PGNF Y 0 A_PulseRefire(1);
Goto Release;
PGNF Y 1 A_PulseFire();
PGNF Z 1;
PGF2 A 0 A_PulseRefire(1);
Goto Release;
PGF2 A 1 A_PulseFire();
PGF2 B 1;
PGF2 C 0 A_PulseRefire(1);
Goto Release;
PGF2 C 1 A_PulseFire();
PGF2 D 1;
PGF2 E 0 A_PulseRefire(1);
Goto Release;
PGF2 E 1 A_PulseFire();
PGF2 F 1;
PGF2 G 0 A_PulseRefire(1);
Goto Release;
PGF2 G 1 A_PulseFire();
PGF2 H 1;
PGF2 I 0 A_PulseRefire(1);
Goto Release;
PGF2 I 1 A_PulseFire();
PGF2 J 1;
PGF2 K 0 A_PulseRefire(1);
Goto Release;
PGF2 K 1 A_PulseFire();
PGF2 L 1;
PGF2 M 0 A_PulseRefire(1);
Goto Release;
PGF2 M 1 A_PulseFire();
PGF2 N 1;
PGNF A 0 A_PulseRefire("Hold");
Release:
PGNC A 0 A_PlaySound("pulse/down",CHAN_WEAPON);
PGNC ABCDEFGHIJKLMNOPQRSTUVWXY 1;
PGNI A 1;
Goto Idle;
AltFire:
PGBS ABCDE 1;
PGBL A 0 A_StartBeam();
AltHold:
PGBL A 1 A_DrainAmmo();
PGBL B 1;
PGBL C 0 A_PulseRefire(1);
Goto AltRelease;
PGBL C 1 A_DrainAmmo();
PGBL D 1;
PGBL E 0 A_PulseRefire(1);
Goto AltRelease;
PGBL E 1 A_DrainAmmo();
PGBL F 1;
PGBL G 0 A_PulseRefire(1);
Goto AltRelease;
PGBL G 1 A_DrainAmmo();
PGBL H 1;
PGBL I 0 A_PulseRefire(1);
Goto AltRelease;
PGBL I 1 A_DrainAmmo();
PGBL J 1;
PGBL A 0 A_PulseRefire("AltHold");
AltRelease:
PGBE A 0 A_StopBeam();
PGBE ABCDE 1;
Goto Idle;
Reload:
PGNI A 1 A_JumpIf(invoker.clipcount >= 50,"Idle");
PGNR A 1 A_Reloading();
PGNR BCDEFGHIJKLMNOPQRSTUVWXYZ 1;
PGR2 ABCDEFGHIJKLMNOPQRSTUVWX 1;
Goto Idle;
Deselect:
PGNS WVUTSRQPONMLKJIHGFEDCBA 1;
PGNS A 1 A_Lower(int.max);
Wait;
Select:
PGNS A 1 A_Raise(int.max);
Wait;
MuzzleFlash:
PMUZ A 1 Bright;
Stop;
}
}

View file

@ -4,7 +4,6 @@ Class ShockAmmo : Ammo
{
Tag "ShockCore";
Inventory.PickupMessage "You picked up a Shock Core.";
Inventory.PickupSound "ut/ammo";
Inventory.Amount 10;
Inventory.MaxAmount 50;
Ammo.BackpackAmount 50;
@ -56,6 +55,7 @@ Class ShockRifleWave : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
alpha -= 1/50.;
}
States
@ -83,6 +83,7 @@ Class ShockBeamRing : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
alpha -= 1./ReactionTime;
}
States
@ -139,6 +140,7 @@ Class ShockBeam : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( !moving ) return;
// step trace
tracedir = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
@ -147,12 +149,13 @@ Class ShockBeam : Actor
// spawn particles
for ( int i=0; i<t.Results.Distance; i+=80 )
Spawn("ShockBeamLight",Vec3Offset(tracedir.x*i,tracedir.y*i,tracedir.z*i));
for ( int i=0; i<t.Results.Distance; i+=8 )
for ( int i=0; i<t.Results.Distance; i+=4 )
{
A_SpawnParticle("F0A0FF",SPF_FULLBRIGHT,15,2,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:1,sizestep:-.1);
A_SpawnParticle("A040FF",SPF_FULLBRIGHT,20,4,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.75,sizestep:-.1);
A_SpawnParticle("8020FF",SPF_FULLBRIGHT,25,6,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.5,sizestep:-.1);
A_SpawnParticle("602080",SPF_FULLBRIGHT,30,8,0,tracedir.x*i,tracedir.y*i,tracedir.z*i,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.25,sizestep:-.1);
Vector3 pofs = tracedir*FRandom[ASMD](-4,4)+(FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1));
A_SpawnParticle("C0A0FF",SPF_FULLBRIGHT,15,2,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:1,sizestep:-.1);
A_SpawnParticle("8040FF",SPF_FULLBRIGHT,20,4,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.75,sizestep:-.1);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,25,6,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.5,sizestep:-.1);
A_SpawnParticle("402080",SPF_FULLBRIGHT,30,8,0,tracedir.x*i+pofs.x,tracedir.y*i+pofs.y,tracedir.z*i+pofs.z,FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),FRandom[ASMD](-.1,.1),startalphaf:.25,sizestep:-.1);
}
if ( totaldist >= 10000.0 )
{
@ -192,6 +195,18 @@ Class ShockBeam : Actor
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);
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](2,8);
A_SpawnParticle("C0A0FF",SPF_FULLBRIGHT,Random[ASMD](20,80),FRandom[ASMD](1.6,4.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.05);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("8040FF",SPF_FULLBRIGHT,Random[ASMD](30,100),FRandom[ASMD](3.2,9.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.75,-1,-.05);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,120),FRandom[ASMD](4.8,11.2),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.05);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,140),FRandom[ASMD](5.6,12.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.05);
}
}
else
{
@ -231,6 +246,19 @@ Class ShockBeam : Actor
Spawn("ShockBeamLight",pos);
A_QuakeEx(2,2,2,5,0,120,"",QF_RELATIVE|QF_SCALEDOWN,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](3,12);
A_SpawnParticle("C0A0FF",SPF_FULLBRIGHT,Random[ASMD](20,40),FRandom[ASMD](1.6,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("8040FF",SPF_FULLBRIGHT,Random[ASMD](30,50),FRandom[ASMD](3.2,4.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.75,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,60),FRandom[ASMD](4.8,5.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,70),FRandom[ASMD](5.6,6.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.1);
}
}
States
{
@ -313,6 +341,7 @@ Class ShockExplLight : DynamicLight
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 160*lifetime;
args[LIGHT_GREEN] = 128*lifetime;
args[LIGHT_BLUE] = 255*lifetime;
@ -368,6 +397,19 @@ Class ShockBall : Actor
A_PlaySound("shock/hit",CHAN_VOICE);
A_PlaySound("shock/ball",CHAN_WEAPON);
A_QuakeEx(4,4,4,30,0,200,"",QF_RELATIVE|QF_SCALEDOWN,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](3,12);
A_SpawnParticle("C0A0FF",SPF_FULLBRIGHT,Random[ASMD](20,40),FRandom[ASMD](1.6,2.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,1,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("8040FF",SPF_FULLBRIGHT,Random[ASMD](30,50),FRandom[ASMD](3.2,4.8),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.75,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("5020FF",SPF_FULLBRIGHT,Random[ASMD](40,60),FRandom[ASMD](4.8,5.6),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.5,-1,-.1);
pvel = (FRandom[ASMD](-1,1),FRandom[ASMD](-1,1),FRandom[ASMD](-1,1)).unit()*FRandom[ASMD](3,12);
A_SpawnParticle("402080",SPF_FULLBRIGHT,Random[ASMD](50,70),FRandom[ASMD](5.6,6.4),0,0,0,0,pvel.x,pvel.y,pvel.z,0,0,0,.25,-1,-.1);
}
}
Default
{
@ -398,10 +440,6 @@ Class ShockBall : Actor
Class ShockRifle : UTWeapon
{
action void A_Selecting()
{
A_PlaySound("shock/select",CHAN_WEAPON);
}
action void A_ShockFire()
{
Weapon weap = Weapon(invoker);
@ -409,9 +447,9 @@ Class ShockRifle : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/fire",CHAN_WEAPON);
A_AlertMonsters();
A_QuakeEx(3,3,3,4,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+3.0*y-4.0*z;
Actor p = Spawn("ShockBeam",origin);
@ -426,9 +464,9 @@ Class ShockRifle : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("shock/altfire",CHAN_WEAPON);
A_AlertMonsters();
A_QuakeEx(3,3,3,8,0,64,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.1);
Vector3 x, y, z;
double a, s;
[x, y, z] = Matrix4.GetAxes(pitch,angle,roll);
Vector3 origin = pos+(0,0,player.viewheight)+10.0*x+3.0*y-4.0*z;
Actor p = Spawn("ShockBall",origin);
@ -442,6 +480,7 @@ Class ShockRifle : UTWeapon
{
Tag "Shock Rifle";
Inventory.PickupMessage "You got the ASMD Shock Rifle.";
Weapon.UpSound "shock/select";
Weapon.SlotNumber 4;
Weapon.AmmoType "ShockAmmo";
Weapon.AmmoUse 1;
@ -457,8 +496,7 @@ Class ShockRifle : UTWeapon
ASMP B -1;
Stop;
Ready:
ASMS A 1 A_Selecting();
ASMS BCDEFGHIJKLMNO 1;
ASMS ABCDEFGHIJKLMNO 1;
Idle:
ASMI A 1
{

View file

@ -17,11 +17,11 @@ Class UTWeapon : Weapon
Default
{
Inventory.PickupSound "ut/weapon";
Weapon.BobStyle "Smooth";
Weapon.BobSpeed 1.5;
Weapon.BobRangeX 0.2;
Weapon.BobRangeY 0.4;
+WEAPON.NOALERT;
}
}

View file

@ -5,7 +5,6 @@ Class WarheadAmmo : Ammo
{
Tag "Redeemer Missile";
Inventory.PickupMessage "You picked up a Redeemer Missile.";
Inventory.PickupSound "ut/ammo";
Inventory.Amount 1;
Inventory.MaxAmount 2;
Ammo.BackpackAmount 0;
@ -48,6 +47,7 @@ Class ShockWave : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( alpha <= 0 ) return;
icount++;
if ( icount == 4 ) Spawn("WarheadSubExplosion",pos);
@ -136,6 +136,12 @@ Class WarheadHitbox : Actor
}
SetOrigin(target.pos-(0,0,height*0.5),true);
}
States
{
Spawn:
TNT1 A 10 A_AlertMonsters(0,AMF_TARGETEMITTER);
Wait;
}
}
Class WarheadExplodLight : DynamicLight
@ -155,6 +161,7 @@ Class WarheadExplodLight : DynamicLight
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
args[LIGHT_RED] = 255*lifetime;
args[LIGHT_GREEN] = 192*lifetime;
args[LIGHT_BLUE] = 128*lifetime;
@ -218,6 +225,7 @@ Class WarShell : Actor
override void Tick()
{
Super.Tick();
if ( globalfreeze || level.frozen ) return;
if ( vel.length() > 0 )
{
Vector3 dir = vel.unit();
@ -251,6 +259,7 @@ Class WarShell : Actor
A_SprayDecal("BigBlast");
A_QuakeEx(8,8,8,20,0,300,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.35);
A_PlaySound("shock/hit",CHAN_VOICE,attenuation:0.5);
A_AlertMonsters();
A_SetRenderStyle(1.0,STYLE_Add);
Spawn("WarheadExplodLight",pos);
let s = Spawn("ShockWave",pos);
@ -264,6 +273,7 @@ Class WarShell : Actor
A_SprayDecal("BigBlast");
A_QuakeEx(8,8,8,20,0,300,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.35);
A_PlaySound("shock/hit",CHAN_VOICE,attenuation:0.5);
A_AlertMonsters();
A_SetRenderStyle(1.0,STYLE_Add);
Spawn("WarheadExplodLight",pos);
}
@ -299,6 +309,7 @@ Class GuidedWarShell : WarShell
override void Tick()
{
Actor.Tick();
if ( globalfreeze || level.frozen ) return;
if ( !bMISSILE ) return;
if ( !target || !target.player || (target.Health <= 0) )
{
@ -475,10 +486,6 @@ Class RedeemerHUDHandler : EventHandler
Class WarheadLauncher : UTWeapon
{
Actor guided;
action void A_Selecting()
{
A_PlaySound("warhead/select",CHAN_WEAPON);
}
action void A_WarheadFire()
{
Weapon weap = Weapon(invoker);
@ -486,6 +493,7 @@ Class WarheadLauncher : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("warhead/fire",CHAN_WEAPON);
A_AlertMonsters();
A_QuakeEx(6,6,6,20,0,100,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
Vector3 x, y, z;
double a, s;
@ -505,6 +513,7 @@ Class WarheadLauncher : UTWeapon
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
A_PlaySound("warhead/fire",CHAN_WEAPON);
A_AlertMonsters();
A_QuakeEx(6,6,6,20,0,100,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:0.2);
Vector3 x, y, z;
double a, s;
@ -524,6 +533,7 @@ Class WarheadLauncher : UTWeapon
{
Tag "Redeemer";
Inventory.PickupMessage "You got the Redeemer.";
Weapon.UpSound "warhead/select";
Weapon.SlotNumber 0;
Weapon.AmmoType "WarheadAmmo";
Weapon.AmmoUse 1;
@ -539,8 +549,7 @@ Class WarheadLauncher : UTWeapon
RDMP B -1;
Stop;
Ready:
WARS A 1 A_Selecting();
WARS BCDEFGHIJKLMNO 1;
WARS ABCDEFGHIJKLMNO 1;
Idle:
WARI A 1
{