diff --git a/code/game/objects/items/devices/swapper.dm b/code/game/objects/items/devices/swapper.dm new file mode 100644 index 0000000000..08646efd98 --- /dev/null +++ b/code/game/objects/items/devices/swapper.dm @@ -0,0 +1,112 @@ +//ported from TG, credit to XDTM +/obj/item/swapper + name = "quantum spin inverter" + desc = "An experimental device that is able to swap the locations of two entities by switching their particles' spin values. Must be linked to another device to function." + icon = 'icons/obj/device.dmi' + icon_state = "swapper" + item_state = "electronic" + w_class = WEIGHT_CLASS_SMALL + item_flags = NOBLUDGEON + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + + var/cooldown = 300 + var/next_use = 0 + var/obj/item/swapper/linked_swapper + +/obj/item/swapper/Destroy() + if(linked_swapper) + linked_swapper.linked_swapper = null //*inception music* + linked_swapper.update_appearance() + linked_swapper = null + return ..() + +/obj/item/swapper/update_icon_state() + icon_state = "swapper[linked_swapper ? "-linked" : null]" + return ..() + +/obj/item/swapper/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/swapper)) + var/obj/item/swapper/other_swapper = I + if(other_swapper.linked_swapper) + to_chat(user, span_warning("[other_swapper] is already linked. Break the current link to establish a new one.")) + return + if(linked_swapper) + to_chat(user, span_warning("[src] is already linked. Break the current link to establish a new one.")) + return + to_chat(user, span_notice("You establish a quantum link between the two devices.")) + linked_swapper = other_swapper + other_swapper.linked_swapper = src + update_appearance() + linked_swapper.update_appearance() + else + return ..() + +/obj/item/swapper/attack_self(mob/living/user) + if(world.time < next_use) + to_chat(user, span_warning("[src] is still recharging.")) + return + if(QDELETED(linked_swapper)) + to_chat(user, span_warning("[src] is not linked with another swapper.")) + return + playsound(src, 'sound/weapons/flash.ogg', 25, TRUE) + to_chat(user, span_notice("You activate [src].")) + playsound(linked_swapper, 'sound/weapons/flash.ogg', 25, TRUE) + if(ismob(linked_swapper.loc)) + var/mob/holder = linked_swapper.loc + to_chat(holder, span_notice("[linked_swapper] starts buzzing.")) + next_use = world.time + cooldown //only the one used goes on cooldown + addtimer(CALLBACK(src, .proc/swap, user), 25) + +/obj/item/swapper/examine(mob/user) + . = ..() + if(world.time < next_use) + . += span_warning("Time left to recharge: [DisplayTimeText(next_use - world.time)].") + if(linked_swapper) + . += span_notice("Linked. Alt-Click to break the quantum link.") + else + . += span_notice("Not Linked. Use on another quantum spin inverter to establish a quantum link.") + +/obj/item/swapper/AltClick(mob/living/user) + if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERY,, FALSE, !iscyborg(user))) //someone mispelled dexterity + return + to_chat(user, span_notice("You break the current quantum link.")) + if(!QDELETED(linked_swapper)) + linked_swapper.linked_swapper = null + linked_swapper.update_appearance() + linked_swapper = null + update_appearance() + +//Gets the topmost teleportable container +/obj/item/swapper/proc/get_teleportable_container() + var/atom/movable/teleportable = src + while(ismovable(teleportable.loc)) + var/atom/movable/AM = teleportable.loc + if(AM.anchored) + break + if(isliving(AM)) + var/mob/living/L = AM + if(L.buckled) + if(L.buckled.anchored) + break + else + var/obj/buckled_obj = L.buckled + buckled_obj.unbuckle_mob(L) + teleportable = AM + return teleportable + +/obj/item/swapper/proc/swap(mob/user) + if(QDELETED(linked_swapper) || world.time < linked_swapper.cooldown) + return + + var/atom/movable/A = get_teleportable_container() + var/atom/movable/B = linked_swapper.get_teleportable_container() + var/target_A = A.drop_location() + var/target_B = B.drop_location() + + //TODO: add a sound effect or visual effect + if(do_teleport(A, target_B, channel = TELEPORT_CHANNEL_QUANTUM)) + do_teleport(B, target_A, channel = TELEPORT_CHANNEL_QUANTUM) + if(ismob(B)) + var/mob/M = B + to_chat(M, span_warning("[linked_swapper] activates, and you find yourself somewhere else.")) diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm index cf6aff5918..b16ffeb9de 100644 --- a/code/modules/research/designs/bluespace_designs.dm +++ b/code/modules/research/designs/bluespace_designs.dm @@ -115,3 +115,13 @@ build_path = /obj/item/pipe/bluespace category = list("Bluespace Designs") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/swapper //ported from TG, credit to XDTM + name = "Quantum Spin Inverter" + desc = "An experimental device that is able to swap the locations of two entities by switching their particles' spin values. Must be linked to another device to function." + id = "swapper" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 500, /datum/material/diamond = 1500, /datum/material/glass = 1000, /datum/material/bluespace = 2000, /datum/material/silver=1000) + build_path = /obj/item/swapper + category = list("Bluespace Designs") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm index 90b69eb28d..802f7854b1 100644 --- a/code/modules/research/techweb/nodes/bluespace_nodes.dm +++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm @@ -61,7 +61,7 @@ display_name = "Bluespace Travel" description = "Application of Bluespace for static teleportation technology." prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick", "bluespace_pipe") + design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick", "bluespace_pipe","swapper") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/unregulated_bluespace diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 08404ec4dd..5254b53d2b 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 7acef3a5ba..28464dedef 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1204,6 +1204,7 @@ #include "code\game\objects\items\devices\reverse_bear_trap.dm" #include "code\game\objects\items\devices\scanners.dm" #include "code\game\objects\items\devices\sensor_device.dm" +#include "code\game\objects\items\devices\swapper.dm" #include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\traitordevices.dm" #include "code\game\objects\items\devices\transfer_valve.dm"