/* Teleportation devices. * Contains: * * Locator * * Hand-tele * * Closet Teleporter * * Inhibitor handling proc for above */ /* * Special inhibitor handling. Different from the one used by teleport datums. */ /proc/check_inhibitors(var/turf/T) for(var/found_inhibitor in GLOB.bluespace_inhibitors) var/obj/machinery/anti_bluespace/AB = found_inhibitor if(T.z != AB.z || get_dist(T, AB) > 8 || (AB.stat & (NOPOWER | BROKEN))) continue else return FALSE return TRUE /* * Locator */ /obj/item/locator name = "locator" desc = "A device that can be used to track those with locator implants." icon = 'icons/obj/item/pinpointer.dmi' icon_state = "pinoff" var/temp = null var/frequency = 1451 var/broadcasting = null var/listening = TRUE obj_flags = OBJ_FLAG_CONDUCTABLE w_class = WEIGHT_CLASS_SMALL item_state = "electronic" throw_speed = 4 throw_range = 20 origin_tech = list(TECH_MAGNET = 1) matter = list(DEFAULT_WALL_MATERIAL = 400) /obj/item/locator/attack_self(mob/user as mob) user.set_machine(src) var/dat if (src.temp) dat = "[src.temp]

Clear" else dat = {" Persistent Signal Locator
Frequency: - - [format_frequency(src.frequency)] + +
Refresh"} user << browse(HTML_SKELETON(dat), "window=radio") onclose(user, "radio") return /obj/item/locator/Topic(href, href_list) ..() if (usr.stat || usr.restrained()) return var/turf/current_location = get_turf(usr)//What turf is the user on? if(!current_location||current_location.z==1)//If turf was not found or they're on z level 1. to_chat(usr, "The [src] is malfunctioning.") return if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) usr.set_machine(src) if (href_list["refresh"]) src.temp = "Persistent Signal Locator
" var/turf/sr = get_turf(src) if (sr) src.temp += "Located Beacons:
" for(var/obj/item/radio/beacon/W in GLOB.teleportbeacons) if (W.get_frequency() == src.frequency) var/turf/tr = get_turf(W) if (tr.z == sr.z && tr) var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) if (direct < 5) direct = "very strong" else if (direct < 10) direct = "strong" else if (direct < 20) direct = "weak" else direct = "very weak" src.temp += "[W.code]-[dir2text(get_dir(sr, tr))]-[direct]
" src.temp += "Extraneous Signals:
" for (var/obj/item/implant/tracking/W in GLOB.implants) if (!W.implanted || !(istype(W.loc,/obj/item/organ/external) || ismob(W.loc))) continue else var/mob/M = W.loc if (M.stat == DEAD) if (M.timeofdeath + W.lifespan_postmortem < world.time) continue var/turf/tr = get_turf(W) if (tr.z == sr.z && tr) var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) if (direct < 20) if (direct < 5) direct = "very strong" else if (direct < 10) direct = "strong" else direct = "weak" src.temp += "[W.id]-[dir2text(get_dir(sr, tr))]-[direct]
" src.temp += "You are at \[[sr.x],[sr.y],[sr.z]\] in orbital coordinates.

Refresh
" else src.temp += "Processing Error: Unable to locate orbital position.
" else if (href_list["freq"]) src.frequency += text2num(href_list["freq"]) src.frequency = sanitize_frequency(src.frequency) else if (href_list["temp"]) src.temp = null if (istype(src.loc, /mob)) attack_self(src.loc) else for(var/mob/M in viewers(1, src)) if (M.client) src.attack_self(M) return /* * Hand-tele */ /obj/item/hand_tele name = "hand tele" desc = "A hand-held bluespace teleporter that can rip open portals to a random nearby location, or lock onto a teleporter with a selected teleportation beacon." icon = 'icons/obj/item/hand_tele.dmi' icon_state = "hand_tele" item_state = "electronic" throwforce = 5 item_flags = ITEM_FLAG_HELD_MAP_TEXT w_class = WEIGHT_CLASS_SMALL throw_speed = 3 throw_range = 5 origin_tech = list(TECH_MAGNET = 1, TECH_BLUESPACE = 3) matter = list(DEFAULT_WALL_MATERIAL = 10000) var/obj/machinery/teleport/pad/linked_pad var/list/active_teleporters var/max_portals = 2 /obj/item/hand_tele/mechanics_hints(mob/user, distance, is_adjacent) . += ..() . += "Ctrl-click to choose which teleportation pad to link to." . += "Use in-hand or alt-click to deploy a portal. " . += "When not linked to a pad, or the pad isn't pointing at a beacon, it will choose a completely random teleportation destination." /obj/item/hand_tele/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(linked_pad) var/area/A = get_area(linked_pad) var/display_name = get_area_display_name(A) . += SPAN_NOTICE("\The [src] is linked to a teleportation pad in [display_name]") else . += SPAN_WARNING("\The [src] isn't linked to any teleportation pads!") /obj/item/hand_tele/set_initial_maptext() held_maptext = SMALL_FONTS(7, "Ready") /obj/item/hand_tele/attack_self(mob/user) var/turf/current_location = get_turf(user)//What turf is the user on? if(!current_location || isAdminLevel(current_location.z)) to_chat(user, SPAN_WARNING("\The [src] can't get a bearing on anything right now.")) return //Cannot make one if too close to an inhibitor if(!check_inhibitors(current_location)) to_chat(user, SPAN_DANGER("\The [src] can't seem to find a lock. Something in the area must be preventing the portal from opening...")) return if(LAZYLEN(active_teleporters) >= max_portals) user.show_message(SPAN_WARNING("\The [src] is recharging!")) return var/turf/teleport_turf if(linked_pad) if(linked_pad.stat & (NOPOWER|BROKEN)) to_chat(user, SPAN_WARNING("The pad \the [src] is connected doesn't seem to be responding!")) return if(!AreConnectedZLevels(current_location.z, linked_pad.z)) to_chat(user, SPAN_WARNING("The pad \the [src] is connected to isn't close enough to lock onto now!")) return if(linked_pad.locked_obj) teleport_turf = get_turf(linked_pad.locked_obj.resolve()) else var/list/potential_turfs = list() for(var/turf/T in orange(10)) if(T.x > world.maxx-8 || T.x < 8) continue //putting them at the edge is dumb if(T.y > world.maxy-8 || T.y < 8) continue if(T.density || turf_contains_dense_objects(T)) continue if(!check_inhibitors(T)) continue potential_turfs += T teleport_turf = pick(potential_turfs) if(!teleport_turf) to_chat(user, SPAN_WARNING("\The [src] was unable to get a lock onto anything!")) return if(isAdminLevel(teleport_turf.z)) to_chat(user, SPAN_WARNING("The signal to the beacon seems to be scrambled!")) return var/obj/effect/portal/P = new /obj/effect/portal(get_turf(src), teleport_turf, src) LAZYADD(active_teleporters, P) if(LAZYLEN(active_teleporters) >= max_portals) check_maptext(SMALL_FONTS(6, "Charge")) add_fingerprint(user) /obj/item/hand_tele/AltClick(mob/user) if(user == loc) attack_self(user) return return ..() /obj/item/hand_tele/CtrlClick(mob/user) if(user == loc) var/turf/current_location = get_turf(src) var/list/teleport_options = list() for(var/obj/machinery/teleport/pad/P in SSmachinery.machinery) if(AreConnectedZLevels(current_location.z, P.z)) var/area/A = get_area(P) var/display_name = get_area_display_name(A) if(P.engaged) teleport_options["[display_name] (Active)"] = P else teleport_options["[display_name] (Inactive)"] = P teleport_options["None (Dangerous)"] = null var/teleport_choice = tgui_input_list(user, "Please select a teleporter to lock in on.", "Hand Teleporter", teleport_options) if(!teleport_choice) return var/old_pad = linked_pad linked_pad = teleport_options[teleport_choice] if(linked_pad) RegisterSignal(linked_pad, COMSIG_QDELETING, PROC_REF(pad_destroyed)) if(old_pad && linked_pad != old_pad) UnregisterSignal(old_pad, COMSIG_QDELETING) return return ..() /obj/item/hand_tele/proc/pad_destroyed() linked_pad = null audible_message("\The [src] beeps, \"Connected pad destroyed, resetting to no-pad.\"", null, 3) /obj/item/hand_tele/proc/remove_portal(var/obj/effect/portal/P) LAZYREMOVE(active_teleporters, P) if(LAZYLEN(active_teleporters) < max_portals) check_maptext(SMALL_FONTS(7, "Ready")) icon_state = "hand_tele" else icon_state = "hand_tele_recharging" /obj/item/closet_teleporter name = "closet teleporter" desc = "A device that allows a user to connect two closets into a bluespace network." icon = 'icons/obj/modular_computers/modular_components.dmi' icon_state = "cpu_normal_photonic" obj_flags = OBJ_FLAG_CONDUCTABLE w_class = WEIGHT_CLASS_SMALL origin_tech = list(TECH_MAGNET = 2, TECH_BLUESPACE = 3) matter = list(DEFAULT_WALL_MATERIAL = 400) var/obj/structure/closet/attached_closet var/obj/item/closet_teleporter/linked_teleporter var/last_use = 0 /obj/item/closet_teleporter/antagonist_hints(mob/user, distance, is_adjacent) . += ..() . += "Left-click a closet with this to install." . += "Once two closets have been 'upgraded', step into one closet and close the door to teleport to the linked closet." . += "It has a one minute cooldown after a batch teleport." /obj/item/closet_teleporter/proc/do_teleport(var/mob/user) if(!attached_closet) to_chat(user, SPAN_WARNING("\The [src] doesn't have an attached closet!")) return FALSE if(!linked_teleporter) to_chat(user, SPAN_WARNING("\The [src] doesn't have a linked teleporter!")) return FALSE if(!linked_teleporter.attached_closet) to_chat(user, SPAN_WARNING("The linked teleporter doesn't have an attached closet!")) return FALSE if(last_use + 600 > world.time) return FALSE if(!check_inhibitors(get_turf(attached_closet)) || !check_inhibitors(get_turf(linked_teleporter.attached_closet))) to_chat(user, SPAN_WARNING("Something near you or your destination is destabilizing the bluespace network between the closets. \The [src] can't get a clear link to the other side!")) return FALSE var/obj/structure/closet/target_closet = linked_teleporter.attached_closet user.forceMove(target_closet.opened ? get_turf(target_closet) : target_closet) if(target_closet.opened) if(user.client) user.client.eye = user.client.mob user.client.perspective = MOB_PERSPECTIVE user.visible_message(SPAN_NOTICE("\The [user] steps out of the back of \the [target_closet]."), SPAN_NOTICE("You teleport into the linked closet, stepping out of it.")) user.set_fullscreen(FALSE, "closet_impaired", /atom/movable/screen/fullscreen/closet_impaired) else if(user.client) user.client.eye = target_closet target_closet.visible_message(SPAN_WARNING("\The [target_closet] rattles.")) to_chat(user, SPAN_NOTICE("You teleport into the target closet, bumping into the closed door.")) target_closet.shake_animation() playsound(get_turf(src), 'sound/effects/grillehit.ogg', 100, TRUE) return TRUE /obj/item/closet_teleporter/Destroy() attached_closet = null if(linked_teleporter?.linked_teleporter == src) linked_teleporter.linked_teleporter = null linked_teleporter = null return ..()