diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 35276fd66..c7cd2a199 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1626,122 +1626,6 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_JumpIfNoAmmo) -//========================================================================== -// -// A_CustomPunch -// -// Berserk is not handled here. That can be done with A_CheckIfInventory -// -//========================================================================== - -enum -{ - CPF_USEAMMO = 1, - CPF_DAGGER = 2, - CPF_PULLIN = 4, - CPF_NORANDOMPUFFZ = 8, - CPF_NOTURN = 16, - CPF_STEALARMOR = 32, -}; - -DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch) -{ - PARAM_ACTION_PROLOGUE(AStateProvider); - PARAM_INT (damage); - PARAM_BOOL (norandom); - PARAM_INT (flags); - PARAM_CLASS (pufftype, AActor); - PARAM_FLOAT (range); - PARAM_FLOAT (lifesteal); - PARAM_INT (lifestealmax); - PARAM_CLASS (armorbonustype, AActor); - PARAM_SOUND (MeleeSound); - PARAM_SOUND (MissSound); - - if (!self->player) - return 0; - - player_t *player = self->player; - AWeapon *weapon = player->ReadyWeapon; - - - DAngle angle; - DAngle pitch; - FTranslatedLineTarget t; - int actualdamage; - - if (!norandom) - damage *= pr_cwpunch() % 8 + 1; - - angle = self->Angles.Yaw + pr_cwpunch.Random2() * (5.625 / 256); - if (range == 0) range = DEFMELEERANGE; - pitch = P_AimLineAttack (self, angle, range, &t, 0., ALF_CHECK3D); - - // only use ammo when actually hitting something! - if ((flags & CPF_USEAMMO) && t.linetarget && weapon && ACTION_CALL_FROM_PSPRITE()) - { - if (!weapon->DepleteAmmo(weapon->bAltFire, true)) - return 0; // out of ammo - } - - if (pufftype == NULL) - pufftype = PClass::FindActor(NAME_BulletPuff); - int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0); - - P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, puffFlags, &t, &actualdamage); - - if (!t.linetarget) - { - if (MissSound) S_Sound(self, CHAN_WEAPON, MissSound, 1, ATTN_NORM); - } - else - { - if (lifesteal > 0 && !(t.linetarget->flags5 & MF5_DONTDRAIN)) - { - if (flags & CPF_STEALARMOR) - { - if (armorbonustype == NULL) - { - armorbonustype = PClass::FindActor("ArmorBonus"); - } - if (armorbonustype != NULL) - { - auto armorbonus = Spawn(armorbonustype); - armorbonus->IntVar(NAME_SaveAmount) *= int(actualdamage * lifesteal); - if (lifestealmax > 0) armorbonus->IntVar("MaxSaveAmount") = lifestealmax; - armorbonus->flags |= MF_DROPPED; - armorbonus->ClearCounters(); - - if (!static_cast(armorbonus)->CallTryPickup(self)) - { - armorbonus->Destroy (); - } - } - } - else - { - P_GiveBody (self, int(actualdamage * lifesteal), lifestealmax); - } - } - if (weapon != NULL) - { - if (MeleeSound) S_Sound(self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM); - else S_Sound (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM); - } - - if (!(flags & CPF_NOTURN)) - { - // turn to face target - self->Angles.Yaw = t.angleFromSource; - } - - if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED; - if (flags & CPF_DAGGER) P_DaggerAlert (self, t.linetarget); - } - return 0; -} - - //========================================================================== // // customizable railgun attack function diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 12f43e9fc..4e7499e1b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -268,71 +268,6 @@ DEFINE_ACTION_FUNCTION(AActor, SoundAlert) return 0; } -//============================================================================ -// -// P_DaggerAlert -// -//============================================================================ - -void P_DaggerAlert(AActor *target, AActor *emitter) -{ - AActor *looker; - sector_t *sec = emitter->Sector; - - if (emitter->LastHeard != NULL) - return; - if (emitter->health <= 0) - return; - if (!(emitter->flags3 & MF3_ISMONSTER)) - return; - if (emitter->flags4 & MF4_INCOMBAT) - return; - emitter->flags4 |= MF4_INCOMBAT; - - emitter->target = target; - FState *painstate = emitter->FindState(NAME_Pain, NAME_Dagger); - if (painstate != NULL) - { - emitter->SetState(painstate); - } - - for (looker = sec->thinglist; looker != NULL; looker = looker->snext) - { - if (looker == emitter || looker == target) - continue; - - if (looker->health <= 0) - continue; - - if (!(looker->flags4 & MF4_SEESDAGGERS)) - continue; - - if (!(looker->flags4 & MF4_INCOMBAT)) - { - if (!P_CheckSight(looker, target) && !P_CheckSight(looker, emitter)) - continue; - - looker->target = target; - if (looker->SeeSound) - { - S_Sound(looker, CHAN_VOICE, looker->SeeSound, 1, ATTN_NORM); - } - looker->SetState(looker->SeeState); - looker->flags4 |= MF4_INCOMBAT; - } - } -} - -DEFINE_ACTION_FUNCTION(AActor, DaggerAlert) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_OBJECT(target, AActor); - // Note that the emitter is self, not the target of the alert! Target can be NULL. - P_DaggerAlert(target, self); - return 0; -} - - //---------------------------------------------------------------------------- // // AActor :: CheckMeleeRange diff --git a/src/p_enemy.h b/src/p_enemy.h index bdc044c5c..0e917e0af 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -46,7 +46,6 @@ struct FLookExParams FState *seestate; }; -void P_DaggerAlert (AActor *target, AActor *emitter); bool P_HitFriend (AActor *self); void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash=false, double maxdist=0); diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2e9f4be15..89ee2ed50 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -584,7 +584,6 @@ class Actor : Thinker native native clearscope int PlayerNumber() const; native void SetFriendPlayer(PlayerInfo player); native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); - native void DaggerAlert(Actor target); native void ClearBounce(); native TerrainDef GetFloorTerrain(); native bool CheckLocalView(int consoleplayer); diff --git a/wadsrc/static/zscript/actor_attacks.txt b/wadsrc/static/zscript/actor_attacks.txt index 3c6c16d0c..3e4c08f80 100644 --- a/wadsrc/static/zscript/actor_attacks.txt +++ b/wadsrc/static/zscript/actor_attacks.txt @@ -116,5 +116,59 @@ extend class Actor } } + //============================================================================ + // + // P_DaggerAlert + // + //============================================================================ + + void DaggerAlert(Actor target) + { + Actor looker; + + if (LastHeard != NULL) + return; + if (health <= 0) + return; + if (!bIsMonster) + return; + if (bInCombat) + return; + bInCombat = true; + + self.target = target; + let painstate = FindState('Pain', 'Dagger'); + if (painstate != NULL) + { + SetState(painstate); + } + + for (looker = cursector.thinglist; looker != NULL; looker = looker.snext) + { + if (looker == self || looker == target) + continue; + + if (looker.health <= 0) + continue; + + if (!looker.bSeesDaggers) + continue; + + if (!looker.bInCombat) + { + if (!looker.CheckSight(target) && !looker.CheckSight(self)) + continue; + + looker.target = target; + if (looker.SeeSound) + { + looker.A_PlaySound(looker.SeeSound, CHAN_VOICE); + } + looker.SetState(looker.SeeState); + looker.bInCombat = true; + } + } + } + } diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt index 62d58b4eb..25c3ad1f3 100644 --- a/wadsrc/static/zscript/inventory/stateprovider.txt +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -2,7 +2,6 @@ class StateProvider : Inventory native { action native state A_JumpIfNoAmmo(statelabel label); - action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = ""); action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0); @@ -175,6 +174,98 @@ class StateProvider : Inventory native return null; } +//========================================================================== +// +// A_CustomPunch +// +// Berserk is not handled here. That can be done with A_CheckIfInventory +// +//========================================================================== + + action void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "") + { + let player = self.player; + if (!player) return; + + let weapon = player.ReadyWeapon; + + double angle; + double pitch; + FTranslatedLineTarget t; + int actualdamage; + + if (!norandom) + damage *= random[cwpunch](1, 8); + + angle = self.Angle + random2[cwpunch]() * (5.625 / 256); + if (range == 0) range = DEFMELEERANGE; + pitch = AimLineAttack (angle, range, t, 0., ALF_CHECK3D); + + // only use ammo when actually hitting something! + if ((flags & CPF_USEAMMO) && t.linetarget && weapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite) + { + if (!weapon.DepleteAmmo(weapon.bAltFire, true)) + return; // out of ammo + } + + if (pufftype == NULL) + pufftype = 'BulletPuff'; + int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0); + + Actor puff; + [puff, actualdamage] = LineAttack (angle, range, pitch, damage, 'Melee', pufftype, puffFlags, t); + + if (!t.linetarget) + { + if (MissSound) A_PlaySound(MissSound, CHAN_WEAPON); + } + else + { + if (lifesteal > 0 && !(t.linetarget.bDontDrain)) + { + if (flags & CPF_STEALARMOR) + { + if (armorbonustype == NULL) + { + armorbonustype = 'ArmorBonus'; + } + if (armorbonustype != NULL) + { + let armorbonus = ArmorBonus(Spawn(armorbonustype)); + armorbonus.SaveAmount *= int(actualdamage * lifesteal); + if (lifestealmax > 0) armorbonus.MaxSaveAmount = lifestealmax; + armorbonus.bDropped = true; + armorbonus.ClearCounters(); + + if (!armorbonus.CallTryPickup(self)) + { + armorbonus.Destroy (); + } + } + } + else + { + GiveBody (int(actualdamage * lifesteal), lifestealmax); + } + } + if (weapon != NULL) + { + if (MeleeSound) A_PlaySound(MeleeSound, CHAN_WEAPON); + else A_PlaySound(AttackSound, CHAN_WEAPON); + } + + if (!(flags & CPF_NOTURN)) + { + // turn to face target + self.Angle = t.angleFromSource; + } + + if (flags & CPF_PULLIN) self.bJustAttacked = true; + if (flags & CPF_DAGGER) t.linetarget.DaggerAlert (self); + } + } + + //--------------------------------------------------------------------------- //