mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
Camera eyes have been lightly refactored (among other things...) (#87805)
## About The Pull Request * A generic /mob/eye/camera type has been made, containing everything needed to interface with a cameranet * /mob/eye/ai_eye has been refactored into a generic /mob/eye/camera instance * Advanced cameras no longer inherit from AI eyes, splitting off behaviour * Camera code has been somewhat cleaned up * Probably some more stuff I'm forgetting right now ## Big man Southport:  ## Changelog 🆑 code: made /proc/getviewsize() pure refactor: mob/eye/ai_eye has been restructured, now inheriting from a generic mob/eye/camera type refactor: advanced cameras and their subtypes are now mob/eye/camera/remote subtypes code: the cameranet no longer expects the user to be an AI eye code: remote camera eyes have had their initialization streamlined code: remote cameras handle assigning and unassigning users by themselves now code: remote cameras now use weakrefs instead of hard referencing owners and origins code: also the sentient disease is_define was removed (we don't have those anymore) fix: AI eyes no longer assign real names to themselves, fixing their orbit name /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -28,8 +28,8 @@ If an issue reports a runtime, it must have the actual runtime call stack provid
|
||||
- usr.loc: the floor (150,25,4) (/turf/open/floor/circuit)
|
||||
- call stack:
|
||||
- Camera Net (/datum/cameranet): visibility(/list (/list), null, /list (/list), 1)
|
||||
- AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/eye/ai_eye))
|
||||
- Inactive AI Eye (/mob/eye/ai_eye): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0)
|
||||
- AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/eye/camera/ai))
|
||||
- Inactive AI Eye (/mob/eye/camera/ai): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0)
|
||||
- AI (/mob/living/silicon/ai): create eye()
|
||||
- AI (/mob/living/silicon/ai): Initialize(0, null, TagGamerGame2 (/mob/dead/new_player))
|
||||
- Atoms (/datum/controller/subsystem/atoms): InitAtom(AI (/mob/living/silicon/ai), 0, /list (/list))
|
||||
|
||||
@@ -202,21 +202,23 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list(
|
||||
|
||||
#define isspider(A) (istype(A, /mob/living/basic/spider))
|
||||
|
||||
|
||||
//Misc mobs
|
||||
#define isobserver(A) (istype(A, /mob/dead/observer))
|
||||
|
||||
#define isdead(A) (istype(A, /mob/dead))
|
||||
|
||||
#define isnewplayer(A) (istype(A, /mob/dead/new_player))
|
||||
//Eye mobs
|
||||
#define iseyemob(A) (istype(A, /mob/eye))
|
||||
|
||||
#define isovermind(A) (istype(A, /mob/eye/blob))
|
||||
|
||||
#define issentientdisease(A) (istype(A, /mob/eye/disease))
|
||||
#define iscameramob(A) (istype(A, /mob/eye/camera))
|
||||
|
||||
#define iseyemob(A) (istype(A, /mob/eye))
|
||||
#define isaicamera(A) (istype(A, /mob/eye/camera/ai))
|
||||
|
||||
#define isaicamera(A) (istype(A, /mob/eye/ai_eye))
|
||||
#define isremotecamera(A) (istype(A, /mob/eye/camera/remote))
|
||||
|
||||
//Dead mobs
|
||||
#define isdead(A) (istype(A, /mob/dead))
|
||||
|
||||
#define isobserver(A) (istype(A, /mob/dead/observer))
|
||||
|
||||
#define isnewplayer(A) (istype(A, /mob/dead/new_player))
|
||||
|
||||
//Objects
|
||||
#define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/proc/getviewsize(view)
|
||||
if(!view) // Just to avoid any runtimes that could otherwise cause constant disconnect loops.
|
||||
stack_trace("Missing value for 'view' in getviewsize(), defaulting to world.view!")
|
||||
view = world.view
|
||||
/proc/getviewsize(view = world.view)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
|
||||
if(isnum(view))
|
||||
var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view
|
||||
|
||||
@@ -59,7 +59,7 @@ GLOBAL_LIST_EMPTY(available_ai_shells)
|
||||
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define
|
||||
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
|
||||
GLOBAL_LIST_EMPTY(bots_list)
|
||||
GLOBAL_LIST_EMPTY(aiEyes)
|
||||
GLOBAL_LIST_EMPTY(camera_eyes)
|
||||
GLOBAL_LIST_EMPTY(suit_sensors_list) //all people with suit sensors on
|
||||
|
||||
/// All alive mobs with clients.
|
||||
|
||||
@@ -362,7 +362,7 @@
|
||||
/atom/movable/screen/plane_master/camera_static/proc/eye_changed(datum/hud/source, atom/old_eye, atom/new_eye)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!isaicamera(new_eye))
|
||||
if(!iscameramob(new_eye))
|
||||
if(!force_hidden)
|
||||
hide_plane(source.mymob)
|
||||
return
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
if(iscyborg(user) && atom_source.Adjacent(user))
|
||||
dust_mob(source, user, cause = "cyborg attack")
|
||||
return
|
||||
if(isaicamera(user))
|
||||
if(iscameramob(user))
|
||||
return
|
||||
if(islarva(user))
|
||||
dust_mob(source, user, cause = "larva attack")
|
||||
|
||||
+10
-16
@@ -1,15 +1,16 @@
|
||||
/mob/eye/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE)
|
||||
/mob/eye/camera/remote/holo/setLoc(turf/destination, force_update = FALSE)
|
||||
// If we're moving outside the space of our projector, then just... don't
|
||||
var/obj/machinery/holopad/H = origin
|
||||
if(!H?.move_hologram(eye_user, destination))
|
||||
var/obj/machinery/holopad/H = origin_ref?.resolve()
|
||||
if(!H?.move_hologram(user_ref?.resolve(), destination))
|
||||
sprint = initial(sprint) // Reset sprint so it doesn't balloon in our calling proc
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/remove_eye_control(mob/living/user)
|
||||
if(user.client)
|
||||
user.reset_perspective(null)
|
||||
user.remote_control = null
|
||||
var/mob/eye/camera/remote/eye = user.remote_control
|
||||
if(!istype(eye))
|
||||
CRASH("Attempted to remove eye control from non-camera eye. Something has gone horribly wrong.")
|
||||
eye.assign_user(null)
|
||||
|
||||
//this datum manages its own references
|
||||
|
||||
@@ -24,7 +25,7 @@
|
||||
var/list/dialed_holopads
|
||||
|
||||
///user's eye, once connected
|
||||
var/mob/eye/ai_eye/remote/holo/eye
|
||||
var/mob/eye/camera/remote/holo/eye
|
||||
///user's hologram, once connected
|
||||
var/obj/effect/overlay/holo_pad_hologram/hologram
|
||||
///hangup action
|
||||
@@ -155,15 +156,8 @@
|
||||
hologram = answering_holopad.activate_holo(user)
|
||||
hologram.HC = src
|
||||
|
||||
//eyeobj code is horrid, this is the best copypasta I could make
|
||||
eye = new
|
||||
eye.origin = answering_holopad
|
||||
eye.eye_initialized = TRUE
|
||||
eye.eye_user = user
|
||||
eye.name = "Camera Eye ([user.name])"
|
||||
user.remote_control = eye
|
||||
user.reset_perspective(eye)
|
||||
eye.setLoc(answering_holopad.loc)
|
||||
eye = new(get_turf(answering_holopad), answering_holopad)
|
||||
eye.assign_user(user)
|
||||
|
||||
hangup = new(eye, src)
|
||||
hangup.Grant(user)
|
||||
|
||||
@@ -881,7 +881,7 @@
|
||||
var/extra_context = ""
|
||||
var/used_name = name
|
||||
|
||||
if(isliving(user) || isovermind(user) || isaicamera(user) || (ghost_screentips && isobserver(user)))
|
||||
if(isliving(user) || isovermind(user) || iscameramob(user) || (ghost_screentips && isobserver(user)))
|
||||
var/obj/item/held_item = user.get_active_held_item()
|
||||
|
||||
if (user.mob_flags & MOB_HAS_SCREENTIPS_NAME_OVERRIDE)
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
. = ..()
|
||||
if(!new_viewer || hud_users_all_z_levels.len != 1)
|
||||
return
|
||||
for(var/mob/eye/ai_eye/eye as anything in GLOB.aiEyes)
|
||||
for(var/mob/eye/camera/ai/eye as anything in GLOB.camera_eyes)
|
||||
eye.update_ai_detect_hud()
|
||||
|
||||
/datum/atom_hud/data/malf_apc
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
var/list/z_lock = list() // Lock use to these z levels
|
||||
var/lock_override = NONE
|
||||
var/mob/eye/ai_eye/remote/eyeobj
|
||||
var/mob/eye/camera/remote/eyeobj
|
||||
var/mob/living/current_user = null
|
||||
var/list/networks = list(CAMERANET_NETWORK_SS13)
|
||||
/// Typepath of the action button we use as "off"
|
||||
@@ -76,27 +76,33 @@
|
||||
/obj/machinery/computer/camera_advanced/syndie/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
||||
return //For syndie nuke shuttle, to spy for station.
|
||||
|
||||
/**
|
||||
* Initializes a camera eye.
|
||||
* Returns TRUE if initialization was successful.
|
||||
* Will return nothing if it runtimes.
|
||||
*/
|
||||
/obj/machinery/computer/camera_advanced/proc/CreateEye()
|
||||
eyeobj = new()
|
||||
eyeobj.origin = src
|
||||
if(eyeobj)
|
||||
CRASH("Tried to make another eyeobj for some reason. Why?")
|
||||
|
||||
eyeobj = new(get_turf(src), src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user)
|
||||
for(var/datum/action/to_grant as anything in actions)
|
||||
to_grant.Grant(user)
|
||||
|
||||
/obj/machinery/proc/remove_eye_control(mob/living/user)
|
||||
CRASH("[type] does not implement ai eye handling")
|
||||
CRASH("[type] does not implement camera eye handling")
|
||||
|
||||
/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user)
|
||||
if(isnull(user?.client))
|
||||
return
|
||||
GrantActions(user)
|
||||
|
||||
current_user = user
|
||||
eyeobj.eye_user = user
|
||||
eyeobj.name = "Camera Eye ([user.name])"
|
||||
user.remote_control = eyeobj
|
||||
user.reset_perspective(eyeobj)
|
||||
eyeobj.setLoc(eyeobj.loc)
|
||||
eyeobj.assign_user(user)
|
||||
GrantActions(user)
|
||||
|
||||
if(should_supress_view_changes)
|
||||
user.client.view_size.supress()
|
||||
begin_processing()
|
||||
@@ -110,14 +116,11 @@
|
||||
for(var/datum/camerachunk/camerachunks_gone as anything in eyeobj.visibleCameraChunks)
|
||||
camerachunks_gone.remove(eyeobj)
|
||||
|
||||
user.reset_perspective(null)
|
||||
if(eyeobj.visible_icon)
|
||||
user.client.images -= eyeobj.user_image
|
||||
eyeobj.assign_user(null)
|
||||
current_user = null
|
||||
|
||||
user.client.view_size.unsupress()
|
||||
|
||||
eyeobj.eye_user = null
|
||||
user.remote_control = null
|
||||
current_user = null
|
||||
playsound(src, 'sound/machines/terminal/terminal_off.ogg', 25, FALSE)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/on_set_is_operational(old_value)
|
||||
@@ -148,39 +151,43 @@
|
||||
if(!QDELETED(current_user))
|
||||
to_chat(user, span_warning("The console is already in use!"))
|
||||
return
|
||||
var/mob/living/L = user
|
||||
if(!eyeobj)
|
||||
CreateEye()
|
||||
if(!eyeobj) //Eye creation failed
|
||||
|
||||
if(eyeobj)
|
||||
give_eye_control(user)
|
||||
eyeobj.setLoc(eyeobj.loc)
|
||||
return
|
||||
if(!eyeobj.eye_initialized)
|
||||
var/camera_location
|
||||
var/turf/myturf = get_turf(src)
|
||||
if(eyeobj.use_static != FALSE)
|
||||
if((!length(z_lock) || (myturf.z in z_lock)) && GLOB.cameranet.checkTurfVis(myturf))
|
||||
camera_location = myturf
|
||||
else
|
||||
for(var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras)
|
||||
if(!C.can_use() || length(z_lock) && !(C.z in z_lock))
|
||||
continue
|
||||
var/list/network_overlap = networks & C.network
|
||||
if(length(network_overlap))
|
||||
camera_location = get_turf(C)
|
||||
break
|
||||
/* We're attempting to initialize the eye past this point */
|
||||
|
||||
if(!CreateEye())
|
||||
to_chat(user, span_warning("\The [src] flashes a bunch of never-ending errors on the display. Something is really wrong."))
|
||||
return
|
||||
|
||||
var/camera_location
|
||||
var/turf/myturf = get_turf(src)
|
||||
var/consider_zlock = (!!length(z_lock))
|
||||
|
||||
if(!eyeobj.use_visibility)
|
||||
if(consider_zlock && !(myturf.z in z_lock))
|
||||
camera_location = locate(round(world.maxx * 0.5), round(world.maxy * 0.5), z_lock[1])
|
||||
else
|
||||
camera_location = myturf
|
||||
if(length(z_lock) && !(myturf.z in z_lock))
|
||||
camera_location = locate(round(world.maxx/2), round(world.maxy/2), z_lock[1])
|
||||
|
||||
if(camera_location)
|
||||
eyeobj.eye_initialized = TRUE
|
||||
give_eye_control(L)
|
||||
eyeobj.setLoc(camera_location)
|
||||
else
|
||||
unset_machine()
|
||||
else
|
||||
give_eye_control(L)
|
||||
eyeobj.setLoc(eyeobj.loc)
|
||||
if((!consider_zlock || (myturf.z in z_lock)) && GLOB.cameranet.checkTurfVis(myturf))
|
||||
camera_location = myturf
|
||||
else
|
||||
for(var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras)
|
||||
if(!C.can_use() || consider_zlock && !(C.z in z_lock))
|
||||
continue
|
||||
var/list/network_overlap = networks & C.network
|
||||
if(length(network_overlap))
|
||||
camera_location = get_turf(C)
|
||||
break
|
||||
|
||||
if(camera_location)
|
||||
give_eye_control(user)
|
||||
eyeobj.setLoc(camera_location, TRUE)
|
||||
else
|
||||
unset_machine()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/attack_robot(mob/user)
|
||||
return attack_hand(user)
|
||||
@@ -188,73 +195,6 @@
|
||||
/obj/machinery/computer/camera_advanced/attack_ai(mob/user)
|
||||
return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise.
|
||||
|
||||
/mob/eye/ai_eye/remote
|
||||
name = "Inactive Camera Eye"
|
||||
ai_detector_visible = FALSE
|
||||
var/sprint = 10
|
||||
var/cooldown = 0
|
||||
var/acceleration = 1
|
||||
var/mob/living/eye_user = null
|
||||
var/obj/machinery/origin
|
||||
var/eye_initialized = 0
|
||||
var/visible_icon = 0
|
||||
var/image/user_image = null
|
||||
|
||||
/mob/eye/ai_eye/remote/update_remote_sight(mob/living/user)
|
||||
user.set_invis_see(SEE_INVISIBLE_LIVING) //can't see ghosts through cameras
|
||||
user.set_sight(SEE_TURFS)
|
||||
return TRUE
|
||||
|
||||
/mob/eye/ai_eye/remote/Destroy()
|
||||
if(origin && eye_user)
|
||||
origin.remove_eye_control(eye_user,src)
|
||||
origin = null
|
||||
. = ..()
|
||||
eye_user = null
|
||||
|
||||
/mob/eye/ai_eye/remote/GetViewerClient()
|
||||
if(eye_user)
|
||||
return eye_user.client
|
||||
return null
|
||||
|
||||
/mob/eye/ai_eye/remote/setLoc(turf/destination, force_update = FALSE)
|
||||
if(eye_user)
|
||||
destination = get_turf(destination)
|
||||
if (destination)
|
||||
abstract_move(destination)
|
||||
else
|
||||
moveToNullspace()
|
||||
|
||||
update_ai_detect_hud()
|
||||
|
||||
if(use_static)
|
||||
GLOB.cameranet.visibility(src, GetViewerClient(), null, use_static)
|
||||
|
||||
if(visible_icon)
|
||||
if(eye_user.client)
|
||||
eye_user.client.images -= user_image
|
||||
user_image = image(icon,loc,icon_state, FLY_LAYER)
|
||||
SET_PLANE(user_image, ABOVE_GAME_PLANE, destination)
|
||||
eye_user.client.images += user_image
|
||||
|
||||
/mob/eye/ai_eye/remote/relaymove(mob/living/user, direction)
|
||||
var/initial = initial(sprint)
|
||||
var/max_sprint = 50
|
||||
|
||||
if(cooldown && cooldown < world.timeofday) // 3 seconds
|
||||
sprint = initial
|
||||
|
||||
for(var/i = 0; i < max(sprint, initial); i += 20)
|
||||
var/turf/step = get_turf(get_step(src, direction))
|
||||
if(step)
|
||||
setLoc(step)
|
||||
|
||||
cooldown = world.timeofday + 5
|
||||
if(acceleration)
|
||||
sprint = min(sprint + 0.5, max_sprint)
|
||||
else
|
||||
sprint = initial
|
||||
|
||||
/datum/action/innate/camera_off
|
||||
name = "End Camera View"
|
||||
button_icon = 'icons/mob/actions/actions_silicon.dmi'
|
||||
@@ -263,8 +203,8 @@
|
||||
/datum/action/innate/camera_off/Activate()
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin_ref.resolve()
|
||||
console.remove_eye_control(owner)
|
||||
|
||||
/datum/action/innate/camera_jump
|
||||
@@ -275,8 +215,8 @@
|
||||
/datum/action/innate/camera_jump/Activate()
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin_ref.resolve()
|
||||
|
||||
var/list/L = list()
|
||||
|
||||
@@ -320,7 +260,7 @@
|
||||
/datum/action/innate/camera_multiz_up/Activate()
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
if(remote_eye.zMove(UP))
|
||||
to_chat(owner, span_notice("You move upwards."))
|
||||
else
|
||||
@@ -334,7 +274,7 @@
|
||||
/datum/action/innate/camera_multiz_down/Activate()
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
if(remote_eye.zMove(DOWN))
|
||||
to_chat(owner, span_notice("You move downwards."))
|
||||
else
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
var/turf/our_turf = get_turf(src)
|
||||
detect_state = PROXIMITY_NONE
|
||||
|
||||
for(var/mob/eye/ai_eye/AI_eye as anything in GLOB.aiEyes)
|
||||
for(var/mob/eye/camera/ai/AI_eye as anything in GLOB.camera_eyes)
|
||||
if(!AI_eye.ai_detector_visible)
|
||||
continue
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
// copied from camera chunks but we are doing a really big edge case here though
|
||||
/obj/item/multitool/ai_detect/proc/surrounding_chunks(turf/epicenter)
|
||||
. = list()
|
||||
var/static_range = /mob/eye/ai_eye::static_visibility_range
|
||||
var/static_range = /mob/eye/camera/ai::static_visibility_range
|
||||
var/x1 = max(1, epicenter.x - static_range)
|
||||
var/y1 = max(1, epicenter.y - static_range)
|
||||
var/x2 = min(world.maxx, epicenter.x + static_range)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/datum/action/innate/construction
|
||||
button_icon = 'icons/mob/actions/actions_construction.dmi'
|
||||
///Console's eye mob
|
||||
var/mob/eye/ai_eye/remote/base_construction/remote_eye
|
||||
var/mob/eye/camera/remote/base_construction/remote_eye
|
||||
///Console itself
|
||||
var/obj/machinery/computer/camera_advanced/base_construction/base_console
|
||||
///Is this used to build only on the station z level?
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Camera console used to control a base building drone
|
||||
*
|
||||
* Using this console will put the user in control of a [base building drone][/mob/eye/ai_eye/remote/base_construction].
|
||||
* Using this console will put the user in control of a [base building drone][/mob/eye/camera/remote/base_construction].
|
||||
* The drone will appear somewhere within the allowed_area var, or if no area is specified, at the location of the console.area
|
||||
* Upon interacting, the user will be granted a set of base building actions that will generally be carried out at the drone's location.
|
||||
* To create a new base builder system, this class should be the only thing that needs to be subtyped.
|
||||
@@ -61,8 +61,7 @@
|
||||
var/turf/spawn_spot = find_spawn_spot()
|
||||
if (!spawn_spot)
|
||||
return FALSE
|
||||
eyeobj = new /mob/eye/ai_eye/remote/base_construction(spawn_spot, src)
|
||||
eyeobj.origin = src
|
||||
eyeobj = new /mob/eye/camera/remote/base_construction(spawn_spot, src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/attackby(obj/item/W, mob/user, params)
|
||||
@@ -95,7 +94,7 @@
|
||||
* The mob is constrained to a given area defined by the base construction console.
|
||||
*
|
||||
*/
|
||||
/mob/eye/ai_eye/remote/base_construction
|
||||
/mob/eye/camera/remote/base_construction
|
||||
name = "construction holo-drone"
|
||||
//Allows any curious crew to watch the base after it leaves. (This is safe as the base cannot be modified once it leaves)
|
||||
move_on_shuttle = TRUE
|
||||
@@ -105,20 +104,20 @@
|
||||
///Reference to the camera console controlling this drone
|
||||
var/obj/machinery/computer/camera_advanced/base_construction/linked_console
|
||||
|
||||
/mob/eye/ai_eye/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link)
|
||||
/mob/eye/camera/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link)
|
||||
linked_console = console_link
|
||||
if(!linked_console)
|
||||
stack_trace("A base consturuction drone was created with no linked console")
|
||||
return INITIALIZE_HINT_QDEL
|
||||
return ..()
|
||||
|
||||
/mob/eye/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE)
|
||||
/mob/eye/camera/remote/base_construction/setLoc(turf/destination, force_update = FALSE)
|
||||
var/area/curr_area = get_area(destination)
|
||||
//Only move if we're in the allowed area. If no allowed area is defined, then we're free to move wherever.
|
||||
if(!linked_console.allowed_area || istype(curr_area, linked_console.allowed_area))
|
||||
return ..()
|
||||
|
||||
/mob/eye/ai_eye/remote/base_construction/relaymove(mob/living/user, direction)
|
||||
/mob/eye/camera/remote/base_construction/relaymove(mob/living/user, direction)
|
||||
//This camera eye is visible, and as such needs to keep its dir updated
|
||||
dir = direction
|
||||
return ..()
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/CreateEye()
|
||||
..()
|
||||
eyeobj.visible_icon = TRUE
|
||||
. = ..()
|
||||
//For observers
|
||||
eyeobj.icon = 'icons/mob/eyemob.dmi'
|
||||
eyeobj.icon_state = "abductor_camera"
|
||||
eyeobj.SetInvisibility(INVISIBILITY_OBSERVER)
|
||||
//For the user
|
||||
eyeobj.set_user_icon(eyeobj.icon, eyeobj.icon_state)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user)
|
||||
if(!abduct_created)
|
||||
@@ -57,7 +58,7 @@
|
||||
to_chat(owner, span_warning("You must wait [DisplayTimeText(use_delay - world.time)] to use the [target] again!"))
|
||||
return
|
||||
var/mob/living/carbon/human/C = owner
|
||||
var/mob/eye/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/eye/camera/remote/remote_eye = C.remote_control
|
||||
var/obj/machinery/abductor/pad/P = target
|
||||
|
||||
var/area/target_area = get_area(remote_eye)
|
||||
@@ -101,7 +102,7 @@
|
||||
to_chat(owner, span_warning("You can only teleport to one place at a time!"))
|
||||
return
|
||||
var/mob/living/carbon/human/C = owner
|
||||
var/mob/eye/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/eye/camera/remote/remote_eye = C.remote_control
|
||||
var/obj/machinery/abductor/pad/P = target
|
||||
|
||||
var/area/target_area = get_area(remote_eye)
|
||||
@@ -151,7 +152,7 @@
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/C = owner
|
||||
var/mob/eye/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/eye/camera/remote/remote_eye = C.remote_control
|
||||
|
||||
var/obj/machinery/abductor/console/console = target
|
||||
console.SetDroppoint(remote_eye.loc,owner)
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
if(!iseyemob(suspect))
|
||||
return
|
||||
if(isaicamera(suspect))
|
||||
var/mob/eye/ai_eye/ai_camera = suspect
|
||||
var/mob/eye/camera/ai/ai_camera = suspect
|
||||
if(!ai_camera.ai)
|
||||
return
|
||||
suspect = ai_camera.ai
|
||||
@@ -193,7 +193,7 @@
|
||||
if(!iseyemob(suspect))
|
||||
return
|
||||
if(isaicamera(suspect))
|
||||
var/mob/eye/ai_eye/ai_camera = suspect
|
||||
var/mob/eye/camera/ai/ai_camera = suspect
|
||||
if(!ai_camera.ai)
|
||||
return
|
||||
suspect = ai_camera.ai
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Eye mob used to look around a [camera network][/datum/cameranet]. \
|
||||
* As it moves, it makes requests to the network to update what the user can and cannot see.
|
||||
*/
|
||||
/mob/eye/camera
|
||||
name = "Inactive Camera Eye"
|
||||
icon = 'icons/mob/eyemob.dmi'
|
||||
icon_state = "generic_camera"
|
||||
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
interaction_range = INFINITY
|
||||
/// If TRUE, the eye will cover turfs hidden to the cameranet with static.
|
||||
var/use_visibility = TRUE
|
||||
/// List of [camera chunks][/datum/camerachunk] visible to this camera.
|
||||
/// Please don't interface with this directly. Use the [cameranet][/datum/cameranet].
|
||||
var/final/list/datum/camerachunk/visibleCameraChunks = list()
|
||||
/// NxN Range of a single camera chunk.
|
||||
var/static_visibility_range = 16
|
||||
|
||||
/mob/eye/camera/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.camera_eyes += src
|
||||
|
||||
/mob/eye/camera/Destroy()
|
||||
for(var/datum/camerachunk/chunk in visibleCameraChunks)
|
||||
chunk.remove(src)
|
||||
GLOB.camera_eyes -= src
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Getter proc for getting the current user's client.
|
||||
*
|
||||
* The base version of this proc returns null.
|
||||
* Subtypes are expected to overload this proc and make it return something meaningful.
|
||||
*/
|
||||
/mob/eye/camera/proc/GetViewerClient()
|
||||
RETURN_TYPE(/client)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
|
||||
return null
|
||||
|
||||
/**
|
||||
* Use this when setting the camera eye's location directly. \
|
||||
* It will also attempt to update visible chunks.
|
||||
*/
|
||||
/mob/eye/camera/proc/setLoc(destination, force_update = FALSE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
destination = get_turf(destination)
|
||||
if(!force_update && (destination == get_turf(src)))
|
||||
return
|
||||
|
||||
if(destination)
|
||||
abstract_move(destination)
|
||||
else
|
||||
moveToNullspace()
|
||||
|
||||
if(use_visibility)
|
||||
update_visibility()
|
||||
update_parallax_contents()
|
||||
|
||||
/// Sends a visibility query to the cameranet.
|
||||
/// Can be used as a signal handler.
|
||||
/mob/eye/camera/proc/update_visibility()
|
||||
SIGNAL_HANDLER
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
if(use_visibility)
|
||||
GLOB.cameranet.visibility(src)
|
||||
|
||||
/mob/eye/camera/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs)
|
||||
. = ..()
|
||||
if(.)
|
||||
setLoc(loc, force_update = TRUE)
|
||||
|
||||
/mob/eye/camera/Move()
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
return
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* A camera controlled by a machine-operating user, like advanced cameras.
|
||||
* Handles assigning/unassigning it's users, as well as applying sight effects.
|
||||
*/
|
||||
/mob/eye/camera/remote
|
||||
/// Weakref to the current user of this eye. Must be a [living mob][/mob/living].
|
||||
var/datum/weakref/user_ref
|
||||
/// Weakref to the creator of this eye. Must be a [machine][/obj/machinery].
|
||||
var/datum/weakref/origin_ref
|
||||
|
||||
/// TRUE if this camera should show itself to the user.
|
||||
var/visible_to_user = FALSE
|
||||
/// If visible_to_user is TRUE, it will show this in the center of the screen.
|
||||
VAR_PROTECTED/image/user_image
|
||||
|
||||
/* The below code could be shared by AI eyes... */
|
||||
|
||||
/// If TRUE, the eye will have acceleration when moving.
|
||||
var/acceleration = TRUE
|
||||
/// Used internally for calculating wait time. (world.timeofday + wait_time)
|
||||
VAR_FINAL/last_moved = 0
|
||||
/// The amount of time that must pass before var/sprint is reset.
|
||||
VAR_PROTECTED/wait_time = 5 DECISECONDS
|
||||
/// The speed of the camera. Scales from initial(sprint) to var/max_sprint
|
||||
VAR_PROTECTED/sprint = 10
|
||||
/// Amount of speed that is added to var/sprint.
|
||||
VAR_PROTECTED/momentum = 0.5
|
||||
/// The maximum sprint that this eye can reach.
|
||||
VAR_PROTECTED/max_sprint = 50
|
||||
|
||||
|
||||
/mob/eye/camera/remote/Initialize(mapload, obj/machinery/creator)
|
||||
if(!creator)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
. = ..()
|
||||
|
||||
origin_ref = WEAKREF(creator)
|
||||
if(visible_to_user)
|
||||
set_user_icon(icon, icon_state)
|
||||
|
||||
/mob/eye/camera/remote/Destroy()
|
||||
var/mob/living/user = user_ref?.resolve()
|
||||
var/obj/machinery/origin = origin_ref?.resolve()
|
||||
if(origin && user)
|
||||
origin.remove_eye_control(user,src)
|
||||
|
||||
assign_user(null)
|
||||
origin_ref = null
|
||||
return ..()
|
||||
|
||||
/mob/eye/camera/remote/proc/assign_user(mob/living/new_user)
|
||||
var/mob/living/old_user = user_ref?.resolve()
|
||||
if(old_user)
|
||||
old_user.remote_control = null
|
||||
old_user.reset_perspective(null)
|
||||
name = initial(src.name)
|
||||
|
||||
var/client/old_user_client = GetViewerClient()
|
||||
if(user_image && old_user_client)
|
||||
old_user_client.images -= user_image
|
||||
|
||||
user_ref = WEAKREF(new_user) //The user_ref can still be null!
|
||||
|
||||
if(new_user)
|
||||
new_user.remote_control = src
|
||||
new_user.reset_perspective(src)
|
||||
name = "Camera Eye ([new_user.name])"
|
||||
|
||||
var/client/new_user_client = GetViewerClient()
|
||||
if(user_image && new_user_client)
|
||||
new_user_client.images += user_image
|
||||
|
||||
/**
|
||||
* Sets the camera's user image to this icon and state.
|
||||
* If chosen_icon is null, the user image will be removed.
|
||||
*/
|
||||
/mob/eye/camera/remote/proc/set_user_icon(icon/chosen_icon, icon_state)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
var/client/user_client = GetViewerClient()
|
||||
|
||||
if(!isnull(chosen_icon))
|
||||
set_user_icon(null) //remove whatever the last icon was
|
||||
if(!isicon(chosen_icon) || !(!isnull(icon_state) && istext(icon_state)))
|
||||
CRASH("Tried to set [src]'s user_image with bad parameters")
|
||||
|
||||
user_image = image(chosen_icon, src, icon_state, FLY_LAYER)
|
||||
if(user_client)
|
||||
user_client.images += user_image
|
||||
else
|
||||
if(user_client)
|
||||
user_client.images -= user_image
|
||||
QDEL_NULL(user_image)
|
||||
|
||||
/mob/eye/camera/remote/update_remote_sight(mob/living/user)
|
||||
user.set_invis_see(SEE_INVISIBLE_LIVING) //can't see ghosts through cameras
|
||||
user.set_sight(SEE_TURFS)
|
||||
return TRUE
|
||||
|
||||
/mob/eye/camera/remote/GetViewerClient()
|
||||
var/mob/living/user = user_ref?.resolve()
|
||||
|
||||
if(user)
|
||||
return user.client
|
||||
return null
|
||||
|
||||
/mob/eye/camera/remote/setLoc(turf/destination, force_update = FALSE)
|
||||
. = ..()
|
||||
|
||||
var/client/user_client = GetViewerClient()
|
||||
if(user_image && user_client)
|
||||
SET_PLANE(user_image, ABOVE_GAME_PLANE, destination) //incase we move a z-level
|
||||
|
||||
/mob/eye/camera/remote/relaymove(mob/living/user, direction)
|
||||
var/initial = initial(src.sprint)
|
||||
|
||||
if(last_moved < world.timeofday) // It's been too long since we last moved, reset sprint
|
||||
sprint = initial
|
||||
|
||||
for(var/i = 0; i < max(sprint, initial); i += 20)
|
||||
var/turf/step = get_turf(get_step(src, direction))
|
||||
if(step)
|
||||
setLoc(step)
|
||||
|
||||
last_moved = world.timeofday + wait_time
|
||||
if(acceleration)
|
||||
sprint = min(sprint + momentum, max_sprint)
|
||||
else
|
||||
sprint = initial
|
||||
@@ -1,4 +1,4 @@
|
||||
// Eye mob, used by cameras and overminds such as blobs.
|
||||
/// Eye mob, used by cameras and overminds such as blobs.
|
||||
/mob/eye
|
||||
name = "eye mob"
|
||||
density = FALSE
|
||||
@@ -8,9 +8,9 @@
|
||||
invisibility = INVISIBILITY_ABSTRACT // No one can see us
|
||||
sight = SEE_SELF
|
||||
status_flags = NONE
|
||||
/// Toggles if the camera can move on shuttles
|
||||
/// Toggles if the eye can move on shuttles
|
||||
var/move_on_shuttle = FALSE
|
||||
/// Toggles if the camera can use emotes
|
||||
/// Toggles if the eye can use emotes
|
||||
var/has_emotes = FALSE
|
||||
|
||||
/mob/eye/Initialize(mapload)
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
var/nuking = FALSE
|
||||
var/obj/machinery/doomsday_device/doomsday_device
|
||||
|
||||
var/mob/eye/ai_eye/eyeobj
|
||||
var/mob/eye/camera/ai/eyeobj
|
||||
var/sprint = 10
|
||||
var/last_moved = 0
|
||||
var/acceleration = TRUE
|
||||
@@ -1139,8 +1139,8 @@
|
||||
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/ai/proc/camera_visibility(mob/eye/ai_eye/moved_eye)
|
||||
GLOB.cameranet.visibility(moved_eye, client, all_eyes, TRUE)
|
||||
/mob/living/silicon/ai/proc/camera_visibility(mob/eye/camera/ai/moved_eye)
|
||||
GLOB.cameranet.visibility(moved_eye)
|
||||
|
||||
/mob/living/silicon/ai/forceMove(atom/destination)
|
||||
. = ..()
|
||||
|
||||
@@ -12,7 +12,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
var/list/obj/machinery/camera/cameras = list()
|
||||
/// The chunks of the map, mapping the areas that the cameras can see.
|
||||
var/list/chunks = list()
|
||||
var/ready = 0
|
||||
|
||||
/// List of images cloned by all chunk static images put onto turfs cameras cant see
|
||||
/// Indexed by the plane offset to use
|
||||
@@ -56,16 +55,12 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
if(!.)
|
||||
chunks[key] = . = new /datum/camerachunk(x, y, lowest.z)
|
||||
|
||||
/// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or its location is set.
|
||||
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes, use_static = TRUE)
|
||||
/// Updates what the camera eye can see. It is recommended you use this when a camera eye moves or its location is set.
|
||||
/datum/cameranet/proc/visibility(list/moved_eyes)
|
||||
if(!islist(moved_eyes))
|
||||
moved_eyes = moved_eyes ? list(moved_eyes) : list()
|
||||
if(islist(other_eyes))
|
||||
other_eyes = (other_eyes - moved_eyes)
|
||||
else
|
||||
other_eyes = list()
|
||||
|
||||
for(var/mob/eye/ai_eye/eye as anything in moved_eyes)
|
||||
for(var/mob/eye/camera/eye as anything in moved_eyes)
|
||||
var/list/visibleChunks = list()
|
||||
//Get the eye's turf in case its located in an object like a mecha
|
||||
var/turf/eye_turf = get_turf(eye)
|
||||
@@ -129,6 +124,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
* to change the time between static updates.
|
||||
*/
|
||||
/datum/cameranet/proc/majorChunkChange(atom/c, choice, update_delay_buffer)
|
||||
PROTECTED_PROC(TRUE)
|
||||
|
||||
if(QDELETED(c) && choice == 1)
|
||||
CRASH("Tried to add a qdeleting camera to the net")
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#define UPDATE_BUFFER_TIME (2.5 SECONDS)
|
||||
|
||||
// CAMERA CHUNK
|
||||
//
|
||||
// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
|
||||
// Allows the AI Eye to stream these chunks and know what it can and cannot see.
|
||||
/**
|
||||
* A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. \
|
||||
* Allows Camera Eyes to stream these chunks and know what it can and cannot see.
|
||||
*/
|
||||
|
||||
/datum/camerachunk
|
||||
///turfs our cameras cant see but are inside our grid. associative list of the form: list(obscured turf = static image on that turf)
|
||||
@@ -16,7 +16,7 @@
|
||||
///list of all turfs, associative with that turf's static image
|
||||
///turf -> /image
|
||||
var/list/turfs = list()
|
||||
///eye mobs that can see turfs in our grid
|
||||
///Camera mobs that can see turfs in our grid
|
||||
var/list/seenby = list()
|
||||
///images currently in use on obscured turfs.
|
||||
var/list/active_static_images = list()
|
||||
@@ -27,24 +27,24 @@
|
||||
var/lower_z
|
||||
var/upper_z
|
||||
|
||||
/// Add an AI eye to the chunk, then update if changed.
|
||||
/datum/camerachunk/proc/add(mob/eye/ai_eye/eye)
|
||||
/// Add a camera eye to the chunk, then update if changed.
|
||||
/datum/camerachunk/proc/add(mob/eye/camera/eye)
|
||||
eye.visibleCameraChunks += src
|
||||
seenby += eye
|
||||
if(changed)
|
||||
update()
|
||||
|
||||
var/client/client = eye.GetViewerClient()
|
||||
if(client && eye.use_static)
|
||||
if(client && eye.use_visibility)
|
||||
client.images += active_static_images
|
||||
|
||||
/// Remove an AI eye from the chunk
|
||||
/datum/camerachunk/proc/remove(mob/eye/ai_eye/eye, remove_static_with_last_chunk = TRUE)
|
||||
/// Remove a camera eye from the chunk
|
||||
/datum/camerachunk/proc/remove(mob/eye/camera/ai/eye)
|
||||
eye.visibleCameraChunks -= src
|
||||
seenby -= eye
|
||||
|
||||
var/client/client = eye.GetViewerClient()
|
||||
if(client && eye.use_static)
|
||||
if(client && eye.use_visibility)
|
||||
client.images -= active_static_images
|
||||
|
||||
/// Called when a chunk has changed. I.E: A wall was deleted.
|
||||
@@ -56,6 +56,7 @@
|
||||
/**
|
||||
* Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
|
||||
* instead be flagged to update the next time an AI Eye moves near it.
|
||||
*
|
||||
* update_delay_buffer is used for cameras that are moving around, which are cyborg inbuilt cameras and
|
||||
* mecha onboard cameras. This buffer should be usually lower than UPDATE_BUFFER_TIME because
|
||||
* otherwise a moving camera can run out of its own view before updating static.
|
||||
@@ -89,8 +90,8 @@
|
||||
///turfs that we could see last update but cant see now
|
||||
var/list/newly_obscured_turfs = visibleTurfs - updated_visible_turfs
|
||||
|
||||
for(var/mob/eye/ai_eye/client_eye as anything in seenby)
|
||||
var/client/client = client_eye.ai?.client || client_eye.client
|
||||
for(var/mob/eye/camera/client_eye as anything in seenby)
|
||||
var/client/client = client_eye.GetViewerClient()
|
||||
if(!client)
|
||||
continue
|
||||
|
||||
@@ -119,8 +120,8 @@
|
||||
|
||||
changed = FALSE
|
||||
|
||||
for(var/mob/eye/ai_eye/client_eye as anything in seenby)
|
||||
var/client/client = client_eye.ai?.client || client_eye.client
|
||||
for(var/mob/eye/camera/client_eye as anything in seenby)
|
||||
var/client/client = client_eye.GetViewerClient()
|
||||
if(!client)
|
||||
continue
|
||||
|
||||
|
||||
@@ -1,43 +1,50 @@
|
||||
// AI EYE
|
||||
//
|
||||
// An invisible (no icon) mob that the AI controls to look around the station with.
|
||||
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
|
||||
/mob/eye/ai_eye
|
||||
/mob/eye/camera/ai
|
||||
name = "Inactive AI Eye"
|
||||
|
||||
icon_state = "ai_camera"
|
||||
icon = 'icons/mob/eyemob.dmi'
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST)
|
||||
var/list/visibleCameraChunks = list()
|
||||
/// The AI who owns this eye.
|
||||
var/mob/living/silicon/ai/ai = null
|
||||
/// Whether this eye will transmit speech near it to the AI.
|
||||
var/relay_speech = FALSE
|
||||
var/use_static = TRUE
|
||||
var/static_visibility_range = 16
|
||||
/// Whether this eye can be found with AI detectors.
|
||||
var/ai_detector_visible = TRUE
|
||||
/// The color of the area if the eye is detectable.
|
||||
var/ai_detector_color = COLOR_RED
|
||||
interaction_range = INFINITY
|
||||
|
||||
/mob/eye/ai_eye/Initialize(mapload)
|
||||
/mob/eye/camera/ai/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.aiEyes += src
|
||||
update_ai_detect_hud()
|
||||
setLoc(loc, TRUE)
|
||||
|
||||
/mob/eye/ai_eye/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
|
||||
. = ..()
|
||||
if(same_z_layer)
|
||||
return
|
||||
update_ai_detect_hud()
|
||||
|
||||
/mob/eye/ai_eye/examine(mob/user) //Displays a silicon's laws to ghosts
|
||||
. = ..()
|
||||
if(istype(ai) && ai.laws && isobserver(user))
|
||||
. += "<b>[ai] has the following laws:</b>"
|
||||
for(var/law in ai.laws.get_law_list(include_zeroth = TRUE))
|
||||
. += law
|
||||
/mob/eye/camera/ai/Destroy()
|
||||
if(ai)
|
||||
ai.all_eyes -= src
|
||||
ai = null
|
||||
if(ai_detector_visible)
|
||||
var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT]
|
||||
hud.remove_atom_from_hud(src)
|
||||
var/list/L = hud_list[AI_DETECT_HUD]
|
||||
QDEL_LIST(L)
|
||||
return ..()
|
||||
|
||||
/mob/eye/ai_eye/proc/update_ai_detect_hud()
|
||||
/**
|
||||
* Returns a list of turfs visible to the client's viewsize. \
|
||||
* Note that this will return an empty list if the camera's loc is not a turf.
|
||||
*/
|
||||
/mob/eye/camera/ai/proc/get_visible_turfs()
|
||||
RETURN_TYPE(/list/turf)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
if(!isturf(loc))
|
||||
return list()
|
||||
var/client/C = GetViewerClient()
|
||||
var/view = C ? getviewsize(C.view) : getviewsize(world.view)
|
||||
var/turf/lowerleft = locate(max(1, x - (view[1] - 1)/2), max(1, y - (view[2] - 1)/2), z)
|
||||
var/turf/upperright = locate(min(world.maxx, lowerleft.x + (view[1] - 1)), min(world.maxy, lowerleft.y + (view[2] - 1)), lowerleft.z)
|
||||
return block(lowerleft, upperright)
|
||||
|
||||
/mob/eye/camera/ai/proc/update_ai_detect_hud()
|
||||
var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT]
|
||||
var/list/old_images = hud_list[AI_DETECT_HUD]
|
||||
if(!ai_detector_visible)
|
||||
@@ -75,42 +82,17 @@
|
||||
active_hud_list[AI_DETECT_HUD] = new_images
|
||||
hud.add_atom_to_hud(src)
|
||||
|
||||
/mob/eye/ai_eye/proc/get_visible_turfs()
|
||||
if(!isturf(loc))
|
||||
return list()
|
||||
var/client/C = GetViewerClient()
|
||||
var/view = C ? getviewsize(C.view) : getviewsize(world.view)
|
||||
var/turf/lowerleft = locate(max(1, x - (view[1] - 1)/2), max(1, y - (view[2] - 1)/2), z)
|
||||
var/turf/upperright = locate(min(world.maxx, lowerleft.x + (view[1] - 1)), min(world.maxy, lowerleft.y + (view[2] - 1)), lowerleft.z)
|
||||
return block(lowerleft, upperright)
|
||||
|
||||
/// Used in cases when the eye is located in a movable object (i.e. mecha)
|
||||
/mob/eye/ai_eye/proc/update_visibility()
|
||||
SIGNAL_HANDLER
|
||||
if(use_static)
|
||||
ai.camera_visibility(src)
|
||||
|
||||
// Use this when setting the aiEye's location.
|
||||
// It will also stream the chunk that the new loc is in.
|
||||
|
||||
/mob/eye/ai_eye/proc/setLoc(destination, force_update = FALSE)
|
||||
/mob/eye/camera/ai/setLoc(destination, force_update = FALSE)
|
||||
if(!ai)
|
||||
return
|
||||
if(!isturf(ai.loc))
|
||||
return
|
||||
destination = get_turf(destination)
|
||||
if(!force_update && (destination == get_turf(src)))
|
||||
return //we are already here!
|
||||
if (destination)
|
||||
abstract_move(destination)
|
||||
else
|
||||
moveToNullspace()
|
||||
if(use_static)
|
||||
ai.camera_visibility(src)
|
||||
|
||||
. = ..()
|
||||
|
||||
if(ai.client && !ai.multicam_on)
|
||||
ai.client.set_eye(src)
|
||||
update_ai_detect_hud()
|
||||
update_parallax_contents()
|
||||
//Holopad
|
||||
if(istype(ai.current, /obj/machinery/holopad))
|
||||
var/obj/machinery/holopad/H = ai.current
|
||||
@@ -122,33 +104,31 @@
|
||||
if(ai.master_multicam)
|
||||
ai.master_multicam.refresh_view()
|
||||
|
||||
/mob/eye/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs)
|
||||
. = ..()
|
||||
if(.)
|
||||
setLoc(loc, force_update = TRUE)
|
||||
/mob/eye/camera/ai/update_visibility()
|
||||
if(ai)
|
||||
ai.camera_visibility(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/eye/ai_eye/Move()
|
||||
return
|
||||
|
||||
/mob/eye/ai_eye/proc/GetViewerClient()
|
||||
/mob/eye/camera/ai/GetViewerClient()
|
||||
if(ai)
|
||||
return ai.client
|
||||
return null
|
||||
|
||||
/mob/eye/ai_eye/Destroy()
|
||||
if(ai)
|
||||
ai.all_eyes -= src
|
||||
ai = null
|
||||
for(var/V in visibleCameraChunks)
|
||||
var/datum/camerachunk/c = V
|
||||
c.remove(src)
|
||||
GLOB.aiEyes -= src
|
||||
if(ai_detector_visible)
|
||||
var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT]
|
||||
hud.remove_atom_from_hud(src)
|
||||
var/list/L = hud_list[AI_DETECT_HUD]
|
||||
QDEL_LIST(L)
|
||||
return ..()
|
||||
/mob/eye/camera/ai/examine(mob/user) //Displays a silicon's laws to ghosts
|
||||
. = ..()
|
||||
if(istype(ai) && ai.laws && isobserver(user))
|
||||
. += "<b>[ai] has the following laws:</b>"
|
||||
for(var/law in ai.laws.get_law_list(include_zeroth = TRUE))
|
||||
. += law
|
||||
|
||||
/mob/eye/camera/ai/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
|
||||
. = ..()
|
||||
if(same_z_layer)
|
||||
return
|
||||
update_ai_detect_hud()
|
||||
|
||||
/*----------------------------------------------------*/
|
||||
|
||||
/atom/proc/move_camera_by_click()
|
||||
if(!isAI(usr))
|
||||
@@ -189,7 +169,6 @@
|
||||
sprint = initial(sprint)
|
||||
|
||||
ai_tracking_tool.reset_tracking()
|
||||
|
||||
#undef SPRINT_PER_STEP
|
||||
#undef MAX_SPRINT
|
||||
#undef SPRINT_PER_TICK
|
||||
@@ -215,12 +194,11 @@
|
||||
/mob/living/silicon/ai/proc/create_eye()
|
||||
if(eyeobj)
|
||||
return
|
||||
eyeobj = new /mob/eye/ai_eye()
|
||||
eyeobj = new /mob/eye/camera/ai()
|
||||
all_eyes += eyeobj
|
||||
eyeobj.ai = src
|
||||
eyeobj.setLoc(loc)
|
||||
eyeobj.name = "[name] (AI Eye)"
|
||||
eyeobj.real_name = eyeobj.name
|
||||
eyeobj.setLoc(loc, TRUE)
|
||||
set_eyeobj_visible(TRUE)
|
||||
|
||||
/mob/living/silicon/ai/proc/set_eyeobj_visible(state = TRUE)
|
||||
@@ -241,7 +219,7 @@
|
||||
acceleration = !acceleration
|
||||
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
|
||||
|
||||
/mob/eye/ai_eye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
|
||||
/mob/eye/camera/ai/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range)
|
||||
. = ..()
|
||||
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && GLOB.cameranet.checkCameraVis(speaker))
|
||||
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
var/mob/living/silicon/ai/ai
|
||||
var/mutable_appearance/highlighted_background
|
||||
var/highlighted = FALSE
|
||||
var/mob/eye/ai_eye/pic_in_pic/aiEye
|
||||
var/mob/eye/camera/ai/pic_in_pic/aiEye
|
||||
|
||||
/atom/movable/screen/movable/pic_in_pic/ai/Initialize(mapload, datum/hud/hud_owner)
|
||||
. = ..()
|
||||
aiEye = new /mob/eye/ai_eye/pic_in_pic()
|
||||
aiEye = new /mob/eye/camera/ai/pic_in_pic()
|
||||
aiEye.screen = src
|
||||
|
||||
/atom/movable/screen/movable/pic_in_pic/ai/Destroy()
|
||||
@@ -126,37 +126,38 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
|
||||
|
||||
//Dummy camera eyes
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic
|
||||
/mob/eye/camera/ai/pic_in_pic
|
||||
name = "Secondary AI Eye"
|
||||
icon_state = "ai_pip_camera"
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
icon_state = "ai_pip_camera"
|
||||
ai_detector_color = COLOR_ORANGE
|
||||
|
||||
var/atom/movable/screen/movable/pic_in_pic/ai/screen
|
||||
var/list/cameras_telegraphed = list()
|
||||
var/telegraph_cameras = TRUE
|
||||
var/telegraph_range = 7
|
||||
ai_detector_color = COLOR_ORANGE
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/GetViewerClient()
|
||||
/mob/eye/camera/ai/pic_in_pic/GetViewerClient()
|
||||
if(screen?.ai)
|
||||
return screen.ai.client
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE)
|
||||
if (destination)
|
||||
abstract_move(destination)
|
||||
else
|
||||
moveToNullspace()
|
||||
/mob/eye/camera/ai/pic_in_pic/update_visibility()
|
||||
if(screen?.ai)
|
||||
screen.ai.camera_visibility(src)
|
||||
else
|
||||
GLOB.cameranet.visibility(src)
|
||||
..()
|
||||
|
||||
/mob/eye/camera/ai/pic_in_pic/setLoc(turf/destination, force_update = FALSE)
|
||||
. = ..()
|
||||
update_camera_telegraphing()
|
||||
update_ai_detect_hud()
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/get_visible_turfs()
|
||||
/mob/eye/camera/ai/pic_in_pic/get_visible_turfs()
|
||||
SHOULD_CALL_PARENT(FALSE) //we do our own thing here
|
||||
return screen ? screen.get_visible_turfs() : list()
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/proc/update_camera_telegraphing()
|
||||
/mob/eye/camera/ai/pic_in_pic/proc/update_camera_telegraphing()
|
||||
if(!telegraph_cameras)
|
||||
return
|
||||
var/list/obj/machinery/camera/add = list()
|
||||
@@ -185,7 +186,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
|
||||
C.in_use_lights++
|
||||
C.update_appearance()
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/proc/disable_camera_telegraphing()
|
||||
/mob/eye/camera/ai/pic_in_pic/proc/disable_camera_telegraphing()
|
||||
telegraph_cameras = FALSE
|
||||
for (var/obj/machinery/camera/C as anything in cameras_telegraphed)
|
||||
if(QDELETED(C))
|
||||
@@ -194,7 +195,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
|
||||
C.update_appearance()
|
||||
cameras_telegraphed.Cut()
|
||||
|
||||
/mob/eye/ai_eye/pic_in_pic/Destroy()
|
||||
/mob/eye/camera/ai/pic_in_pic/Destroy()
|
||||
disable_camera_telegraphing()
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
//Xenobio control console
|
||||
/mob/eye/ai_eye/remote/xenobio
|
||||
visible_icon = TRUE
|
||||
icon = 'icons/mob/eyemob.dmi'
|
||||
icon_state = "generic_camera"
|
||||
/mob/eye/camera/remote/xenobio
|
||||
visible_to_user = TRUE
|
||||
var/allowed_area = null
|
||||
|
||||
/mob/eye/ai_eye/remote/xenobio/Initialize(mapload)
|
||||
/mob/eye/camera/remote/xenobio/Initialize(mapload)
|
||||
var/area/our_area = get_area(loc)
|
||||
allowed_area = our_area.name
|
||||
. = ..()
|
||||
|
||||
/mob/eye/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE)
|
||||
/mob/eye/camera/remote/xenobio/setLoc(turf/destination, force_update = FALSE)
|
||||
var/area/new_area = get_area(destination)
|
||||
|
||||
if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE))
|
||||
return ..()
|
||||
|
||||
/mob/eye/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
/mob/eye/camera/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -84,11 +82,9 @@
|
||||
stored_slimes -= gone
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio/CreateEye()
|
||||
eyeobj = new /mob/eye/ai_eye/remote/xenobio(get_turf(src))
|
||||
eyeobj.origin = src
|
||||
eyeobj.visible_icon = TRUE
|
||||
eyeobj.icon = 'icons/mob/eyemob.dmi'
|
||||
eyeobj.icon_state = "generic_camera"
|
||||
eyeobj = new /mob/eye/camera/remote/xenobio(get_turf(src), src)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user)
|
||||
. = ..()
|
||||
@@ -151,7 +147,7 @@ Boilerplate check for a valid area to perform a camera action in.
|
||||
Checks if the AI eye is on a valid turf and then checks if the target turf is xenobiology compatible
|
||||
Due to keyboard shortcuts, the second one is not necessarily the remote eye's location.
|
||||
*/
|
||||
/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/eye/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf)
|
||||
/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/eye/camera/remote/xenobio/remote_eye, turf/open/target_turf)
|
||||
if(!GLOB.cameranet.checkTurfVis(remote_eye.loc))
|
||||
to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
|
||||
return FALSE
|
||||
@@ -228,7 +224,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!target || !isliving(owner))
|
||||
return
|
||||
var/mob/living/owner_mob = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
|
||||
if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
|
||||
@@ -245,7 +241,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!target || !isliving(owner))
|
||||
return
|
||||
var/mob/living/owner_mob = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
|
||||
if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
|
||||
@@ -264,7 +260,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!target || !isliving(owner))
|
||||
return
|
||||
var/mob/living/living_owner = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = living_owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
|
||||
if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
|
||||
@@ -282,7 +278,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!target || !isliving(owner))
|
||||
return
|
||||
var/mob/living/owner_mob = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
var/obj/machinery/monkey_recycler/recycler = xeno_console.connected_recycler
|
||||
|
||||
@@ -305,7 +301,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!target || !isliving(owner))
|
||||
return
|
||||
var/mob/living/owner_mob = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
|
||||
if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
|
||||
@@ -324,7 +320,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
return
|
||||
|
||||
var/mob/living/owner_mob = owner
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = owner_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
|
||||
|
||||
if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
|
||||
@@ -375,8 +371,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!isslime(target_slime))
|
||||
return
|
||||
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
|
||||
return
|
||||
@@ -391,8 +387,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/basic/slime/target_slime)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
|
||||
return
|
||||
@@ -404,8 +400,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/user_mob = user
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user_mob.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.validate_area(user, remote_eye, target_turf))
|
||||
return
|
||||
@@ -430,8 +426,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
return
|
||||
|
||||
var/cleanup = FALSE
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.validate_area(user, remote_eye, target_turf))
|
||||
return
|
||||
@@ -449,8 +445,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!ismonkey(target_mob))
|
||||
return
|
||||
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.connected_recycler)
|
||||
to_chat(user, span_warning("There is no connected monkey recycler. Use a multitool to link one."))
|
||||
@@ -466,8 +462,8 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
|
||||
if(!isslime(target_slime))
|
||||
return
|
||||
|
||||
var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/xenobio/remote_eye = user.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin_ref.resolve()
|
||||
|
||||
if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
|
||||
return
|
||||
|
||||
@@ -107,8 +107,8 @@
|
||||
shuttle_port = null
|
||||
return
|
||||
|
||||
eyeobj = new /mob/eye/ai_eye/remote/shuttle_docker(null, src)
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
eyeobj = new /mob/eye/camera/remote/shuttle_docker(null, src)
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
the_eye.setDir(shuttle_port.dir)
|
||||
var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z)
|
||||
for(var/area/shuttle_area as anything in shuttle_port.shuttle_areas)
|
||||
@@ -125,10 +125,12 @@
|
||||
I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
the_eye.placement_images[I] = list(x_off, y_off)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user)
|
||||
..()
|
||||
if(!QDELETED(user) && user.client)
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/list/to_add = list()
|
||||
to_add += the_eye.placement_images
|
||||
to_add += the_eye.placed_images
|
||||
@@ -141,7 +143,7 @@
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
|
||||
..()
|
||||
if(!QDELETED(user) && user.client)
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/list/to_remove = list()
|
||||
to_remove += the_eye.placement_images
|
||||
to_remove += the_eye.placed_images
|
||||
@@ -155,7 +157,7 @@
|
||||
if(designating_target_loc || !current_user)
|
||||
return
|
||||
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/landing_clear = checkLandingSpot()
|
||||
if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED))
|
||||
to_chat(current_user, span_warning("Targeting transit location, please wait [DisplayTimeText(designate_time)]..."))
|
||||
@@ -223,7 +225,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot()
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/list/image_cache = the_eye.placement_images
|
||||
the_eye.setDir(turn(the_eye.dir, -90))
|
||||
for(var/i in 1 to image_cache.len)
|
||||
@@ -239,7 +241,7 @@
|
||||
checkLandingSpot()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot()
|
||||
var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj
|
||||
var/turf/eyeturf = get_turf(the_eye)
|
||||
if(!eyeturf)
|
||||
return SHUTTLE_DOCKER_BLOCKED
|
||||
@@ -316,22 +318,17 @@
|
||||
add_jumpable_port(dock.shuttle_id)
|
||||
return TRUE
|
||||
|
||||
/mob/eye/ai_eye/remote/shuttle_docker
|
||||
visible_icon = FALSE
|
||||
use_static = FALSE
|
||||
/mob/eye/camera/remote/shuttle_docker
|
||||
use_visibility = FALSE
|
||||
var/list/image/placement_images = list()
|
||||
var/list/image/placed_images = list()
|
||||
|
||||
/mob/eye/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin)
|
||||
src.origin = origin
|
||||
return ..()
|
||||
|
||||
/mob/eye/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE)
|
||||
/mob/eye/camera/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE)
|
||||
. = ..()
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin_ref?.resolve()
|
||||
console.checkLandingSpot()
|
||||
|
||||
/mob/eye/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user)
|
||||
/mob/eye/camera/remote/shuttle_docker/update_remote_sight(mob/living/user)
|
||||
user.set_sight(BLIND|SEE_TURFS)
|
||||
// Pale blue, should look nice I think
|
||||
user.lighting_color_cutoffs = list(30, 40, 50)
|
||||
@@ -346,8 +343,8 @@
|
||||
/datum/action/innate/shuttledocker_rotate/Activate()
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref.resolve()
|
||||
origin.rotateLandingSpot()
|
||||
|
||||
/datum/action/innate/shuttledocker_place
|
||||
@@ -358,8 +355,8 @@
|
||||
/datum/action/innate/shuttledocker_place/Activate()
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref.resolve()
|
||||
origin.placeLandingSpot(owner)
|
||||
|
||||
/datum/action/innate/camera_jump/shuttle_docker
|
||||
@@ -369,8 +366,8 @@
|
||||
/datum/action/innate/camera_jump/shuttle_docker/Activate()
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin
|
||||
var/mob/eye/camera/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin_ref.resolve()
|
||||
|
||||
playsound(console, 'sound/machines/terminal/terminal_prompt_deny.ogg', 25, FALSE)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
)
|
||||
ignored += typesof(/mob/eye/imaginary_friend)
|
||||
ignored += typesof(/mob/living/silicon/robot/model)
|
||||
ignored += typesof(/mob/eye/ai_eye/remote/base_construction)
|
||||
ignored += typesof(/mob/eye/ai_eye/remote/shuttle_docker)
|
||||
ignored += typesof(/mob/eye/camera/remote/base_construction)
|
||||
ignored += typesof(/mob/eye/camera/remote/shuttle_docker)
|
||||
for (var/mob_type in typesof(/mob) - ignored)
|
||||
var/mob/mob_instance = allocate(mob_type)
|
||||
if(!islist(mob_instance.faction))
|
||||
|
||||
@@ -289,9 +289,9 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests())
|
||||
//No heart to give
|
||||
returnable_list += typesof(/obj/structure/ethereal_crystal)
|
||||
//No linked console
|
||||
returnable_list += typesof(/mob/eye/ai_eye/remote/base_construction)
|
||||
returnable_list += typesof(/mob/eye/camera/remote/base_construction)
|
||||
//See above
|
||||
returnable_list += typesof(/mob/eye/ai_eye/remote/shuttle_docker)
|
||||
returnable_list += typesof(/mob/eye/camera/remote/shuttle_docker)
|
||||
//Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky
|
||||
returnable_list += typesof(/obj/effect/anomaly/grav/high)
|
||||
//See above
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
mecha_flags |= SILICON_PILOT
|
||||
moved_inside(AI)
|
||||
AI.eyeobj?.forceMove(src)
|
||||
AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/eye/ai_eye, update_visibility))
|
||||
AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/eye/camera/ai, update_visibility))
|
||||
AI.controlled_equipment = src
|
||||
AI.remote_control = src
|
||||
add_occupant(AI)
|
||||
|
||||
@@ -4799,6 +4799,8 @@
|
||||
#include "code\modules\mob\dead\observer\observer_say.dm"
|
||||
#include "code\modules\mob\dead\observer\orbit.dm"
|
||||
#include "code\modules\mob\eye\eye.dm"
|
||||
#include "code\modules\mob\eye\camera\camera.dm"
|
||||
#include "code\modules\mob\eye\camera\remote.dm"
|
||||
#include "code\modules\mob\living\blood.dm"
|
||||
#include "code\modules\mob\living\damage_procs.dm"
|
||||
#include "code\modules\mob\living\death.dm"
|
||||
|
||||
Reference in New Issue
Block a user