diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 24c3a2a2903..be81a2e3bb8 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -1294,6 +1294,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/storage/box/syndie_kit/bonerepair cost = 4 +/datum/uplink_item/device_tools/syndicate_teleporter + name = "Experimental Syndicate Teleporter" + desc = "The Syndicate teleporter is a handheld device that teleports the user 4-8 meters forward. \ + Beware, teleporting into a wall will make the teleporter do a parallel emergency teleport, \ + but if that emergency teleport fails, it will kill you. \ + Has 4 charges, recharges, warrenty voided if exposed to EMP." + reference = "TELE" + item = /obj/item/storage/box/syndie_kit/teleporter + cost = 8 + /datum/uplink_item/device_tools/thermal_drill name = "Thermal Safe Drill" desc = "A tungsten carbide thermal drill with magnetic clamps for the purpose of drilling hardened objects. Guaranteed 100% jam proof." diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 1ffa9cceb88..2336be40cfb 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -168,3 +168,203 @@ effective or pretty fucking useless. GLOB.active_jammers |= src else GLOB.active_jammers -= src + +/obj/item/teleporter + name = "Syndicate teleporter" + desc = "A strange syndicate version of a cult veil shifter. Warrenty voided if exposed to EMP." + icon = 'icons/obj/device.dmi' + icon_state = "syndi-tele" + throwforce = 5 + w_class = WEIGHT_CLASS_SMALL + throw_speed = 4 + throw_range = 10 + flags = CONDUCT + item_state = "electronic" + origin_tech = "magnets=3;combat=3;syndicate=3" + var/tp_range = 8 + var/inner_tp_range = 3 + var/charges = 4 + var/max_charges = 4 + var/saving_throw_distance = 3 + var/flawless = FALSE + +/obj/item/teleporter/Initialize(mapload, ...) + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/teleporter/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/teleporter/examine(mob/user) + . = ..() + . += "[src] has [charges] out of [max_charges] charges left." + +/obj/item/teleporter/attack_self(mob/user) + attempt_teleport(user, FALSE) + +/obj/item/teleporter/process() + if(prob(10) && charges < max_charges) + charges++ + +/obj/item/teleporter/emp_act(severity) + if(prob(50 / severity)) + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/user = loc + to_chat(user, "The [src] buzzes and activates!") + attempt_teleport(user, TRUE) + else + visible_message(" The [src] activates and blinks out of existence!") + do_sparks(2, 1, src) + qdel(src) + +/obj/item/teleporter/proc/attempt_teleport(mob/user, EMP_D = FALSE) + if(!charges) + to_chat(user, "The [src] is recharging still.") + return + + var/mob/living/carbon/C = user + var/turf/mobloc = get_turf(C) + var/list/turfs = new/list() + var/found_turf = FALSE + var/list/bagholding = user.search_contents_for(/obj/item/storage/backpack/holding) + for(var/turf/T in range(user, tp_range)) + if(!is_teleport_allowed(T.z)) + break + if(!(length(bagholding) && !flawless)) //Chaos if you have a bag of holding + if(get_dir(C, T) != C.dir) + continue + if(T in range(user, inner_tp_range)) + continue + if(T.x > world.maxx-tp_range || T.x < tp_range) + continue //putting them at the edge is dumb + if(T.y > world.maxy-tp_range || T.y < tp_range) + continue + + turfs += T + found_turf = TRUE + + if(found_turf) + if(user.loc != mobloc) // No locker / mech / sleeper teleporting, that breaks stuff + to_chat(C, "The [src] will not work here!") + charges-- + var/turf/destination = pick(turfs) + if(tile_check(destination) || flawless) // Why is there so many bloody floor types + var/turf/fragging_location = destination + telefrag(fragging_location, user) + C.forceMove(destination) + playsound(mobloc, "sparks", 50, TRUE) + new/obj/effect/temp_visual/teleport_abductor/syndi_teleporter(mobloc) + playsound(destination, "sparks", 50, TRUE) + new/obj/effect/temp_visual/teleport_abductor/syndi_teleporter(destination) + else if (EMP_D == FALSE && !(bagholding.len && !flawless)) // This is where the fun begins + var/direction = get_dir(user, destination) + panic_teleport(user, destination, direction) + else // Emp activated? Bag of holding? No saving throw for you + get_fragged(user, destination) + else + to_chat(C, "The [src] will not work here!") + +/obj/item/teleporter/proc/tile_check(turf/T) + if(istype(T, /turf/simulated/floor) || istype(T, /turf/space) || istype(T, /turf/simulated/shuttle/floor) || istype(T, /turf/simulated/shuttle/floor4) || istype(T, /turf/simulated/shuttle/plating)) + return TRUE + +/obj/item/teleporter/proc/panic_teleport(mob/user, turf/destination, direction = NORTH) + var/saving_throw + switch(direction) + if(NORTH || SOUTH) + if(prob(50)) + saving_throw = EAST + else + saving_throw = WEST + if(EAST || WEST) + if(prob(50)) + saving_throw = NORTH + else + saving_throw = SOUTH + else + saving_throw = NORTH // just in case + + var/mob/living/carbon/C = user + var/turf/mobloc = get_turf(C) + var/list/turfs = list() + var/found_turf = FALSE + for(var/turf/T in range(destination, saving_throw_distance)) + if(get_dir(destination, T) != saving_throw) + continue + if(T.x > world.maxx-saving_throw_distance || T.x < saving_throw_distance) + continue //putting them at the edge is dumb + if(T.y > world.maxy-saving_throw_distance || T.y < saving_throw_distance) + continue + if(!tile_check(T)) + continue // We are only looking for safe tiles on the saving throw, since we are nice + turfs += T + found_turf = TRUE + + if(found_turf) + var/turf/new_destination = pick(turfs) + var/turf/fragging_location = new_destination + telefrag(fragging_location, user) + C.forceMove(new_destination) + playsound(mobloc, "sparks", 50, TRUE) + new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(mobloc) + new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(new_destination) + playsound(new_destination, "sparks", 50, TRUE) + else //We tried to save. We failed. Death time. + get_fragged(user, destination) + + +/obj/item/teleporter/proc/get_fragged(mob/user, turf/destination) + var/turf/mobloc = get_turf(user) + user.forceMove(destination) + playsound(mobloc, "sparks", 50, TRUE) + new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(mobloc) + new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(destination) + playsound(destination, "sparks", 50, TRUE) + playsound(destination, "sound/magic/disintegrate.ogg", 50, TRUE) + destination.ex_act(rand(1,2)) + for(var/obj/item/W in user) + if(istype(W, /obj/item/organ)|| istype(W, /obj/item/implant)) + continue + if(!user.unEquip(W)) + qdel(W) + to_chat(user, "You teleport into the wall, the teleporter tries to save you, but--") + user.gib() + +/obj/item/teleporter/proc/telefrag(turf/fragging_location, mob/user) + for(var/mob/living/M in fragging_location)//Hit everything in the turf + M.apply_damage(20, BRUTE) + M.Stun(3) + M.Weaken(3) + to_chat(M, " [user] teleports into you, knocking you to the floor with the bluespace wave!") + +/obj/item/paper/teleporter + name = "Teleporter Guide" + icon_state = "paper" + info = {"Instructions on your new prototype syndicate teleporter
+
+ This teleporter will teleport the user 4-8 meters in the direction they are facing. Unlike the cult veil shifter, you can not drag people with you.
+
+ It has 4 charges, and will recharge uses over time. No, sticking the teleporter into the tesla, an APC, a microwave, or an electrified door, will not make it charge faster.
+
+ Warning: Teleporting into walls will activate a failsafe teleport parallel up to 3 meters, but the user will be ripped apart and gibbed in a wall if it fails.
+
+ Do not expose the teleporter to electromagnetic pulses or attempt to use with a bag of holding, unwanted malfunctions may occur. +"} +/obj/item/storage/box/syndie_kit/teleporter + name = "syndicate teleporter kit" + +/obj/item/storage/box/syndie_kit/teleporter/New() + ..() + new /obj/item/teleporter(src) + new /obj/item/paper/teleporter(src) + return + +/obj/effect/temp_visual/teleport_abductor/syndi_teleporter + duration = 5 + +/obj/item/teleporter/admin + desc = "A strange syndicate version of a cult veil shifter. \n This one seems EMP proof, and with much better saftey protocols." + charges = 8 + max_charges = 8 + flawless = TRUE diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 6cf80471a0b..912f1d12a84 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ