From 652606f70b89c62cb419fe1f151564a1e0e5df54 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 Nov 2018 19:29:52 +0100 Subject: [PATCH] - scriptified A_Explode and relatives. --- src/p_actionfunctions.cpp | 113 --------------- src/p_enemy.cpp | 14 -- src/p_local.h | 2 +- src/p_map.cpp | 14 +- src/p_mobj.cpp | 23 ---- wadsrc/static/zscript/actor.txt | 68 +-------- wadsrc/static/zscript/actor_attacks.txt | 175 +++++++++++++++++++++++- wadsrc/static/zscript/constants.txt | 10 ++ 8 files changed, 200 insertions(+), 219 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 50ff36e23..ff375974c 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -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 diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 4e7499e1b..72e9b6e09 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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; diff --git a/src/p_local.h b/src/p_local.h index 66a1b304e..26d6f8b64 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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); diff --git a/src/p_map.cpp b/src/p_map.cpp index 33916fdb2..fc29afb06 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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 diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9d3b7d931..6ee0e6126 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 1021977e9..49762d994 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -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 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 MissileType = MissileName; - DoAttack(false, true, 0, 0, MissileType, MissileHeight); - } - - deprecated("2.3") void A_ComboAttack() - { - Class MissileType = MissileName; - DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); - } - - void A_BasicAttack(int melee_damage, sound melee_sound, class 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 missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_Burst(class 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 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 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(); diff --git a/wadsrc/static/zscript/actor_attacks.txt b/wadsrc/static/zscript/actor_attacks.txt index 44c32d1f9..22a2a4386 100644 --- a/wadsrc/static/zscript/actor_attacks.txt +++ b/wadsrc/static/zscript/actor_attacks.txt @@ -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 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 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 MissileType = MissileName; + DoAttack(false, true, 0, 0, MissileType, MissileHeight); + } + + deprecated("2.3") void A_ComboAttack() + { + Class MissileType = MissileName; + DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); + } + + void A_BasicAttack(int melee_damage, sound melee_sound, class missile_type, double missile_height) + { + DoAttack(true, true, melee_damage, melee_sound, missile_type, missile_height); + } - } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index ccb3f4848..fe2c8a901 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -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 +};