diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 8492789db..bcedd1429 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -34,53 +34,6 @@ void A_Countdown (AActor *); // Flame Thrower ------------------------------------------------------------ -//============================================================================ -// -// A_FlameDie -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FlameDie) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->flags |= MF_NOGRAVITY; - self->Vel.Z = pr_flamedie() & 3; - return 0; -} - -//============================================================================ -// -// A_FireFlamer -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer) -{ - PARAM_ACTION_PROLOGUE(AActor); - - player_t *player = self->player; - - if (player != NULL) - { - AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL) - { - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - } - player->mo->PlayAttacking2 (); - } - - self->Angles.Yaw += pr_flamethrower.Random2() * (5.625/256.); - self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile")); - if (self != NULL) - { - self->Vel.Z += 5; - } - return 0; -} - // Mauler ------------------------------------------------------------------- //============================================================================ @@ -210,135 +163,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaulerTorpedoWave) return 0; } -class APhosphorousFire : public AActor -{ - DECLARE_CLASS (APhosphorousFire, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(APhosphorousFire, false, false) - -int APhosphorousFire::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if (target->flags & MF_NOBLOOD) - { - return damage / 2; - } - return Super::DoSpecialDamage (target, damage, damagetype); -} - -DEFINE_ACTION_FUNCTION(AActor, A_BurnArea) -{ - PARAM_SELF_PROLOGUE(AActor); - - P_RadiusAttack (self, self->target, 128, 128, self->DamageType, RADF_HURTSOURCE); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_Burnination) -{ - PARAM_SELF_PROLOGUE(AActor); - - self->Vel.Z -= 8; - self->Vel.X += (pr_phburn.Random2 (3)); - self->Vel.Y += (pr_phburn.Random2 (3)); - S_Sound (self, CHAN_VOICE, "world/largefire", 1, ATTN_NORM); - - // Only the main fire spawns more. - if (!(self->flags & MF_DROPPED)) - { - // Original x and y offsets seemed to be like this: - // x + (((pr_phburn() + 12) & 31) << F.RACBITS); - // - // But that creates a lop-sided burn because it won't use negative offsets. - int xofs, xrand = pr_phburn(); - int yofs, yrand = pr_phburn(); - - // Adding 12 is pointless if you're going to mask it afterward. - xofs = xrand & 31; - if (xrand & 128) - { - xofs = -xofs; - } - - yofs = yrand & 31; - if (yrand & 128) - { - yofs = -yofs; - } - - DVector2 pos = self->Vec2Offset((double)xofs, (double)yofs); - sector_t * sector = P_PointInSector(pos); - - // The sector's floor is too high so spawn the flame elsewhere. - if (sector->floorplane.ZatPoint(pos) > self->Z() + self->MaxStepHeight) - { - pos = self->Pos(); - } - - AActor *drop = Spawn (DVector3(pos, self->Z() + 4.), ALLOW_REPLACE); - if (drop != NULL) - { - drop->Vel.X = self->Vel.X + pr_phburn.Random2 (7); - drop->Vel.Y = self->Vel.Y + pr_phburn.Random2 (7); - drop->Vel.Z = self->Vel.Z - 1; - drop->reactiontime = (pr_phburn() & 3) + 2; - drop->flags |= MF_DROPPED; - } - } - return 0; -} - -//============================================================================ -// -// A_FireGrenade -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_FireGrenade) -{ - PARAM_ACTION_PROLOGUE(AActor); - PARAM_CLASS(grenadetype, AActor); - PARAM_ANGLE(angleofs); - PARAM_STATE(flash) - - player_t *player = self->player; - AActor *grenade; - DAngle an; - AWeapon *weapon; - - if (player == nullptr || grenadetype == nullptr) - return 0; - - if ((weapon = player->ReadyWeapon) == nullptr) - return 0; - - if (!weapon->DepleteAmmo (weapon->bAltFire)) - return 0; - - P_SetPsprite (player, PSP_FLASH, flash, true); - - if (grenadetype != nullptr) - { - self->AddZ(32); - grenade = P_SpawnSubMissile (self, grenadetype, self); - self->AddZ(-32); - if (grenade == nullptr) - return 0; - - if (grenade->SeeSound != 0) - { - S_Sound (grenade, CHAN_VOICE, grenade->SeeSound, 1, ATTN_NORM); - } - - grenade->Vel.Z = (-self->Angles.Pitch.TanClamped()) * grenade->Speed + 8; - - DVector2 offset = self->Angles.Yaw.ToVector(self->radius + grenade->radius); - DAngle an = self->Angles.Yaw + angleofs; - offset += an.ToVector(15); - grenade->SetOrigin(grenade->Vec3Offset(offset.X, offset.Y, 0.), false); - } - return 0; -} - diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 39c8f8e0d..26e341aab 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1356,7 +1356,6 @@ subsector_t *P_PointInSubsector (double x, double y) return (subsector_t *)((BYTE *)node - 1); } - //========================================================================== // // PointOnLine diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 2d2472cbd..16fc790c0 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1971,4 +1971,3 @@ sector_t *P_PointInSectorBuggy(double x, double y) subsector_t *ssec = (subsector_t *)((BYTE *)node - 1); return ssec->sector; } - diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 04a9e9433..5e2a9f039 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7560,6 +7560,15 @@ DEFINE_ACTION_FUNCTION(AActor, Vec2OffsetZ) ACTION_RETURN_VEC3(self->Vec2OffsetZ(x, y, z, absolute)); } +DEFINE_ACTION_FUNCTION(AActor, Vec2Offset) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_BOOL_DEF(absolute); + ACTION_RETURN_VEC2(self->Vec2Offset(x, y, absolute)); +} + DEFINE_ACTION_FUNCTION(AActor, Vec3Offset) { PARAM_SELF_PROLOGUE(AActor); diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index e6302199b..2b8097e55 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1050,6 +1050,35 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub } } +DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_INT_DEF(flags); + PARAM_FLOAT_DEF(steph); + sector_t *resultsec; + F3DFloor *resultff; + double resultheight = self->NextLowestFloorAt(x, y, z, flags, steph, &resultsec, &resultff); + + if (numret > 2) + { + ret[2].SetPointer(resultff, ATAG_GENERIC); + numret = 3; + } + if (numret > 1) + { + ret[1].SetPointer(resultsec, ATAG_GENERIC); + } + if (numret > 0) + { + ret[0].SetFloat(resultheight); + } + return numret; +} + + //=========================================================================== // // @@ -1103,6 +1132,16 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub self->RemoveForceField(); return 0; } + + + DEFINE_ACTION_FUNCTION(_Sector, PointInSector) + { + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + ACTION_RETURN_POINTER(P_PointInSector(x, y)); + } + //=========================================================================== // // diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index eb6e30dcb..cbba151f5 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -193,6 +193,8 @@ zscript/strife/weapondagger.txt zscript/strife/weaponcrossbow.txt zscript/strife/weaponassault.txt zscript/strife/weaponmissile.txt +zscript/strife/weaponflamer.txt +zscript/strife/weapongrenade.txt zscript/strife/sigil.txt zscript/chex/chexmonsters.txt diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5279372fd..37306db39 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -361,6 +361,7 @@ class Actor : Thinker native native vector3 Vec3Offset(double x, double y, double z, bool absolute = false); native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false); native vector2 Vec2Angle(double length, double angle, bool absolute = false); + native vector2 Vec2Offset(double x, double y, bool absolute = false); native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false); native void VelFromAngle(double speed = 0, double angle = 0); native void Thrust(double speed = 0, double angle = 0); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index b0abc73ec..08125952d 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -247,7 +247,10 @@ struct Sector native native double, Sector, F3DFloor NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0); + native double, Sector, F3DFloor NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0); + native void RemoveForceField(); + native static Sector PointInSector(Vector2 pt); } struct Wads diff --git a/wadsrc/static/zscript/strife/strifeweapons.txt b/wadsrc/static/zscript/strife/strifeweapons.txt index ae0bc1284..9e2f2c84f 100644 --- a/wadsrc/static/zscript/strife/strifeweapons.txt +++ b/wadsrc/static/zscript/strife/strifeweapons.txt @@ -50,88 +50,6 @@ class StrifeSpark : StrifePuff } } -// Flame Thrower ------------------------------------------------------------ - -class FlameThrower : StrifeWeapon -{ - Default - { - +FLOORCLIP - Weapon.SelectionOrder 2100; - Weapon.Kickback 0; - Weapon.AmmoUse1 1; - Weapon.AmmoGive1 100; - Weapon.UpSound "weapons/flameidle"; - Weapon.ReadySound "weapons/flameidle"; - Weapon.AmmoType1 "EnergyPod"; - Inventory.Icon "FLAMA0"; - Tag "$TAG_FLAMER"; - Inventory.PickupMessage "$TXT_FLAMER"; - } - - action native void A_FireFlamer (); - - States - { - Spawn: - FLAM A -1; - Stop; - Ready: - FLMT AB 3 A_WeaponReady; - Loop; - Deselect: - FLMT A 1 A_Lower; - Loop; - Select: - FLMT A 1 A_Raise; - Loop; - Fire: - FLMF A 2 A_FireFlamer; - FLMF B 3 A_ReFire; - Goto Ready; - } -} - - -// Flame Thrower Projectile ------------------------------------------------- - -class FlameMissile : Actor -{ - Default - { - Speed 15; - Height 11; - Radius 8; - Mass 10; - Damage 4; - DamageType "Fire"; - ReactionTime 8; - Projectile; - -NOGRAVITY - +STRIFEDAMAGE - MaxStepHeight 4; - RenderStyle "Add"; - SeeSound "weapons/flamethrower"; - Obituary "$OB_MPFLAMETHROWER"; - } - - native void A_FlameDie (); - - States - { - Spawn: - FRBL AB 3 Bright; - FRBL C 3 Bright A_Countdown; - Loop; - Death: - FRBL D 5 Bright A_FlameDie; - FRBL EFGHI 5 Bright; - Stop; - } - -} - - // Mauler ------------------------------------------------------------------- // The scatter version @@ -306,209 +224,3 @@ class MaulerTorpedoWave : Actor } -// High-Explosive Grenade --------------------------------------------------- - -class HEGrenade : Actor -{ - Default - { - Speed 15; - Radius 13; - Height 13; - Mass 20; - Damage 1; - Reactiontime 30; - Projectile; - -NOGRAVITY - +STRIFEDAMAGE - +BOUNCEONACTORS - +EXPLODEONWATER - MaxStepHeight 4; - BounceType "Doom"; - BounceFactor 0.5; - BounceCount 2; - SeeSound "weapons/hegrenadeshoot"; - DeathSound "weapons/hegrenadebang"; - Obituary "$OB_MPSTRIFEGRENADE"; - } - States - { - Spawn: - GRAP AB 3 A_Countdown; - Loop; - Death: - BNG4 A 0 Bright A_NoGravity; - BNG4 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); - BNG4 A 2 Bright A_Explode(192, 192, alert:true); - BNG4 BCDEFGHIJKLMN 3 Bright; - Stop; - } -} - -// White Phosphorous Grenade ------------------------------------------------ - -class PhosphorousGrenade : Actor -{ - Default - { - Speed 15; - Radius 13; - Height 13; - Mass 20; - Damage 1; - Reactiontime 40; - Projectile; - -NOGRAVITY - +STRIFEDAMAGE - +BOUNCEONACTORS - +EXPLODEONWATER - BounceType "Doom"; - MaxStepHeight 4; - BounceFactor 0.5; - BounceCount 2; - SeeSound "weapons/phgrenadeshoot"; - DeathSound "weapons/phgrenadebang"; - Obituary "$OB_MPPHOSPHOROUSGRENADE"; - } - States - { - Spawn: - GRIN AB 3 A_Countdown; - Loop; - Death: - BNG3 A 2 A_SpawnItemEx("PhosphorousFire"); - Stop; - } -} - -// Fire from the Phoshorous Grenade ----------------------------------------- - -class PhosphorousFire : Actor native -{ - Default - { - Reactiontime 120; - DamageType "Fire"; - +NOBLOCKMAP - +FLOORCLIP - +NOTELEPORT - +NODAMAGETHRUST - +DONTSPLASH - RenderStyle "Add"; - Obituary "$OB_MPPHOSPHOROUSGRENADE"; - } - - native void A_Burnarea (); - native void A_Burnination (); - - States - { - Spawn: - BNG3 B 2 Bright A_Burnarea; - BNG3 C 2 Bright A_Countdown; - FLBE A 2 Bright A_Burnination; - FLBE B 2 Bright A_Countdown; - FLBE C 2 Bright A_Burnarea; - FLBE D 3 Bright A_Countdown; - FLBE E 3 Bright A_Burnarea; - FLBE F 3 Bright A_Countdown; - FLBE G 3 Bright A_Burnination; - Goto Spawn+5; - Death: - FLBE H 2 Bright; - FLBE I 2 Bright A_Burnination; - FLBE JK 2 Bright; - Stop; - } -} - -// High-Explosive Grenade Launcher ------------------------------------------ - -class StrifeGrenadeLauncher : StrifeWeapon -{ - Default - { - +FLOORCLIP - Weapon.SelectionOrder 2400; - Weapon.AmmoUse1 1; - Weapon.AmmoGive1 12; - Weapon.AmmoType1 "HEGrenadeRounds"; - Weapon.SisterWeapon "StrifeGrenadeLauncher2"; - Inventory.Icon "GRNDA0"; - Tag "$TAG_GLAUNCHER1"; - Inventory.PickupMessage "$TXT_GLAUNCHER"; - } - - action native void A_FireGrenade (class grenadetype, double angleofs, statelabel flash); - - States - { - Spawn: - GRND A -1; - Stop; - Ready: - GREN A 1 A_WeaponReady; - Loop; - Deselect: - GREN A 1 A_Lower; - Loop; - Select: - GREN A 1 A_Raise; - Loop; - Fire: - GREN A 5 A_FireGrenade("HEGrenade", -90, "Flash"); - GREN B 10; - GREN A 5 A_FireGrenade("HEGrenade", 90, "Flash2"); - GREN C 10; - GREN A 0 A_ReFire; - Goto Ready; - Flash: - GREF A 5 Bright A_Light1; - Goto LightDone; - Flash2: - GREF B 5 Bright A_Light2; - Goto LightDone; - } - -} - -// White Phosphorous Grenade Launcher --------------------------------------- - -class StrifeGrenadeLauncher2 : StrifeGrenadeLauncher -{ - Default - { - Weapon.SelectionOrder 3200; - Weapon.AmmoUse1 1; - Weapon.AmmoGive1 0; - Weapon.AmmoType1 "PhosphorusGrenadeRounds"; - Weapon.SisterWeapon "StrifeGrenadeLauncher"; - Tag "$TAG_GLAUNCHER2"; - } - States - { - Ready: - GREN D 1 A_WeaponReady; - Loop; - Deselect: - GREN D 1 A_Lower; - Loop; - Select: - GREN D 1 A_Raise; - Loop; - Fire: - GREN D 5 A_FireGrenade("PhosphorousGrenade", -90, "Flash"); - GREN E 10; - GREN D 5 A_FireGrenade("PhosphorousGrenade", 90, "Flash2"); - GREN F 10; - GREN A 0 A_ReFire; - Goto Ready; - Flash: - GREF C 5 Bright A_Light1; - Goto LightDone; - Flash2: - GREF D 5 Bright A_Light2; - Goto LightDone; - } -} - diff --git a/wadsrc/static/zscript/strife/weaponflamer.txt b/wadsrc/static/zscript/strife/weaponflamer.txt new file mode 100644 index 000000000..9a47bc242 --- /dev/null +++ b/wadsrc/static/zscript/strife/weaponflamer.txt @@ -0,0 +1,118 @@ +// Flame Thrower ------------------------------------------------------------ + +class FlameThrower : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 2100; + Weapon.Kickback 0; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 100; + Weapon.UpSound "weapons/flameidle"; + Weapon.ReadySound "weapons/flameidle"; + Weapon.AmmoType1 "EnergyPod"; + Inventory.Icon "FLAMA0"; + Tag "$TAG_FLAMER"; + Inventory.PickupMessage "$TXT_FLAMER"; + } + + States + { + Spawn: + FLAM A -1; + Stop; + Ready: + FLMT AB 3 A_WeaponReady; + Loop; + Deselect: + FLMT A 1 A_Lower; + Loop; + Select: + FLMT A 1 A_Raise; + Loop; + Fire: + FLMF A 2 A_FireFlamer; + FLMF B 3 A_ReFire; + Goto Ready; + } + + //============================================================================ + // + // A_FireFlamer + // + //============================================================================ + + action void A_FireFlamer () + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + } + + player.mo.PlayAttacking2 (); + + Angle += Random2[Flamethrower]() * (5.625/256.); + Actor mo = SpawnPlayerMissile ("FlameMissile"); + if (mo != NULL) + { + mo.Vel.Z += 5; + } + } +} + + +// Flame Thrower Projectile ------------------------------------------------- + +class FlameMissile : Actor +{ + Default + { + Speed 15; + Height 11; + Radius 8; + Mass 10; + Damage 4; + DamageType "Fire"; + ReactionTime 8; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + MaxStepHeight 4; + RenderStyle "Add"; + SeeSound "weapons/flamethrower"; + Obituary "$OB_MPFLAMETHROWER"; + } + + States + { + Spawn: + FRBL AB 3 Bright; + FRBL C 3 Bright A_Countdown; + Loop; + Death: + FRBL D 5 Bright A_FlameDie; + FRBL EFGHI 5 Bright; + Stop; + } + + //============================================================================ + // + // A_FlameDie + // + //============================================================================ + + void A_FlameDie () + { + bNoGravity = true; + Vel.Z = random[FlameDie]() & 3; + } +} + diff --git a/wadsrc/static/zscript/strife/weapongrenade.txt b/wadsrc/static/zscript/strife/weapongrenade.txt new file mode 100644 index 000000000..7a775c57b --- /dev/null +++ b/wadsrc/static/zscript/strife/weapongrenade.txt @@ -0,0 +1,315 @@ +// High-Explosive Grenade Launcher ------------------------------------------ + +class StrifeGrenadeLauncher : StrifeWeapon +{ + Default + { + +FLOORCLIP + Weapon.SelectionOrder 2400; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 12; + Weapon.AmmoType1 "HEGrenadeRounds"; + Weapon.SisterWeapon "StrifeGrenadeLauncher2"; + Inventory.Icon "GRNDA0"; + Tag "$TAG_GLAUNCHER1"; + Inventory.PickupMessage "$TXT_GLAUNCHER"; + } + + States + { + Spawn: + GRND A -1; + Stop; + Ready: + GREN A 1 A_WeaponReady; + Loop; + Deselect: + GREN A 1 A_Lower; + Loop; + Select: + GREN A 1 A_Raise; + Loop; + Fire: + GREN A 5 A_FireGrenade("HEGrenade", -90, "Flash"); + GREN B 10; + GREN A 5 A_FireGrenade("HEGrenade", 90, "Flash2"); + GREN C 10; + GREN A 0 A_ReFire; + Goto Ready; + Flash: + GREF A 5 Bright A_Light1; + Goto LightDone; + Flash2: + GREF B 5 Bright A_Light2; + Goto LightDone; + } + + //============================================================================ + // + // A_FireGrenade + // + //============================================================================ + + action void A_FireGrenade (class grenadetype, double angleofs, statelabel flash) + { + if (player == null) + { + return; + } + + Weapon weapon = player.ReadyWeapon; + if (weapon != null) + { + if (!weapon.DepleteAmmo (weapon.bAltFire)) + return; + + player.SetPsprite (PSP_FLASH, weapon.FindState(flash), true); + } + + if (grenadetype != null) + { + AddZ(32); + Actor grenade = SpawnSubMissile (grenadetype, self); + AddZ(-32); + if (grenade == null) + return; + + if (grenade.SeeSound != 0) + { + grenade.A_PlaySound (grenade.SeeSound, CHAN_VOICE); + } + + grenade.Vel.Z = (-clamp(tan(Pitch), -5, 5)) * grenade.Speed + 8; + + Vector2 offset = AngleToVector(angle, radius + grenade.radius); + double an = Angle + angleofs; + offset += AngleToVector(an, 15); + grenade.SetOrigin(grenade.Vec3Offset(offset.X, offset.Y, 0.), false); + } + } +} + +// White Phosphorous Grenade Launcher --------------------------------------- + +class StrifeGrenadeLauncher2 : StrifeGrenadeLauncher +{ + Default + { + Weapon.SelectionOrder 3200; + Weapon.AmmoUse1 1; + Weapon.AmmoGive1 0; + Weapon.AmmoType1 "PhosphorusGrenadeRounds"; + Weapon.SisterWeapon "StrifeGrenadeLauncher"; + Tag "$TAG_GLAUNCHER2"; + } + States + { + Ready: + GREN D 1 A_WeaponReady; + Loop; + Deselect: + GREN D 1 A_Lower; + Loop; + Select: + GREN D 1 A_Raise; + Loop; + Fire: + GREN D 5 A_FireGrenade("PhosphorousGrenade", -90, "Flash"); + GREN E 10; + GREN D 5 A_FireGrenade("PhosphorousGrenade", 90, "Flash2"); + GREN F 10; + GREN A 0 A_ReFire; + Goto Ready; + Flash: + GREF C 5 Bright A_Light1; + Goto LightDone; + Flash2: + GREF D 5 Bright A_Light2; + Goto LightDone; + } +} + +// High-Explosive Grenade --------------------------------------------------- + +class HEGrenade : Actor +{ + Default + { + Speed 15; + Radius 13; + Height 13; + Mass 20; + Damage 1; + Reactiontime 30; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + +BOUNCEONACTORS + +EXPLODEONWATER + MaxStepHeight 4; + BounceType "Doom"; + BounceFactor 0.5; + BounceCount 2; + SeeSound "weapons/hegrenadeshoot"; + DeathSound "weapons/hegrenadebang"; + Obituary "$OB_MPSTRIFEGRENADE"; + } + States + { + Spawn: + GRAP AB 3 A_Countdown; + Loop; + Death: + BNG4 A 0 Bright A_NoGravity; + BNG4 A 0 Bright A_SetRenderStyle(1, STYLE_Normal); + BNG4 A 2 Bright A_Explode(192, 192, alert:true); + BNG4 BCDEFGHIJKLMN 3 Bright; + Stop; + } +} + +// White Phosphorous Grenade ------------------------------------------------ + +class PhosphorousGrenade : Actor +{ + Default + { + Speed 15; + Radius 13; + Height 13; + Mass 20; + Damage 1; + Reactiontime 40; + Projectile; + -NOGRAVITY + +STRIFEDAMAGE + +BOUNCEONACTORS + +EXPLODEONWATER + BounceType "Doom"; + MaxStepHeight 4; + BounceFactor 0.5; + BounceCount 2; + SeeSound "weapons/phgrenadeshoot"; + DeathSound "weapons/phgrenadebang"; + Obituary "$OB_MPPHOSPHOROUSGRENADE"; + } + States + { + Spawn: + GRIN AB 3 A_Countdown; + Loop; + Death: + BNG3 A 2 A_SpawnItemEx("PhosphorousFire"); + Stop; + } +} + +// Fire from the Phoshorous Grenade ----------------------------------------- + +class PhosphorousFire : Actor +{ + Default + { + Reactiontime 120; + DamageType "Fire"; + +NOBLOCKMAP + +FLOORCLIP + +NOTELEPORT + +NODAMAGETHRUST + +DONTSPLASH + RenderStyle "Add"; + Obituary "$OB_MPPHOSPHOROUSGRENADE"; + } + + States + { + Spawn: + BNG3 B 2 Bright A_Burnarea; + BNG3 C 2 Bright A_Countdown; + FLBE A 2 Bright A_Burnination; + FLBE B 2 Bright A_Countdown; + FLBE C 2 Bright A_Burnarea; + FLBE D 3 Bright A_Countdown; + FLBE E 3 Bright A_Burnarea; + FLBE F 3 Bright A_Countdown; + FLBE G 3 Bright A_Burnination; + Goto Spawn+5; + Death: + FLBE H 2 Bright; + FLBE I 2 Bright A_Burnination; + FLBE JK 2 Bright; + Stop; + } + + int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if (target.bNoBlood) + { + return damage / 2; + } + return Super.DoSpecialDamage (target, damage, damagetype); + } + + // This function is mostly redundant and only kept in case some mod references it. + void A_Burnarea () + { + A_Explode(128, 128); + } + + void A_Burnination () + { + Vel.Z -= 8; + Vel.X += (random2[PHBurn] (3)); + Vel.Y += (random2[PHBurn] (3)); + A_PlaySound ("world/largefire", CHAN_VOICE); + + // Only the main fire spawns more. + if (!bDropped) + { + // Original x and y offsets seemed to be like this: + // x + (((pr_phburn() + 12) & 31) << F.RACBITS); + // + // But that creates a lop-sided burn because it won't use negative offsets. + int xofs, xrand = random[PHBurn](); + int yofs, yrand = random[PHBurn](); + + // Adding 12 is pointless if you're going to mask it afterward. + xofs = xrand & 31; + if (xrand & 128) + { + xofs = -xofs; + } + + yofs = yrand & 31; + if (yrand & 128) + { + yofs = -yofs; + } + + Vector2 newpos = Vec2Offset(xofs, yofs); + + Sector sec = Sector.PointInSector(newpos); + // Consider portals and 3D floors instead of just using the current sector's z. + double floorh = sec.NextLowestFloorAt(newpos.x, newpos.y, pos.z+4, 0, MaxStepHeight); + + // The sector's floor is too high so spawn the flame elsewhere. + if (floorh + MaxStepHeight) + { + newpos = Pos.xy; + } + + Actor drop = Spawn("PhosphorousFire", (newpos, pos.z + 4.), ALLOW_REPLACE); + if (drop != NULL) + { + drop.Vel.X = Vel.X + random2[PHBurn] (7); + drop.Vel.Y = Vel.Y + random2[PHBurn] (7); + drop.Vel.Z = Vel.Z - 1; + drop.reactiontime = (random[PHBurn]() & 3) + 2; + drop.bDropped = true; + } + } + } + + +} +