From d8e8645d823c4942fcd3bd2329d640493f67b4ec Mon Sep 17 00:00:00 2001 From: Mykola Ambartsumov Date: Sun, 29 Sep 2024 00:35:58 +0300 Subject: [PATCH] ZScriptify a detection check in P_LookForPlayers --- src/playsim/actor.h | 8 ++ src/playsim/p_enemy.cpp | 18 +--- src/playsim/p_local.h | 2 + src/playsim/p_mobj.cpp | 99 +++++++++++++++++++ wadsrc/static/zscript/actors/actor.zs | 4 +- wadsrc/static/zscript/actors/player/player.zs | 18 ++-- 6 files changed, 119 insertions(+), 30 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index bbf2eaf9879..ded92caf112 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -949,6 +949,14 @@ class AActor final : public DThinker // Do I hate the other actor? bool IsHostile (AActor *other); + // Can I detect the other actor? + bool CanDetect(AActor *other); + bool CallCanDetect(AActor *other); + + // Can I be detected by the other actor? + bool CanBeDetectedBy(AActor *other); + bool CallCanBeDetectedBy(AActor *other); + inline bool IsNoClip2() const; void CheckPortalTransition(bool islinked); DVector3 GetPortalTransition(double byoffset, sector_t **pSec = NULL); diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index cf15cbf3888..d991e7f4f42 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -59,7 +59,6 @@ static FRandom pr_opendoor ("OpenDoor"); static FRandom pr_trywalk ("TryWalk"); static FRandom pr_newchasedir ("NewChaseDir"); static FRandom pr_lookformonsters ("LookForMonsters"); -static FRandom pr_lookforplayers ("LookForPlayers"); static FRandom pr_scaredycat ("Anubis"); FRandom pr_chase ("Chase"); FRandom pr_facetarget ("FaceTarget"); @@ -1843,22 +1842,9 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) continue; } - // [RC] Well, let's let special monsters with this flag active be able to see - // the player then, eh? - if(!(actor->flags6 & MF6_SEEINVISIBLE)) + if ( !actor->CallCanDetect(player->mo) || !player->mo->CallCanBeDetectedBy(actor) ) { - if ((player->mo->flags & MF_SHADOW && !(actor->Level->i_compatflags & COMPATF_INVISIBILITY)) || - player->mo->flags3 & MF3_GHOST) - { - if (player->mo->Distance2D (actor) > 128 && player->mo->Vel.XY().LengthSquared() < 5*5) - { // Player is sneaking - can't detect - continue; - } - if (pr_lookforplayers() < 225) - { // Player isn't sneaking, but still didn't detect - continue; - } - } + continue; } // [RH] Need to be sure the reactiontime is 0 if the monster is diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index cde45f403ca..6adcc3fe154 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -63,6 +63,8 @@ struct FRenderViewpoint; #define USERANGE (64.) #define DEFMELEERANGE (64.) +#define DEFMELEEDELTA (20.) + #define MISSILERANGE (32*64.) #define PLAYERMISSILERANGE (8192.) // [RH] New MISSILERANGE for players diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index e8a6c247a0c..e44f35a8b6c 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -139,6 +139,7 @@ static FRandom pr_missiledamage ("MissileDamage"); static FRandom pr_multiclasschoice ("MultiClassChoice"); static FRandom pr_rockettrail("RocketTrail"); static FRandom pr_uniquetid("UniqueTID"); +static FRandom pr_canbedetectedby("CanBeDetectedBy"); // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -7532,6 +7533,104 @@ bool AActor::IsHostile (AActor *other) return true; } +//========================================================================== +// +// AActor :: CanBeDetectedBy +// +// Override this if you want to customize the conditions in which another +// actor can detect this one with A_Look +// +//========================================================================== + +bool AActor::CanBeDetectedBy(AActor *other) +{ + static FName SneakSpeed = FName("SneakSpeed"); + static FName NonSneakDetectionChance = FName("NonSneakDetectionChance"); + if (this->player) + { + if (!(other->flags6 & MF6_SEEINVISIBLE)) + { + if (((this->flags & MF_SHADOW) && !(this->Level->i_compatflags & COMPATF_INVISIBILITY)) || (this->flags3 & MF3_GHOST)) + { + double distancesquared = this->Distance2DSquared(other); + double velsquared = this->Vel.LengthSquared(); + double meleerange = other->meleerange + DEFMELEEDELTA; + double sneakspeedsquared = this->FloatVar(SneakSpeed); + sneakspeedsquared = sneakspeedsquared * sneakspeedsquared; + + if (distancesquared > (2 * meleerange * 2 * meleerange) && velsquared < sneakspeedsquared) + { + // Player is sneaking - can't detect + return false; + } + double nonsneakdetectionchance = this->FloatVar(NonSneakDetectionChance); + if (pr_canbedetectedby.GenRand_Real1() < nonsneakdetectionchance) + { + // Player isn't sneaking, but still didn't detect + return false; + } + } + } + } + return true; +} + +DEFINE_ACTION_FUNCTION(AActor, CanBeDetectedBy) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_BOOL(self->CanBeDetectedBy(other)); +} + +bool AActor::CallCanBeDetectedBy(AActor *other) +{ + IFVIRTUAL(AActor, CanBeDetectedBy) + { + VMValue params[] = { (DObject*)this, other }; + int retv; + VMReturn ret(&retv); + VMCall(func, params, 2, &ret, 1); + return !!retv; + } + return CanBeDetectedBy(other); +} + +//========================================================================== +// +// AActor :: CanDetect +// +// Customize this if you want to customize the conditions under which this +// actor can detect another one with A_Look +// +//========================================================================== + +bool AActor::CanDetect(AActor *other) +{ + return true; +} + +DEFINE_ACTION_FUNCTION(AActor, CanDetect) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(other, AActor); + ACTION_RETURN_BOOL(self->CanDetect(other)); +} + +bool AActor::CallCanDetect(AActor *other) +{ + IFVIRTUAL(AActor, CanDetect) + { + VMValue params[] = { (DObject*)this, other }; + int retv; + VMReturn ret(&retv); + VMCall(func, params, 2, &ret, 1); + return !!retv; + } + return CanDetect(other); +} + + + //========================================================================== // // AActor :: DoSpecialDamage diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 31dc0805264..acfcd636609 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -861,6 +861,8 @@ class Actor : Thinker native native bool BouncePlane(readonly plane); native void PlayBounceSound(bool onFloor); native bool ReflectOffActor(Actor blocking); + native virtual bool CanDetect(Actor actor); + native virtual bool CanBeDetectedBy(Actor actor); clearscope double PitchTo(Actor target, double zOfs = 0, double targZOfs = 0, bool absolute = false) const { @@ -1482,8 +1484,6 @@ class Actor : Thinker native { if (player == NULL) Destroy(); } - - States(Actor, Overlay, Weapon, Item) { diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 69e534b70fc..ab32199ca21 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -53,6 +53,8 @@ class PlayerPawn : Actor double FullHeight; double curBob; double prevBob; + double SneakSpeed; // Speed at which the player is considered to be sneaking (used for non-vanilla blursphere and heretic ghostsphere) + double NonSneakDetectionChance; // Chance to detect the player while they're sneaking and invisible meta Name HealingRadiusType; meta Name InvulMode; @@ -82,6 +84,8 @@ class PlayerPawn : Actor property ViewBob: ViewBob; property ViewBobSpeed: ViewBobSpeed; property WaterClimbSpeed : WaterClimbSpeed; + property SneakSpeed : SneakSpeed; + property NonSneakDetectionChance : NonSneakDetectionChance; flagdef NoThrustWhenInvul: PlayerFlags, 0; flagdef CanSuperMorph: PlayerFlags, 1; @@ -133,6 +137,8 @@ class PlayerPawn : Actor Player.ViewBobSpeed 20; Player.WaterClimbSpeed 3.5; Player.TeleportFreezeTime 18; + Player.SneakSpeed 5.0; + Player.NonSneakDetectionChance 225.0 / 255.0; Obituary "$OB_MPDEFAULT"; } @@ -256,12 +262,6 @@ class PlayerPawn : Actor virtual void MorphPlayerThink() { } - - //---------------------------------------------------------------------------- - // - // - // - //---------------------------------------------------------------------------- virtual void OnRespawn() { @@ -279,12 +279,6 @@ class PlayerPawn : Actor bRespawnInvul = true; // [RH] special effect } } - - //---------------------------------------------------------------------------- - // - // - // - //---------------------------------------------------------------------------- override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) {