mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified A_Explode and relatives.
This commit is contained in:
parent
44d51a6de9
commit
652606f70b
8 changed files with 200 additions and 219 deletions
|
@ -1186,119 +1186,6 @@ DEFINE_ACTION_FUNCTION(AActor, CheckInventory)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parameterized version of A_Explode
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
XF_HURTSOURCE = 1,
|
||||
XF_NOTMISSILE = 4,
|
||||
XF_NOACTORTYPE = 1 << 3,
|
||||
XF_NOSPLASH = 16,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Explode)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_INT (damage);
|
||||
PARAM_INT (distance);
|
||||
PARAM_INT (flags);
|
||||
PARAM_BOOL (alert);
|
||||
PARAM_INT (fulldmgdistance);
|
||||
PARAM_INT (nails);
|
||||
PARAM_INT (naildamage);
|
||||
PARAM_CLASS (pufftype, AActor);
|
||||
PARAM_NAME (damagetype);
|
||||
|
||||
if (damage < 0) // get parameters from metadata
|
||||
{
|
||||
damage = self->IntVar(NAME_ExplosionDamage);
|
||||
distance = self->IntVar(NAME_ExplosionRadius);
|
||||
flags = !self->BoolVar(NAME_DontHurtShooter);
|
||||
alert = false;
|
||||
}
|
||||
if (distance <= 0) distance = damage;
|
||||
|
||||
// NailBomb effect, from SMMU but not from its source code: instead it was implemented and
|
||||
// generalized from the documentation at http://www.doomworld.com/eternity/engine/codeptrs.html
|
||||
|
||||
if (nails)
|
||||
{
|
||||
DAngle ang;
|
||||
for (int i = 0; i < nails; i++)
|
||||
{
|
||||
ang = i*360./nails;
|
||||
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
|
||||
P_LineAttack(self, ang, MISSILERANGE, 0.,
|
||||
//P_AimLineAttack (self, ang, MISSILERANGE),
|
||||
naildamage, NAME_Hitscan, pufftype, (self->flags & MF_MISSILE) ? LAF_TARGETISSOURCE : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & XF_NOACTORTYPE) && damagetype == NAME_None)
|
||||
{
|
||||
damagetype = self->DamageType;
|
||||
}
|
||||
|
||||
int pflags = 0;
|
||||
if (flags & XF_HURTSOURCE) pflags |= RADF_HURTSOURCE;
|
||||
if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT;
|
||||
|
||||
int count = P_RadiusAttack (self, self->target, damage, distance, damagetype, pflags, fulldmgdistance);
|
||||
if (!(flags & XF_NOSPLASH)) P_CheckSplash(self, distance);
|
||||
if (alert && self->target != NULL && self->target->player != NULL)
|
||||
{
|
||||
P_NoiseAlert(self->target, self);
|
||||
}
|
||||
ACTION_RETURN_INT(count);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_RadiusThrust
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
RTF_AFFECTSOURCE = 1,
|
||||
RTF_NOIMPACTDAMAGE = 2,
|
||||
RTF_NOTMISSILE = 4,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_RadiusThrust)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_INT (force);
|
||||
PARAM_INT (distance);
|
||||
PARAM_INT (flags);
|
||||
PARAM_INT (fullthrustdistance);
|
||||
|
||||
bool sourcenothrust = false;
|
||||
|
||||
if (force == 0) force = 128;
|
||||
if (distance <= 0) distance = abs(force);
|
||||
|
||||
// Temporarily negate MF2_NODMGTHRUST on the shooter, since it renders this function useless.
|
||||
if (!(flags & RTF_NOTMISSILE) && self->target != NULL && self->target->flags2 & MF2_NODMGTHRUST)
|
||||
{
|
||||
sourcenothrust = true;
|
||||
self->target->flags2 &= ~MF2_NODMGTHRUST;
|
||||
}
|
||||
|
||||
P_RadiusAttack (self, self->target, force, distance, self->DamageType, flags | RADF_NODAMAGE, fullthrustdistance);
|
||||
P_CheckSplash(self, distance);
|
||||
|
||||
if (sourcenothrust)
|
||||
{
|
||||
self->target->flags2 |= MF2_NODMGTHRUST;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_RadiusDamageSelf
|
||||
|
|
|
@ -3409,20 +3409,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_Pain)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// A_Detonate
|
||||
// killough 8/9/98: same as A_Explode, except that the damage is variable
|
||||
//
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Detonate)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
int damage = self->GetMissileDamage(0, 1);
|
||||
P_RadiusAttack (self, self->target, damage, damage, self->DamageType, RADF_HURTSOURCE);
|
||||
P_CheckSplash(self, damage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CheckBossDeath (AActor *actor)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -359,7 +359,6 @@ void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff); // hitsc
|
|||
void P_TraceBleed (int damage, AActor *target); // random direction version
|
||||
bool P_HitFloor (AActor *thing);
|
||||
bool P_HitWater (AActor *thing, sector_t *sec, const DVector3 &pos, bool checkabove = false, bool alert = true, bool force = false);
|
||||
void P_CheckSplash(AActor *self, double distance);
|
||||
|
||||
struct FRailParams
|
||||
{
|
||||
|
@ -410,6 +409,7 @@ enum
|
|||
RADF_SOURCEISSPOT = 4,
|
||||
RADF_NODAMAGE = 8,
|
||||
RADF_THRUSTZ = 16,
|
||||
RADF_OLDRADIUSDAMAGE = 32
|
||||
};
|
||||
int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
|
||||
FName damageType, int flags, int fulldamagedistance=0);
|
||||
|
|
|
@ -6229,7 +6229,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom
|
|||
// them far too "active." BossBrains also use the old code
|
||||
// because some user levels require they have a height of 16,
|
||||
// which can make them near impossible to hit with the new code.
|
||||
if ((flags & RADF_NODAMAGE) || !((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG))
|
||||
if (((flags & RADF_NODAMAGE) || !((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG)) && !(flags & RADF_OLDRADIUSDAMAGE))
|
||||
{
|
||||
double points = P_GetRadiusDamage(false, bombspot, thing, bombdamage, bombdistance, fulldamagedistance, bombsource == thing);
|
||||
double check = int(points) * bombdamage;
|
||||
|
@ -6306,6 +6306,18 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom
|
|||
return count;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, RadiusAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(bombsource, AActor);
|
||||
PARAM_INT(bombdamage);
|
||||
PARAM_INT(bombdistance);
|
||||
PARAM_NAME(damagetype);
|
||||
PARAM_INT(flags);
|
||||
PARAM_INT(fulldamagedistance);
|
||||
ACTION_RETURN_INT(P_RadiusAttack(self, bombsource, bombdamage, bombdistance, damagetype, flags, fulldamagedistance));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SECTOR HEIGHT CHANGING
|
||||
|
|
|
@ -6777,29 +6777,6 @@ DEFINE_ACTION_FUNCTION(AActor, HitFloor)
|
|||
ACTION_RETURN_BOOL(P_HitFloor(self));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_CheckSplash
|
||||
//
|
||||
// Checks for splashes caused by explosions
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_CheckSplash(AActor *self, double distance)
|
||||
{
|
||||
sector_t *floorsec;
|
||||
self->Sector->LowestFloorAt(self, &floorsec);
|
||||
if (self->Z() <= self->floorz + distance && self->floorsector == floorsec && self->Sector->GetHeightSec() == NULL && floorsec->heightsec == NULL)
|
||||
{
|
||||
// Explosion splashes never alert monsters. This is because A_Explode has
|
||||
// a separate parameter for that so this would get in the way of proper
|
||||
// behavior.
|
||||
DVector3 pos = self->PosRelative(floorsec);
|
||||
pos.Z = self->floorz;
|
||||
P_HitWater (self, floorsec, pos, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_CheckMissileSpawn
|
||||
|
|
|
@ -964,69 +964,6 @@ class Actor : Thinker native
|
|||
native bool A_LineEffect(int boomspecial = 0, int tag = 0);
|
||||
// End of MBF redundant functions.
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// old customizable attack functions which use actor parameters.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
private void DoAttack (bool domelee, bool domissile, int MeleeDamage, Sound MeleeSound, Class<Actor> MissileType,double MissileHeight)
|
||||
{
|
||||
let targ = target;
|
||||
if (targ == NULL) return;
|
||||
|
||||
A_FaceTarget ();
|
||||
if (domelee && MeleeDamage>0 && CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[CustomMelee](1, 8) * MeleeDamage;
|
||||
if (MeleeSound) A_PlaySound (MeleeSound, CHAN_WEAPON);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else if (domissile && MissileType != NULL)
|
||||
{
|
||||
// This seemingly senseless code is needed for proper aiming.
|
||||
double add = MissileHeight + GetBobOffset() - 32;
|
||||
AddZ(add);
|
||||
Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), targ, MissileType, false);
|
||||
AddZ(-add);
|
||||
|
||||
if (missile)
|
||||
{
|
||||
// automatic handling of seeker missiles
|
||||
if (missile.bSeekerMissile)
|
||||
{
|
||||
missile.tracer = targ;
|
||||
}
|
||||
missile.CheckMissileSpawn(radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_MeleeAttack()
|
||||
{
|
||||
DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0);
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_MissileAttack()
|
||||
{
|
||||
Class<Actor> MissileType = MissileName;
|
||||
DoAttack(false, true, 0, 0, MissileType, MissileHeight);
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_ComboAttack()
|
||||
{
|
||||
Class<Actor> MissileType = MissileName;
|
||||
DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
|
||||
}
|
||||
|
||||
void A_BasicAttack(int melee_damage, sound melee_sound, class<actor> missile_type, double missile_height)
|
||||
{
|
||||
DoAttack(true, true, melee_damage, melee_sound, missile_type, missile_height);
|
||||
}
|
||||
|
||||
|
||||
native void A_MonsterRail();
|
||||
native void A_Pain();
|
||||
native void A_NoBlocking(bool drop = true);
|
||||
|
@ -1038,7 +975,6 @@ class Actor : Thinker native
|
|||
native void A_VileChase();
|
||||
native bool A_CheckForResurrection();
|
||||
native void A_BossDeath();
|
||||
native void A_Detonate();
|
||||
bool A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0)
|
||||
{
|
||||
return Level.ExecuteSpecial(special, self, null, false, arg1, arg2, arg3, arg4, arg5);
|
||||
|
@ -1110,10 +1046,10 @@ class Actor : Thinker native
|
|||
native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
|
||||
native void A_CustomComboAttack(class<Actor> missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
|
||||
native void A_Burst(class<Actor> chunktype);
|
||||
native void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0);
|
||||
native void A_RadiusDamageSelf(int damage = 128, double distance = 128, int flags = 0, class<Actor> flashtype = null);
|
||||
native int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff", name damagetype = "none");
|
||||
native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false);
|
||||
native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0);
|
||||
|
||||
native void A_Stop();
|
||||
native void A_Respawn(int flags = 1);
|
||||
native void A_RestoreSpecialPosition();
|
||||
|
|
|
@ -529,7 +529,180 @@ extend class Actor
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_CheckSplash
|
||||
//
|
||||
// Checks for splashes caused by explosions
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckSplash(double distance)
|
||||
{
|
||||
double floorh;
|
||||
sector floorsec;
|
||||
[floorh, floorsec] = curSector.LowestFloorAt(pos.XY);
|
||||
|
||||
if (pos.Z <= floorz + distance && floorsector == floorsec && curSector.GetHeightSec() == NULL && floorsec.heightsec == NULL)
|
||||
{
|
||||
// Explosion splashes never alert monsters. This is because A_Explode has
|
||||
// a separate parameter for that so this would get in the way of proper
|
||||
// behavior.
|
||||
Vector3 pos = PosRelative(floorsec);
|
||||
pos.Z = floorz;
|
||||
HitWater (floorsec, pos, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parameterized version of A_Explode
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldmgdistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff", name damagetype = "none")
|
||||
{
|
||||
|
||||
if (damage < 0) // get parameters from metadata
|
||||
{
|
||||
damage = ExplosionDamage;
|
||||
distance = ExplosionRadius;
|
||||
flags = !DontHurtShooter;
|
||||
alert = false;
|
||||
}
|
||||
if (distance <= 0) distance = damage;
|
||||
|
||||
// NailBomb effect, from SMMU but not from its source code: instead it was implemented and
|
||||
// generalized from the documentation at http://www.doomworld.com/eternity/engine/codeptrs.html
|
||||
|
||||
if (nails)
|
||||
{
|
||||
double ang;
|
||||
for (int i = 0; i < nails; i++)
|
||||
{
|
||||
ang = i*360./nails;
|
||||
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
|
||||
LineAttack(ang, MISSILERANGE, 0.,
|
||||
//P_AimLineAttack (self, ang, MISSILERANGE),
|
||||
naildamage, 'Hitscan', pufftype, bMissile ? LAF_TARGETISSOURCE : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & XF_EXPLICITDAMAGETYPE) && damagetype == 'None')
|
||||
{
|
||||
damagetype = self.DamageType;
|
||||
}
|
||||
|
||||
int pflags = 0;
|
||||
if (flags & XF_HURTSOURCE) pflags |= RADF_HURTSOURCE;
|
||||
if (flags & XF_NOTMISSILE) pflags |= RADF_SOURCEISSPOT;
|
||||
|
||||
int count = RadiusAttack (target, damage, distance, damagetype, pflags, fulldmgdistance);
|
||||
if (!(flags & XF_NOSPLASH)) CheckSplash(distance);
|
||||
if (alert && target != NULL && target.player != NULL)
|
||||
{
|
||||
SoundAlert(target);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_RadiusThrust
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0)
|
||||
{
|
||||
if (force == 0) force = 128;
|
||||
if (distance <= 0) distance = abs(force);
|
||||
|
||||
bool nothrust = target.bNoDamageThrust;
|
||||
// Temporarily negate MF2_NODMGTHRUST on the shooter, since it renders this function useless.
|
||||
if (!(flags & RTF_NOTMISSILE) && target != NULL)
|
||||
{
|
||||
target.bNoDamageThrust = false;
|
||||
}
|
||||
|
||||
RadiusAttack (target, force, distance, DamageType, flags | RADF_NODAMAGE, fullthrustdistance);
|
||||
CheckSplash(distance);
|
||||
target.bNoDamageThrust = nothrust;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_Detonate
|
||||
// killough 8/9/98: same as A_Explode, except that the damage is variable
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void A_Detonate()
|
||||
{
|
||||
int damage = GetMissileDamage(0, 1);
|
||||
RadiusAttack (target, damage, damage, DamageType, RADF_HURTSOURCE);
|
||||
CheckSplash(damage);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// old customizable attack functions which use actor parameters.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
private void DoAttack (bool domelee, bool domissile, int MeleeDamage, Sound MeleeSound, Class<Actor> MissileType,double MissileHeight)
|
||||
{
|
||||
let targ = target;
|
||||
if (targ == NULL) return;
|
||||
|
||||
A_FaceTarget ();
|
||||
if (domelee && MeleeDamage>0 && CheckMeleeRange ())
|
||||
{
|
||||
int damage = random[CustomMelee](1, 8) * MeleeDamage;
|
||||
if (MeleeSound) A_PlaySound (MeleeSound, CHAN_WEAPON);
|
||||
int newdam = targ.DamageMobj (self, self, damage, 'Melee');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : damage, self);
|
||||
}
|
||||
else if (domissile && MissileType != NULL)
|
||||
{
|
||||
// This seemingly senseless code is needed for proper aiming.
|
||||
double add = MissileHeight + GetBobOffset() - 32;
|
||||
AddZ(add);
|
||||
Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), targ, MissileType, false);
|
||||
AddZ(-add);
|
||||
|
||||
if (missile)
|
||||
{
|
||||
// automatic handling of seeker missiles
|
||||
if (missile.bSeekerMissile)
|
||||
{
|
||||
missile.tracer = targ;
|
||||
}
|
||||
missile.CheckMissileSpawn(radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_MeleeAttack()
|
||||
{
|
||||
DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0);
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_MissileAttack()
|
||||
{
|
||||
Class<Actor> MissileType = MissileName;
|
||||
DoAttack(false, true, 0, 0, MissileType, MissileHeight);
|
||||
}
|
||||
|
||||
deprecated("2.3") void A_ComboAttack()
|
||||
{
|
||||
Class<Actor> MissileType = MissileName;
|
||||
DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
|
||||
}
|
||||
|
||||
void A_BasicAttack(int melee_damage, sound melee_sound, class<actor> missile_type, double missile_height)
|
||||
{
|
||||
DoAttack(true, true, melee_damage, melee_sound, missile_type, missile_height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1247,3 +1247,13 @@ enum SPAC
|
|||
|
||||
SPAC_PlayerActivate = (SPAC_Cross|SPAC_Use|SPAC_Impact|SPAC_Push|SPAC_AnyCross|SPAC_UseThrough|SPAC_UseBack),
|
||||
};
|
||||
|
||||
enum RadiusDamageFlags
|
||||
{
|
||||
RADF_HURTSOURCE = 1,
|
||||
RADF_NOIMPACTDAMAGE = 2,
|
||||
RADF_SOURCEISSPOT = 4,
|
||||
RADF_NODAMAGE = 8,
|
||||
RADF_THRUSTZ = 16,
|
||||
RADF_OLDRADIUSDAMAGE = 32
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue