mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-18 18:42:08 +01:00
* Adds examine boxes. * lint * what kind of dreams did you dream? * unlimited * midgardsormr * sdsd * fixes --------- Co-authored-by: Matt Atlas <liermattia@gmail.com>
310 lines
11 KiB
Plaintext
310 lines
11 KiB
Plaintext
/* 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 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/device.dmi'
|
|
icon_state = "locator"
|
|
var/temp = null
|
|
var/frequency = 1451
|
|
var/broadcasting = null
|
|
var/listening = TRUE
|
|
obj_flags = OBJ_FLAG_CONDUCTABLE
|
|
w_class = ITEMSIZE_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]<BR><BR><A href='byond://?src=\ref[src];temp=1'>Clear</A>"
|
|
else
|
|
dat = {"
|
|
<B>Persistent Signal Locator</B><HR>
|
|
Frequency:
|
|
<A href='byond://?src=\ref[src];freq=-10'>-</A>
|
|
<A href='byond://?src=\ref[src];freq=-2'>-</A> [format_frequency(src.frequency)]
|
|
<A href='byond://?src=\ref[src];freq=2'>+</A>
|
|
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
|
|
|
|
<A href='?src=\ref[src];refresh=1'>Refresh</A>"}
|
|
user << browse(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 = "<B>Persistent Signal Locator</B><HR>"
|
|
var/turf/sr = get_turf(src)
|
|
|
|
if (sr)
|
|
src.temp += "<B>Located Beacons:</B><BR>"
|
|
|
|
for(var/obj/item/device/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]<BR>"
|
|
|
|
src.temp += "<B>Extraneous Signals:</B><BR>"
|
|
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]<BR>"
|
|
|
|
src.temp += "<B>You are at \[[sr.x],[sr.y],[sr.z]\]</B> in orbital coordinates.<BR><BR><A href='byond://?src=\ref[src];refresh=1'>Refresh</A><BR>"
|
|
else
|
|
src.temp += "<B><span class='warning'>Processing Error:</span></B> Unable to locate orbital position.<BR>"
|
|
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."
|
|
desc_info = "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."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "hand_tele"
|
|
item_state = "electronic"
|
|
throwforce = 5
|
|
item_flags = ITEM_FLAG_HELD_MAP_TEXT
|
|
w_class = ITEMSIZE_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/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
|
|
. = ..()
|
|
if(linked_pad)
|
|
var/area/A = get_area(linked_pad)
|
|
. += SPAN_NOTICE("\The [src] is linked to a teleportation pad in [A.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)
|
|
if(P.engaged)
|
|
teleport_options["[A.name] (Active)"] = P
|
|
else
|
|
teleport_options["[A.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)
|
|
GLOB.destroyed_event.register(linked_pad, src, PROC_REF(pad_destroyed))
|
|
if(old_pad && linked_pad != old_pad)
|
|
GLOB.destroyed_event.unregister(old_pad, src)
|
|
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"))
|
|
|
|
/obj/item/closet_teleporter
|
|
name = "closet teleporter"
|
|
desc = "A device that allows a user to connect two closets into a bluespace network."
|
|
desc_antag = "Click a closet with this to install. Step into the closet and close the door to teleport to the linked closet. It has a one minute cooldown after a batch teleport."
|
|
icon = 'icons/obj/modular_components.dmi'
|
|
icon_state = "cpu_normal_photonic"
|
|
obj_flags = OBJ_FLAG_CONDUCTABLE
|
|
w_class = ITEMSIZE_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/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)
|
|
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."))
|
|
else
|
|
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 ..()
|