Added MF9_BLOCKSIGHT.

This flag allows actors with MF9_DOBLOCKSIGHT to have their vision blocked when calling P_CheckSight(), if an obstacle with the flag gets in the way.
This commit is contained in:
inkoalawetrust 2024-01-28 16:26:22 +02:00
parent 458d81cede
commit e67b8f574b
7 changed files with 69 additions and 9 deletions

View file

@ -442,7 +442,9 @@ enum ActorFlag9
MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ? MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ?
MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty.
MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors.
MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states
MF9_BLOCKSIGHT = 0X00000020, // [inkoalawetrust] This actors' hitbox blocks P_CheckSight().
MF9_DOBLOCKSIGHT = 0x00000040 // [inkoalawetrust] When calling P_CheckSight(), this actor checks for MF9_BLOCKSIGHT actors.
}; };
// --- mobj.renderflags --- // --- mobj.renderflags ---

View file

@ -249,17 +249,17 @@ extern TArray<spechit_t> spechit;
extern TArray<spechit_t> portalhit; extern TArray<spechit_t> portalhit;
int P_TestMobjLocation (AActor *mobj); int P_TestMobjLocation (AActor *mobj);
int P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL); int P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL);
bool P_CheckPosition(AActor *thing, const DVector2 &pos, bool actorsonly = false); bool P_CheckPosition(AActor *thing, const DVector2 &pos, bool actorsonly = false);
void P_DoMissileDamage(AActor* inflictor, AActor* target); void P_DoMissileDamage(AActor* inflictor, AActor* target);
bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, bool actorsonly = false); bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, bool actorsonly = false);
AActor *P_CheckOnmobj (AActor *thing); AActor* P_CheckOnmobj (AActor *thing);
void P_FakeZMovement (AActor *mo); void P_FakeZMovement (AActor *mo);
bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false);
bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor = NULL, bool missilecheck = false); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor = NULL, bool missilecheck = false);
bool P_CheckMove(AActor *thing, const DVector2 &pos, FCheckPosition& tm, int flags); bool P_CheckMove(AActor *thing, const DVector2 &pos, FCheckPosition& tm, int flags);
bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags = 0); bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags = 0);
void P_ApplyTorque(AActor *mo); void P_ApplyTorque(AActor *mo);
@ -270,7 +270,8 @@ void P_SlideMove (AActor* mo, const DVector2 &pos, int numsteps);
bool P_BounceWall (AActor *mo); bool P_BounceWall (AActor *mo);
bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop); bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop);
bool P_ReflectOffActor(AActor* mo, AActor* blocking); bool P_ReflectOffActor(AActor* mo, AActor* blocking);
int P_CheckSight (AActor *t1, AActor *t2, int flags=0); int P_CheckSight (AActor *t1, AActor *t2, int flags=0);
AActor* P_CheckForSightBlock(AActor* t1, AActor* t2);
enum ESightFlags enum ESightFlags
{ {

View file

@ -36,6 +36,7 @@
#include "g_levellocals.h" #include "g_levellocals.h"
#include "actorinlines.h" #include "actorinlines.h"
#include "shadowinlines.h"
static FRandom pr_botchecksight ("BotCheckSight"); static FRandom pr_botchecksight ("BotCheckSight");
static FRandom pr_checksight ("CheckSight"); static FRandom pr_checksight ("CheckSight");
@ -838,6 +839,38 @@ sightcounts[2]++;
===================== =====================
*/ */
ETraceStatus CheckForSightBlockers(FTraceResults& res, void* userdata)
{
SightCheckData* output = (SightCheckData*)userdata;
if (res.HitType == TRACE_HitActor && res.Actor && (res.Actor->flags9 & MF9_BLOCKSIGHT))
{
output->HitSightBlocker = res.Actor;
return TRACE_Stop;
}
if (res.HitType != TRACE_HitActor)
{
return TRACE_Stop;
}
return TRACE_Continue;
}
// [inkoalawetrust] Check if an MF9_BLOCKSIGHT actor is standing between t1 and t2.
AActor* P_CheckForSightBlock(AActor* t1, AActor* t2)
{
FTraceResults result;
SightCheckData SightCheck;
SightCheck.HitSightBlocker = nullptr;
DVector3 dir = t1->Vec3To(t2);
double dist = dir.Length();
DVector3 origin = t1->PosPlusZ(t1->Height * 0.75); //Standard sight checks are done at this height too.
Trace(origin, t1->Sector, dir, dist, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, t1, result, 0, CheckForSightBlockers, &SightCheck);
return SightCheck.HitSightBlocker;
}
int P_CheckSight (AActor *t1, AActor *t2, int flags) int P_CheckSight (AActor *t1, AActor *t2, int flags)
{ {
SightCycles.Clock(); SightCycles.Clock();
@ -904,6 +937,18 @@ sightcounts[0]++;
} }
} }
// [inkoalawetrust] All trivial checks passed, now check for MF9_BLOCKSIGHT
if (t1->flags9 & MF9_DOBLOCKSIGHT)
{
AActor* blocker = P_CheckForSightBlock(t1, t2);
if (blocker != nullptr)
{
res = false;
goto done;
}
}
// An unobstructed LOS is possible. // An unobstructed LOS is possible.
// Now look from eyes of t1 to any part of t2. // Now look from eyes of t1 to any part of t2.

View file

@ -25,9 +25,11 @@ inline FRandom pr_shadowaimz("VerticalShadowAim");
// //
//========================================================================== //==========================================================================
// Generic actor sight check data.
struct SightCheckData struct SightCheckData
{ {
AActor* HitShadow; AActor* HitShadow;
AActor* HitSightBlocker;
}; };
inline ETraceStatus CheckForShadowBlockers(FTraceResults& res, void* userdata) inline ETraceStatus CheckForShadowBlockers(FTraceResults& res, void* userdata)

View file

@ -353,6 +353,8 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9), DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9),
DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9), DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9),
DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9), DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9),
DEFINE_FLAG(MF9, BLOCKSIGHT, AActor, flags9),
DEFINE_FLAG(MF9, DOBLOCKSIGHT, AActor, flags9),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -1453,6 +1453,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckSight, P_CheckSight)
ACTION_RETURN_BOOL(P_CheckSight(self, target, flags)); ACTION_RETURN_BOOL(P_CheckSight(self, target, flags));
} }
DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckForSightBlocker, P_CheckForSightBlock)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT_NOT_NULL(target, AActor);
ACTION_RETURN_OBJECT(P_CheckForSightBlock(self, target));
}
static void GiveSecret(AActor *self, bool printmessage, bool playsound) static void GiveSecret(AActor *self, bool printmessage, bool playsound)
{ {
P_GiveSecret(self->Level, self, printmessage, playsound, -1); P_GiveSecret(self->Level, self, printmessage, playsound, -1);

View file

@ -776,6 +776,7 @@ class Actor : Thinker native
native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class<Actor> pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.); native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class<Actor> pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.);
native bool LineTrace(double angle, double distance, double pitch, int flags = 0, double offsetz = 0., double offsetforward = 0., double offsetside = 0., out FLineTraceData data = null); native bool LineTrace(double angle, double distance, double pitch, int flags = 0, double offsetz = 0., double offsetforward = 0., double offsetside = 0., out FLineTraceData data = null);
native bool CheckSight(Actor target, int flags = 0); native bool CheckSight(Actor target, int flags = 0);
native Actor CheckForSightBlocker (Actor target);
native bool IsVisible(Actor other, bool allaround, LookExParams params = null); native bool IsVisible(Actor other, bool allaround, LookExParams params = null);
native bool, Actor, double PerformShadowChecks (Actor other, Vector3 pos); native bool, Actor, double PerformShadowChecks (Actor other, Vector3 pos);
native bool HitFriend(); native bool HitFriend();