MASTERNOSEE flag (#1601)

Makes it so that if an actor's master is invisible due to camera/mirror/portal shenanigans, then the actor will also be invisible. Name based off of an Unreal Engine flag that does the exact same thing.

Co-authored-by: Christoph Oelckers <coelckers@users.noreply.github.com>
This commit is contained in:
Sally Cochenour 2022-05-31 06:34:15 -04:00 committed by GitHub
parent 2c69afa118
commit bb42e541e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 12 deletions

View file

@ -426,6 +426,7 @@ enum ActorFlag8
MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalawetrust] Friendly monster will not follow players.
MF8_SEEFRIENDLYMONSTERS = 0X08000000, // [inkoalawetrust] Hostile monster can see friendly monsters.
MF8_CROSSLINECHECK = 0x10000000, // [MC]Enables CanCrossLine virtual
MF8_MASTERNOSEE = 0x20000000, // Don't show object in first person if their master is the current camera.
};
// --- mobj.renderflags ---

View file

@ -728,17 +728,25 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
DVector3 thingpos = thing->InterpolatedPosition(vp.TicFrac);
if (thruportal == 1) thingpos += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
// Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here
if (thing == camera && !vp.showviewer)
AActor *viewmaster = thing;
if ((thing->flags8 & MF8_MASTERNOSEE) && thing->master != nullptr)
{
DVector3 thingorigin = thing->Pos();
if (thruportal == 1) thingorigin += di->Level->Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
if (fabs(thingorigin.X - vp.ActorPos.X) < 2 && fabs(thingorigin.Y - vp.ActorPos.Y) < 2) return;
viewmaster = thing->master;
}
// Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here
if (viewmaster == camera && !vp.showviewer)
{
DVector3 vieworigin = viewmaster->Pos();
if (thruportal == 1) vieworigin += di->Level->Displacements.getOffset(viewmaster->Sector->PortalGroup, sector->PortalGroup);
if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2) return;
}
// Thing is invisible if close to the camera.
if (thing->renderflags & RF_MAYBEINVISIBLE)
if (viewmaster->renderflags & RF_MAYBEINVISIBLE)
{
if (fabs(thingpos.X - vp.Pos.X) < 32 && fabs(thingpos.Y - vp.Pos.Y) < 32) return;
DVector3 viewpos = viewmaster->InterpolatedPosition(vp.TicFrac);
if (thruportal == 1) viewpos += di->Level->Displacements.getOffset(viewmaster->Sector->PortalGroup, sector->PortalGroup);
if (fabs(viewpos.X - vp.Pos.X) < 32 && fabs(viewpos.Y - vp.Pos.Y) < 32) return;
}
// Too close to the camera. This doesn't look good if it is a sprite.
@ -1370,11 +1378,33 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
DVector3 newpos = savedpos;
sector_t fakesector;
if (!vp.showviewer && th == vp.camera)
if (!vp.showviewer)
{
if (fabs(savedpos.X - vp.ActorPos.X) < 2 && fabs(savedpos.Y - vp.ActorPos.Y) < 2)
AActor *viewmaster = th;
if ((th->flags8 & MF8_MASTERNOSEE) && th->master != nullptr)
{
continue;
viewmaster = th->master;
}
if (viewmaster == vp.camera)
{
DVector3 vieworigin = viewmaster->Pos();
if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2)
{
// Same as the original position
continue;
}
P_TranslatePortalXY(line, vieworigin.X, vieworigin.Y);
P_TranslatePortalZ(line, vieworigin.Z);
if (fabs(vieworigin.X - vp.ActorPos.X) < 2 && fabs(vieworigin.Y - vp.ActorPos.Y) < 2)
{
// Same as the translated position
// (This is required for MASTERNOSEE actors with 3D models)
continue;
}
}
}

View file

@ -997,6 +997,7 @@ namespace swrenderer
// Don't waste time projecting sprites that are definitely not visible.
if (thing == nullptr ||
(thing->renderflags & RF_INVISIBLE) ||
(thing->renderflags & RF_MAYBEINVISIBLE) ||
!thing->RenderStyle.IsVisible(thing->Alpha) ||
!thing->IsVisibleToPlayer() ||
!thing->IsInsideVisibleAngles())
@ -1004,6 +1005,16 @@ namespace swrenderer
return false;
}
if ((thing->flags8 & MF8_MASTERNOSEE) && thing->master != nullptr)
{
// Make MASTERNOSEE actors invisible if their master
// is invisible due to viewpoint shenanigans.
if (thing->master->renderflags & RF_MAYBEINVISIBLE)
{
return false;
}
}
// check renderrequired vs ~r_rendercaps, if anything matches we don't support that feature,
// check renderhidden vs r_rendercaps, if anything matches we do support that feature and should hide it.
if ((!r_debug_disable_vis_filter && !!(thing->RenderRequired & ~r_renderercaps)) ||

View file

@ -389,7 +389,7 @@ namespace swrenderer
if (dist1 + dist2 < distp + 1)
{
viewpoint.camera->renderflags |= RF_INVISIBLE;
viewpoint.camera->renderflags |= RF_MAYBEINVISIBLE;
}
}
}

View file

@ -171,7 +171,7 @@ namespace swrenderer
// Never draw the player unless in chasecam mode
if (!MainThread()->Viewport->viewpoint.showviewer)
{
MainThread()->Viewport->viewpoint.camera->renderflags |= RF_INVISIBLE;
MainThread()->Viewport->viewpoint.camera->renderflags |= RF_MAYBEINVISIBLE;
}
RenderThreadSlices();

View file

@ -341,6 +341,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF8, DONTFOLLOWPLAYERS, AActor, flags8),
DEFINE_FLAG(MF8, SEEFRIENDLYMONSTERS, AActor, flags8),
DEFINE_FLAG(MF8, CROSSLINECHECK, AActor, flags8),
DEFINE_FLAG(MF8, MASTERNOSEE, AActor, flags8),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),