2022-11-30 18:39:06 +00:00
|
|
|
class DukeGreenSlime : DukeActor
|
|
|
|
{
|
|
|
|
default
|
|
|
|
{
|
|
|
|
spriteset "GREENSLIME", "GREENSLIME1", "GREENSLIME2", "GREENSLIME3", "GREENSLIME4", "GREENSLIME5", "GREENSLIME6", "GREENSLIME7";
|
2022-12-19 21:40:16 +00:00
|
|
|
+INTERNAL_BADGUY;
|
|
|
|
+KILLCOUNT;
|
2022-12-16 11:47:30 +00:00
|
|
|
+DONTDIVEALIVE;
|
|
|
|
+FORCESECTORSHADE;
|
|
|
|
+SHRINKAUTOAIM;
|
2022-12-30 21:09:33 +00:00
|
|
|
+NOHITJIBS;
|
2022-12-23 07:55:13 +00:00
|
|
|
sparkoffset -8;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override void Initialize()
|
|
|
|
{
|
2023-01-08 15:38:30 +00:00
|
|
|
self.scale = (0.625, 0.625);
|
|
|
|
self.clipdist = 20;
|
|
|
|
self.extra = 1;
|
|
|
|
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override void PlayFTASound()
|
|
|
|
{
|
|
|
|
self.PlayActorSound("SLIM_RECOG");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override void Tick()
|
|
|
|
{
|
|
|
|
let sectp = self.sector;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
self.temp_data[1] += 128;
|
|
|
|
|
|
|
|
if (sectp.floorstat & CSTAT_SECTOR_SKY)
|
|
|
|
{
|
|
|
|
self.Destroy();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
double xx;
|
|
|
|
DukePlayer p;
|
|
|
|
[p, xx] = self.findplayer();
|
|
|
|
let pactor = p.actor;
|
|
|
|
|
|
|
|
if (xx > 1280)
|
|
|
|
{
|
|
|
|
self.timetosleep++;
|
|
|
|
if (self.timetosleep > Duke.SLEEPTIME)
|
|
|
|
{
|
|
|
|
self.timetosleep = 0;
|
|
|
|
self.ChangeStat(STAT_ZOMBIEACTOR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == -5) // FROZEN
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.temp_data[3]++;
|
|
|
|
if (self.temp_data[3] > 280)
|
|
|
|
{
|
|
|
|
self.pal = 0;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.makeitfall();
|
|
|
|
self.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
|
|
|
self.setSpriteSetImage(2);
|
|
|
|
self.extra = 1;
|
|
|
|
self.pal = 1;
|
|
|
|
j = self.ifhitbyweapon();
|
|
|
|
if (j >= 0)
|
|
|
|
{
|
2022-12-16 15:56:47 +00:00
|
|
|
if (j == 1) // freeze damage
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
for (j = 16; j >= 0; j--)
|
|
|
|
{
|
|
|
|
let a = frandom(0, 360);
|
|
|
|
let vel = frandom(0, 2) + 2;
|
|
|
|
let zvel = 4 - frandom(0, 4);
|
|
|
|
|
2022-12-04 12:09:47 +00:00
|
|
|
static const name pieces[] = {'DukeGlassPieces', 'DukeGlassPieces1', 'DukeGlassPieces2'};
|
2022-11-30 18:39:06 +00:00
|
|
|
let k = dlevel.SpawnActor(self.sector, self.pos, pieces[j % 3], -32, (0.5625, 0.5625), a, vel, zvel, self, STAT_MISC);
|
|
|
|
if (k) k.pal = 1;
|
|
|
|
}
|
2023-04-07 07:46:51 +00:00
|
|
|
self.addkill();
|
2022-11-30 18:39:06 +00:00
|
|
|
self.PlayActorSound("GLASS_BREAKING");
|
|
|
|
self.Destroy();
|
|
|
|
}
|
|
|
|
else if (xx < 64 && p.quick_kick == 0)
|
|
|
|
{
|
|
|
|
let ang = absangle(pactor.angle, (self.pos.XY - pactor.pos.XY).Angle());
|
|
|
|
if (ang < 22.5)
|
|
|
|
p.quick_kick = 14;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xx < 99.75)
|
|
|
|
self.cstat = 0;
|
|
|
|
else self.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == -4) //On the player
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
if (pactor.extra < 1)
|
|
|
|
{
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.SetPosition(self.pos);
|
|
|
|
|
|
|
|
self.angle = pactor.angle;
|
|
|
|
|
|
|
|
if ((p.PlayerInput(Duke.SB_FIRE) || (p.quick_kick > 0)) && pactor.extra > 0)
|
|
|
|
if (p.quick_kick > 0 || (p.curr_weapon != DukeWpn.HANDREMOTE_WEAPON && p.curr_weapon != DukeWpn.HANDBOMB_WEAPON && p.curr_weapon != DukeWpn.TRIPBOMB_WEAPON && p.ammo_amount[p.curr_weapon] >= 0))
|
|
|
|
{
|
|
|
|
for (int x = 0; x < 8; x++)
|
|
|
|
{
|
|
|
|
let a = frandom(0, 360);
|
|
|
|
let vel = frandom(0, 4) + 4;
|
|
|
|
let zvel = -frandom(0, 16) - self.vel.Z * 0.25;
|
|
|
|
|
|
|
|
let spawned = dlevel.SpawnActor(self.sector, self.pos.plusZ(-8), "DukeScrap", -8, (0.75, 0.75), a, vel, zvel, self, STAT_MISC);
|
|
|
|
if (spawned)
|
|
|
|
{
|
|
|
|
if (spawned) spawned.spriteextra = DukeScrap.Scrap3 + random(0, 3);
|
|
|
|
spawned.pal = 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.PlayActorSound("SLIM_DYING");
|
|
|
|
self.PlayActorSound("SQUISHED");
|
|
|
|
if (random(0, 255) < 32)
|
|
|
|
{
|
|
|
|
let spawned = self.spawn("DukeBloodPool");
|
|
|
|
if (spawned) spawned.pal = 0;
|
|
|
|
}
|
2023-04-07 07:46:51 +00:00
|
|
|
self.addkill();
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -3;
|
2022-11-30 18:39:06 +00:00
|
|
|
if (p.somethingonplayer == self)
|
|
|
|
p.somethingonplayer = nullptr;
|
|
|
|
self.Destroy();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.pos.Z = pactor.pos.Z + pactor.viewzoffset + 8 + p.pyoff - (self.temp_data[2] + tan(pactor.pitch) * 2048.) * zmaptoworld;
|
|
|
|
|
|
|
|
if (self.temp_data[2] > 512)
|
|
|
|
self.temp_data[2] -= 128;
|
|
|
|
|
|
|
|
if (self.temp_data[2] < 348)
|
|
|
|
self.temp_data[2] += 128;
|
|
|
|
|
|
|
|
if (p.newOwner != nullptr)
|
|
|
|
{
|
|
|
|
p.newOwner = nullptr;
|
|
|
|
pactor.restoreloc();
|
|
|
|
|
|
|
|
p.cursector = Raze.updatesector(pactor.pos.XY, p.cursector);
|
|
|
|
|
|
|
|
DukeStatIterator it;
|
|
|
|
for (let ac = it.First(STAT_ACTOR); ac; ac = it.Next())
|
|
|
|
{
|
2022-12-16 16:53:47 +00:00
|
|
|
if (ac.bCAMERA) ac.yint = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.temp_data[3] > 0)
|
|
|
|
{
|
|
|
|
static const int frames[] = { 5,5,6,6,7,7,6,5 };
|
|
|
|
|
|
|
|
self.setSpriteSetImage(frames[self.temp_data[3]]);
|
|
|
|
|
|
|
|
if (self.temp_data[3] == 5)
|
|
|
|
{
|
|
|
|
let psp = pactor;
|
|
|
|
psp.extra -= random(5, 8);
|
|
|
|
self.PlayActorSound("SLIM_ATTACK");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.temp_data[3] < 7) self.temp_data[3]++;
|
|
|
|
else self.temp_data[3] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self.setSpriteSetImage(5);
|
|
|
|
if (Duke.rnd(32))
|
|
|
|
self.temp_data[3] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
double add = (Raze.BobVal(self.temp_data[1]) * 2) * REPEAT_SCALE;
|
|
|
|
self.scale = (0.3125 + add, 0.234375 + add);
|
|
|
|
self.pos.XY = pactor.pos.XY + pactor.angle.ToVector() * 8;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (self.vel.X < 4 && xx < 48)
|
|
|
|
{
|
|
|
|
if (p.somethingonplayer == nullptr)
|
|
|
|
{
|
|
|
|
p.somethingonplayer = self;
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == 3 || self.counter == 2) //Falling downward
|
2022-11-30 18:39:06 +00:00
|
|
|
self.temp_data[2] = (12 << 8);
|
|
|
|
else self.temp_data[2] = -(13 << 8); //Climbing up duke
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -4;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
j = self.ifhitbyweapon();
|
|
|
|
if (j >= 0)
|
|
|
|
{
|
|
|
|
self.PlayActorSound("SLIM_DYING");
|
|
|
|
|
|
|
|
if (p.somethingonplayer == self)
|
|
|
|
p.somethingonplayer = nullptr;
|
|
|
|
|
2022-12-16 15:56:47 +00:00
|
|
|
if (j == 1) // freeze damage
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.PlayActorSound("SOMETHINGFROZE");
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -5; self.temp_data[3] = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-04-07 07:46:51 +00:00
|
|
|
self.addkill();
|
2022-11-30 18:39:06 +00:00
|
|
|
|
|
|
|
if (random(0, 255) < 32)
|
|
|
|
{
|
|
|
|
let spawned = self.spawn("DukeBloodPool");
|
|
|
|
if (spawned) spawned.pal = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int x = 0; x < 8; x++)
|
|
|
|
{
|
|
|
|
let a = frandom(0, 360);
|
|
|
|
let vel = frandom(0, 4) + 4;
|
|
|
|
let zvel = -frandom(0, 16) - self.vel.Z * 0.25;
|
|
|
|
|
|
|
|
let spawned = dlevel.SpawnActor(self.sector, self.pos.plusZ(-8), "DukeScrap", -8, (0.75, 0.75), a, vel, zvel, self, STAT_MISC);
|
|
|
|
if (spawned)
|
|
|
|
{
|
|
|
|
spawned.spriteextra = DukeScrap.Scrap3 + random(0, 3);
|
|
|
|
spawned.pal = 6;
|
|
|
|
}
|
|
|
|
}
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -3;
|
2022-11-30 18:39:06 +00:00
|
|
|
self.Destroy();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// All weap
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == -1) //Shrinking down
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.makeitfall();
|
|
|
|
|
|
|
|
self.cstat &= ~CSTAT_SPRITE_YFLIP;
|
|
|
|
self.setSpriteSetImage(4);
|
|
|
|
|
2023-03-25 13:32:35 +00:00
|
|
|
if (self.scale.X > 0.5 ) self.scale.X -= random(0, 7) * REPEAT_SCALE;
|
|
|
|
if (self.scale.Y > 0.25 ) self.scale.Y -= random(0, 7) * REPEAT_SCALE;
|
2022-11-30 18:39:06 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
self.scale = (0.625, 0.25);
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2022-12-22 08:49:42 +00:00
|
|
|
else if (self.counter != -2) self.getglobalz();
|
2022-11-30 18:39:06 +00:00
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == -2) //On top of somebody (an enemy)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
DukeActor s5 = self.temp_actor;
|
|
|
|
self.makeitfall();
|
|
|
|
if (s5)
|
|
|
|
{
|
|
|
|
s5.vel.X = 0;
|
|
|
|
|
|
|
|
self.pos = s5.pos + s5.angle.ToVector() * 0.5;
|
2023-03-19 00:30:01 +00:00
|
|
|
self.setspriteSetImage(2 + (Duke.global_random() & 1));
|
2022-11-30 18:39:06 +00:00
|
|
|
|
|
|
|
if (self.scale.Y < 1) self.scale.Y += (0.03125);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (self.scale.X < 0.5) self.scale.X += (0.0625);
|
|
|
|
else
|
|
|
|
{
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -1;
|
2023-03-25 13:32:35 +00:00
|
|
|
self.temp_actor = nullptr;
|
2022-11-30 18:39:06 +00:00
|
|
|
double dist = (self.pos.XY - s5.pos.XY).LengthSquared();
|
|
|
|
if (dist < 48*48) {
|
|
|
|
s5.scale.X = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-25 13:32:35 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
self.temp_data[0] = -1;
|
|
|
|
}
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check randomly to see of there is an actor near
|
|
|
|
if (Duke.rnd(32))
|
|
|
|
{
|
|
|
|
DukeSectIterator it;
|
|
|
|
for (let a2 = it.First(self.sector); a2; a2 = it.Next())
|
|
|
|
{
|
2022-12-16 16:53:47 +00:00
|
|
|
if (a2.bGREENSLIMEFOOD)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
double dist = (self.pos.XY - a2.pos.XY).LengthSquared();
|
|
|
|
if (dist < 48*48 && (abs(self.pos.Z - a2.pos.Z) < 16)) //Gulp them
|
|
|
|
{
|
|
|
|
self.temp_actor = a2;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = -2;
|
2022-11-30 18:39:06 +00:00
|
|
|
self.temp_data[1] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Moving on the ground or ceiling
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == 0 || self.counter == 2)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.setspriteSetImage(0);
|
|
|
|
|
|
|
|
if (random(0, 511) == 0)
|
|
|
|
self.PlayActorSound("SLIM_ROAM");
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == 2)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.vel.Z = 0;
|
|
|
|
self.cstat &= ~CSTAT_SPRITE_YFLIP;
|
|
|
|
|
|
|
|
if ((sectp.ceilingstat & CSTAT_SECTOR_SKY) || (self.ceilingz + 24) < self.pos.Z)
|
|
|
|
{
|
|
|
|
self.pos.Z += 8;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 3;
|
2022-11-30 18:39:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self.cstat |= CSTAT_SPRITE_YFLIP;
|
|
|
|
self.makeitfall();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PlayClock & 4) self.DoMove(CLIPMASK0);
|
|
|
|
|
|
|
|
if (self.vel.X > 6)
|
|
|
|
{
|
|
|
|
self.vel.X -= 1/8.;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (self.vel.X < 2) self.vel.X += 0.25;
|
|
|
|
self.vel.X = 4 - Raze.BobVal(512 + self.temp_data[1]) * 2;
|
|
|
|
self.angle += deltaangle(self.angle, (pactor.pos.XY - self.pos.XY).Angle()) * 0.125;
|
|
|
|
// TJR
|
|
|
|
}
|
|
|
|
|
|
|
|
self.scale.X = (0.5625 + Raze.BobVal(512 + self.temp_data[1]) * 0.125);
|
|
|
|
self.scale.Y = (0.25 + Raze.BobVal(self.temp_data[1]) * 0.03125);
|
|
|
|
|
|
|
|
if (Duke.rnd(4) && (sectp.ceilingstat & CSTAT_SECTOR_SKY) == 0 &&
|
|
|
|
abs(self.floorz - self.ceilingz) < 192)
|
|
|
|
{
|
|
|
|
self.vel.Z = 0;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter++;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == 1)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.setspriteSetImage(0);
|
|
|
|
if (self.scale.Y < 0.625) self.scale.Y += (0.125);
|
|
|
|
if (self.scale.X > 0.125 ) self.scale.X += (-0.0625);
|
|
|
|
if (self.vel.Z > -12)
|
|
|
|
self.vel.Z -= 348 / 256.;
|
|
|
|
self.pos.Z += self.vel.Z;
|
|
|
|
if (self.pos.Z < self.ceilingz + 16)
|
|
|
|
{
|
|
|
|
self.pos.Z = self.ceilingz + 16;
|
|
|
|
self.vel.X = 0;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 2;
|
2022-11-30 18:39:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-22 08:49:42 +00:00
|
|
|
if (self.counter == 3)
|
2022-11-30 18:39:06 +00:00
|
|
|
{
|
|
|
|
self.setspriteSetImage(1);
|
|
|
|
self.makeitfall();
|
|
|
|
|
|
|
|
if (self.pos.Z > self.floorz - 8)
|
|
|
|
{
|
|
|
|
self.scale.Y += (-0.0625);
|
|
|
|
self.scale.X += (0.03125);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (self.scale.Y < 0.5625) self.scale.Y += (0.125);
|
|
|
|
if (self.scale.X > 0.125 ) self.scale.X += (-0.0625);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.pos.Z > self.floorz - 8)
|
|
|
|
{
|
|
|
|
self.pos.Z = self.floorz - 8;
|
2022-12-22 08:49:42 +00:00
|
|
|
self.counter = 0;
|
2022-11-30 18:39:06 +00:00
|
|
|
self.vel.X = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|