Files
Bubberstation/code/datums/components/clothing_fov_visor.dm
Azarak 680ca7d3b9 Field of View and Blindness improvements [bounty + upstream push] (#63312)
About The Pull Request

I have received exemption from the freeze by Oranges.
This PR was originally done for Skyrat-tg, as a bounty. Oranges took interest and Skyrat people approved taking it upstream so I did. (original PR Skyrat-SS13/Skyrat-tg#9912 )
Features:
This PR adds "field of view" mechanics, which by default don't do anything.
Once you pick up and wear a gas mask you'll notice a cone behind you.
That cone will hide all mobs, projectiles and projectile effects.
HOWEVER... hidden things in the cone (or for people who are blind or nearsighted) will play a visual effect.

The fov cone shadow density can be adjusted

Technicalities:
Originally a component, but by Watermelon's advice I have made this a datumized behaviour instead. (semi-component) This way it is faster, less memory use etc. Once again a component
People have native fov, which can be enabled by a config, by default it's off. (or by an admin verb)
People have fov traits, which add the fov impairings to you, gas masks do that now. All clothes have a support for possibly applying them.
Moves all things that should be hidden onto a new plane which is just above GAME_PLANE, that was we can efficiently filter them out of clients views.
Being dead or extending your eye view (xenobio console) will disable the FOV mask.

This PR was brought to you by Skyrat paying me aswell as rotational mathematics


Why It's Good For The Game

Oranges approves so it's good.
Changelog

cl
add: Gas Masks now limit your field of view
add: Added field of view mechanics. It's darkness can be tweaked by a pref
add: Blind, nearsighted and fov-limited people will now see sounds as visual effects.
/cl
2021-12-14 15:52:52 +13:00

61 lines
2.3 KiB
Plaintext

/// An element to add a FOV trait to the wearer, removing it when an item is unequipped, but only as long as the visor is up.
/datum/component/clothing_fov_visor
/// What's the FOV angle of the trait we're applying to the wearer
var/fov_angle
/// Keeping track of the visor of our clothing.
var/visor_up = FALSE
/// Because of clothing code not being too good, we need keep track whether we are worn.
var/is_worn = FALSE
/datum/component/clothing_fov_visor/Initialize(fov_angle)
. = ..()
if(!isclothing(parent))
return COMPONENT_INCOMPATIBLE
var/obj/item/clothing/clothing_parent = parent
src.fov_angle = fov_angle
src.visor_up = clothing_parent.up //Initial values could vary, so we need to get it.
/datum/component/clothing_fov_visor/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
RegisterSignal(parent, COMSIG_CLOTHING_VISOR_TOGGLE, .proc/on_visor_toggle)
/datum/component/clothing_fov_visor/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_CLOTHING_VISOR_TOGGLE))
return ..()
/// On dropping the item, remove the FoV trait if visor was down.
/datum/component/clothing_fov_visor/proc/on_drop(datum/source, mob/living/dropper)
SIGNAL_HANDLER
is_worn = FALSE
if(visor_up)
return
dropper.remove_fov_trait(source.type, fov_angle)
dropper.update_fov()
/// On equipping the item, add the FoV trait if visor isn't up.
/datum/component/clothing_fov_visor/proc/on_equip(obj/item/source, mob/living/equipper, slot)
SIGNAL_HANDLER
if(!(source.slot_flags & slot)) //If EQUIPPED TO HANDS FOR EXAMPLE
return
is_worn = TRUE
if(visor_up)
return
equipper.add_fov_trait(source.type, fov_angle)
equipper.update_fov()
/// On toggling the visor, we may want to add or remove FOV trait from the wearer.
/datum/component/clothing_fov_visor/proc/on_visor_toggle(datum/source, visor_state)
SIGNAL_HANDLER
visor_up = visor_state
if(!is_worn)
return
var/obj/item/clothing/clothing_parent = parent
var/mob/living/wearer = clothing_parent.loc //This has to be the case due to equip/dropped keeping track.
if(visor_up)
wearer.remove_fov_trait(source.type, fov_angle)
wearer.update_fov()
else
wearer.add_fov_trait(source.type, fov_angle)
wearer.update_fov()