From ccc694bbcd3f159d3b098fb2cface3ebc1ce4c17 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Thu, 7 Jan 2016 17:09:02 -0600 Subject: [PATCH 1/5] - Added the following flags, all affixed with CPXF_: - NODISTANCE: Disables distance checking. - CHECKSIGHT: The qualifying actor must be in sight in order to count. - SET: Gets the first qualifying actor and sets the calling actor's specified pointer to it. - SETONPTR: If the function is being aimed at another actor other than the caller, sets that actor's pointers instead. Requires a SET* flag to work. - FARTHEST: The actor farthest from the checking actor is set as the pointer. Requires a SET* flag to work. - CLOSEST: The closest qualifying actor is set as the pointer. Requires a SET* flag to work. --- src/thingdef/thingdef_codeptr.cpp | 83 ++++++++++++++++++++++++++---- wadsrc/static/actors/constants.txt | 8 +++ 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 89299e0fa..5dac7adbe 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5908,6 +5908,14 @@ enum CPXFflags CPXF_COUNTDEAD = 1 << 3, CPXF_DEADONLY = 1 << 4, CPXF_EXACT = 1 << 5, + CPXF_SETTARGET = 1 << 6, + CPXF_SETMASTER = 1 << 7, + CPXF_SETTRACER = 1 << 8, + CPXF_FARTHEST = 1 << 9, + CPXF_CLOSEST = 1 << 10, + CPXF_SETONPTR = 1 << 11, + CPXF_NODISTANCE = 1 << 12, + CPXF_CHECKSIGHT = 1 << 13, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { @@ -5920,17 +5928,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) ACTION_PARAM_INT(ptr, 5); ACTION_SET_RESULT(false); //No inventory chain results please. + + if (!jump) + { + if (!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER))) + return; + } AActor *ref = COPY_AAPTR(self, ptr); //We need these to check out. - if (!ref || !jump || !classname || distance <= 0) + if (!ref || !classname || ((distance <= 0) && !(flags & CPXF_NODISTANCE))) return; int counter = 0; bool result = false; + const double distsquared = (double)distance * (double)distance; + double closer, farther = 0, current = closer = distsquared; + const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); + const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); + TThinkerIterator it; - AActor * mo; + AActor *mo, *dist = NULL; //[MC] Process of elimination, I think, will get through this as quickly and //efficiently as possible. @@ -5949,12 +5968,37 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) else if (classname != mo->GetClass()) continue; - //Make sure it's in range and respect the desire for Z or not. - if (P_AproxDistance(ref->x - mo->x, ref->y - mo->y) < distance && - ((flags & CPXF_NOZ) || - ((ref->z > mo->z && ref->z - (mo->z + mo->height) < distance) || - (ref->z <= mo->z && mo->z - (ref->z + ref->height) < distance)))) + //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use + //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. + //Ripped from sphere checking in A_RadiusGive (along with a number of things). + + TVector3 spos(ref->x, ref->y, ((flags & CPXF_NOZ) ? 0 : (ref->z + ref->height / 2))); + TVector3 tpos(mo->x, mo->y, ((flags & CPXF_NOZ) ? 0 : (mo->z + mo->height / 2))); + if ((flags & CPXF_NODISTANCE) || (tpos - spos).LengthSquared() <= distsquared) { + if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) + continue; + + if (ptrWillChange && ptrDistPref) + { + spos.Z = ref->z + ref->height / 2; //This one cannot have NOZ checking. + tpos.Z = mo->z + mo->height / 2; + current = (tpos - spos).LengthSquared(); + + if ((flags & CPXF_CLOSEST) && ((current < closer) || !closer)) + { + dist = mo; + closer = current; //This actor's closer. Set the new standard. + } + else if ((flags & CPXF_FARTHEST) && (current > farther)) + { + dist = mo; + farther = current; + } + else if (!dist) + dist = mo; //Just get the last one and call it quits if there's nothing selected. + } + if (mo->flags6 & MF6_KILLED) { if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY))) @@ -5972,17 +6016,38 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) if (counter > count) { result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true; - break; + + //However, if we have one SET* flag and either the closest or farthest flags, keep the funcion going. + if (ptrWillChange && ptrDistPref) + continue; + else + break; } } } + if (ptrWillChange && dist != NULL) + { + if (flags & CPXF_SETONPTR) + { + if (flags & CPXF_SETTARGET) ref->target = dist; + if (flags & CPXF_SETMASTER) ref->master = dist; + if (flags & CPXF_SETTRACER) ref->tracer = dist; + } + else + { + if (flags & CPXF_SETTARGET) self->target = dist; + if (flags & CPXF_SETMASTER) self->master = dist; + if (flags & CPXF_SETTRACER) self->tracer = dist; + } + } + if (counter == count) result = true; else if (counter < count) result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT)); - + if (!jump) return; if (result) { diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 213e2109d..835e73dbf 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -497,6 +497,14 @@ enum CPXF_COUNTDEAD = 1 << 3, CPXF_DEADONLY = 1 << 4, CPXF_EXACT = 1 << 5, + CPXF_SETTARGET = 1 << 6, + CPXF_SETMASTER = 1 << 7, + CPXF_SETTRACER = 1 << 8, + CPXF_FARTHEST = 1 << 9, + CPXF_CLOSEST = 1 << 10, + CPXF_SETONPTR = 1 << 11, + CPXF_NODISTANCE = 1 << 12, + CPXF_CHECKSIGHT = 1 << 13, }; // Flags for A_CheckBlock From b51bbf66b0ef421738c3516b17f0ad73518b0733 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Thu, 21 Jan 2016 21:15:50 -0600 Subject: [PATCH 2/5] - Fixed pointer setting not working due to requiring more than the SET* flags. - Changed search algorithm to be square and utilize fixed_t instead. --- src/thingdef/thingdef_codeptr.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index f10497711..f7cad3a5e 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5996,8 +5996,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) int counter = 0; bool result = false; - const double distsquared = (double)distance * (double)distance; - double closer, farther = 0, current = closer = distsquared; + if (flags & CPXF_NODISTANCE) distance = (FIXED_MAX/2); + fixed_t closer = distance, farther = 0, current = distance; const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); @@ -6027,20 +6027,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) fixedvec3 diff = ref->Vec3To(mo); diff.z += (ref->height - mo->height) / 2; - double lengthsquared = TVector3(diff.x, diff.y, (flags & CPXF_NOZ) ? 0 : diff.z).LengthSquared(); - if ((flags & CPXF_NODISTANCE) || lengthsquared <= distsquared) + if ((flags & CPXF_NODISTANCE) || (ref->AproxDistance(mo) < distance && + ((flags & CPXF_NOZ) || + ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || + (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) { if ((flags & CPXF_CHECKSIGHT) && !(P_CheckSight(mo, ref, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))) continue; - if (ptrWillChange && ptrDistPref) + if (ptrWillChange) { - //Saves on needless recalculation as we already included Z above, so don't do it again - //if we did not use the flag the first time. - if (flags & CPXF_NOZ) - lengthsquared = TVector3(diff.x, diff.y, diff.z).LengthSquared(); - - current = lengthsquared; //This one cannot have NOZ checking. + current = ref->AproxDistance(mo); if ((flags & CPXF_CLOSEST) && ((current < closer) || !closer)) { From 823edc4a690e51c0fc8d6ca796342f4a62f72f39 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Thu, 21 Jan 2016 21:23:43 -0600 Subject: [PATCH 3/5] - Cleaned up leftovers. --- src/thingdef/thingdef_codeptr.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index f7cad3a5e..28a7dfcf6 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -6024,9 +6024,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. //Ripped from sphere checking in A_RadiusGive (along with a number of things). - - fixedvec3 diff = ref->Vec3To(mo); - diff.z += (ref->height - mo->height) / 2; if ((flags & CPXF_NODISTANCE) || (ref->AproxDistance(mo) < distance && ((flags & CPXF_NOZ) || ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || From ced35e98fbb8f327729970d107f3a431eb9c6495 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Mon, 25 Jan 2016 10:07:00 -0600 Subject: [PATCH 4/5] Remove needless check. --- src/thingdef/thingdef_codeptr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 28a7dfcf6..37f228eb1 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -6036,7 +6036,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { current = ref->AproxDistance(mo); - if ((flags & CPXF_CLOSEST) && ((current < closer) || !closer)) + if ((flags & CPXF_CLOSEST) && (current < closer)) { dist = mo; closer = current; //This actor's closer. Set the new standard. From 1c0ef1d367f99941181b3e585445e6f9d4d12d4e Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Tue, 26 Jan 2016 10:00:20 -0600 Subject: [PATCH 5/5] Removed CPXF_NODISTANCE. --- src/thingdef/thingdef_codeptr.cpp | 8 +++----- wadsrc/static/actors/constants.txt | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 37f228eb1..4349c4b39 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5968,8 +5968,7 @@ enum CPXFflags CPXF_FARTHEST = 1 << 9, CPXF_CLOSEST = 1 << 10, CPXF_SETONPTR = 1 << 11, - CPXF_NODISTANCE = 1 << 12, - CPXF_CHECKSIGHT = 1 << 13, + CPXF_CHECKSIGHT = 1 << 12, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) { @@ -5991,12 +5990,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) AActor *ref = COPY_AAPTR(self, ptr); //We need these to check out. - if (!ref || !classname || ((distance <= 0) && !(flags & CPXF_NODISTANCE))) + if (!ref || !classname || (distance <= 0)) return; int counter = 0; bool result = false; - if (flags & CPXF_NODISTANCE) distance = (FIXED_MAX/2); fixed_t closer = distance, farther = 0, current = distance; const bool ptrWillChange = !!(flags & (CPXF_SETTARGET | CPXF_SETMASTER | CPXF_SETTRACER)); const bool ptrDistPref = !!(flags & (CPXF_CLOSEST | CPXF_FARTHEST)); @@ -6024,7 +6022,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity) //[MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use //Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly. //Ripped from sphere checking in A_RadiusGive (along with a number of things). - if ((flags & CPXF_NODISTANCE) || (ref->AproxDistance(mo) < distance && + if ((ref->AproxDistance(mo) < distance && ((flags & CPXF_NOZ) || ((ref->Z() > mo->Z() && ref->Z() - mo->Top() < distance) || (ref->Z() <= mo->Z() && mo->Z() - ref->Top() < distance))))) diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 090a1330d..23694fda7 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -504,8 +504,7 @@ enum CPXF_FARTHEST = 1 << 9, CPXF_CLOSEST = 1 << 10, CPXF_SETONPTR = 1 << 11, - CPXF_NODISTANCE = 1 << 12, - CPXF_CHECKSIGHT = 1 << 13, + CPXF_CHECKSIGHT = 1 << 12, }; // Flags for A_CheckBlock