diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index cd47fdde438..a2804c06abe 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -45,6 +45,8 @@ #define ANTAG_HUD "23" // for fans to identify pins #define FAN_HUD "24" +/// Mech camera HUD +#define DIAG_CAMERA_HUD "25" //by default everything in the hud_list of an atom is an image //a value in hud_list with one of these will change that behavior diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 281bfb1dd1d..6ef13c5bcd8 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -55,10 +55,10 @@ /datum/atom_hud/data/diagnostic /datum/atom_hud/data/diagnostic/basic - hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD) + hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD) /datum/atom_hud/data/diagnostic/advanced - hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD) + hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD) /datum/atom_hud/data/bot_path // This hud exists so the bot can see itself, that's all @@ -421,7 +421,6 @@ Diagnostic HUDs! else holder.icon_state = "hudnobatt" - /obj/vehicle/sealed/mecha/proc/diag_hud_set_mechstat() var/image/holder = hud_list[DIAG_STAT_HUD] var/icon/I = icon(icon, icon_state, dir) @@ -447,6 +446,16 @@ Diagnostic HUDs! new_icon_state = "hudtracking" holder.icon_state = new_icon_state +///Shows inbuilt camera on the mech; if the camera's view range was affected by an EMP, shows a red blip while it's affected +/obj/vehicle/sealed/mecha/proc/diag_hud_set_camera() + var/image/holder = hud_list[DIAG_CAMERA_HUD] + var/icon/I = icon(icon, icon_state, dir) + holder.pixel_y = I.Height() - world.icon_size + if(chassis_camera.is_emp_scrambled) + holder.icon_state = "hudcamera_empd" + return + holder.icon_state = "hudcamera" + /*~~~~~~~~~ Bots! ~~~~~~~~~~*/ diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 5119b17c284..2d9a2a221b4 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -66,6 +66,39 @@ c_tag = "[format_text(camera_area.name)] #[number]" +///The internal camera object for exosuits, applied by the camera upgrade +/obj/machinery/camera/exosuit + c_tag = "Exosuit: unspecified" + desc = "This camera belongs in a mecha. If you see this, tell a coder!" + network = list("ss13", "rd") + short_range = 1 //used when the camera gets EMPd + ///Number of the camera and thus the name of the mech + var/number = 0 + ///Currently used name of the mech + var/current_name = null + ///Whether the camera was recently affected by an EMP and is thus unfocused, shortening view_range + var/is_emp_scrambled = FALSE + +///Restore the camera's view default view range after an EMP +/obj/machinery/camera/exosuit/proc/emp_refocus(obj/vehicle/sealed/mecha/our_chassis) + is_emp_scrambled = FALSE + setViewRange(initial(view_range)) + our_chassis.diag_hud_set_camera() + +///Updates the c_tag of the mech camera while preventing duplicate c_tag usage due to having mechs with the same name +/obj/machinery/camera/exosuit/proc/update_c_tag(obj/vehicle/sealed/mecha/mech) + //List of all used mech names + var/static/list/existing_mech_names = list() + //Name of the mech passed with this proc. We use format_text to wipe away stuff like `\initial` to prevent c_tag from erroring out + var/mech_name = format_text(mech.name) + + if(current_name && current_name != mech_name) //decrease by 1 to preserve correct naming numeration + existing_mech_names[current_name] -= 1 + number = existing_mech_names[mech_name] + 1 + existing_mech_names[mech_name] = number + + c_tag = "Exosuit: [mech_name] #[number]" + current_name = mech_name // UPGRADE PROCS diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 0d9c9579852..73f6169d632 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -131,24 +131,25 @@ var/list/visible_turfs = list() - // Is this camera located in or attached to a living thing? If so, assume the camera's loc is the living thing. - var/cam_location = isliving(active_camera.loc) ? active_camera.loc : active_camera + // Get the camera's turf to correctly gather what's visible from it's turf, in case it's located in a moving object (borgs / mechs) + var/new_cam_turf = get_turf(active_camera) // If we're not forcing an update for some reason and the cameras are in the same location, // we don't need to update anything. // Most security cameras will end here as they're not moving. - var/newturf = get_turf(cam_location) - if(last_camera_turf == newturf) + if(last_camera_turf == new_cam_turf) return // Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs. - last_camera_turf = get_turf(cam_location) + last_camera_turf = new_cam_turf - var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, cam_location) : view(active_camera.view_range, cam_location) + //Here we gather what's visible from the camera's POV based on its view_range and xray modifier if present + var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, new_cam_turf) : view(active_camera.view_range, new_cam_turf) for(var/turf/visible_turf in visible_things) visible_turfs += visible_turf + //Get coordinates for a rectangle area that contains the turfs we see so we can then clear away the static in the resulting rectangle area var/list/bbox = get_bbox_of_atoms(visible_turfs) var/size_x = bbox[3] - bbox[1] + 1 var/size_y = bbox[4] - bbox[2] + 1 @@ -179,21 +180,23 @@ // Returns the list of cameras accessible from this computer /obj/machinery/computer/security/proc/get_available_cameras() var/list/L = list() - for (var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras) - if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras + for (var/obj/machinery/camera/cam as anything in GLOB.cameranet.cameras) + //Get the camera's turf in case it's inside something like a borg + var/turf/camera_turf = get_turf(cam) + if((is_away_level(z) || is_away_level(camera_turf.z)) && (camera_turf.z != z))//if on away mission, can only receive feed from same z_level cameras continue - L.Add(C) + L.Add(cam) var/list/D = list() - for(var/obj/machinery/camera/C in L) - if(!C.network) + for(var/obj/machinery/camera/cam in L) + if(!cam.network) stack_trace("Camera in a cameranet has no camera network") continue - if(!(islist(C.network))) + if(!(islist(cam.network))) stack_trace("Camera in a cameranet has a non-list camera network") continue - var/list/tempnetwork = C.network & network + var/list/tempnetwork = cam.network & network if(tempnetwork.len) - D["[C.c_tag]"] = C + D["[cam.c_tag]"] = cam return D // SECURITY MONITORS diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 87f0d6f7f75..27920dc2513 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -67,7 +67,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) for(var/mob/camera/ai_eye/eye as anything in moved_eyes) var/list/visibleChunks = list() - ///Get the eye's turf in case it's located in an object like a mecha + //Get the eye's turf in case it's located in an object like a mecha var/turf/eye_turf = get_turf(eye) if(eye.loc) var/static_range = eye.static_visibility_range @@ -110,10 +110,14 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) if(c.can_use()) majorChunkChange(c, 1) -/// Used for Cyborg cameras. Since portable cameras can be in ANY chunk. -/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c) - if(c.can_use()) - majorChunkChange(c, 1) +/** + * Used for Cyborg/mecha cameras. Since portable cameras can be in ANY chunk. + * update_delay_buffer is passed all the way to hasChanged() from their camera updates on movement + * to change the time between static updates. +*/ +/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/updating_camera, update_delay_buffer) + if(updating_camera.can_use()) + majorChunkChange(updating_camera, 1, update_delay_buffer) /** * Never access this proc directly!!!! @@ -121,8 +125,10 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) * It will also add the atom to the cameras list if you set the choice to 1. * Setting the choice to 0 will remove the camera from the chunks. * If you want to update the chunks around an object, without adding/removing a camera, use choice 2. + * update_delay_buffer is passed all the way to hasChanged() from portable camera updates on movement + * to change the time between static updates. */ -/datum/cameranet/proc/majorChunkChange(atom/c, choice) +/datum/cameranet/proc/majorChunkChange(atom/c, choice, update_delay_buffer) if(QDELETED(c) && choice == 1) CRASH("Tried to add a qdeleting camera to the net") @@ -142,7 +148,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) else if(choice == 1) // You can't have the same camera in the list twice. chunk.cameras["[T.z]"] |= c - chunk.hasChanged() + chunk.hasChanged(update_delay_buffer = update_delay_buffer) /// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0. /datum/cameranet/proc/checkCameraVis(mob/living/target) diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index c5549116fde..7d3b192721b 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -56,10 +56,13 @@ /** * 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. */ -/datum/camerachunk/proc/hasChanged(update_now = 0) +/datum/camerachunk/proc/hasChanged(update_now = 0, update_delay_buffer = UPDATE_BUFFER_TIME) if(seenby.len || update_now) - addtimer(CALLBACK(src, PROC_REF(update)), UPDATE_BUFFER_TIME, TIMER_UNIQUE) + addtimer(CALLBACK(src, PROC_REF(update)), update_delay_buffer, TIMER_UNIQUE) else changed = TRUE @@ -145,6 +148,10 @@ if(sillycone.builtInCamera?.can_use()) local_cameras += sillycone.builtInCamera + for(var/obj/vehicle/sealed/mecha/mech in urange(CHUNK_SIZE, locate(x + (CHUNK_SIZE / 2), y + (CHUNK_SIZE / 2), z_level))) + if(mech.chassis_camera?.can_use()) + local_cameras += mech.chassis_camera + cameras["[z_level]"] = local_cameras var/image/mirror_from = GLOB.cameranet.obscured_images[GET_Z_PLANE_OFFSET(z_level) + 1] diff --git a/code/modules/mob/living/silicon/silicon_movement.dm b/code/modules/mob/living/silicon/silicon_movement.dm index d225ccf9c16..0ea6ece169c 100644 --- a/code/modules/mob/living/silicon/silicon_movement.dm +++ b/code/modules/mob/living/silicon/silicon_movement.dm @@ -1,22 +1,24 @@ +//We only call a camera static update if we have successfully moved and the camera is present and working /mob/living/silicon/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() - update_camera_location(old_loc) + if(builtInCamera?.can_use()) + update_camera_location(old_loc) -/mob/living/silicon/forceMove(atom/destination) - . = ..() - //Only bother updating the camera if we actually managed to move - if(.) - update_camera_location(destination) - -/mob/living/silicon/proc/do_camera_update(oldLoc) - if(!QDELETED(builtInCamera) && oldLoc != get_turf(src)) - GLOB.cameranet.updatePortableCamera(builtInCamera) - updating = FALSE - -#define SILICON_CAMERA_BUFFER 10 /mob/living/silicon/proc/update_camera_location(oldLoc) oldLoc = get_turf(oldLoc) - if(!QDELETED(builtInCamera) && !updating && oldLoc != get_turf(src)) + if(!updating && oldLoc != get_turf(src)) updating = TRUE - addtimer(CALLBACK(src, PROC_REF(do_camera_update), oldLoc), SILICON_CAMERA_BUFFER) + do_camera_update(oldLoc) + +///The static update delay on movement of the camera in a borg we use +#define SILICON_CAMERA_BUFFER 0.5 SECONDS + +/** + * The actual update - also passes our unique update buffer. This makes our static update faster than stationary cameras, + * helping us to avoid running out of the camera's FoV. +*/ +/mob/living/silicon/proc/do_camera_update(oldLoc) + if(oldLoc != get_turf(src)) + GLOB.cameranet.updatePortableCamera(builtInCamera, SILICON_CAMERA_BUFFER) + updating = FALSE #undef SILICON_CAMERA_BUFFER diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index 44a1262ab5e..71cdeb9eb9c 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -137,24 +137,25 @@ var/list/visible_turfs = list() - // Is this camera located in or attached to a living thing? If so, assume the camera's loc is the living thing. - var/cam_location = isliving(active_camera.loc) ? active_camera.loc : active_camera + // Get the camera's turf to correctly gather what's visible from it's turf, in case it's located in a moving object (borgs / mechs) + var/new_cam_turf = get_turf(active_camera) // If we're not forcing an update for some reason and the cameras are in the same location, // we don't need to update anything. // Most security cameras will end here as they're not moving. - var/newturf = get_turf(cam_location) - if(last_camera_turf == newturf) + if(last_camera_turf == new_cam_turf) return // Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs. - last_camera_turf = get_turf(cam_location) + last_camera_turf = new_cam_turf - var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, cam_location) : view(active_camera.view_range, cam_location) + //Here we gather what's visible from the camera's POV based on its view_range and xray modifier if present + var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, new_cam_turf) : view(active_camera.view_range, new_cam_turf) for(var/turf/visible_turf in visible_things) visible_turfs += visible_turf + //Get coordinates for a rectangle area that contains the turfs we see so we can then clear away the static in the resulting rectangle area var/list/bbox = get_bbox_of_atoms(visible_turfs) var/size_x = bbox[3] - bbox[1] + 1 var/size_y = bbox[4] - bbox[2] + 1 @@ -172,7 +173,9 @@ /datum/computer_file/program/secureye/proc/get_available_cameras() var/list/L = list() for (var/obj/machinery/camera/cam as anything in GLOB.cameranet.cameras) - if(!is_station_level(cam.z))//Only show station cameras. + //Get the camera's turf in case it's inside something like a borg + var/turf/camera_turf = get_turf(cam) + if(!is_station_level(camera_turf.z))//Only show station cameras. continue L.Add(cam) var/list/camlist = list() diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index b856c5ba68d..f4a333e2cb5 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1315,6 +1315,34 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE +/datum/design/mecha_camera + name = "Exosuit External Camera Kit" + desc = "A durable CCTV camera designed for exosuit operations." + id = "mecha_camera" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/camera_kit + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500, /datum/material/plasma = 200, /datum/material/titanium = 200) + construction_time = 50 + category = list( + RND_CATEGORY_MECHFAB_EQUIPMENT, + RND_CATEGORY_MECHFAB_RIPLEY, + RND_CATEGORY_MECHFAB_GYGAX, + RND_CATEGORY_MECHFAB_DURAND, + RND_CATEGORY_MECHFAB_HONK, + RND_CATEGORY_MECHFAB_PHAZON, + RND_CATEGORY_MECHFAB_CLARKE + ) + category = list( + RND_CATEGORY_MECHFAB_EQUIPMENT + RND_SUBCATEGORY_MECHFAB_EQUIPMENT_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_RIPLEY + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_GYGAX + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_DURAND + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_HONK + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_PHAZON + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES, + RND_CATEGORY_MECHFAB_CLARKE + RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE + /datum/design/synthetic_flash name = "Flash" desc = "When a problem arises, SCIENCE is the solution." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 2c57e7deb7c..6d272dd1bc5 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -866,6 +866,7 @@ prereq_ids = list("base") design_ids = list( "paicard", + "mecha_camera" ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index b835eb2f55e..c239b3c2bd9 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -33,7 +33,7 @@ light_on = FALSE light_range = 8 generic_canpass = FALSE - hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD) + hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD) mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi' ///How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain. var/normal_step_energy_drain = 10 @@ -84,7 +84,12 @@ ///Special version of the radio, which is unsellable var/obj/item/radio/mech/radio + ///List of installed remote tracking beacons, including AI control beacons var/list/trackers = list() + ///Camera installed into the mech + var/obj/machinery/camera/exosuit/chassis_camera + ///Portable camera camerachunk update + var/updating = FALSE var/max_temperature = 25000 @@ -281,6 +286,8 @@ QDEL_NULL(spark_system) QDEL_NULL(smoke_system) QDEL_NULL(ui_view) + QDEL_NULL(trackers) + QDEL_NULL(chassis_camera) GLOB.mechas_list -= src //global mech list for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diff --git a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm index 437cf648a16..2b80ca48ea0 100644 --- a/code/modules/vehicles/mecha/equipment/tools/other_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/other_tools.dm @@ -510,3 +510,21 @@ icon_state = initial(icon_state) if(!locate(/obj/item/mecha_parts/mecha_equipment/concealed_weapon_bay) in mech.contents) //if no others exist mech.mech_type &= ~EXOSUIT_MODULE_CONCEALED_WEP_BAY + +/obj/item/mecha_parts/camera_kit + name = "exosuit-mounted camera" + desc = "A security camera meant for exosuit-mounted surveillance-on-the-go." + icon = 'icons/mecha/mecha_equipment.dmi' + icon_state = "mecha_camera" + w_class = WEIGHT_CLASS_SMALL + +/obj/item/mecha_parts/camera_kit/try_attach_part(mob/user, obj/vehicle/sealed/mecha/mech, attach_right) + if(mech.chassis_camera) + balloon_alert(user, "already has a camera!") + return FALSE + + . = ..() + + mech.chassis_camera = new /obj/machinery/camera/exosuit (mech) + mech.chassis_camera.update_c_tag(mech) + mech.diag_hud_set_camera() diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index ef3d33fa8df..fedbefaf7c5 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -168,6 +168,13 @@ take_damage(30 / severity, BURN, ENERGY, 1) log_message("EMP detected", LOG_MECHA, color="red") + //Mess with the focus of the inbuilt camera if present + if(chassis_camera && !chassis_camera.is_emp_scrambled) + chassis_camera.setViewRange(chassis_camera.short_range) + chassis_camera.is_emp_scrambled = TRUE + diag_hud_set_camera() + addtimer(CALLBACK(chassis_camera, TYPE_PROC_REF(/obj/machinery/camera/exosuit, emp_refocus), src), 10 SECONDS / severity) + if(!equipment_disabled && LAZYLEN(occupants)) //prevent spamming this message with back-to-back EMPs to_chat(occupants, span_warning("Error -- Connection to equipment control unit has been lost.")) addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/vehicle/sealed/mecha, restore_equipment)), 3 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) diff --git a/code/modules/vehicles/mecha/mecha_movement.dm b/code/modules/vehicles/mecha/mecha_movement.dm index d36693bc49f..d1513d4b3ee 100644 --- a/code/modules/vehicles/mecha/mecha_movement.dm +++ b/code/modules/vehicles/mecha/mecha_movement.dm @@ -148,3 +148,31 @@ var/mob/mob_obstacle = obstacle if(mob_obstacle.move_resist <= move_force) step(obstacle, dir) + +//Following procs are camera static update related and are basically ripped off of code\modules\mob\living\silicon\silicon_movement.dm + +//We only call a camera static update if we have successfully moved and have a camera installed +/obj/vehicle/sealed/mecha/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) + . = ..() + if(chassis_camera) + update_camera_location(old_loc) + +/obj/vehicle/sealed/mecha/proc/update_camera_location(oldLoc) + oldLoc = get_turf(oldLoc) + if(!updating && oldLoc != get_turf(src)) + updating = TRUE + do_camera_update(oldLoc) + +///The static update delay on movement of the camera in a mech we use +#define MECH_CAMERA_BUFFER 0.5 SECONDS + +/** + * The actual update - also passes our unique update buffer. This makes our static update faster than stationary cameras, + * helping us to avoid running out of the camera's FoV. An EMPd mecha with a lowered view_range on its camera can still + * sometimes run out into static before updating, however. +*/ +/obj/vehicle/sealed/mecha/proc/do_camera_update(oldLoc) + if(oldLoc != get_turf(src)) + GLOB.cameranet.updatePortableCamera(chassis_camera, MECH_CAMERA_BUFFER) + updating = FALSE +#undef MECH_CAMERA_BUFFER diff --git a/code/modules/vehicles/mecha/mecha_ui.dm b/code/modules/vehicles/mecha/mecha_ui.dm index 5a38b944a86..b8bb8402ab3 100644 --- a/code/modules/vehicles/mecha/mecha_ui.dm +++ b/code/modules/vehicles/mecha/mecha_ui.dm @@ -240,7 +240,11 @@ if(is_ic_filtered(userinput) || is_soft_ic_filtered(userinput)) tgui_alert(usr, "You cannot set a name that contains a word prohibited in IC chat!") return + if(userinput == format_text(name)) //default mecha names may have improper span artefacts in their name, so we format the name + to_chat(usr, span_notice("You rename [name] to... well, [userinput].")) + return name = userinput + chassis_camera.update_c_tag(src) if("toggle_safety") set_safety(usr) return diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index ad53c49a5b2..18d884df2ac 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/icons/mob/huds/hud.dmi b/icons/mob/huds/hud.dmi index 588f3745a32..cec784b7389 100644 Binary files a/icons/mob/huds/hud.dmi and b/icons/mob/huds/hud.dmi differ