From 79177cf98e1385b62c6d36808797d1463049bee0 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 27 Jan 2016 14:54:46 -0600 Subject: [PATCH 1/4] Set up the subfunction. --- src/thingdef/thingdef_codeptr.cpp | 121 ++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 1764717f5..46a358d20 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4975,6 +4975,127 @@ enum RadiusGiveFlags RGF_EITHER = 1 << 17, }; +static bool DoRadiusGive(AActor *self, AActor *thing, const PClass *item, int amount, fixed_t distance, int flags, const PClass *filter, FName species, fixed_t mindist) +{ + //[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s). + bool filterpass = DoCheckClass(thing, filter, !!(flags & RGF_EXFILTER)), + speciespass = DoCheckSpecies(thing, species, !!(flags & RGF_EXSPECIES)); + + if ((flags & RGF_EITHER) ? (!(filterpass || speciespass)) : (!(filterpass && speciespass))) + { + if (thing != self) //Don't let filter and species obstruct RGF_GIVESELF. + return false; + } + + if (thing == self) + { + if (!(flags & RGF_GIVESELF)) + return false; + } + + //Check for target, master, and tracer flagging. + bool targetPass = true; + bool masterPass = true; + bool tracerPass = true; + bool ptrPass = false; + if ((thing != self) && (flags & (RGF_NOTARGET | RGF_NOMASTER | RGF_NOTRACER))) + { + if ((thing == self->target) && (flags & RGF_NOTARGET)) + targetPass = false; + if ((thing == self->master) && (flags & RGF_NOMASTER)) + masterPass = false; + if ((thing == self->tracer) && (flags & RGF_NOTRACER)) + tracerPass = false; + + ptrPass = (flags & RGF_INCLUSIVE) ? (targetPass || masterPass || tracerPass) : (targetPass && masterPass && tracerPass); + + //We should not care about what the actor is here. It's safe to abort this actor. + if (!ptrPass) + return false; + } + + //Next, actor flag checking. + bool selfPass = !!((flags & RGF_GIVESELF) && thing == self); + bool corpsePass = !!((flags & RGF_CORPSES) && thing->flags & MF_CORPSE); + bool killedPass = !!((flags & RGF_KILLED) && thing->flags6 & MF6_KILLED); + bool monsterPass = !!((flags & RGF_MONSTERS) && thing->flags3 & MF3_ISMONSTER); + bool objectPass = !!((flags & RGF_OBJECTS) && (thing->player == NULL) && (!(thing->flags3 & MF3_ISMONSTER)) + && ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE))); + bool playerPass = !!((flags & RGF_PLAYERS) && (thing->player != NULL) && (thing->player->mo == thing)); + bool voodooPass = !!((flags & RGF_VOODOO) && (thing->player != NULL) && (thing->player->mo != thing)); + //Self calls priority over the rest of this. + if (!selfPass) + { + //If it's specifically a monster/object/player/voodoo... Can be either or... + if (monsterPass || objectPass || playerPass || voodooPass) + { + //...and is dead, without desire to give to the dead... + if (((thing->health <= 0) && !(corpsePass || killedPass))) + { + //Skip! + return false; + } + } + } + + bool itemPass = !!((flags & RGF_ITEMS) && thing->IsKindOf(RUNTIME_CLASS(AInventory))); + bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE); + + if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass) + { + + fixedvec3 diff = self->Vec3To(thing); + diff.z += (thing->height - self->height) / 2; + if (flags & RGF_CUBE) + { // check if inside a cube + double dx = fabs((double)(diff.x)); + double dy = fabs((double)(diff.y)); + double dz = fabs((double)(diff.z)); + double dist = (double)distance; + double min = (double)mindist; + if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min))) + { + return false; + } + } + else + { // check if inside a sphere + double distsquared = double(distance) * double(distance); + double minsquared = double(mindist) * double(mindist); + double lengthsquared = TVector3(diff.x, diff.y, diff.z).LengthSquared(); + if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared))) + { + return false; + } + } + + if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) + { // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight. + AInventory *gift = static_cast(Spawn(item, 0, 0, 0, NO_REPLACE)); + if (gift->IsKindOf(RUNTIME_CLASS(AHealth))) + { + gift->Amount *= amount; + } + else + { + gift->Amount = amount; + } + gift->flags |= MF_DROPPED; + gift->ClearCounters(); + if (!gift->CallTryPickup(thing)) + { + gift->Destroy(); + return false; + } + else + { + return true; + } + } + } + return false; +} + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) { ACTION_PARAM_START(7); From 846f14c03de44f7298bfd3da48f8083d5f8a4828 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 27 Jan 2016 14:56:06 -0600 Subject: [PATCH 2/4] Remove the loop. --- src/thingdef/thingdef_codeptr.cpp | 121 +----------------------------- 1 file changed, 1 insertion(+), 120 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 46a358d20..d0eb6baf0 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5118,128 +5118,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) { amount = 1; } - FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance)); - AActor *thing; bool given = false; - while ((thing = it.Next())) - { - //[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s). - bool filterpass = DoCheckClass(thing, filter, !!(flags & RGF_EXFILTER)), - speciespass = DoCheckSpecies(thing, species, !!(flags & RGF_EXSPECIES)); - - if ((flags & RGF_EITHER) ? (!(filterpass || speciespass)) : (!(filterpass && speciespass))) - { - if (thing != self) //Don't let filter and species obstruct RGF_GIVESELF. - continue; - } - - if (thing == self) - { - if (!(flags & RGF_GIVESELF)) - continue; - } - - //Check for target, master, and tracer flagging. - bool targetPass = true; - bool masterPass = true; - bool tracerPass = true; - bool ptrPass = false; - if ((thing != self) && (flags & (RGF_NOTARGET | RGF_NOMASTER | RGF_NOTRACER))) - { - if ((thing == self->target) && (flags & RGF_NOTARGET)) - targetPass = false; - if ((thing == self->master) && (flags & RGF_NOMASTER)) - masterPass = false; - if ((thing == self->tracer) && (flags & RGF_NOTRACER)) - tracerPass = false; - - ptrPass = (flags & RGF_INCLUSIVE) ? (targetPass || masterPass || tracerPass) : (targetPass && masterPass && tracerPass); - - //We should not care about what the actor is here. It's safe to abort this actor. - if (!ptrPass) - continue; - } - - //Next, actor flag checking. - bool selfPass = !!((flags & RGF_GIVESELF) && thing == self); - bool corpsePass = !!((flags & RGF_CORPSES) && thing->flags & MF_CORPSE); - bool killedPass = !!((flags & RGF_KILLED) && thing->flags6 & MF6_KILLED); - bool monsterPass = !!((flags & RGF_MONSTERS) && thing->flags3 & MF3_ISMONSTER); - bool objectPass = !!((flags & RGF_OBJECTS) && (thing->player == NULL) && (!(thing->flags3 & MF3_ISMONSTER)) - && ((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE))); - bool playerPass = !!((flags & RGF_PLAYERS) && (thing->player != NULL) && (thing->player->mo == thing)); - bool voodooPass = !!((flags & RGF_VOODOO) && (thing->player != NULL) && (thing->player->mo != thing)); - //Self calls priority over the rest of this. - if (!selfPass) - { - //If it's specifically a monster/object/player/voodoo... Can be either or... - if (monsterPass || objectPass || playerPass || voodooPass) - { - //...and is dead, without desire to give to the dead... - if (((thing->health <= 0) && !(corpsePass || killedPass))) - { - //Skip! - continue; - } - } - } - - bool itemPass = !!((flags & RGF_ITEMS) && thing->IsKindOf(RUNTIME_CLASS(AInventory))); - bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE); - - if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass) - { - - fixedvec3 diff = self->Vec3To(thing); - diff.z += (thing->height - self->height) / 2; - if (flags & RGF_CUBE) - { // check if inside a cube - double dx = fabs((double)(diff.x)); - double dy = fabs((double)(diff.y)); - double dz = fabs((double)(diff.z)); - double dist = (double)distance; - double min = (double)mindist; - if ((dx > dist || dy > dist || dz > dist) || (min && (dx < min && dy < min && dz < min))) - { - continue; - } - } - else - { // check if inside a sphere - double distsquared = double(distance) * double(distance); - double minsquared = double(mindist) * double(mindist); - double lengthsquared = TVector3(diff.x, diff.y, diff.z).LengthSquared(); - if (lengthsquared > distsquared || (minsquared && (lengthsquared < minsquared))) - { - continue; - } - } - - if ((flags & RGF_NOSIGHT) || P_CheckSight(thing, self, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) - { // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight. - AInventory *gift = static_cast(Spawn(item, 0, 0, 0, NO_REPLACE)); - if (gift->IsKindOf(RUNTIME_CLASS(AHealth))) - { - gift->Amount *= amount; - } - else - { - gift->Amount = amount; - } - gift->flags |= MF_DROPPED; - gift->ClearCounters(); - if (!gift->CallTryPickup(thing)) - { - gift->Destroy(); - } - else - { - given = true; - } - } - } - } + ACTION_SET_RESULT(given); } From 2da868656eeba7197f1a371a5f097dae42a5c66c Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Wed, 27 Jan 2016 15:22:05 -0600 Subject: [PATCH 3/4] Finalize loop and prioritize missile searching. --- src/thingdef/thingdef_codeptr.cpp | 39 ++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d0eb6baf0..4f674955c 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4977,6 +4977,19 @@ enum RadiusGiveFlags static bool DoRadiusGive(AActor *self, AActor *thing, const PClass *item, int amount, fixed_t distance, int flags, const PClass *filter, FName species, fixed_t mindist) { + // [MC] We only want to make an exception for missiles here. Nothing else. + bool missilePass = !!((flags & RGF_MISSILES) && thing->isMissile()); + if (thing == self) + { + if (!(flags & RGF_GIVESELF)) + return false; + } + else if (thing->isMissile()) + { + if (!missilePass) + return false; + } + //[MC] Check for a filter, species, and the related exfilter/expecies/either flag(s). bool filterpass = DoCheckClass(thing, filter, !!(flags & RGF_EXFILTER)), speciespass = DoCheckSpecies(thing, species, !!(flags & RGF_EXSPECIES)); @@ -4987,12 +5000,6 @@ static bool DoRadiusGive(AActor *self, AActor *thing, const PClass *item, int am return false; } - if (thing == self) - { - if (!(flags & RGF_GIVESELF)) - return false; - } - //Check for target, master, and tracer flagging. bool targetPass = true; bool masterPass = true; @@ -5039,7 +5046,6 @@ static bool DoRadiusGive(AActor *self, AActor *thing, const PClass *item, int am } bool itemPass = !!((flags & RGF_ITEMS) && thing->IsKindOf(RUNTIME_CLASS(AInventory))); - bool missilePass = !!((flags & RGF_MISSILES) && thing->flags & MF_MISSILE); if (selfPass || monsterPass || corpsePass || killedPass || itemPass || objectPass || missilePass || playerPass || voodooPass) { @@ -5120,7 +5126,24 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) } AActor *thing; bool given = false; - + if (flags & RGF_MISSILES) + { + TThinkerIterator it; + while ((thing = it.Next())) + { + bool giving = !!(DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)); + if (giving) given = true; + } + } + else + { + FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance)); + while ((thing = it.Next())) + { + bool giving = !!(DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)); + if (giving) given = true; + } + } ACTION_SET_RESULT(given); } From eeca536d9a38daf99ad8bc0c7ce9c360c550aaa9 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 29 Jan 2016 10:41:05 -0600 Subject: [PATCH 4/4] Clean up a few things. --- src/thingdef/thingdef_codeptr.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 4f674955c..b25d108cc 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5131,8 +5131,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) TThinkerIterator it; while ((thing = it.Next())) { - bool giving = !!(DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)); - if (giving) given = true; + if (DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)) given = true; } } else @@ -5140,8 +5139,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) FBlockThingsIterator it(FBoundingBox(self->X(), self->Y(), distance)); while ((thing = it.Next())) { - bool giving = !!(DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)); - if (giving) given = true; + if (DoRadiusGive(self, thing, item, amount, distance, flags, filter, species, mindist)) given = true; } } ACTION_SET_RESULT(given);