var/list/GPS_list = list() /obj/item/device/gps name = "global positioning system" desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power." icon = 'icons/obj/gps.dmi' icon_state = "gps-gen" w_class = ITEMSIZE_TINY slot_flags = SLOT_BELT origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_MAGNET = 1) matter = list(DEFAULT_WALL_MATERIAL = 500) var/gps_tag = "GEN0" var/emped = FALSE var/updating = TRUE // Lets users lock the UI so they don't have to deal with constantly shifting signals var/tracking = FALSE // Will not show other signals or emit its own signal if false. var/long_range = FALSE // If true, can see farther, depending on get_map_levels(). var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown. var/hide_signal = FALSE // If true, signal is not visible to other GPS devices. var/can_hide_signal = FALSE // If it can toggle the above var. /obj/item/device/gps/Initialize() . = ..() GPS_list += src name = "global positioning system ([gps_tag])" update_icon() /obj/item/device/gps/Destroy() GPS_list -= src return ..() /obj/item/device/gps/AltClick(mob/user) toggletracking(user) /obj/item/device/gps/proc/toggletracking(mob/living/user) if(!istype(user)) return if(emped) to_chat(user, "It's busted!") return if(tracking) to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") tracking = FALSE update_icon() else to_chat(user, "[src] is now tracking, and visible to other GPS devices.") tracking = TRUE update_icon() /obj/item/device/gps/emp_act(severity) if(emped) // Without a fancy callback system, this will have to do. return var/severity_modifier = severity ? severity : 4 // In case emp_act gets called without any arguments. var/duration = 5 MINUTES / severity_modifier emped = TRUE update_icon() spawn(duration) emped = FALSE update_icon() visible_message("\The [src] appears to be functional again.") /obj/item/device/gps/update_icon() cut_overlays() if(emped) add_overlay("emp") else if(tracking) add_overlay("working") /obj/item/device/gps/attack_self(mob/user) tgui_interact(user) /obj/item/device/gps/examine(mob/user) . = ..() . += display() // Compiles all the data not available directly from the GPS // Like the positions and directions to all other GPS units /obj/item/device/gps/proc/display_list() var/list/dat = list() var/turf/curr = get_turf(src) var/area/my_area = get_area(src) dat["my_area_name"] = my_area.name dat["curr_x"] = curr.x dat["curr_y"] = curr.y dat["curr_z"] = curr.z dat["curr_z_name"] = using_map.get_zlevel_name(curr.z) dat["gps_list"] = list() dat["z_level_detection"] = using_map.get_map_levels(curr.z, long_range) for(var/obj/item/device/gps/G in GPS_list - src) if(!G.tracking || G.emped || G.hide_signal) continue var/turf/T = get_turf(G) if(!T) continue if(local_mode && curr.z != T.z) continue if(!(T.z in dat["z_level_detection"])) continue var/gps_data[0] gps_data["ref"] = G gps_data["gps_tag"] = G.gps_tag var/area/A = get_area(G) gps_data["area_name"] = A.get_name() gps_data["z_name"] = using_map.get_zlevel_name(T.z) gps_data["direction"] = get_adir(curr, T) gps_data["degrees"] = round(Get_Angle(curr,T)) gps_data["distX"] = T.x - curr.x gps_data["distY"] = T.y - curr.y gps_data["distance"] = get_dist(curr, T) gps_data["local"] = (curr.z == T.z) gps_data["x"] = T.x gps_data["y"] = T.y dat["gps_list"][++dat["gps_list"].len] = gps_data return dat /obj/item/device/gps/proc/display() if(!tracking) . = "The device is off. Alt-click it to turn it on." return if(emped) . = "It's busted!" return var/list/dat = list() var/list/gps_data = display_list() dat += "Current location: [gps_data["my_area_name"]] ([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])" dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ \[Toggle Scan Range\] \ [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" if(gps_data["gps_list"].len) dat += "Detected signals;" for(var/gps in gps_data["gps_list"]) if(istype(gps_data["ref"], /obj/item/device/gps/internal/poi)) dat += " [gps["gps_tag"]]: [gps["area_name"]] - [gps["local"] ? "[gps["direction"]] Dist: [round(gps["distance"], 10)]m" : "in \the [gps["z_name"]]"]" else dat += " [gps["gps_tag"]]: [gps["area_name"]], ([gps["x"]], [gps["y"]]) - [gps["local"] ? "[gps["direction"]] Dist: [gps["distX"] ? "[abs(round(gps["distX"], 1))]m [(gps["distX"] > 0) ? "E" : "W"], " : ""][gps["distY"] ? "[abs(round(gps["distY"], 1))]m [(gps["distY"] > 0) ? "N" : "S"]" : ""]" : "in \the [gps["z_name"]]"]" else dat += "No other signals detected." . = dat /obj/item/device/gps/Topic(var/href, var/list/href_list) if(..()) return 1 if(href_list["tag"]) var/a = input("Please enter desired tag.", name, gps_tag) as text a = uppertext(copytext(sanitize(a), 1, 11)) if(in_range(src, usr)) gps_tag = a name = "global positioning system ([gps_tag])" to_chat(usr, "You set your GPS's tag to '[gps_tag]'.") if(href_list["range"]) local_mode = !local_mode to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].") if(href_list["hide"]) if(!can_hide_signal) return hide_signal = !hide_signal to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.") /obj/item/device/gps/tgui_interact(mob/user, datum/tgui/ui) if(emped) to_chat(user, "[src] fizzles weakly.") return ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "Gps", name) ui.open() ui.set_autoupdate(updating) /obj/item/device/gps/tgui_data(mob/user) var/list/data = list() data["power"] = tracking data["tag"] = gps_tag data["updating"] = updating data["globalmode"] = !local_mode if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed return data var/turf/curr = get_turf(src) data["currentArea"] = "[get_area_name(curr, TRUE)]" data["currentCoords"] = list(curr.x, curr.y, curr.z) data["currentCoordsText"] = "[curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)]" data["zLevelDetection"] = using_map.get_map_levels(curr.z, long_range) var/list/signals = list() data["signals"] = list() for(var/obj/item/device/gps/G in GPS_list - src) if(!G.tracking || G.emped || G.hide_signal) continue var/turf/T = get_turf(G) if(!T) continue if(local_mode && curr.z != T.z) continue if(!(T.z in data["zLevelDetection"])) continue var/list/signal = list() signal["entrytag"] = G.gps_tag //Name or 'tag' of the GPS signal["coords"] = list(T.x, T.y, T.z) signal["coordsText"] = "[T.x], [T.y], [using_map.get_zlevel_name(T.z)]" if(T.z == curr.z) //Distance/Direction calculations for same z-level only signal["dist"] = max(get_dist(curr, T), 0) //Distance between the src and remote GPS turfs signal["degrees"] = round(Get_Angle(curr, T)) //0-360 degree directional bearing, for more precision. signals += list(signal) //Add this signal to the list of signals data["signals"] = signals return data /obj/item/device/gps/tgui_act(action, params) if(..()) return TRUE switch(action) if("rename") var/a = stripped_input(usr, "Please enter desired tag.", name, gps_tag, 20) if(!a) return gps_tag = a name = "global positioning system ([gps_tag])" . = TRUE if("power") toggletracking(usr) . = TRUE if("updating") updating = !updating . = TRUE if("globalmode") local_mode = !local_mode . = TRUE /obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these. tracking = TRUE /obj/item/device/gps/command icon_state = "gps-com" gps_tag = "COM0" /obj/item/device/gps/command/on tracking = TRUE /obj/item/device/gps/security icon_state = "gps-sec" gps_tag = "SEC0" /obj/item/device/gps/security/on tracking = TRUE /obj/item/device/gps/security/hos icon_state = "gps-sec-hos" gps_tag = "HOS0" /obj/item/device/gps/security/hos/on tracking = TRUE /obj/item/device/gps/medical icon_state = "gps-med" gps_tag = "MED0" /obj/item/device/gps/medical/on tracking = TRUE /obj/item/device/gps/medical/cmo icon_state = "gps-med-cmo" gps_tag = "CMO0" /obj/item/device/gps/medical/cmo/on tracking = TRUE /obj/item/device/gps/science icon_state = "gps-sci" gps_tag = "SCI0" /obj/item/device/gps/science/on tracking = TRUE /obj/item/device/gps/science/rd icon_state = "gps-sci-rd" gps_tag = "RD0" /obj/item/device/gps/science/rd/on tracking = TRUE /obj/item/device/gps/engineering icon_state = "gps-eng" gps_tag = "ENG0" /obj/item/device/gps/engineering/on tracking = TRUE /obj/item/device/gps/engineering/atmos icon_state = "gps-eng-atm" gps_tag = "ATM0" /obj/item/device/gps/engineering/atmos/on tracking = TRUE /obj/item/device/gps/engineering/ce icon_state = "gps-eng-ce" gps_tag = "CE0" /obj/item/device/gps/engineering/ce/on tracking = TRUE /obj/item/device/gps/mining icon_state = "gps-mine" gps_tag = "MINE0" desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power." /obj/item/device/gps/mining/on tracking = TRUE /obj/item/device/gps/explorer icon_state = "gps-exp" gps_tag = "EXP0" desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power." /obj/item/device/gps/explorer/on tracking = TRUE /obj/item/device/gps/robot icon_state = "gps-borg" gps_tag = "SYNTH0" desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \ Alt+click to toggle power." tracking = TRUE // On by default. /obj/item/device/gps/internal // Base type for immobile/internal GPS units. icon_state = "internal" gps_tag = "Eerie Signal" desc = "Report to a coder immediately." invisibility = INVISIBILITY_MAXIMUM tracking = TRUE // Meant to point to a location, so it needs to be on. anchored = TRUE /obj/item/device/gps/internal/base gps_tag = "NT_BASE" desc = "A homing signal from NanoTrasen's outpost." /obj/item/device/gps/internal/poi gps_tag = "Unidentified Signal" desc = "A signal that seems forboding." /obj/item/device/gps/syndie icon_state = "gps-syndie" gps_tag = "NULL" desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 2) long_range = TRUE hide_signal = TRUE can_hide_signal = TRUE /obj/item/device/gps/syndie/display(mob/user) if(!tracking) . = "The device is off. Alt-click it to turn it on." return if(emped) . = "It's busted!" return var/list/dat = list() var/list/gps_data = display_list() dat += "Current location: [gps_data["my_area_name"]] ([gps_data["curr_x"]], [gps_data["curr_y"]], [gps_data["curr_z_name"]])" dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ \[Toggle Scan Range\] \ [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" if(gps_data["gps_list"].len) dat += "Detected signals;" for(var/gps in gps_data["gps_list"]) dat += " [gps["gps_tag"]]: [gps["area_name"]] ([gps["x"]], [gps["y"]], [gps["z_name"]]) [gps["local"] ? "Dist: [gps["distance"]]m Dir: [gps["degrees"]]° ([gps["direction"]])" :""]" else dat += "No other signals detected." . = dat