Current commit does not run and I don't know why.

Sentry partially implemented.
Motion Detector implemented.
Light/Dark Flares implemented.
This commit is contained in:
Marisa the Magician 2019-09-06 00:20:14 +02:00
commit f2cdf34c98
18 changed files with 835 additions and 50 deletions

View file

@ -713,6 +713,36 @@ Class BetaFlare : UnrealInventory
if ( Owner ) Owner.RemoveInventory(self);
Destroy();
}
override bool Use( bool pickup )
{
if ( pickup || bActive || (charge < defaultcharge) ) 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(ThrownClass,origin);
a.target = Owner;
a.angle = Owner.angle;
a.pitch = Owner.pitch;
a.vel += x*a.speed;
for ( Inventory i=Owner.Inv; i; i=i.Inv )
{
if ( !(i is 'BetaFlare') ) continue;
UnrealInventory(i).bActive = true;
UnrealInventory(i).Charge = 0;
i.tracer = a;
}
return false;
}
override void DoEffect()
{
Super.DoEffect();
if ( !bActive )
{
charge = min(defaultcharge,charge+1);
return;
}
else if ( !tracer ) bActive = false;
}
Default
{
Inventory.MaxAmount 1;
@ -728,6 +758,7 @@ Class LightFlare : BetaFlare
{
Tag "$T_LFLARES";
Inventory.Icon "I_FlarBL";
BetaFlare.ThrownClass "LightFlareThrown";
}
}
@ -737,19 +768,232 @@ Class DarkFlare : BetaFlare
{
Tag "$T_DFLARES";
Inventory.Icon "I_FlarBD";
BetaFlare.ThrownClass "DarkFlareThrown";
}
}
Class BetaFlareThrown
Class BetaFlareThrown : 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;
}
virtual void A_SpawnEffect()
{
}
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);
b = Spawn("FlareHitbox",pos);
b.master = self;
}
b.A_AlertMonsters(0,AMF_TARGETEMITTER);
ReactionTime--;
}
States
{
Spawn:
FLAR A 1
{
if ( GetAge() >= 9 ) A_SpawnEffect();
return A_JumpIf(ReactionTime<=0,"Death");
}
Wait;
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 ( b ) b.Destroy();
A_StopSound(CHAN_VOICE);
return ResolveState("Fizz");
}
A_SpawnEffect();
return A_JumpIf(ReactionTime<=0,1);
}
Wait;
FLAR A 0
{
if ( b ) b.Destroy();
if ( waterlevel > 0 ) return ResolveState("Fizz");
A_RemoveLight('PLight');
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 0 A_RemoveLight('PLight');
FLAR A 1
{
special1++;
if ( special1 > 150 ) A_FadeOut();
}
Wait;
}
}
Class LightFlareThrown : BetaFlareThrown
{
override void A_SpawnEffect()
{
Vector3 x, y, z;
double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
for ( int i=0; i<4; i++ )
{
a = FRandom[BFlare](0,360);
s = FRandom[BFlare](0,0.15);
let t = Spawn("LightFlareParticle",pos+x*4+z);
t.vel = (x+y*cos(a)*s+z*sin(a)*s).unit()*FRandom[BFlare](1,4);
}
}
override void Tick()
{
Super.Tick();
if ( GetAge() == 9 ) A_AttachLightDef('PLight','LIGHTFLARE');
}
}
Class DarkFlareThrown : BetaFlareThrown
{
override void A_SpawnEffect()
{
Vector3 x, y, z;
double a, s;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
for ( int i=0; i<3; i++ )
{
a = FRandom[BFlare](0,360);
s = FRandom[BFlare](0,0.5);
let t = Spawn("DarkFlareParticle",pos+x*4+z);
t.vel = (x+y*cos(a)*s+z*sin(a)*s).unit()*FRandom[BFlare](4,8);
}
}
override void Tick()
{
Super.Tick();
if ( GetAge() == 9 ) A_AttachLightDef('PLight','DARKFLARE');
}
}
Class LightFlareParticle : UTSmoke
{
Default
{
StencilColor "FFFFFF";
Scale 0.2;
}
}
Class DarkFlareParticle : UTSmoke
{
Default
{
StencilColor "000000";
Scale 2.2;
}
}
Class Dampener : UnrealInventory
@ -1123,6 +1367,46 @@ Class SentryItem : UnrealInventory
Inventory.RespawnTics 1050;
UnrealInventory.Charge 300;
}
override bool Use( bool pickup )
{
if ( pickup ) return false;
if ( bActive ) 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*90.);
origin = level.Vec3Offset(origin,(0,0,-GetDefaultByType("MinigunSentryBase").Height*.5));
if ( !level.IsPointInLevel(origin) )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOROOM"));
return false;
}
let a = Spawn("MinigunSentryBase",origin);
if ( !a.TestMobjLocation() )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOROOM"));
a.Destroy();
return false;
}
bActive = true;
tracer = a;
a.target = Owner;
a.angle = Owner.angle;
a.pitch = 0;
a.roll = 0;
return false;
}
override void DoEffect()
{
Super.DoEffect();
if ( !bActive ) return;
if ( !tracer )
{
bActive = false;
DepleteOrDestroy();
return;
}
Charge = tracer.Health;
}
States
{
Spawn:
@ -1131,9 +1415,125 @@ Class SentryItem : UnrealInventory
}
}
// overlay for muzzle flash
Class MinigunSentryX : Actor
{
Default
{
RenderStyle "Add";
+NOGRAVITY;
+NOBLOCKMAP;
+INTERPOLATEANGLES;
}
override void Tick()
{
Super.Tick();
if ( !tracer || !tracer.InStateSequence(tracer.CurState,tracer.FindState("MissileLoop")) )
{
Destroy();
return;
}
SetOrigin(tracer.pos,true);
angle = tracer.angle;
pitch = tracer.pitch;
roll = tracer.roll;
}
States
{
Spawn:
SENF A 1 Bright;
TNT1 A 2;
SENF D 1 Bright;
TNT1 A 2;
SENF G 1 Bright;
TNT1 A 2;
SENF J 1 Bright;
TNT1 A 2;
SENF M 1 Bright;
TNT1 A 2;
SENF P 1 Bright;
TNT1 A 2;
Stop;
}
}
// The "head" of the sentry, attaches to the body
Class MinigunSentry : Actor
{
const maxangle = 60;
const maxpitch = 30;
Default
{
+NOGRAVITY;
+NOBLOCKMAP;
+INTERPOLATEANGLES;
+FRIENDLY;
}
override void Tick()
{
Super.Tick();
if ( !master )
{
Destroy();
return;
}
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(master.pitch,master.angle,master.roll);
SetOrigin(level.Vec3Offset(master.pos,z*38),true);
}
double _PitchTo( Actor other )
{
if ( !other ) return 0;
Vector3 otherpos = level.Vec3Diff(pos,other.Vec3Offset(0,0,other.height/2));
double dist = otherpos.length();
if ( dist > 0 ) return -asin(otherpos.z/dist);
return 0;
}
bool TargetVisible()
{
if ( !target || (target.Health <= 0) || !CheckSight(target) ) return false;
double angledelta = DeltaAngle(master.angle,AngleTo(target));
double pitchdelta = DeltaAngle(master.pitch,_PitchTo(target));
if ( (abs(angledelta) > maxangle) || (abs(pitchdelta) > maxpitch) ) return false;
return true;
}
void A_SentryFaceTarget()
{
if ( !TargetVisible() ) return;
double angledelta = DeltaAngle(angle,AngleTo(target));
double pitchdelta = DeltaAngle(pitch,_PitchTo(target));
double angleturn = clamp(abs(angledelta)*0.1,2,15);
double pitchturn = clamp(abs(pitchdelta)*0.1,2,15);
angle = clamp(angle+clamp(angledelta,-angleturn,angleturn),master.angle-maxangle,master.angle+maxangle);
pitch = clamp(pitch+clamp(pitchdelta,-pitchturn,pitchturn),master.pitch-maxpitch,master.pitch+maxpitch);
}
void A_SentryFaceDir( int dest, statelabel next )
{
double angledelta = DeltaAngle(angle,master.angle+dest);
double pitchdelta = DeltaAngle(pitch,master.pitch);
if ( max(abs(angledelta),abs(pitchdelta)) < 2 )
{
angle = master.angle+dest;
pitch = master.pitch;
SetStateLabel(next);
return;
}
angle = clamp(angle+clamp(angledelta,-2,2),master.angle-maxangle,master.angle+maxangle);
pitch = clamp(pitch+clamp(pitchdelta,-2,2),master.pitch-maxpitch,master.pitch+maxpitch);
}
void A_SentryAttack()
{
special1 = max(0,special1-1);
if ( (special1 <= 0) && master.master && master.master.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_SENTRYDRY"));
A_SentryFaceTarget();
A_PlaySound("sentry/fire",CHAN_WEAPON);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
// TODO actually fire bullets
let c = Spawn("UCasing",level.Vec3Offset(pos,-x*7+y*2+z*2));
c.vel = x*FRandom[Junk](-1.5,1.5)+y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
}
States
{
Spawn:
@ -1142,23 +1542,164 @@ Class MinigunSentry : Actor
SENR ABCDEFGHIJKLMNO 3;
Goto Idle;
Idle:
SENI A 1;
SENI A 1 A_SentryFaceDir(0,1);
Wait;
Fire:
SENW ABCDEFGHIJKLMNOPQR 1;
Goto FireLoop;
FireLoop:
SENF ABCDEFGHIJKLMNOPQR 1;
SENI A 1
{
A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP);
A_SentryFaceDir(-maxangle,1);
return A_JumpIf(TargetVisible(),"See");
}
Wait;
SENI AAAAAA 1
{
A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP);
return A_JumpIf(TargetVisible(),"See");
}
SENI A 1
{
A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP);
A_SentryFaceDir(maxangle,1);
return A_JumpIf(TargetVisible(),"See");
}
Wait;
SENI AAAAAA 1
{
A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP);
return A_JumpIf(TargetVisible(),"See");
}
Goto Idle+1;
See:
SENI A 1
{
if ( !TargetVisible() )
{
A_ClearTarget();
return ResolveState("Idle");
}
A_SentryFaceTarget();
if ( special1 > 0 ) A_Chase(null,"Missile",flags:CHF_DONTMOVE|CHF_DONTTURN);
return ResolveState(null);
}
Wait;
Missile:
SENW A 0
{
A_PlaySound("sentry/wind",looping:true);
master.SetStateLabel("Missile");
}
SENW ABCDEFGHIJKLMNOPQR 1 A_SentryFaceTarget();
Goto MissileLoop;
MissileLoop:
SENF A 0
{
let f = Spawn("MinigunSentryX",pos);
f.angle = angle;
f.pitch = pitch;
f.roll = roll;
f.tracer = self;
}
SENF A 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF A 1 A_SentryAttack();
SENF BC 1 A_SentryFaceTarget();
SENF D 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF D 1 A_SentryAttack();
SENF EF 1 A_SentryFaceTarget();
SENF G 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF G 1 A_SentryAttack();
SENF HI 1 A_SentryFaceTarget();
SENF J 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF J 1 A_SentryAttack();
SENF KL 1 A_SentryFaceTarget();
SENF M 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF M 1 A_SentryAttack();
SENF NO 1 A_SentryFaceTarget();
SENF P 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd");
SENF P 1 A_SentryAttack();
SENF QR 1 A_SentryFaceTarget();
Loop;
FireEnd:
SENU ABCDEFGHIJKLMNOPQR 1;
Goto Idle;
MissileEnd:
SENU A 0
{
A_PlaySound("sentry/unwind");
master.SetStateLabel("MissileEnd");
}
SENU ABCDEFGHIJKLMNOPQR 1 A_SentryFaceTarget();
Goto See;
}
}
// The body of the sentry
Class MinigunSentryBase : Actor
{
const sentryammo = 200;
Default
{
Health 300;
Mass int.max;
Radius 12;
Height 48;
+SOLID;
+SHOOTABLE;
+NOBLOOD;
+DONTTHRUST;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
if ( master && master.player ) SetTag(String.Format(StringTable.Localize("$T_OWNEDSENTRY"),master.player.GetUserName());
else SetTag(StringTable.Localize("$T_SENTRY"));
tracer = Spawn("MinigunSentry",pos);
tracer.special1 = sentryammo;
tracer.master = self;
tracer.angle = angle;
tracer.pitch = pitch;
tracer.roll = roll;
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
tracer.SetOrigin(level.Vec3Offset(pos,z*38),false);
if ( !deathmatch ) return;
if ( master && master.player ) tracer.SetFriendPlayer(master.player);
else tracer.bFRIENDLY = false;
}
override string GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
if ( victim == master ) return String.Format(StringTable.Localize("$O_OWNSENTRY"),GetTag());
return String.Format(StringTable.Localize("$O_SENTRY"),GetTag());
}
override void Touch( Actor toucher )
{
if ( !toucher.player ) return;
if ( deathmatch )
{
if ( master && (toucher != master) && master.CheckLocalView() )
Console.Printf(StringTable.Localize("$M_SENTRYHIJACK"));
master = toucher;
SetTag(String.Format(StringTable.Localize("$T_OWNEDSENTRY"),toucher.player.GetUserName());
tracer.A_ClearTarget();
tracer.SetFriendPlayer(toucher.player);
}
let amo = toucher.FindInventory("UMiniAmmo");
if ( !amo || (amo.Amount <= 0) || (tracer.special1 >= sentryammo) ) return;
A_PlaySound("misc/i_pkup",CHAN_ITEM);
int xammo = min(sentryammo-tracer.special1,amo.Amount);
tracer.special1 += xammo;
amo.Amount -= xammo;
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
int dmg = Super.DamageMobj(inflictor,source,damage,mod,flags,angle);
if ( !tracer.target ) tracer.target = target;
return dmg;
}
override void Die( Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath )
{
if ( master && master.CheckLocalView() )
Console.Printf(StringTable.Localize("$M_SENTRYDOWN"));
if ( tracer ) tracer.Destroy();
Super.Die(source,inflictor,dmgflags,MeansOfDeath);
}
States
{
Spawn:
@ -1168,13 +1709,13 @@ Class MinigunSentryBase : Actor
Idle:
SENI A 1;
Wait;
Fire:
Missile:
SENW ABCDEFGHIJKLMNOPQR 1;
Goto FireLoop;
FireLoop:
Goto MissileLoop;
MissileLoop:
SENF ABCDEFGHIJKLMNOPQR 1;
Loop;
FireEnd:
MissileEnd:
SENU ABCDEFGHIJKLMNOPQR 1;
Goto Idle;
}