qzdoom-gpl/wadsrc/static/zscript/hexen/blastradius.txt
Christoph Oelckers 3d61d2c1f4 - reviewd script code for spawn calls that did not check their results.
Nothing should ever assume that spawning an actor is unconditionally successful. There can always be some edge cases where this is not the case.
2016-12-31 15:40:51 +01:00

173 lines
4.1 KiB
Text

class ArtiBlastRadius : CustomInventory
{
Default
{
+FLOATBOB
Inventory.DefMaxAmount;
Inventory.PickupFlash "PickupFlash";
+INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND
Inventory.Icon "ARTIBLST";
Inventory.PickupSound "misc/p_pkup";
Inventory.PickupMessage "$TXT_ARTIBLASTRADIUS";
Tag "$TAG_ARTIBLASTRADIUS";
}
States
{
Spawn:
BLST ABCDEFGH 4 Bright;
Loop;
Use:
TNT1 A 0 A_Blast;
}
}
//==========================================================================
//
// A_Blast is public to Actor
//
//==========================================================================
extend class Actor
{
/* For reference, the default values:
#define BLAST_RADIUS_DIST 255.0
#define BLAST_SPEED 20.0
#define BLAST_FULLSTRENGTH 255
*/
//==========================================================================
//
// AArtiBlastRadius :: BlastActor
//
//==========================================================================
private void BlastActor (Actor victim, double strength, double speed, Class<Actor> blasteffect, bool dontdamage)
{
if (!victim.SpecialBlastHandling (self, strength))
{
return;
}
double ang = AngleTo(victim);
Vector2 move = AngleToVector(ang, speed);
victim.Vel.XY = move;
// Spawn blast puff
ang -= 180.;
Vector3 spawnpos = victim.Vec3Offset(
(victim.radius + 1) * cos(ang),
(victim.radius + 1) * sin(ang),
(victim.Height / 2) - victim.Floorclip);
Actor mo = Spawn (blasteffect, spawnpos, ALLOW_REPLACE);
if (mo)
{
mo.Vel.XY = victim.Vel.XY;
}
if (victim.bMissile)
{
// [RH] Floor and ceiling huggers should not be blasted vertically.
if (!victim.bFloorHugger && !victim.bCeilingHugger)
{
victim.Vel.Z = 8;
if (mo != null) mo.Vel.Z = 8;
}
}
else
{
victim.Vel.Z = 1000. / victim.Mass;
}
if (victim.player)
{
// Players handled automatically
}
else if (!dontdamage)
{
victim.bBlasted = true;
}
if (victim.bTouchy)
{ // Touchy objects die when blasted
victim.bArmed = false; // Disarm
victim.DamageMobj(self, self, victim.health, 'Melee', DMG_FORCED);
}
}
//==========================================================================
//
// AArtiBlastRadius :: Activate
//
// Blast all actors away
//
//==========================================================================
action void A_Blast(int blastflags = 0, double strength = 255, double radius = 255, double speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius")
{
if (player && (blastflags & BF_USEAMMO) && invoker == player.ReadyWeapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
{
Weapon weapon = player.ReadyWeapon;
if (weapon != null && !weapon.DepleteAmmo(weapon.bAltFire))
{
return;
}
}
A_PlaySound (blastsound, CHAN_AUTO);
if (!(blastflags & BF_DONTWARN))
{
SoundAlert (self);
}
ThinkerIterator it = ThinkerIterator.Create("Actor");
Actor mo;
while ( (mo = Actor(it.Next ())) )
{
if (mo == self || (mo.bBoss && !(blastflags & BF_AFFECTBOSSES)) || mo.bDormant || mo.bDontBlast)
{ // Not a valid monster: originator, boss, dormant, or otherwise protected
continue;
}
if (mo.bIceCorpse || mo.bCanBlast)
{
// Let these special cases go
}
else if (mo.bIsMonster && mo.health <= 0)
{
continue;
}
else if (!mo.player && !mo.bMissile && !mo.bIsMonster && !mo.bCanBlast && !mo.bTouchy && !mo.bVulnerable)
{ // Must be monster, player, missile, touchy or vulnerable
continue;
}
if (Distance2D(mo) > radius)
{ // Out of range
continue;
}
if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo))
{
// in another region and cannot be seen.
continue;
}
BlastActor (mo, strength, speed, blasteffect, !!(blastflags & BF_NOIMPACTDAMAGE));
}
}
}
// Blast Effect -------------------------------------------------------------
class BlastEffect : Actor
{
Default
{
+NOBLOCKMAP +NOGRAVITY +NOCLIP
+NOTELEPORT
RenderStyle "Translucent";
Alpha 0.666;
}
States
{
Spawn:
RADE ABCDEFGHI 4;
Stop;
}
}