Added MF9_SHADOWBLOCK.

Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. The shooter needs to have MF9_DOSHADOWBLOCK to check for actors with this flag.
This commit is contained in:
inkoalawetrust 2023-01-16 22:49:47 +02:00 committed by Rachael Alexanderson
parent 162dbf0554
commit c729b831af
5 changed files with 77 additions and 16 deletions

View file

@ -439,6 +439,8 @@ enum ActorFlag8
enum ActorFlag9 enum ActorFlag9
{ {
MF9_SHADOWAIM = 0x00000001, // [inkoalawetrust] Monster still gets aim penalty from aiming at shadow actors even with MF6_SEEINVISIBLE on. MF9_SHADOWAIM = 0x00000001, // [inkoalawetrust] Monster still gets aim penalty from aiming at shadow actors even with MF6_SEEINVISIBLE on.
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.
}; };
// --- mobj.renderflags --- // --- mobj.renderflags ---

View file

@ -1227,7 +1227,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun)
self->Angles.Yaw = self->AngleTo(self->target,- self->target->Vel.X * veleffect, -self->target->Vel.Y * veleffect); self->Angles.Yaw = self->AngleTo(self->target,- self->target->Vel.X * veleffect, -self->target->Vel.Y * veleffect);
} }
A_CustomRailgun_ShadowHandling(self); A_CustomRailgun_ShadowHandling(self, spawnofs_xy, spawnofs_z, spread_xy, flags);
} }
if (!(flags & CRF_EXPLICITANGLE)) if (!(flags & CRF_EXPLICITANGLE))

View file

@ -6706,7 +6706,7 @@ AActor *P_SpawnMissileXYZ (DVector3 pos, AActor *source, AActor *dest, PClassAct
} }
th->Vel = velocity.Resized(speed); th->Vel = velocity.Resized(speed);
P_SpawnMissileXYZ_ShadowHandling(source,dest,th); P_SpawnMissileXYZ_ShadowHandling(source,dest,th,pos);
th->AngleFromVel(); th->AngleFromVel();
@ -6828,7 +6828,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActo
an = source->Angles.Yaw; an = source->Angles.Yaw;
an += P_SpawnMissileZAimed_ShadowHandling(source,dest); an += P_SpawnMissileZAimed_ShadowHandling(source,dest,source->PosAtZ(z));
dist = source->Distance2D (dest); dist = source->Distance2D (dest);
speed = GetDefaultSpeed (type); speed = GetDefaultSpeed (type);

View file

@ -24,9 +24,55 @@ extern FRandom pr_crailgun;
// //
//========================================================================== //==========================================================================
inline bool CheckShadowFlags(AActor* self, AActor* other) struct ShadowCheckData
{ {
return (other->flags & MF_SHADOW && (!(self->flags6 & MF6_SEEINVISIBLE) || self->flags9 & MF9_SHADOWAIM)); bool HitShadow;
};
static ETraceStatus CheckForShadowBlockers(FTraceResults& res, void* userdata)
{
ShadowCheckData* output = (ShadowCheckData*)userdata;
if (res.HitType == TRACE_HitActor && res.Actor && (res.Actor->flags9 & MF9_SHADOWBLOCK))
{
output->HitShadow = true;
return TRACE_Stop;
}
if (res.HitType != TRACE_HitActor)
{
return TRACE_Stop;
}
return TRACE_Continue;
}
// [inkoalawetrust] Check if an MF9_SHADOWBLOCK actor is standing between t1 and t2.
inline bool P_CheckForShadowBlock(AActor* t1, AActor* t2, DVector3 pos)
{
FTraceResults result;
ShadowCheckData ShadowCheck;
ShadowCheck.HitShadow = false;
DVector3 dir = t1->Vec3To(t2);
double dist = dir.Length();
Trace(pos, t1->Sector, dir, dist, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, t1, result, 0, CheckForShadowBlockers, &ShadowCheck);
return ShadowCheck.HitShadow;
}
inline bool AffectedByShadows(AActor* self, AActor* other)
{
return (!(self->flags6 & MF6_SEEINVISIBLE) || self->flags9 & MF9_SHADOWAIM);
}
inline bool CheckForShadows(AActor* self, AActor* other, DVector3 pos)
{
return (other->flags & MF_SHADOW || self->flags9 & MF9_DOSHADOWBLOCK && P_CheckForShadowBlock(self, other, pos));
}
inline bool PerformShadowChecks(AActor* self, AActor* other, DVector3 pos)
{
return (AffectedByShadows(self, other) && CheckForShadows(self, other, pos));
} }
//========================================================================== //==========================================================================
@ -35,11 +81,11 @@ inline bool CheckShadowFlags(AActor* self, AActor* other)
// //
//========================================================================== //==========================================================================
inline void P_SpawnMissileXYZ_ShadowHandling(AActor* source, AActor* target, AActor* missile) inline void P_SpawnMissileXYZ_ShadowHandling(AActor* source, AActor* target, AActor* missile, DVector3 pos)
{ {
// invisible target: rotate velocity vector in 2D // invisible target: rotate velocity vector in 2D
// [RC] Now monsters can aim at invisible player as if they were fully visible. // [RC] Now monsters can aim at invisible player as if they were fully visible.
if (CheckShadowFlags(source,target)) if (PerformShadowChecks(source,target,pos))
{ {
DAngle an = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)); DAngle an = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256));
double c = an.Cos(); double c = an.Cos();
@ -55,9 +101,9 @@ inline void P_SpawnMissileXYZ_ShadowHandling(AActor* source, AActor* target, AAc
} }
//P_SpawnMissileZAimed uses a local variable for the angle it passes on. //P_SpawnMissileZAimed uses a local variable for the angle it passes on.
inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target) inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target, DVector3 pos)
{ {
if (CheckShadowFlags(source,target)) if (PerformShadowChecks(source,target,pos))
{ {
return DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)); return DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.));
} }
@ -67,7 +113,7 @@ inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target
inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn, DAngle other_angle) inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn, DAngle other_angle)
{ {
// This will never work well if the turn angle is limited. // This will never work well if the turn angle is limited.
if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && CheckShadowFlags(self, other)) if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && PerformShadowChecks(self, other,self->PosAtZ(self->Center())))
{ {
self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.));
} }
@ -76,16 +122,28 @@ inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn,
inline void A_MonsterRail_ShadowHandling(AActor* self) inline void A_MonsterRail_ShadowHandling(AActor* self)
{ {
if (CheckShadowFlags(self, self->target)) double shootZ = self->Center() - self->FloatSpeed - self->Floorclip; // The formula P_RailAttack uses, minus offset_z since A_MonsterRail doesn't use it.
if (PerformShadowChecks(self, self->target,self->PosAtZ(shootZ)))
{ {
self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45. / 256); self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45. / 256);
} }
return; return;
} }
inline void A_CustomRailgun_ShadowHandling(AActor* self) //Also passes parameters to determine a firing position for the SHADOWBLOCK check.
inline void A_CustomRailgun_ShadowHandling(AActor* self, double spawnofs_xy, double spawnofs_z, DAngle spread_xy, int flags)
{ {
if (CheckShadowFlags(self, self->target)) // [inkoalawetrust] The exact formula P_RailAttack uses to determine where the railgun trace should spawn from.
DVector2 shootXY = (self->Vec2Angle(spawnofs_xy, (self->Angles.Yaw + spread_xy) - DAngle::fromDeg(90.)));
double shootZ = self->Center() - self->FloatSpeed + spawnofs_z - self->Floorclip;
if (flags & 16) shootZ += self->AttackOffset(); //16 is RGF_CENTERZ
DVector3 checkPos;
checkPos.X = shootXY.X;
checkPos.Y = shootXY.Y;
checkPos.Z = shootZ;
if (PerformShadowChecks(self, self->target, checkPos))
{ {
DAngle rnd = DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); DAngle rnd = DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.));
self->Angles.Yaw += rnd; self->Angles.Yaw += rnd;
@ -96,5 +154,5 @@ inline void A_CustomRailgun_ShadowHandling(AActor* self)
//A_WolfAttack directly harms the target instead of firing a hitscan or projectile. So it handles shadows by lowering the chance of harming the target. //A_WolfAttack directly harms the target instead of firing a hitscan or projectile. So it handles shadows by lowering the chance of harming the target.
inline bool A_WolfAttack_ShadowHandling(AActor* self) inline bool A_WolfAttack_ShadowHandling(AActor* self)
{ {
return (CheckShadowFlags(self, self->target)); return (PerformShadowChecks(self, self->target, self->PosAtZ(self->Center())));
} }

View file

@ -348,6 +348,8 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF8, ONLYSLAMSOLID, AActor, flags8), DEFINE_FLAG(MF8, ONLYSLAMSOLID, AActor, flags8),
DEFINE_FLAG(MF9, SHADOWAIM, AActor, flags9), DEFINE_FLAG(MF9, SHADOWAIM, AActor, flags9),
DEFINE_FLAG(MF9, DOSHADOWBLOCK, AActor, flags9),
DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -357,8 +359,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags), DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags),
DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags), DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags),
DEFINE_FLAG(RF, ROLLSPRITE, AActor, renderflags), // [marrub] roll the sprite billboard DEFINE_FLAG(RF, ROLLSPRITE, AActor, renderflags), // [marrub] roll the sprite billboard
// [fgsfds] Flat sprites DEFINE_FLAG(RF, FLATSPRITE, AActor, renderflags), // [fgsfds] Flat sprites
DEFINE_FLAG(RF, FLATSPRITE, AActor, renderflags),
DEFINE_FLAG(RF, WALLSPRITE, AActor, renderflags), DEFINE_FLAG(RF, WALLSPRITE, AActor, renderflags),
DEFINE_FLAG(RF, DONTFLIP, AActor, renderflags), DEFINE_FLAG(RF, DONTFLIP, AActor, renderflags),
DEFINE_FLAG(RF, ROLLCENTER, AActor, renderflags), DEFINE_FLAG(RF, ROLLCENTER, AActor, renderflags),