Files
siliconsandGitHub 21883078ce /datum/emote - emote refactor, adds vocal cues (#6725)
datumizes and standardizes all emotes because that file is in the
fucking way of my saycode rewrite
adds vocal cues
2025-11-14 23:54:43 +01:00

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)