diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 6a009677e1..4199a28bba 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -109,6 +109,9 @@
//Area flags, possibly more to come
#define RAD_SHIELDED 1 //shielded from radiation, clearly
+// VOREStation Edit Begin
+#define BLUE_SHIELDED 2 // shield from bluespace teleportation (telescience)
+// VOREStation Edit End
// Custom layer definitions, supplementing the default TURF_LAYER, MOB_LAYER, etc.
#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
diff --git a/code/game/area/Space Station 13 areas_vr.dm b/code/game/area/Space Station 13 areas_vr.dm
index 0e639737ae..476cb6bd61 100644
--- a/code/game/area/Space Station 13 areas_vr.dm
+++ b/code/game/area/Space Station 13 areas_vr.dm
@@ -1,44 +1,54 @@
/area/crew_quarters/sleep/vistor_room_1
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_2
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_3
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_4
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_5
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_6
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_7
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_8
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_9
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_10
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_11
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/crew_quarters/sleep/vistor_room_12
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | BLUE_SHIELDED
/area/teleporter/departing
name = "\improper Long-Range Teleporter"
icon_state = "teleporter"
music = "signal"
+// Override telescience shielding on some areas
+/area/security/armoury
+ flags = BLUE_SHIELDED
+
+/area/security/tactical
+ flags = BLUE_SHIELDED
+
+/area/security/nuke_storage
+ flags = BLUE_SHIELDED
+
// New shuttles
/area/shuttle/administration/transit
name = "Deep Space (AS)"
diff --git a/code/modules/telesci/bscyrstal.dm b/code/modules/telesci/bscyrstal.dm
new file mode 100644
index 0000000000..083cf56462
--- /dev/null
+++ b/code/modules/telesci/bscyrstal.dm
@@ -0,0 +1,46 @@
+// Bluespace crystals, used in telescience and when crushed it will blink you to a random turf.
+
+/obj/item/weapon/ore/bluespace_crystal
+ name = "bluespace crystal"
+ desc = "A glowing bluespace crystal, not much is known about how they work. It looks very delicate."
+ icon = 'icons/obj/telescience.dmi'
+ icon_state = "bluespace_crystal"
+ w_class = ITEMSIZE_TINY
+ origin_tech = list(TECH_BLUESPACE = 6, TECH_MATERIAL = 3)
+ var/blink_range = 8 // The teleport range when crushed/thrown at someone.
+
+/obj/item/weapon/ore/bluespace_crystal/New()
+ ..()
+ pixel_x = rand(-5, 5)
+ pixel_y = rand(-5, 5)
+
+/obj/item/weapon/ore/bluespace_crystal/attack_self(mob/user)
+ user.visible_message("[user] crushes [src]!", "You crush [src]!")
+ var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ s.set_up(5, 1, get_turf(src))
+ s.start()
+ blink_mob(user)
+ user.unEquip(src)
+ qdel(src)
+
+/obj/item/weapon/ore/bluespace_crystal/proc/blink_mob(mob/living/L)
+ do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg')
+
+/obj/item/weapon/ore/bluespace_crystal/throw_impact(atom/hit_atom)
+ if(!..()) // not caught in mid-air
+ visible_message("[src] fizzles and disappears upon impact!")
+ var/turf/T = get_turf(hit_atom)
+ var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ s.set_up(5, 1, T)
+ s.start()
+ if(isliving(hit_atom))
+ blink_mob(hit_atom)
+ qdel(src)
+
+// Artifical bluespace crystal, doesn't give you much research.
+
+/obj/item/weapon/ore/bluespace_crystal/artificial
+ name = "artificial bluespace crystal"
+ desc = "An artificially made bluespace crystal, it looks delicate."
+ origin_tech = list(TECH_BLUESPACE = 3, TECH_PHORON = 4)
+ blink_range = 4 // Not as good as the organic stuff!
diff --git a/code/modules/telesci/construction.dm b/code/modules/telesci/construction.dm
new file mode 100644
index 0000000000..fdb66857a5
--- /dev/null
+++ b/code/modules/telesci/construction.dm
@@ -0,0 +1,53 @@
+#ifndef T_BOARD
+#error T_BOARD macro is not defined but we need it!
+#endif
+
+// The circuit boards
+
+/obj/item/weapon/circuitboard/telesci_console
+ name = T_BOARD("Telepad Control Console")
+ build_path = /obj/machinery/computer/telescience
+ origin_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 3, TECH_PHORON = 4)
+
+/obj/item/weapon/circuitboard/telesci_pad
+ name = T_BOARD("Telepad")
+ board_type = new /datum/frame/frame_types/machine
+ build_path = /obj/machinery/telepad
+ origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_PHORON = 4, TECH_BLUESPACE = 5)
+ req_components = list(
+ /obj/item/weapon/ore/bluespace_crystal = 1,
+ /obj/item/weapon/stock_parts/capacitor = 2,
+ /obj/item/stack/cable_coil = 5,
+ /obj/item/weapon/stock_parts/console_screen = 1)
+
+// The Designs
+
+/datum/design/circuit/telesci_console
+ name = "Telepad Control Console"
+ id = "telesci_console"
+ req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 3, TECH_PHORON = 4)
+ build_path = /obj/item/weapon/circuitboard/telesci_console
+ sort_string = "HAAEA"
+
+/datum/design/circuit/telesci_pad
+ name = "Telepad"
+ id = "telesci_pad"
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_PHORON = 4, TECH_BLUESPACE = 5)
+ build_path = /obj/item/weapon/circuitboard/telesci_pad
+ sort_string = "HAAEB"
+
+/datum/design/item/telesci_gps
+ name = "AR sunglasses"
+ id = "telesci_gps"
+ req_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 1000)
+ build_path = /obj/item/device/gps/advanced
+ sort_string = "HAAEB"
+
+/datum/design/item/bluespace_crystal
+ name = "Artificial Bluespace Crystal"
+ id = "bluespace_crystal"
+ req_tech = list(TECH_BLUESPACE = 3, TECH_PHORON = 4)
+ materials = list("diamond" = 1500, "phoron" = 1500)
+ build_path = /obj/item/weapon/ore/bluespace_crystal/artificial
+ sort_string = "HAAEC"
diff --git a/code/modules/telesci/gps_advanced.dm b/code/modules/telesci/gps_advanced.dm
new file mode 100644
index 0000000000..7953b674d3
--- /dev/null
+++ b/code/modules/telesci/gps_advanced.dm
@@ -0,0 +1,78 @@
+var/global/list/GPS_list = list()
+
+// These are distinguished from the ordinary "Relay Position Devices" that just print your location
+// In that they are also all networked with each other to show each other's locations.
+/obj/item/device/gps/advanced
+ name = "global positioning system"
+ desc = "Helping lost spacemen find their way through the planets since 1995."
+ icon = 'icons/obj/telescience.dmi'
+ icon_state = "gps-c"
+ w_class = ITEMSIZE_SMALL
+ slot_flags = SLOT_BELT
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+ var/gpstag = "COM0"
+ var/emped = 0
+
+/obj/item/device/gps/advanced/New()
+ ..()
+ GPS_list.Add(src)
+ name = "global positioning system ([gpstag])"
+ overlays += "working"
+
+/obj/item/device/gps/advanced/Del()
+ GPS_list.Remove(src)
+ ..()
+
+/obj/item/device/gps/advanced/emp_act(severity)
+ emped = 1
+ overlays -= "working"
+ overlays += "emp"
+ spawn(300)
+ emped = 0
+ overlays -= "emp"
+ overlays += "working"
+
+/obj/item/device/gps/advanced/attack_self(mob/user as mob)
+
+ var/obj/item/device/gps/advanced/t = ""
+ if(emped)
+ t += "ERROR"
+ else
+ t += "
Set Tag "
+ t += "
Tag: [gpstag]"
+
+ for(var/obj/item/device/gps/advanced/G in GPS_list)
+ var/turf/pos = get_turf(G)
+ var/area/gps_area = get_area(G)
+ var/tracked_gpstag = G.gpstag
+ if(G.emped == 1)
+ t += "
[tracked_gpstag]: ERROR"
+ else
+ t += "
[tracked_gpstag]: [format_text(gps_area.name)] ([pos.x], [pos.y], [pos.z])"
+
+ var/datum/browser/popup = new(user, "GPS", name, 600, 450)
+ popup.set_content(t)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+
+/obj/item/device/gps/advanced/Topic(href, href_list)
+ ..()
+ if(href_list["tag"] )
+ var/a = input("Please enter desired tag.", name, gpstag) as text
+ a = uppertext(copytext(sanitize(a), 1, 5))
+ if(src.loc == usr)
+ gpstag = a
+ name = "global positioning system ([gpstag])"
+ attack_self(usr)
+
+/obj/item/device/gps/advanced/science
+ icon_state = "gps-s"
+ gpstag = "SCI0"
+
+/obj/item/device/gps/advanced/engineering
+ icon_state = "gps-e"
+ gpstag = "ENG0"
+
+/obj/item/device/gps/advanced/security
+ icon_state = "gps-sec"
+ gpstag = "SEC0"
diff --git a/code/modules/telesci/telepad.dm b/code/modules/telesci/telepad.dm
new file mode 100644
index 0000000000..1440482241
--- /dev/null
+++ b/code/modules/telesci/telepad.dm
@@ -0,0 +1,47 @@
+///SCI TELEPAD///
+/obj/machinery/telepad
+ name = "telepad"
+ desc = "A bluespace telepad used for teleporting objects to and from a location."
+ icon = 'icons/obj/telescience.dmi'
+ icon_state = "pad-idle"
+ anchored = 1
+ use_power = 1
+ circuit = /obj/item/weapon/circuitboard/telesci_pad
+ idle_power_usage = 200
+ active_power_usage = 5000
+ var/efficiency
+
+/obj/machinery/telepad/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/ore/bluespace_crystal(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 5)
+ RefreshParts()
+ update_icon()
+
+/obj/machinery/telepad/RefreshParts()
+ var/E
+ for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
+ E += C.rating
+ efficiency = E
+
+/obj/machinery/telepad/attackby(obj/item/W as obj, mob/user as mob)
+ src.add_fingerprint(user)
+
+ if(default_deconstruction_screwdriver(user, W))
+ return
+ if(default_deconstruction_crowbar(user, W))
+ return
+ if(default_part_replacement(user, W))
+ return
+ if(panel_open)
+ if(istype(W, /obj/item/device/multitool))
+ var/obj/item/device/multitool/M = W
+ M.connectable = src
+ user << "You save the data in the [M.name]'s buffer."
+ return 1
+
+ return ..()
diff --git a/code/modules/telesci/telesci_computer.dm b/code/modules/telesci/telesci_computer.dm
new file mode 100644
index 0000000000..bc4c92b611
--- /dev/null
+++ b/code/modules/telesci/telesci_computer.dm
@@ -0,0 +1,354 @@
+/obj/machinery/computer/telescience
+ name = "\improper Telepad Control Console"
+ desc = "Used to teleport objects to and from the telescience telepad."
+ icon_screen = "teleport"
+ icon_keyboard = "teleport_key"
+ circuit = /obj/item/weapon/circuitboard/telesci_console
+ var/sending = 1
+ var/obj/machinery/telepad/telepad = null
+ var/temp_msg = "Telescience control console initialized.
Welcome."
+
+ // VARIABLES //
+ var/teles_left // How many teleports left until it becomes uncalibrated
+ var/datum/projectile_data/last_tele_data = null
+ var/z_co = 1
+ var/power_off
+ var/rotation_off
+ var/last_target
+
+ var/rotation = 0
+ var/angle = 45
+ var/power = 5
+
+ // Based on the power used
+ var/teleport_cooldown = 0 // every index requires a bluespace crystal
+ var/list/power_options = list(5, 10, 20, 25, 30, 40, 50, 80, 100)
+ var/teleporting = 0
+ var/starting_crystals = 2
+ var/max_crystals = 4
+ var/list/crystals = list()
+ var/obj/item/device/gps/inserted_gps
+
+/obj/machinery/computer/telescience/New()
+ ..()
+ recalibrate()
+
+/obj/machinery/computer/telescience/Destroy()
+ eject()
+ if(inserted_gps)
+ inserted_gps.forceMove(loc)
+ inserted_gps = null
+ return ..()
+
+/obj/machinery/computer/telescience/examine(mob/user)
+ ..()
+ user << "There are [crystals.len ? crystals.len : "no"] bluespace crystal\s in the crystal slots."
+
+/obj/machinery/computer/telescience/initialize()
+ ..()
+ for(var/i = 1; i <= starting_crystals; i++)
+ crystals += new /obj/item/weapon/ore/bluespace_crystal/artificial(src) // starting crystals
+
+/obj/machinery/computer/telescience/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/weapon/ore/bluespace_crystal))
+ if(crystals.len >= max_crystals)
+ user << "There are not enough crystal slots."
+ return
+ if(!user.drop_item())
+ return
+ crystals += W
+ W.forceMove(src)
+ user.visible_message("[user] inserts [W] into \the [src]'s crystal slot.", "You insert [W] into \the [src]'s crystal slot.")
+ updateDialog()
+ else if(istype(W, /obj/item/device/gps))
+ if(!inserted_gps)
+ inserted_gps = W
+ user.unEquip(W)
+ W.forceMove(src)
+ user.visible_message("[user] inserts [W] into \the [src]'s GPS device slot.", "You insert [W] into \the [src]'s GPS device slot.")
+ else if(istype(W, /obj/item/device/multitool))
+ var/obj/item/device/multitool/M = W
+ if(M.connectable && istype(M.connectable, /obj/machinery/telepad))
+ telepad = M.connectable
+ M.connectable = null
+ user << "You upload the data from the [W.name]'s buffer."
+ else
+ return ..()
+
+/obj/machinery/computer/telescience/attack_ai(mob/user)
+ src.attack_hand(user)
+
+/obj/machinery/computer/telescience/attack_hand(mob/user)
+ if(..())
+ return
+ ui_interact(user)
+
+/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ user.set_machine(src)
+ var/data[0]
+
+ if(!telepad)
+ in_use = 0 //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console
+ data["noTelepad"] = 1
+ else
+ data["insertedGps"] = inserted_gps
+ data["tempMsg"] = temp_msg
+ data["rotation"] = rotation
+ data["angle"] = angle
+ data["power"] = power
+ data["currentZ"] = z_co
+ data["lastTeleData"] = list()
+
+ data["powerOptions"] = new/list(power_options.len)
+ for(var/i = 1; i <= power_options.len; i++)
+ var/enabled = (crystals.len + telepad.efficiency >= i);
+ data["powerOptions"][i] = list("power" = power_options[i], "enabled" = enabled)
+
+ data["sectorOptions"] = list()
+ for(var/z in config.player_levels)
+ data["sectorOptions"] += z
+
+ if(last_tele_data)
+ data["lastTeleData"]["src_x"] = last_tele_data.src_x
+ data["lastTeleData"]["src_y"] = last_tele_data.src_y
+ data["lastTeleData"]["distance"] = last_tele_data.distance
+ data["lastTeleData"]["time"] = last_tele_data.time
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "telescience_console.tmpl", src.name, 400, 450)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(5)
+
+/obj/machinery/computer/telescience/proc/sparks()
+ if(telepad)
+ var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ s.set_up(5, 1, get_turf(telepad))
+ s.start()
+ else
+ return
+
+/obj/machinery/computer/telescience/proc/telefail()
+ sparks()
+ visible_message("The telepad weakly fizzles.")
+ return
+
+/obj/machinery/computer/telescience/proc/doteleport(mob/user)
+
+ if(teleport_cooldown > world.time)
+ temp_msg = "Telepad is recharging power.
Please wait [round((teleport_cooldown - world.time) / 10)] seconds."
+ return
+
+ if(teleporting)
+ temp_msg = "Telepad is in use.
Please wait."
+ return
+
+ if(telepad)
+ var/truePower = Clamp(power + power_off, 1, 1000)
+ var/trueRotation = rotation + rotation_off
+ var/trueAngle = Clamp(angle, 1, 90)
+
+ var/datum/projectile_data/proj_data = projectile_trajectory(telepad.x, telepad.y, trueRotation, trueAngle, truePower)
+ last_tele_data = proj_data
+
+ var/trueX = Clamp(round(proj_data.dest_x, 1), 1, world.maxx)
+ var/trueY = Clamp(round(proj_data.dest_y, 1), 1, world.maxy)
+ var/spawn_time = round(proj_data.time) * 10
+
+ var/turf/target = locate(trueX, trueY, z_co)
+ last_target = target
+ var/area/A = get_area(target)
+ flick("pad-beam", telepad)
+
+ if(spawn_time > 15) // 1.5 seconds
+ playsound(telepad.loc, 'sound/weapons/flash.ogg', 25, 1)
+ // Wait depending on the time the projectile took to get there
+ teleporting = 1
+ temp_msg = "Powering up bluespace crystals.
Please wait."
+
+
+ spawn(round(proj_data.time) * 10) // in seconds
+ if(!telepad)
+ return
+ if(telepad.stat & NOPOWER)
+ return
+ teleporting = 0
+ teleport_cooldown = world.time + (power * 2)
+ teles_left -= 1
+
+ // use a lot of power
+ use_power(power * 10)
+
+ var/datum/effect/effect/system/spark_spread/S = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ S.set_up(5, 1, get_turf(telepad))
+ S.start()
+
+ if(!A || (A.flags & BLUE_SHIELDED))
+ telefail()
+ temp_msg = "ERROR!
Target is shielded from bluespace intersection!"
+ return
+
+ temp_msg = "Teleport successful.
"
+ if(teles_left < 10)
+ temp_msg += "
Calibration required soon."
+ else
+ temp_msg += "Data printed below."
+
+ var/sparks = get_turf(target)
+ var/datum/effect/effect/system/spark_spread/Y = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ Y.set_up(5, 1, sparks)
+ Y.start()
+
+ var/turf/source = target
+ var/turf/dest = get_turf(telepad)
+ var/log_msg = ""
+ log_msg += ": [key_name(user)] has teleported "
+
+ if(sending)
+ source = dest
+ dest = target
+
+ flick("pad-beam", telepad)
+ playsound(telepad.loc, 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
+ for(var/atom/movable/ROI in source)
+ // if is anchored, don't let through
+ if(ROI.anchored)
+ if(isliving(ROI))
+ var/mob/living/L = ROI
+ if(L.buckled)
+ // TP people on office chairs
+ if(L.buckled.anchored)
+ continue
+
+ log_msg += "[key_name(L)] (on a chair), "
+ else
+ continue
+ else if(!isobserver(ROI))
+ continue
+ if(ismob(ROI))
+ var/mob/T = ROI
+ log_msg += "[key_name(T)], "
+ else
+ log_msg += "[ROI.name]"
+ if (istype(ROI, /obj/structure/closet))
+ var/obj/structure/closet/C = ROI
+ log_msg += " ("
+ for(var/atom/movable/Q as mob|obj in C)
+ if(ismob(Q))
+ log_msg += "[key_name(Q)], "
+ else
+ log_msg += "[Q.name], "
+ if (dd_hassuffix(log_msg, "("))
+ log_msg += "empty)"
+ else
+ log_msg += ")"
+ log_msg += ", "
+ do_teleport(ROI, dest)
+
+ if (!dd_hassuffix(log_msg, ", "))
+ log_msg += "nothing"
+ log_msg += " [sending ? "to" : "from"] [trueX], [trueY], [z_co] ([A ? A.name : "null area"])"
+ investigate_log(log_msg, "telesci")
+ updateDialog()
+
+/obj/machinery/computer/telescience/proc/teleport(mob/user)
+ if(rotation == null || angle == null || z_co == null)
+ temp_msg = "ERROR!
Set a angle, rotation and sector."
+ return
+ if(power <= 0)
+ telefail()
+ temp_msg = "ERROR!
No power selected!"
+ return
+ if(angle < 1 || angle > 90)
+ telefail()
+ temp_msg = "ERROR!
Elevation is less than 1 or greater than 90."
+ return
+ if(!(z_co in config.player_levels))
+ telefail()
+ temp_msg = "ERROR! Sector is outside known time and space!"
+ return
+ if(teles_left > 0)
+ doteleport(user)
+ else
+ telefail()
+ temp_msg = "ERROR!
Calibration required."
+ return
+ return
+
+/obj/machinery/computer/telescience/proc/eject()
+ for(var/obj/item/I in crystals)
+ I.forceMove(src.loc)
+ crystals -= I
+ power = 0
+
+/obj/machinery/computer/telescience/Topic(href, href_list)
+ if(..())
+ return
+ if(!telepad)
+ updateDialog()
+ return
+ if(telepad.panel_open)
+ temp_msg = "Telepad undergoing physical maintenance operations."
+
+ if(href_list["setrotation"])
+ var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num
+ if(..()) // Check after we input a value, as they could've moved after they entered something
+ return
+ rotation = Clamp(new_rot, -900, 900)
+ rotation = round(rotation, 0.01)
+
+ if(href_list["setangle"])
+ var/new_angle = input("Please input desired elevation in degrees.", name, angle) as num
+ if(..())
+ return
+ angle = Clamp(round(new_angle, 0.1), 1, 9999)
+
+ if(href_list["setpower"])
+ var/index = href_list["setpower"]
+ index = text2num(index)
+ if(index != null && power_options[index])
+ if(crystals.len + telepad.efficiency >= index)
+ power = power_options[index]
+
+ if(href_list["setz"])
+ var/new_z = text2num(href_list["setz"])
+ if(new_z in config.player_levels)
+ z_co = new_z
+
+ if(href_list["ejectGPS"])
+ if(inserted_gps)
+ inserted_gps.forceMove(loc)
+ inserted_gps = null
+
+ if(href_list["setMemory"])
+ if(last_target && inserted_gps)
+ // TODO - What was this even supposed to do??
+ //inserted_gps.locked_location = last_target
+ temp_msg = "Location saved."
+ else
+ temp_msg = "ERROR!
No data was stored."
+
+ if(href_list["send"])
+ sending = 1
+ teleport(usr)
+
+ if(href_list["receive"])
+ sending = 0
+ teleport(usr)
+
+ if(href_list["recal"])
+ recalibrate()
+ sparks()
+ temp_msg = "NOTICE:
Calibration successful."
+
+ if(href_list["eject"])
+ eject()
+ temp_msg = "NOTICE:
Bluespace crystals ejected."
+
+ updateDialog()
+
+/obj/machinery/computer/telescience/proc/recalibrate()
+ teles_left = rand(40, 50)
+ power_off = rand(-4, 4)
+ rotation_off = rand(-10, 10)
diff --git a/icons/obj/telescience.dmi b/icons/obj/telescience.dmi
new file mode 100644
index 0000000000..34d42f100f
Binary files /dev/null and b/icons/obj/telescience.dmi differ
diff --git a/nano/templates/telescience_console.tmpl b/nano/templates/telescience_console.tmpl
index 4f88267510..80cf58a3df 100644
--- a/nano/templates/telescience_console.tmpl
+++ b/nano/templates/telescience_console.tmpl
@@ -2,19 +2,60 @@
Title: Telescience Control UI
Used In File(s): \code\modules\telesci\telesci_computer.dm
-->
-