swwmgz_m/zscript/swwm_monsters.zsc

512 lines
10 KiB
Text

// enemies 'n stuff
// Less mean-spirited Keen
Class SWWMHangingKeen : Actor
{
action void A_DropKeen()
{
Spawn("SWWMDroppedKeen",Vec3Offset(0,0,8));
if ( target ) SWWMUtility.MarkAchievement("keen",target.player);
}
override bool Used( Actor user )
{
// test vertical range
Vector3 diff = level.Vec3Diff(user.Vec3Offset(0,0,user.Height/2),Vec3Offset(0,0,Height/2));
double rang = user.player?PlayerPawn(user.player.mo).UseRange:(user.Height/2);
if ( abs(diff.z) > rang ) return false;
if ( Health > 0 )
{
DamageMobj(user,user,Health,'Untie',DMG_FORCED|DMG_THRUSTLESS);
return true;
}
return false;
}
Default
{
Tag "$FN_KEEN";
Health 100;
Radius 10;
Height 54;
Mass int.max;
PainChance 256;
+SOLID;
+SPAWNCEILING;
+NOGRAVITY;
+SHOOTABLE;
+NOICEDEATH;
+DONTFALL;
+NOBLOOD;
+DONTTHRUST;
}
States
{
Spawn:
KEE2 A -1;
Stop;
Death:
KEE2 A 6 A_StartSound("newkeen/hit");
KEE2 B 6 A_DropKeen();
KEE2 C 6;
KEE2 DE 6;
KEE2 F 30;
KEE2 F -1 A_KeenDie();
Stop;
Pain:
KEE2 G 4 A_StartSound("newkeen/hit");
KEE2 G 8;
Goto Spawn;
}
}
Class SWWMDroppedKeen : Actor
{
Default
{
Radius 10;
Height 32;
Gravity .5;
+NOBLOCKMAP;
}
States
{
Spawn:
KEE3 A 0 NoDelay
{
A_StartSound("newkeen/fall",volume:.5);
A_StartSound("newkeen/die",CHAN_VOICE);
}
KEE3 A 1 A_JumpIf(pos.z<=floorz,1);
Wait;
KEE3 B 1
{
A_StartSound("newkeen/bounce");
vel.z = 4;
}
KEE3 B 1 A_JumpIf(pos.z<=floorz,1);
Wait;
KEE3 B 1
{
A_StartSound("newkeen/bounce",volume:.8);
vel.z = 2;
}
KEE3 B 1 A_JumpIf(pos.z<=floorz,1);
Wait;
KEE3 B 12 A_StartSound("newkeen/bounce",volume:.6);
TNT1 A 1 { Spawn("TeleportFog",pos,ALLOW_REPLACE); }
Stop;
}
}
Class SWWMBossBrainExpl : SWWMNonInteractiveActor
{
void A_Ignite()
{
A_QuakeEx(3.,3.,3.,20,0,400,"",QF_RELATIVE|QF_SCALEDOWN|QF_3D,falloff:300,rollintensity:2.);
A_StartSound("explodium/hit",CHAN_VOICE,CHANF_DEFAULT,.4,.5);
Scale *= FRandom[ExploS](0.8,1.1);
Scale.x *= RandomPick[ExploS](-1,1);
Scale.y *= RandomPick[ExploS](-1,1);
int numpt = Random[ExploS](8,16);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,6);
let s = Spawn("SWWMSmoke",pos);
s.vel = pvel;
s.SetShade(Color(1,1,1)*Random[ExploS](64,224));
s.special1 = Random[ExploS](1,4);
s.scale *= 2.8;
s.alpha *= .4;
}
numpt = Random[ExploS](5,10);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](2,12);
let s = Spawn("SWWMSpark",pos);
s.vel = pvel;
}
numpt = Random[ExploS](10,15);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](2,24);
let s = Spawn("SWWMChip",pos);
s.vel = pvel;
}
numpt = int(Random[ExploS](-1,2)+special1);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("SWWMBossBrainExplArm",pos);
s.target = target;
}
}
Default
{
RenderStyle "Add";
Scale 2.5;
+FORCEXYBILLBOARD;
}
States
{
Spawn:
TNT1 A 10;
TNT1 A 0 A_Ignite();
XEX1 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] 1 Bright;
Stop;
}
}
Class SWWMBossBrainExplArm : Actor
{
Default
{
PROJECTILE;
+THRUACTORS;
+BOUNCEONWALLS;
+BOUNCEONFLOORS;
+BOUNCEONCEILINGS;
-NOGRAVITY;
+NOFRICTION;
Gravity 0.35;
BounceFactor 1.0;
Radius 4;
Height 4;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
reactiontime = Random[ExploS](10,15);
double ang, pt;
ang = FRandom[ExploS](0,360);
pt = FRandom[ExploS](-90,90);
vel = SWWMUtility.Vec3FromAngles(ang,pt)*FRandom[ExploS](8.,20.);
}
States
{
Spawn:
TNT1 A 1
{
A_CountDown();
Spawn("ExplodiumMagTrail",pos);
Vector3 pvel = SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*FRandom[ExploS](1,5);
let s = SWWMAnimSprite.SpawnAt("SWWMHalfSmoke",pos);
s.vel = pvel+vel*.2;
s.scolor = Color(1,1,1)*Random[ExploS](64,224);
s.framestep = Random[ExploS](2,4);
s.scale *= 2.4;
s.alpha *= 0.1+.4*(ReactionTime/15.);
}
Wait;
}
}
Class SWWMBossBrainPain : SWWMNonInteractiveActor
{
Default
{
RenderStyle "Add";
}
States
{
Spawn:
MBRN B 1 Bright A_FadeOut(.05);
Wait;
}
}
Class SWWMBossBrain : BossBrain
{
bool eyeless;
bool tntdir;
int smallcooldown;
override void PostBeginPlay()
{
Super.PostBeginPlay();
let ti = ThinkerIterator.Create("BossEye");
Actor eye;
if ( eye = Actor(ti.Next()) ) eyeless = false;
else eyeless = true;
if ( !eyeless )
{
// proper boss
bCOUNTKILL = true;
level.total_monsters++;
// check if the eye is to the north of us (TNT MAP30)
if ( eye.pos.y > pos.y ) tntdir = true;
}
}
void SpawnBrainExpl( bool death = false )
{
if ( death )
{
// big explosions throughout
for ( int x=-350; x<=350; x+=10 )
{
let s = Spawn("SWWMBossBrainExpl",Vec2OffsetZ(x,tntdir?280:-280,Random[BrainExplode](120,500)));
s.tics = Random[BrainExplode](5,120);
s.special1 = Random[BrainExplode](0,3);
}
return;
}
if ( level.maptime < smallcooldown ) return;
smallcooldown = level.maptime+10;
// small explosion on brain hole
for ( int x=-40; x<=40; x+=20 )
{
let s = Spawn("SWWMBossBrainExpl",Vec2OffsetZ(x,tntdir?280:-280,Random[BrainExplode](380,420)));
s.tics = Random[BrainExplode](1,10);
s.scale *= .5;
}
}
// kill every single monster in the map, burn away spawn cubes, remove eyes
// just let players have their 100% kills in peace
void EverythingDies()
{
let ti = ThinkerIterator.Create("Actor");
Actor a;
while ( a = Actor(ti.Next()) )
{
if ( a is 'BossEye' ) a.SetStateLabel("Null");
else if ( a is 'SpawnShot' )
{
a.Spawn("SpawnFire",a.pos,ALLOW_REPLACE);
a.SetStateLabel("Null");
}
else if ( (a.Health > 0) && (a.bBossSpawned || a.bCOUNTKILL) )
a.DamageMobj(self,self,a.Health,'EndMii',DMG_FORCED|DMG_THRUSTLESS);
}
}
Default
{
Tag "$FN_BOSSBRAIN";
Radius 16;
Height 32;
+NOBLOOD;
+CASTSPRITESHADOW;
}
States
{
Spawn:
MBRN A -1;
Stop;
Pain:
MBRN A 10
{
A_StartSound("brain/pain",CHAN_VOICE,attenuation:ATTN_NONE);
A_QuakeEx(3.,3.,3.,15,0,65535,"",QF_RELATIVE|QF_SCALEDOWN,falloff:65535,rollIntensity:.3);
if ( !eyeless ) SpawnBrainExpl(false);
Spawn("SWWMBossBrainPain",pos);
}
Goto Spawn;
Death:
MBRN A 20
{
A_SetTranslation('DeadOats');
A_StartSound("brain/death",CHAN_VOICE,attenuation:ATTN_NONE);
A_QuakeEx(9.,9.,9.,120,0,65535,"",QF_RELATIVE|QF_SCALEDOWN,falloff:65535,rollIntensity:1.);
if ( !eyeless )
{
SpawnBrainExpl(true);
EverythingDies();
}
Spawn("SWWMBossBrainPain",pos);
}
MBRN A 1
{
A_FadeOut(.025,FTF_CLAMP);
return A_JumpIf(alpha<=0,1);
}
Wait;
MBRN A 80;
MBRN A 1 A_BrainDie();
Stop;
}
}
// MAP31/MAP32 wolfenstein enemies (rough DOS replication)
Class SWWMGuard : Actor
{
Default
{
Scale 2;
Health 20;
Radius 25;
Height 90;
Speed 12;
PainChance 170;
Monster;
+FLOORCLIP;
SeeSound "wolf3d/guardsight";
DeathSound "wolf3d/guarddie";
AttackSound "wolf3d/guardfire";
Obituary "$OB_WOLFGUARD";
Tag "$FN_WOLFGUARD";
Species "WolfensteinSS";
DropItem "Clip";
}
States
{
Spawn:
XGRD A 5 A_Look;
Wait;
See:
XGRD BBCCDDEE 2 A_Chase;
Loop;
Missile:
XGRD FG 8 A_FaceTarget;
XGRD H 0 A_StartSound(AttackSound,CHAN_WEAPON);
XGRD H 8 Bright A_CustomBulletAttack(22.5,0,1,Random[PosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
Goto See;
Pain:
XGRD I 0 A_JumpIf(Health&1,2);
XGRD I 2 A_Pain();
Goto See;
XGRD J 2 A_Pain();
Goto See;
Death:
XGRD K 5;
XGRD L 5 A_Scream();
XGRD M 5 A_NoBlocking();
XGRD N -1;
Stop;
}
}
Class SWWMSS : Actor
{
Default
{
Scale 2;
Health 50;
Radius 40;
Height 112;
Speed 12;
PainChance 170;
Monster;
+FLOORCLIP;
SeeSound "wolf3d/sssight";
DeathSound "wolf3d/ssdie";
AttackSound "wolf3d/ssfire";
Obituary "$OB_WOLFSS_ORIG";
Tag "$FN_WOLFSS_ORIG";
Species "WolfensteinSS";
DropItem "Clip";
}
States
{
Spawn:
XSSW W 5 A_Look;
Wait;
See:
XSSW AABBCCDD 2 A_Chase;
Loop;
Missile:
XSSW EF 5 A_FaceTarget();
XSSW G 0 A_StartSound(AttackSound,CHAN_WEAPON);
XSSW G 2 Bright A_CustomBulletAttack(22.5,0,1,Random[CPosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
XSSW F 3 A_FaceTarget();
XSSW G 2 Bright A_CustomBulletAttack(22.5,0,1,Random[CPosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
XSSW F 3 A_FaceTarget();
XSSW G 2 Bright A_CustomBulletAttack(22.5,0,1,Random[CPosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
XSSW F 3 A_FaceTarget();
XSSW G 2 Bright A_CustomBulletAttack(22.5,0,1,Random[CPosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
Goto See;
Pain:
XSSW H 0 A_JumpIf(Health&1,2);
XSSW H 2 A_Pain();
Goto See;
XSSW I 2 A_Pain();
Goto See;
Death:
XSSW J 5;
XSSW K 5 A_Scream();
XSSW L 5 A_NoBlocking();
XSSW M -1;
Stop;
}
}
Class SWWMHans : Actor
{
Default
{
Scale 2;
Health 1200;
Radius 40;
Height 112;
Mass 1000;
Speed 12;
Monster;
MinMissileChance 160;
MissileChanceMult .5;
+BOSS;
+FLOORCLIP;
+NORADIUSDMG;
+DONTMORPH;
+LOOKALLAROUND;
AttackSound "wolf3d/hansfire";
DeathSound "wolf3d/hansdie";
SeeSound "wolf3d/hanssight";
Obituary "$OB_WOLFHANS";
Tag "$FN_WOLFHANS";
Species "WolfensteinSS";
}
States
{
Spawn:
XHNS A 5 A_Look();
Wait;
See:
XHNS AABBCCDD 2 A_Chase();
Loop;
Missile:
XHNS E 8 A_FaceTarget();
XHNS F 4 A_FaceTarget();
XHNS G 0 A_StartSound(AttackSound,CHAN_WEAPON);
XHNS GFGFGE 3 Bright A_CustomBulletAttack(22.5,0,3,Random[CPosAttack](1,5)*3,flags:CBAF_NORANDOM,spawnheight:64);
Goto See;
Death:
XHNS H 10;
XHNS I 10 A_Scream();
XHNS J 10 A_NoBlocking();
XHNS K -1;
Stop;
}
}
Class SWWMDog : Actor
{
Default
{
Scale 2;
Health 1;
Speed 12;
Radius 24;
Height 56;
Mass 100;
Monster;
AttackSound "wolf3d/dogbite";
DeathSound "wolf3d/dogdie";
SeeSound "wolf3d/dogsight";
Obituary "$OB_DOG";
Tag "$FN_DOG";
}
States
{
Spawn:
XDOG A 5 A_Look();
Wait;
See:
XDOG AABBCCDD 2 A_Chase();
Loop;
Melee:
XDOG EF 5 A_FaceTarget();
XDOG G 5 A_SargAttack();
XDOG EA 5;
Goto See;
Death:
XDOG H 5;
XDOG I 5 A_Scream();
XDOG J 5 A_NoBlocking();
XDOG K -1;
Stop;
}
}