gzdoom/wadsrc/static/zscript/actors/shared/ice.zs

196 lines
4.1 KiB
Text

//==========================================================================
//
// Ice chunk
//
//==========================================================================
class IceChunk : Actor
{
Default
{
Radius 3;
Height 4;
Mass 5;
Gravity 0.125;
+DROPOFF
+CANNOTPUSH
+FLOORCLIP
+NOTELEPORT
+NOBLOCKMAP
+MOVEWITHSECTOR
}
void A_IceSetTics ()
{
tics = random[IceTics](70, 133);
Name dtype = GetFloorTerrain().DamageMOD;
if (dtype == 'Fire')
{
tics >>= 2;
}
else if (dtype == 'Ice')
{
tics <<= 1;
}
}
States
{
Spawn:
ICEC ABCD 10 A_IceSetTics;
Stop;
}
}
//==========================================================================
//
// A chunk of ice that is also a player
//
//==========================================================================
class IceChunkHead : PlayerChunk
{
Default
{
Radius 3;
Height 4;
Mass 5;
Gravity 0.125;
DamageType "Ice";
+DROPOFF
+CANNOTPUSH
}
States
{
Spawn:
ICEC A 0;
ICEC A 10 A_CheckPlayerDone;
wait;
}
}
extend class Actor
{
//============================================================================
//
// A_FreezeDeath
//
//============================================================================
void A_FreezeDeath()
{
int t = random[freezedeath]();
tics = 75+t+random[freezedeath]();
bSolid = bShootable = bNoBlood = bIceCorpse = bPushable = bTelestomp = bCanPass = bSlidesOnWalls = bCrashed = true;
Height = Default.Height;
A_SetRenderStyle(1, STYLE_Normal);
A_PlaySound ("misc/freeze", CHAN_BODY);
// [RH] Andy Baker's stealth monsters
if (bStealth)
{
Alpha = 1;
visdir = 0;
}
if (player)
{
player.damagecount = 0;
player.poisoncount = 0;
player.bonuscount = 0;
}
else if (bIsMonster && special)
{ // Initiate monster death actions
A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]);
special = 0;
}
}
//============================================================================
//
// A_FreezeDeathChunks
//
//============================================================================
void A_FreezeDeathChunks()
{
if (Vel != (0,0,0) && !bShattering)
{
tics = 3*TICRATE;
return;
}
Vel = (0,0,0);
A_PlaySound ("misc/icebreak", CHAN_BODY);
// [RH] In Hexen, this creates a random number of shards (range [24,56])
// with no relation to the size of the self shattering. I think it should
// base the number of shards on the size of the dead thing, so bigger
// things break up into more shards than smaller things.
// An actor with radius 20 and height 64 creates ~40 chunks.
int numChunks = max(4, int(radius * Height)/32);
int i = Random[FreezeDeathChunks](0, numChunks/4 - 1);
for (i = max(24, numChunks + i); i >= 0; i--)
{
double xo = (random[FreezeDeathChunks]() - 128)*radius / 128;
double yo = (random[FreezeDeathChunks]() - 128)*radius / 128;
double zo = (random[FreezeDeathChunks]() * Height / 255);
Actor mo = Spawn("IceChunk", Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
if (mo)
{
mo.SetState (mo.SpawnState + random[FreezeDeathChunks](0, 2));
mo.Vel.X = random2[FreezeDeathChunks]() / 128.;
mo.Vel.Y = random2[FreezeDeathChunks]() / 128.;
mo.Vel.Z = (mo.pos.Z - pos.Z) / Height * 4;
}
}
if (player)
{ // attach the player's view to a chunk of ice
Actor head = Spawn("IceChunkHead", pos + (0, 0, player.mo.ViewHeight), ALLOW_REPLACE);
if (head != null)
{
head.Vel.X = random2[FreezeDeathChunks]() / 128.;
head.Vel.Y = random2[FreezeDeathChunks]() / 128.;
head.Vel.Z = (head.pos.Z - pos.Z) / Height * 4;
head.health = health;
head.Angle = Angle;
if (head is "PlayerPawn")
{
head.player = player;
head.player.mo = PlayerPawn(head);
player = null;
head.ObtainInventory (self);
}
head.Pitch = 0.;
if (head.player.camera == self)
{
head.player.camera = head;
}
}
}
// [RH] Do some stuff to make this more useful outside Hexen
if (bBossDeath)
{
A_BossDeath();
}
A_NoBlocking();
SetStateLabel('null');
}
void A_GenericFreezeDeath()
{
A_SetTranslation('Ice');
A_FreezeDeath();
}
}