mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-20 09:16:55 +01:00
datumizes and standardizes all emotes because that file is in the fucking way of my saycode rewrite adds vocal cues
256 lines
7.4 KiB
Plaintext
256 lines
7.4 KiB
Plaintext
/**
|
|
* Sets us to a /datum/perspective
|
|
* If none is specified, defaults to self_perspective.
|
|
*
|
|
* See [code/datums/perspective.dm] for more info.
|
|
*
|
|
* @params
|
|
* - P - perspective or atom - if atom, get_perspective() will be called on
|
|
* - apply - whether to apply to client. this shold be false when resetting
|
|
* due to a logout because the whole point is logout kills perspective!
|
|
* - forceful - if the client is desynced from our using perspective, do we force it back?
|
|
* - no_optimizations - if true, it'll be a true reset. use for things like cancel camera view which should always force updates.
|
|
*/
|
|
/mob/proc/reset_perspective(datum/perspective/P, apply = TRUE, forceful = TRUE, no_optimizations)
|
|
if(P)
|
|
ASSERT(istype(P) || ismovable(P))
|
|
if(!no_optimizations && ( \
|
|
P? (ismovable(P)? (istype(using_perspective, /datum/perspective/self/temporary) && (using_perspective.eye == P)) : (using_perspective == P)) \
|
|
: \
|
|
(using_perspective && (using_perspective == self_perspective)) \
|
|
))
|
|
// if we don't need to reset, assume it's an update.
|
|
// this is bad practice but stuff like mechs need this to work, since
|
|
// they reset for brainmobs but only need to update for others.
|
|
update_perspective(TRUE)
|
|
return
|
|
if(ismovable(P))
|
|
var/atom/movable/AM = P
|
|
P = AM.get_perspective()
|
|
/// first of all if we are already on the right perspective we really don't care!
|
|
if(!client) // this is way easier if no client, and microoptimization
|
|
if(using_perspective)
|
|
using_perspective.remove_mob(src, TRUE)
|
|
if(using_perspective)
|
|
stack_trace("using perspective didn't clear us")
|
|
using_perspective = null
|
|
P = P || get_perspective()
|
|
P.add_mob(src)
|
|
return
|
|
var/old = using_perspective
|
|
// get old perspective first
|
|
if(using_perspective)
|
|
using_perspective.remove_mob(src, TRUE)
|
|
if(using_perspective)
|
|
stack_trace("using perspective didn't clear us")
|
|
using_perspective = null
|
|
// if no P, return us
|
|
if(!P)
|
|
P = get_perspective()
|
|
else
|
|
if(P.reset_on_logout && !client)
|
|
// if there's a P but client is gone, and it resets, use us again
|
|
P = get_perspective()
|
|
// great, P exists
|
|
// tell it to add us
|
|
P.add_mob(src)
|
|
// signal
|
|
SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE, P)
|
|
// if client exists and we want to apply
|
|
if(apply && client)
|
|
if(!forceful)
|
|
// if not forceful, only shunt if we're not desynced
|
|
if(client.using_perspective == old)
|
|
client.set_perspective(P)
|
|
else
|
|
client.set_perspective(P)
|
|
|
|
/**
|
|
* verb that allows someone to instantly shunt their perspective back to the default
|
|
*/
|
|
/mob/verb/cancel_camera()
|
|
set name = "Cancel Camera View"
|
|
set category = VERB_CATEGORY_OOC
|
|
|
|
reset_perspective(no_optimizations = TRUE, apply = TRUE, forceful = TRUE)
|
|
|
|
/**
|
|
* gets the perspective we're using
|
|
*/
|
|
/mob/proc/get_using_perspective()
|
|
RETURN_TYPE(/datum/perspective)
|
|
return using_perspective || get_perspective()
|
|
|
|
/mob/get_perspective()
|
|
// mobs never lazygen their perspectives
|
|
ensure_self_perspective()
|
|
return ..()
|
|
|
|
/**
|
|
* updates our curent perspective
|
|
*/
|
|
/mob/proc/update_perspective(shunted)
|
|
if(!client)
|
|
return
|
|
if(using_perspective != client.using_perspective) // shunt them back in, useful if something's temporarily shunted our client away
|
|
if(!client.using_perspective)
|
|
reset_perspective(using_perspective)
|
|
CRASH("client had no using perspective, how? in mob/update_perspective")
|
|
if(shunted)
|
|
CRASH("Caught an infinite loop. What's going on here?")
|
|
reset_perspective(using_perspective)
|
|
return
|
|
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_PERSPECTIVE)
|
|
if(isnull(using_perspective))
|
|
return
|
|
using_perspective.update(client)
|
|
|
|
/**
|
|
* we're considered to be viewing from some/something else's perspective
|
|
*/
|
|
/mob/proc/IsRemoteViewing()
|
|
return get_using_perspective()?.considered_remote(src)
|
|
|
|
/**
|
|
* for mob make_perspective, set our current_values
|
|
*/
|
|
/mob/make_perspective()
|
|
. = ..()
|
|
self_perspective.see_invisible = see_invisible
|
|
self_perspective.sight = sight
|
|
update_vision()
|
|
|
|
//? Perspective - Shunting / Remote Viewing
|
|
|
|
/**
|
|
* wrapper for things like holocalls and overmaps that shunt our view
|
|
* returns TRUE or FALSE based on if we moved their perspective
|
|
* will refuse to if the mob was already shunted
|
|
* *USE THE RETURN VALUE*
|
|
*
|
|
* @params
|
|
* - perspective - this must be a /datum/perspective or an /atom.
|
|
*/
|
|
/mob/proc/shunt_perspective(datum/perspective/perspective)
|
|
if(perspective_shunted())
|
|
return FALSE
|
|
if(ismovable(perspective))
|
|
var/atom/movable/AM = perspective
|
|
perspective = AM.temporary_perspective()
|
|
reset_perspective(perspective)
|
|
return TRUE
|
|
|
|
/**
|
|
* wrapper for when we want to un-shunt our perspective
|
|
* from a shunt_perspective call.
|
|
*/
|
|
/mob/proc/unshunt_perspective()
|
|
if(!perspective_shunted())
|
|
return FALSE
|
|
reset_perspective()
|
|
return TRUE
|
|
|
|
/**
|
|
* returns if our perspective is shunted elsewhere
|
|
*/
|
|
/mob/proc/perspective_shunted()
|
|
return self_perspective != using_perspective
|
|
|
|
//? Perspective - Self
|
|
|
|
// * ALL OF THESE SHOULD BE REGEXED LATER *
|
|
// However, there is currently no way to deal with the getters due to them requiring self_perspective be set, but
|
|
// we don't necessarily want all mobs to have it, as perspectives are generally for client'd mobs
|
|
// We'll decide later, the setters/getters work for now.
|
|
|
|
/**
|
|
* wrapper for self_perspective.AddSight for regexing later
|
|
*/
|
|
/mob/proc/AddSightSelf(flags)
|
|
ensure_self_perspective()
|
|
self_perspective.AddSight(flags)
|
|
|
|
/**
|
|
* ditto
|
|
*/
|
|
/mob/proc/RemoveSightSelf(flags)
|
|
ensure_self_perspective()
|
|
self_perspective.RemoveSight(flags)
|
|
|
|
/**
|
|
* ditto
|
|
*/
|
|
/mob/proc/SetSightSelf(flags)
|
|
ensure_self_perspective()
|
|
self_perspective.SetSight(flags)
|
|
|
|
/**
|
|
* ditto
|
|
*/
|
|
/mob/proc/SetSeeInvisibleSelf(see_invisible)
|
|
ensure_self_perspective()
|
|
self_perspective.SetSeeInvis(see_invisible)
|
|
|
|
//? Darksight
|
|
|
|
/**
|
|
* get our innate darksight
|
|
*/
|
|
/mob/proc/innate_vision()
|
|
RETURN_TYPE(/datum/vision/baseline)
|
|
return vision_override || GLOB.default_darksight
|
|
|
|
/**
|
|
* get all darksight datums, ordered. 1 (front of list) is applied first.
|
|
*/
|
|
/mob/proc/query_vision()
|
|
RETURN_TYPE(/list)
|
|
var/list/built = vision_modifiers?.Copy() || list()
|
|
built.Insert(1, innate_vision())
|
|
return built
|
|
|
|
/**
|
|
* updates our vision data and pushes it to perspective
|
|
*/
|
|
/mob/proc/update_vision()
|
|
ensure_self_perspective()
|
|
self_perspective.push_vision_stack(query_vision())
|
|
|
|
/mob/proc/sort_vision_modifiers()
|
|
if(isnull(vision_modifiers))
|
|
return
|
|
tim_sort(vision_modifiers)
|
|
|
|
/mob/proc/add_vision_modifier(datum/vision/modifier)
|
|
ASSERT(!isnull(modifier))
|
|
if(ispath(modifier))
|
|
modifier = cached_vision_holder(modifier)
|
|
ASSERT(!(modifier in vision_modifiers))
|
|
LAZYINITLIST(vision_modifiers)
|
|
BINARY_INSERT(modifier, vision_modifiers, /datum/vision, modifier, priority, COMPARE_KEY)
|
|
update_vision()
|
|
|
|
/mob/proc/remove_vision_modifier(datum/vision/modifier)
|
|
ASSERT(!isnull(modifier))
|
|
if(ispath(modifier))
|
|
modifier = cached_vision_holder(modifier)
|
|
LAZYREMOVE(vision_modifiers, modifier)
|
|
update_vision()
|
|
|
|
/**
|
|
* returns if we have this exact modifier
|
|
* usually you use this with paths / cached ones.
|
|
*/
|
|
/mob/proc/has_vision_modifier(datum/vision/modifier)
|
|
if(ispath(modifier))
|
|
modifier = cached_vision_holder(modifier)
|
|
return modifier in vision_modifiers
|
|
|
|
//? Helpers
|
|
|
|
/**
|
|
* TODO: this doesn't work on client global planes like admin plane.
|
|
*/
|
|
/mob/proc/can_see_plane(val)
|
|
return val <= BYOND_PLANE || val >= HUD_PLANE || self_perspective?.is_plane_visible(val)
|