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:
parent
d718eb6a9c
commit
73e8e8ada9
96 changed files with 1437 additions and 133 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue