diff --git a/src/p_local.h b/src/p_local.h index 4b8b40a85..ebbaeace5 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -161,7 +161,7 @@ PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); int P_Thing_CheckInputNum(player_t *p, int inputnum); int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch); -bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr); +int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting = false); enum { diff --git a/src/p_things.cpp b/src/p_things.cpp index 6f01715ad..d94ba6a01 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -696,16 +696,16 @@ int P_Thing_CheckInputNum(player_t *p, int inputnum) } return renum; } -bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr) +int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int count, int flags, int ptr, bool counting) { AActor *ref = COPY_AAPTR(self, ptr); // We need these to check out. if (!ref || !classname || distance <= 0) - return false; + return 0; int counter = 0; - bool result = false; + int result = 0; double closer = distance, farther = 0, current = distance; const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); @@ -740,7 +740,7 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in if ((ref->Distance2D(mo) < distance && ((flags & CPXF_NOZ) || ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || - (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) + (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) { if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) continue; @@ -766,19 +766,19 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in { if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) continue; - counter++; } else { if (flags & CPXF_DEADONLY) continue; - counter++; } + counter++; // Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal. - if (counter > count) - { - result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true; + // Don't abort if calling the counting version CheckProximity non-action function. + if (!counting && counter > count) + { + result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? 0 : 1; // However, if we have one SET* flag and either the closest or farthest flags, keep the function going. if (ptrWillChange && ptrDistPref) @@ -805,12 +805,14 @@ bool P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, in } } - if (counter == count) - result = true; - else if (counter < count) - result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); - - return result; + if (!counting) + { + if (counter == count) + result = 1; + else if (counter < count) + result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)) ? 1 : 0; + } + return counting ? counter : result; } int P_Thing_Warp(AActor *caller, AActor *reference, double xofs, double yofs, double zofs, DAngle angle, int flags, double heightoffset, double radiusoffset, DAngle pitch) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 17c5b5cf5..cd90e08e5 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -643,6 +643,38 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetPlayerInput) return 0; } +//========================================================================== +// +// GetProximity +// +// NON-ACTION function of A_CheckProximity that returns how much it counts. +// Takes a pointer as anyone may or may not be a player. +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetProximity) +{ + if (numret > 0) + { + PARAM_SELF_PROLOGUE(AActor); + PARAM_CLASS(classname, AActor); + PARAM_FLOAT(distance); + PARAM_INT_OPT(flags) { flags = 0; } + PARAM_INT_OPT(ptr) { ptr = AAPTR_DEFAULT; } + + AActor *mobj = COPY_AAPTR(self, ptr); + if (mobj == nullptr) + { + ret->SetInt(0); + } + else + { + ret->SetInt(P_Thing_CheckProximity(self, classname, distance, 0, flags, ptr, true)); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 1d27ad01a..d28c8ebc3 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -50,6 +50,7 @@ ACTOR Actor native //: Thinker native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); native float GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); + native int GetProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT);