mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-01-04 06:31:47 +00:00
* Refactor/deduplicate camera eye code Camera Eyes previously had duplicated logic across several files. This change uncooks the spaghetti. Additionally, half-baked support for TG's multicam feature has been removed, as it was not functional or in use. * lets ff now * Camera Eye refactor fixes and finishing touches This change completes a refactor of AI eyes, which were previously used by xenobio consoles, syndicate and abductor camera consoles, shuttle docking computers, holograms, and, of course, the AI. Duplicated logic has been extracted to an abstract base mob, /mob/camera/eye, from which new types for each of the above now derive. Functionality is largely the same, with only a few minor cosmetic differences (i.e. camera eyes are now appropriately named given their type and user), as well as a quality-of-life enhancement for holograms, slowing their movement speed to base run speed to prevent users from accidentally zooming out of calls. * Camera eye refactor: Fix AI acceleration toggle The acceleration toggle was broken in the camera eye refactor, as previously the boolean was stored on the AI rather than its eye. This change fixes that. * Camera eye refactor: Fix syndicate cam visibility With the camera eye refactor, the syndicate advanced camera consoles lost the ability to view maintenance tunnels and other areas without active cameras, seeing static in their place instead (as all other cameras do). This change reinstates the original behavior. * Camera eye refactor: Convert spaces to tabs * Camera eye refactor: Fix CRLF * Apply suggestions from code review General minor code quality improvements suggested by GDNgit Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * Apply suggestions from code review Rename parameter names to avoid src accesses, remove an ambiguous and unused mob_define and holopad range variable from a previous WIP, change the for loop in /mob/camera/eye/relaymove to a for-to loop, and change the chat message warning, sent when an AI Eye is created on an AI that already has one, to a stack trace * Adds toggle to AI commands for fast holograms * Refactor ripped Hologram Eye relaymove Previously, the relaymove proc for hologram eyes was redundant and nearly impossible to read. It has been separated out into a few different named procs, and has had its use of `spawn` removed. * Remove unnecessary src access * Fix bug involving shuttle placement outlines The camera eye refactor that this commit is a part of introduced a bug that prevented shuttle placement outlines from showing up on first use of the shuttle console. This change fixes that bug. * Unrevert some changes from #26306 lost in merge * Remove erroneous free xray vision on advanced cams * Autodoc camera acceleration vars * Remove redundant null var initialization per code review Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com> Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com> * Changed variables to camel_case, autodocs, cleanup Changed a number of camera eye-related variables to camel_case style, added appropriate autodoc comments, as per code review. Also removed an unused cameranet function, modified the call signature of a cameranet function to be more semantic, and changed a qdel-on-initialize in camera eyes to return INITIALIZE_HINT_QDEL instead. Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * Remove stray qdel(src) per code review Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com> --------- Signed-off-by: asciodev <81930475+asciodev@users.noreply.github.com> Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
192 lines
7.3 KiB
Plaintext
192 lines
7.3 KiB
Plaintext
/// Camera eyes are remote-control mobs that can move and see throughout the global cameranet.
|
|
/// They're used in AI eyes, holograms, advanced camera consoles, abductor consoles, shuttle consoles,
|
|
/// and xenobiology consoles. When created, the user with which they are initialized will be granted control,
|
|
/// and their movements will be relayed to the camera eye instead. When destroyed, the user's control of the
|
|
/// camera eye will be released; if they were previously remote controlling another object (such as another
|
|
/// camera eye) then they will be put back in control of that object; otherwise they will return to their body.
|
|
/mob/camera/eye
|
|
name = "Inactive Camera Eye"
|
|
icon = 'icons/obj/abductor.dmi'
|
|
icon_state = "camera_target"
|
|
alpha = 127
|
|
invisibility = SEE_INVISIBLE_OBSERVER
|
|
|
|
/// The list of camera chunks currently visible to the camera eye.
|
|
var/list/visible_camera_chunks = list()
|
|
/// The user controlling the eye.
|
|
var/mob/living/user
|
|
/// The thing that the user was previously remote controlling before this eye.
|
|
var/user_previous_remote_control
|
|
/// The object that created the eye.
|
|
var/origin
|
|
/// If true, speech near the camera eye will be relayed to its controller.
|
|
var/relay_speech = FALSE
|
|
/// Sets the camera eye visibility range; does not expand viewport, only affects cameranet obscuring
|
|
var/static_visibility_range = 16
|
|
/// Toggles whether this eye is detectable by AI Detectors.
|
|
var/ai_detector_visible = TRUE
|
|
/// Toggles whether the eye's icon should be visible to its user.
|
|
var/visible_icon = FALSE
|
|
/// The list of cameranets that this camera eye can see and access.
|
|
var/list/networks = list("SS13")
|
|
/// The in-memory image of the camera eye's icon.
|
|
var/image/user_image
|
|
|
|
// Camera acceleration settings
|
|
// Initially, the camera moves one turf per move. If there is no movement for
|
|
// cooldown_rate in deciseconds, the camera will reset to this movement rate.
|
|
// Every move otherwise increases sprint by acceleration_rate, until sprint
|
|
// exceeds sprint_threshold, and the movement rate increases by one per move.
|
|
// The movement rate is 1 + round(sprint / sprint_threshold).
|
|
|
|
/// The maximum sprint value - this caps acceleration
|
|
var/max_sprint = 50
|
|
/// The minimum sprint needed to increase base velocity
|
|
var/sprint_threshold = 20
|
|
/// The amount that sprint is increased per move
|
|
var/acceleration_rate = 0.5
|
|
/// Keeps track of acceleration - movement rate is 1 + round(sprint / sprint_threshold)
|
|
var/sprint = 10
|
|
/// The absolute time that sprint will reset to its initial value
|
|
var/cooldown = 0
|
|
/// The time after which sprint should be reset to its initial state, if no movements are made
|
|
var/cooldown_rate = 5
|
|
/// Toggles camera acceleration on or off.
|
|
var/acceleration = 1
|
|
|
|
/mob/camera/eye/Initialize(mapload, owner_name, camera_origin, mob/living/user)
|
|
. = ..()
|
|
name = "Camera Eye ([owner_name])"
|
|
origin = camera_origin
|
|
give_control(user)
|
|
update_visibility()
|
|
refresh_visible_icon()
|
|
if(!validate_active_cameranet())
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/// Validates that there is an active cameranet. If strict is 0, does nothing.
|
|
/// Returns 1 if there is an active cameranet. Warns the user and returns 0 if there is not.
|
|
/mob/camera/eye/proc/validate_active_cameranet(strict = 0)
|
|
var/camera = first_active_camera()
|
|
if(strict && !camera)
|
|
to_chat(user, "<span class='warning'>ERROR: No linked and active camera network found.</span>")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/// Returns the turf of the first active camera in the global cameranet.
|
|
/mob/camera/eye/proc/first_active_camera()
|
|
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
|
if(!C.can_use())
|
|
continue
|
|
if(length(C.network & networks))
|
|
return get_turf(C)
|
|
|
|
/// Updates what the global cameranet can see with respect to this eye and its user's client.
|
|
/mob/camera/eye/proc/update_visibility()
|
|
GLOB.cameranet.visibility(src, user.client)
|
|
|
|
/// Refreshes user_image in the user's client.images.
|
|
/mob/camera/eye/proc/refresh_visible_icon()
|
|
if(visible_icon && user.client)
|
|
user.client.images -= user_image
|
|
user_image = image(icon,loc,icon_state,FLY_LAYER)
|
|
user.client.images += user_image
|
|
|
|
/// Sets the camera eye's location to T, updates global cameranet visibility, and refreshes user_images.
|
|
/mob/camera/eye/set_loc(T)
|
|
if(user)
|
|
T = get_turf(T)
|
|
..(T)
|
|
update_visibility()
|
|
refresh_visible_icon()
|
|
|
|
/// Disables independent movement by camera eyes; camera eyes must be controlled by relaymove.
|
|
/mob/camera/eye/Move()
|
|
return FALSE
|
|
|
|
/// If `usr` is an AI, set the camera eye's location to the location of the atom clicked.
|
|
/atom/proc/move_camera_by_click()
|
|
if(is_ai(usr))
|
|
var/mob/living/silicon/ai/AI = usr
|
|
if(AI.eyeobj && (AI.client.eye == AI.eyeobj) && (AI.eyeobj.z == z))
|
|
AI.camera_follow = null
|
|
if(isturf(loc) || isturf(src))
|
|
AI.eyeobj.set_loc(src)
|
|
|
|
/// Returns the user's client, if it exists; otherwise returns null.
|
|
/mob/camera/eye/proc/get_viewer_client()
|
|
return user?.client
|
|
|
|
/// Removes obscured chunk images and user_images from the user's client.images.
|
|
/mob/camera/eye/proc/remove_images()
|
|
var/client/C = get_viewer_client()
|
|
if(!C)
|
|
return
|
|
for(var/datum/camerachunk/chunk as anything in visible_camera_chunks)
|
|
C.images -= chunk.obscured
|
|
if(visible_icon)
|
|
C.images -= user_image
|
|
|
|
/// Calls `remove_images`, changes the user's remote control from this camera eye to `user_previous_remote_control`.
|
|
/mob/camera/eye/proc/release_control()
|
|
if(!istype(user))
|
|
return
|
|
if(user.client)
|
|
user.reset_perspective(user.client.mob)
|
|
remove_images()
|
|
user.remote_control = null
|
|
if(user_previous_remote_control)
|
|
user.reset_perspective(user_previous_remote_control)
|
|
user.remote_control = user_previous_remote_control
|
|
user_previous_remote_control = null
|
|
user = null
|
|
|
|
/// Forces this eye's current user to release control, renames this eye, and grants `new_user` control of this eye.
|
|
/mob/camera/eye/proc/give_control(mob/new_user)
|
|
if(!istype(new_user))
|
|
return
|
|
release_control()
|
|
user = new_user
|
|
rename_camera(user.name)
|
|
if(istype(user.remote_control))
|
|
user_previous_remote_control = user.remote_control
|
|
user.remote_control = src
|
|
user.reset_perspective(src)
|
|
|
|
/// Renames the camera eye (only visible in observer Orbit menu)
|
|
/mob/camera/eye/proc/rename_camera(new_name)
|
|
name = "Camera Eye ([new_name])"
|
|
|
|
/// Remove this eye from all chunks containing it.
|
|
/mob/camera/eye/proc/release_chunks()
|
|
for(var/datum/camerachunk/chunk as anything in visible_camera_chunks)
|
|
chunk.remove(src)
|
|
|
|
/mob/camera/eye/Destroy()
|
|
release_control()
|
|
release_chunks()
|
|
return ..()
|
|
|
|
/// Called when the user controlling this eye attempts to move; uses camera acceleration settings.
|
|
/mob/camera/eye/relaymove(mob/user,direct)
|
|
var/initial = initial(sprint)
|
|
|
|
if(cooldown && cooldown < world.timeofday)
|
|
sprint = initial
|
|
|
|
for(var/i in 0 to sprint step sprint_threshold)
|
|
var/turf/next_step= get_turf(get_step(src, direct))
|
|
if(next_step)
|
|
set_loc(next_step)
|
|
|
|
cooldown = world.timeofday + cooldown_rate
|
|
if(acceleration)
|
|
sprint = min(sprint + acceleration_rate, max_sprint)
|
|
else
|
|
sprint = initial
|
|
|
|
/// If `relay_speech` is truthy, allows the camera eye's user to hear speech spoken at the eye's location.
|
|
/mob/camera/eye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
|
|
if(relay_speech)
|
|
user.hear_say(message_pieces, verb, italics, speaker, speech_sound, sound_vol, sound_frequency)
|