diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 8d86826ac2..e01bf5669b 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -73,6 +73,8 @@ #define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next) #define COMPONENT_BLOCK_REACH 1 #define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin) + #define COMPONENT_BLOCK_TELEPORT 1 ///////////////// #define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost) #define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 73711fe02d..2ba1563001 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -455,6 +455,13 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define SUMMON_GUNS "guns" #define SUMMON_MAGIC "magic" +#define TELEPORT_CHANNEL_BLUESPACE "bluespace" //Classic bluespace teleportation, requires a sender but no receiver +#define TELEPORT_CHANNEL_QUANTUM "quantum" //Quantum-based teleportation, requires both sender and receiver, but is free from normal disruption +#define TELEPORT_CHANNEL_WORMHOLE "wormhole" //Wormhole teleportation, is not disrupted by bluespace fluctuations but tends to be very random or unsafe +#define TELEPORT_CHANNEL_MAGIC "magic" //Magic teleportation, does whatever it wants (unless there's antimagic) +#define TELEPORT_CHANNEL_CULT "cult" //Cult teleportation, does whatever it wants (unless there's holiness) +#define TELEPORT_CHANNEL_FREE "free" //Anything else + //Run the world with this parameter to enable a single run though of the game setup and tear down process with unit tests in between #define TEST_RUN_PARAMETER "test-run" //Force the log directory to be something specific in the data/logs folder diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 0623e2f5f9..6462a1998a 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -5,11 +5,19 @@ // effectout: effect to show right after teleportation // asoundin: soundfile to play before teleportation // asoundout: soundfile to play after teleportation -// force_teleport: if false, teleport will use Move() proc (dense objects will prevent teleportation) // no_effects: disable the default effectin/effectout of sparks -/proc/do_teleport(atom/movable/teleatom, atom/destination, precision=null, force_teleport=TRUE, datum/effect_system/effectin=null, datum/effect_system/effectout=null, asoundin=null, asoundout=null, no_effects=FALSE) +// forceMove: if false, teleport will use Move() proc (dense objects will prevent teleportation) +// forced: whether or not to ignore no_teleport +/proc/do_teleport(atom/movable/teleatom, atom/destination, precision=null, forceMove = FALSE, datum/effect_system/effectin=null, datum/effect_system/effectout=null, asoundin=null, asoundout=null, no_effects=FALSE, channel=TELEPORT_CHANNEL_BLUESPACE, forced = FALSE) // teleporting most effects just deletes them - if(iseffect(teleatom) && !istype(teleatom, /obj/effect/dummy/chameleon)) + var/static/list/delete_atoms = typecacheof(list( + /obj/effect, + )) - typecacheof(list( + /obj/effect/dummy/chameleon, + /obj/effect/wisp, + /obj/effect/mob_spawn + )) + if(delete_atoms[teleatom.type]) qdel(teleatom) return FALSE @@ -17,25 +25,37 @@ // if the precision is not specified, default to 0, but apply BoH penalties if (isnull(precision)) precision = 0 - if(istype(teleatom, /obj/item/storage/backpack/holding)) - precision = rand(1,100) - var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding) - var/list/bagholding = typecache_filter_list(teleatom.GetAllContents(), bag_cache) - if(bagholding.len) - precision = max(rand(1,100)*bagholding.len,100) - if(isliving(teleatom)) - var/mob/living/MM = teleatom - to_chat(MM, "The bluespace interface on your bag of holding interferes with the teleport!") + switch(channel) + if(TELEPORT_CHANNEL_BLUESPACE) + if(istype(teleatom, /obj/item/storage/backpack/holding)) + precision = rand(1,100) - // if effects are not specified and not explicitly disabled, sparks - if ((!effectin || !effectout) && !no_effects) - var/datum/effect_system/spark_spread/sparks = new - sparks.set_up(5, 1, teleatom) - if (!effectin) - effectin = sparks - if (!effectout) - effectout = sparks + var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding) + var/list/bagholding = typecache_filter_list(teleatom.GetAllContents(), bag_cache) + if(bagholding.len) + precision = max(rand(1,100)*bagholding.len,100) + if(isliving(teleatom)) + var/mob/living/MM = teleatom + to_chat(MM, "The bluespace interface on your bag of holding interferes with the teleport!") + + // if effects are not specified and not explicitly disabled, sparks + if ((!effectin || !effectout) && !no_effects) + var/datum/effect_system/spark_spread/sparks = new + sparks.set_up(5, 1, teleatom) + if (!effectin) + effectin = sparks + if (!effectout) + effectout = sparks + if(TELEPORT_CHANNEL_QUANTUM) + // if effects are not specified and not explicitly disabled, rainbow sparks + if ((!effectin || !effectout) && !no_effects) + var/datum/effect_system/spark_spread/quantum/sparks = new + sparks.set_up(5, 1, teleatom) + if (!effectin) + effectin = sparks + if (!effectout) + effectout = sparks // perform the teleport var/turf/curturf = get_turf(teleatom) @@ -45,11 +65,15 @@ return FALSE var/area/A = get_area(curturf) - if(A.noteleport) + var/area/B = get_area(destturf) + if(!forced && (A.noteleport || B.noteleport)) + return FALSE + + if(SEND_SIGNAL(destturf, COMSIG_ATOM_INTERCEPT_TELEPORT, channel, curturf, destturf)) return FALSE tele_play_specials(teleatom, curturf, effectin, asoundin) - var/success = force_teleport ? teleatom.forceMove(destturf) : teleatom.Move(destturf) + var/success = forceMove ? teleatom.forceMove(destturf) : teleatom.Move(destturf) if (success) log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") tele_play_specials(teleatom, destturf, effectout, asoundout) diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 86fcefb340..43582e39bf 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -361,14 +361,16 @@ return button_icon_state = "warp_down" owner.update_action_buttons() + QDEL_NULL(warping) + if(!do_teleport(user, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) + to_chat(user, "Warp Failed. Something deflected our attempt to warp to [AR].") + return T.visible_message("[user] warps in!") playsound(user, 'sound/magic/magic_missile.ogg', 50, TRUE) playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE) - user.forceMove(get_turf(T)) user.setDir(SOUTH) flash_color(user, flash_color = "#AF0AAF", flash_time = 5) R.remove_eye_control(user) - QDEL_NULL(warping) /datum/action/innate/servant_warp/proc/is_canceled() return !cancel diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 4016c32162..db59f3f413 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -127,7 +127,7 @@ if(first_inner) log_msg += "empty" log_msg += ")" - do_teleport(ROI, dest, no_effects = !first) + do_teleport(ROI, dest, no_effects = !first, channel = TELEPORT_CHANNEL_BLUESPACE) first = FALSE if (first) @@ -206,7 +206,7 @@ /obj/item/storage/briefcase/launchpad/PopulateContents() new /obj/item/pen(src) - new /obj/item/launchpad_remote(src, pad) + new /obj/item/launchpad_remote(src, pad) /obj/item/storage/briefcase/launchpad/attack_self(mob/user) if(!isturf(user.loc)) //no setting up in a locker @@ -227,7 +227,7 @@ L.pad = src.pad to_chat(user, "You link [pad] to [L].") else - return ..() + return ..() /obj/item/launchpad_remote name = "folder" diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm index 7a8552607b..b5ef38b42c 100644 --- a/code/game/machinery/quantum_pad.dm +++ b/code/game/machinery/quantum_pad.dm @@ -36,7 +36,7 @@ to_chat(user, "The panel is screwed in, obstructing the linking device.") else to_chat(user, "The linking device is now able to be scanned with a multitool.") - + /obj/machinery/quantumpad/RefreshParts() var/E = 0 for(var/obj/item/stock_parts/capacitor/C in component_parts) @@ -74,15 +74,26 @@ to_chat(user, "There is no quantum pad data saved in [I]'s buffer!") return TRUE + else if(istype(I, /obj/item/quantum_keycard)) + var/obj/item/quantum_keycard/K = I + if(K.qpad) + to_chat(user, "You insert [K] into [src]'s card slot, activating it.") + interact(user, K.qpad) + else + to_chat(user, "You insert [K] into [src]'s card slot, initiating the link procedure.") + if(do_after(user, 40, target = src)) + to_chat(user, "You complete the link between [K] and [src].") + K.qpad = src + if(default_deconstruction_crowbar(I)) return return ..() -/obj/machinery/quantumpad/interact(mob/user) - if(!linked_pad || QDELETED(linked_pad)) +/obj/machinery/quantumpad/interact(mob/user, obj/machinery/quantumpad/target_pad = linked_pad) + if(!target_pad || QDELETED(target_pad)) if(!map_pad_link_id || !initMappedLink()) - to_chat(user, "There is no linked pad!") + to_chat(user, "Target pad not found!") return if(world.time < last_teleport + teleport_cooldown) @@ -93,18 +104,18 @@ to_chat(user, "[src] is charging up. Please wait.") return - if(linked_pad.teleporting) - to_chat(user, "Linked pad is busy. Please wait.") + if(target_pad.teleporting) + to_chat(user, "Target pad is busy. Please wait.") return - if(linked_pad.stat & NOPOWER) - to_chat(user, "Linked pad is not responding to ping.") + if(target_pad.stat & NOPOWER) + to_chat(user, "Target pad is not responding to ping.") return add_fingerprint(user) - doteleport(user) + doteleport(user, target_pad) /obj/machinery/quantumpad/proc/sparks() - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + var/datum/effect_system/spark_spread/quantum/s = new s.set_up(5, 1, get_turf(src)) s.start() @@ -117,8 +128,8 @@ if(linked_pad) ghost.forceMove(get_turf(linked_pad)) -/obj/machinery/quantumpad/proc/doteleport(mob/user) - if(linked_pad) +/obj/machinery/quantumpad/proc/doteleport(mob/user, obj/machinery/quantumpad/target_pad = linked_pad) + if(target_pad) playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, 1) teleporting = TRUE @@ -130,7 +141,7 @@ to_chat(user, "[src] is unpowered!") teleporting = FALSE return - if(!linked_pad || QDELETED(linked_pad) || linked_pad.stat & NOPOWER) + if(!target_pad || QDELETED(target_pad) || target_pad.stat & NOPOWER) to_chat(user, "Linked pad is not responding to ping. Teleport aborted.") teleporting = FALSE return @@ -141,26 +152,30 @@ // use a lot of power use_power(10000 / power_efficiency) sparks() - linked_pad.sparks() + target_pad.sparks() flick("qpad-beam", src) playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5) - flick("qpad-beam", linked_pad) - playsound(get_turf(linked_pad), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5) + flick("qpad-beam", target_pad) + playsound(get_turf(target_pad), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5) for(var/atom/movable/ROI in get_turf(src)) + if(QDELETED(ROI)) + continue //sleeps in CHECK_TICK + // 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 + //only TP living mobs buckled to non anchored items + if(!L.buckled || L.buckled.anchored) + continue else continue + //Don't TP camera mobs else if(!isobserver(ROI)) continue - do_teleport(ROI, get_turf(linked_pad)) + do_teleport(ROI, get_turf(target_pad),null,TRUE,null,null,null,null,TRUE, channel = TELEPORT_CHANNEL_QUANTUM) + CHECK_TICK /obj/machinery/quantumpad/proc/initMappedLink() . = FALSE diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index cc83e6502a..64081a77e4 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -66,7 +66,7 @@ visible_message("Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.") return if (ismovableatom(M)) - if(do_teleport(M, com.target)) + if(do_teleport(M, com.target, channel = TELEPORT_CHANNEL_BLUESPACE)) use_power(5000) if(!calibrated && prob(30 - ((accurate) * 10))) //oh dear a problem log_game("[M] ([key_name(M)]) was turned into a fly person") diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 80c92c7922..a8ba9850ff 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -17,7 +17,7 @@ return var/turf/T = get_turf(target) if(T) - do_teleport(chassis, T, 4) + do_teleport(chassis, T, 4, channel = TELEPORT_CHANNEL_BLUESPACE) return 1 diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 91df57052e..fbe25c5d1b 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -190,11 +190,11 @@ /obj/effect/anomaly/bluespace/anomalyEffect() ..() for(var/mob/living/M in range(1,src)) - do_teleport(M, locate(M.x, M.y, M.z), 4) + do_teleport(M, locate(M.x, M.y, M.z), 4, channel = TELEPORT_CHANNEL_BLUESPACE) /obj/effect/anomaly/bluespace/Bumped(atom/movable/AM) if(isliving(AM)) - do_teleport(AM, locate(AM.x, AM.y, AM.z), 8) + do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE) /obj/effect/anomaly/bluespace/detonate() var/turf/T = safepick(get_area_turfs(impact_area)) diff --git a/code/game/objects/effects/blessing.dm b/code/game/objects/effects/blessing.dm index 06ba2bb47c..5df90d65c7 100644 --- a/code/game/objects/effects/blessing.dm +++ b/code/game/objects/effects/blessing.dm @@ -16,3 +16,12 @@ I.alpha = 64 I.appearance_flags = RESET_ALPHA add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/blessedAware, "blessing", I) + RegisterSignal(loc, COMSIG_ATOM_INTERCEPT_TELEPORT, .proc/block_cult_teleport) + +/obj/effect/blessing/Destroy() + UnregisterSignal(loc, COMSIG_ATOM_INTERCEPT_TELEPORT) + return ..() + +/obj/effect/blessing/proc/block_cult_teleport(datum/source, channel, turf/origin, turf/destination) + if(channel == TELEPORT_CHANNEL_CULT) + return COMPONENT_BLOCK_TELEPORT \ No newline at end of file diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 0656d9b3ca..19b0dc76dd 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -26,7 +26,7 @@ /obj/effect/particle_effect/sparks/Initialize() . = ..() - flick("sparks", src) // replay the animation + flick(icon_state, src) // replay the animation playsound(src, "sparks", 100, TRUE) var/turf/T = loc if(isturf(T)) @@ -48,6 +48,8 @@ /datum/effect_system/spark_spread effect_type = /obj/effect/particle_effect/sparks +/datum/effect_system/spark_spread/quantum + effect_type = /obj/effect/particle_effect/sparks/quantum //electricity @@ -55,5 +57,9 @@ name = "lightning" icon_state = "electricity" +/obj/effect/particle_effect/sparks/quantum + name = "quantum sparks" + icon_state = "quantum_sparks" + /datum/effect_system/lightning_spread effect_type = /obj/effect/particle_effect/sparks/electricity diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index d69cfd38ef..631b87cada 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -20,6 +20,7 @@ var/mech_sized = FALSE var/obj/effect/portal/linked var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted. + var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE var/creator var/turf/hard_target //For when a portal needs a hard target and isn't to be linked. var/atmos_link = FALSE //Link source/destination atmos. @@ -34,6 +35,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "anom" mech_sized = TRUE + teleport_channel = TELEPORT_CHANNEL_WORMHOLE /obj/effect/portal/Move(newloc) for(var/T in newloc) @@ -160,7 +162,7 @@ no_effect = TRUE else last_effect = world.time - if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect)) + if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel)) if(istype(M, /obj/item/projectile)) var/obj/item/projectile/P = M P.ignore_source_check = TRUE diff --git a/code/game/objects/items/devices/quantum_keycard.dm b/code/game/objects/items/devices/quantum_keycard.dm new file mode 100644 index 0000000000..37079722c0 --- /dev/null +++ b/code/game/objects/items/devices/quantum_keycard.dm @@ -0,0 +1,32 @@ +/obj/item/quantum_keycard + name = "quantum keycard" + desc = "A keycard able to link to a quantum pad's particle signature, allowing other quantum pads to travel there instead of their linked pad." + icon = 'icons/obj/device.dmi' + icon_state = "quantum_keycard" + item_state = "card-id" + lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' + w_class = WEIGHT_CLASS_TINY + var/obj/machinery/quantumpad/qpad + +/obj/item/quantum_keycard/examine(mob/user) + ..() + if(qpad) + to_chat(user, "It's currently linked to a quantum pad.") + to_chat(user, "Alt-click to unlink the keycard.") + else + to_chat(user, "Insert [src] into an active quantum pad to link it.") + +/obj/item/quantum_keycard/AltClick(mob/living/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + to_chat(user, "You start pressing [src]'s unlink button...") + if(do_after(user, 40, target = src)) + to_chat(user, "The keycard beeps twice and disconnects the quantum link.") + qpad = null + +/obj/item/quantum_keycard/update_icon() + if(qpad) + icon_state = "quantum_keycard_on" + else + icon_state = initial(icon_state) diff --git a/code/game/objects/items/scrolls.dm b/code/game/objects/items/scrolls.dm index 07f6edb828..28a4664a24 100644 --- a/code/game/objects/items/scrolls.dm +++ b/code/game/objects/items/scrolls.dm @@ -66,7 +66,8 @@ to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") return - user.forceMove(pick(L)) - - smoke.start() - uses-- + if(do_teleport(user, pick(L), forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC, forced = TRUE)) + smoke.start() + uses-- + else + to_chat(user, "The spell matrix was disrupted by something near the destination.") diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 522e1a1153..49a735af9c 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -33,7 +33,7 @@ use(1) /obj/item/stack/ore/bluespace_crystal/proc/blink_mob(mob/living/L) - do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg') + do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) /obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom) if(!..()) // not caught in mid-air diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm index 341c85fa1c..40392c19c3 100644 --- a/code/game/objects/items/teleprod.dm +++ b/code/game/objects/items/teleprod.dm @@ -10,7 +10,7 @@ . = ..() if(!. || !istype(M) || M.anchored) return - do_teleport(M, get_turf(M), 15) + do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE) /obj/item/melee/baton/cattleprod/teleprod/clowning_around(mob/living/user) user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \ @@ -18,7 +18,7 @@ SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK) user.Knockdown(stunforce*3) playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1) - if(do_teleport(user, get_turf(user), 50)) + if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE)) deductcharge(hitcost) else deductcharge(hitcost * 0.25) diff --git a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm b/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm index ea2ec4d6ef..5cf7ab7923 100644 --- a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm +++ b/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm @@ -133,6 +133,9 @@ return FALSE if(!uses) return FALSE + if(!do_teleport(A, get_turf(linked_gateway), channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) + visible_message("[A] bounces off [src]!") + return FALSE if(isliving(A)) var/mob/living/user = A to_chat(user, "You pass through [src] and appear elsewhere!") @@ -141,7 +144,6 @@ playsound(linked_gateway, 'sound/effects/empulse.ogg', 50, 1) transform = matrix() * 1.5 linked_gateway.transform = matrix() * 1.5 - A.forceMove(get_turf(linked_gateway)) if(!no_cost) uses = max(0, uses - 1) linked_gateway.uses = max(0, linked_gateway.uses - 1) diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm index 552a747651..510c279f3c 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm @@ -27,7 +27,7 @@ to_chat(invoker, "Stargazers can't be built off-station.") return return ..() - + //Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power. /datum/clockwork_scripture/create_object/integration_cog @@ -224,12 +224,14 @@ . = ..() /datum/clockwork_scripture/abscond/scripture_effects() - var/take_pulling = invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST) + var/mob/living/pulled_mob = invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST) var/turf/T if(GLOB.ark_of_the_clockwork_justiciar) T = get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) else T = get_turf(pick(GLOB.servant_spawns)) + if(!do_teleport(invoker, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) + return invoker.visible_message("[invoker] flickers and phases out of existence!", \ "You feel a dizzying sense of vertigo as you're yanked back to Reebe!") T.visible_message("[invoker] flickers and phases into existence!") @@ -237,10 +239,9 @@ playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE) do_sparks(5, TRUE, invoker) do_sparks(5, TRUE, T) - if(take_pulling) + if(pulled_mob && do_teleport(pulled_mob, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) adjust_clockwork_power(-special_power_cost) - invoker.pulling.forceMove(T) - invoker.forceMove(T) + invoker.start_pulling(pulled_mob) //forcemove resets pulls, so we need to re-pull if(invoker.client) animate(invoker.client, color = client_color, time = 25) diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm index 2b1d9d5f02..4cf7c1ba60 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm @@ -131,10 +131,10 @@ if(!M || !M.current) continue if(isliving(M.current) && M.current.stat != DEAD) + var/turf/t_turf if(isAI(M.current)) - M.current.forceMove(get_step(get_step(src, NORTH),NORTH)) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark. - else - M.current.forceMove(get_turf(src)) + t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark. + do_teleport(M, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE) M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash) M.current.clear_fullscreen("flash", 5) playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index a5fd516a42..f58ffc56d2 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -490,11 +490,12 @@ to_chat(user, "The target rune is blocked. Attempting to teleport to it would be massively unwise.") return uses-- - user.visible_message("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!", \ - "You speak the words of the talisman and find yourself somewhere else!", "You hear a sharp crack.") + var/turf/origin = get_turf(user) var/mob/living/L = target - L.forceMove(dest) - dest.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") + if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT)) + origin.visible_message("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!", \ + "You speak the words of the talisman and find yourself somewhere else!", "You hear a sharp crack.") + dest.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") ..() //Shackles diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 9a17c3270b..dc2c29eb6d 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -568,7 +568,7 @@ var/mob/living/carbon/C = user if(C.pulling) var/atom/movable/pulled = C.pulling - pulled.forceMove(T) + do_teleport(pulled, T, channel = TELEPORT_CHANNEL_CULT) . = pulled /obj/item/cult_shift/attack_self(mob/user) @@ -593,13 +593,12 @@ new /obj/effect/temp_visual/dir_setting/cult/phase/out(mobloc, C.dir) var/atom/movable/pulled = handle_teleport_grab(destination, C) - C.forceMove(destination) - if(pulled) - C.start_pulling(pulled) //forcemove resets pulls, so we need to re-pull - - new /obj/effect/temp_visual/dir_setting/cult/phase(destination, C.dir) - playsound(destination, 'sound/effects/phasein.ogg', 25, 1) - playsound(destination, "sparks", 50, 1) + if(do_teleport(C, destination, channel = TELEPORT_CHANNEL_CULT)) + if(pulled) + C.start_pulling(pulled) //forcemove resets pulls, so we need to re-pull + new /obj/effect/temp_visual/dir_setting/cult/phase(destination, C.dir) + playsound(destination, 'sound/effects/phasein.ogg', 25, 1) + playsound(destination, "sparks", 50, 1) else to_chat(C, "The veil cannot be torn here!") diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index be8d3b2e0a..bbab86729b 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -422,6 +422,7 @@ structure_check() searches for nearby cultist structures required for the invoca return var/movedsomething = FALSE var/moveuserlater = FALSE + var/movesuccess = FALSE for(var/atom/movable/A in T) if(ishuman(A)) new /obj/effect/temp_visual/dir_setting/cult/phase/out(T, A.dir) @@ -432,20 +433,26 @@ structure_check() searches for nearby cultist structures required for the invoca continue if(!A.anchored) movedsomething = TRUE - A.forceMove(target) + if(do_teleport(A, T, forceMove = TRUE, channel = TELEPORT_CHANNEL_CULT)) + movesuccess = TRUE if(movedsomething) ..() - visible_message("There is a sharp crack of inrushing air, and everything above the rune disappears!", null, "You hear a sharp crack.") - to_chat(user, "You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"].") if(moveuserlater) - user.forceMove(target) + if(do_teleport(user, T, channel = TELEPORT_CHANNEL_CULT)) + movesuccess = TRUE + if(movesuccess) + visible_message("There is a sharp crack of inrushing air, and everything above the rune disappears!", null, "You hear a sharp crack.") + to_chat(user, "You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"].") + else + to_chat(user, "You[moveuserlater ? "r vision blurs briefly, but nothing happens":" try send everything above the rune away, but the teleportation fails"].") if(is_mining_level(z) && !is_mining_level(target.z)) //No effect if you stay on lavaland actual_selected_rune.handle_portal("lava") else var/area/A = get_area(T) if(A.map_name == "Space") actual_selected_rune.handle_portal("space", T) - target.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") + if(movesuccess) + target.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") else fail_invoke() diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index 9fb2c3e2b7..87cee7586d 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -488,7 +488,7 @@ S.set_up(4,0,get_turf(target)) S.start() playsound(src,'sound/effects/sparks4.ogg',50,1) - do_teleport(target, F, 0) + do_teleport(target, F, 0, channel = TELEPORT_CHANNEL_BLUESPACE) /mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE) if(!tesla_shock) diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 86493f6322..08e00ea0f4 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -408,7 +408,7 @@ break var/turf/potential_T = find_safe_turf() if(T.z != potential_T.z || abs(get_dist_euclidian(potential_T,T)) > 50 - breakout) - user.forceMove(potential_T) + do_teleport(user, potential_T, channel = TELEPORT_CHANNEL_MAGIC) user.canmove = 0 T = potential_T break diff --git a/code/modules/events/wizard/shuffle.dm b/code/modules/events/wizard/shuffle.dm index ec253f13c3..7e37429223 100644 --- a/code/modules/events/wizard/shuffle.dm +++ b/code/modules/events/wizard/shuffle.dm @@ -27,7 +27,7 @@ for(var/mob/living/carbon/human/H in mobs) if(!moblocs) break //locs aren't always unique, so this may come into play - do_teleport(H, moblocs[moblocs.len]) + do_teleport(H, moblocs[moblocs.len], channel = TELEPORT_CHANNEL_MAGIC) moblocs.len -= 1 for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 412e54878a..bb601b7c82 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -63,4 +63,4 @@ hard_target = P.loc if(!hard_target) return - do_teleport(M, hard_target, 1, 1, 0, 0) ///You will appear adjacent to the beacon + do_teleport(M, hard_target, 1, 1, 0, 0, channel = TELEPORT_CHANNEL_WORMHOLE) ///You will appear adjacent to the beacon diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 17462c0626..db529e8ffb 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -290,15 +290,15 @@ var/teleport_radius = max(round(G.seed.potency / 10), 1) var/turf/T = get_turf(target) new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect... - do_teleport(target, T, teleport_radius) + do_teleport(target, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE) /datum/plant_gene/trait/teleport/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C) var/teleport_radius = max(round(G.seed.potency / 10), 1) var/turf/T = get_turf(C) to_chat(C, "You slip through spacetime!") - do_teleport(C, T, teleport_radius) + do_teleport(C, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE) if(prob(50)) - do_teleport(G, T, teleport_radius) + do_teleport(G, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE) else new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect... qdel(G) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 2c663b4094..88dd59749c 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -420,7 +420,7 @@ H.visible_message("[H] teleports!", "You destabilize and teleport!") new /obj/effect/particle_effect/sparks(get_turf(H)) playsound(get_turf(H), "sparks", 50, 1) - do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg') + do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) last_teleport = world.time /datum/species/golem/bluespace/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) @@ -486,7 +486,7 @@ spark_system.set_up(10, 0, src) spark_system.attach(H) spark_system.start() - do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg') + do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) last_teleport = world.time UpdateButtonIcon() //action icon looks unavailable sleep(cooldown + 5) diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index 8fb1de18df..ff2f453207 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -22,7 +22,7 @@ var/mob/living/M = target if(!M.anchored && M != summoner && !hasmatchingsummoner(M)) new /obj/effect/temp_visual/guardian/phase/out(get_turf(M)) - do_teleport(M, M, 10) + do_teleport(M, M, 10, channel = TELEPORT_CHANNEL_BLUESPACE) for(var/mob/living/L in range(1, M)) if(hasmatchingsummoner(L)) //if the summoner matches don't hurt them continue diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm index 8ef70e439f..794683e69f 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/support.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm @@ -142,5 +142,5 @@ L.flash_act() A.visible_message("[A] disappears in a flash of light!", \ "Your vision is obscured by a flash of light!") - do_teleport(A, beacon, 0) + do_teleport(A, beacon, 0, channel = TELEPORT_CHANNEL_BLUESPACE) new /obj/effect/temp_visual/guardian/phase(get_turf(A)) diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index e3724fdf31..42033d8c88 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -131,7 +131,7 @@ no_den_usage = 1 /obj/item/gun/magic/wand/teleport/zap_self(mob/living/user) - if(do_teleport(user, user, 10)) + if(do_teleport(user, user, 10, channel = TELEPORT_CHANNEL_MAGIC)) var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(3, user.loc) smoke.start() diff --git a/code/modules/projectiles/projectile/energy/net_snare.dm b/code/modules/projectiles/projectile/energy/net_snare.dm index f5d0607341..c8333a811c 100644 --- a/code/modules/projectiles/projectile/energy/net_snare.dm +++ b/code/modules/projectiles/projectile/energy/net_snare.dm @@ -42,10 +42,10 @@ /obj/effect/nettingportal/proc/pop(teletarget) if(teletarget) for(var/mob/living/L in get_turf(src)) - do_teleport(L, teletarget, 2)//teleport what's in the tile to the beacon + do_teleport(L, teletarget, 2, channel = TELEPORT_CHANNEL_BLUESPACE)//teleport what's in the tile to the beacon else for(var/mob/living/L in get_turf(src)) - do_teleport(L, L, 15) //Otherwise it just warps you off somewhere. + do_teleport(L, L, 15, channel = TELEPORT_CHANNEL_BLUESPACE) //Otherwise it just warps you off somewhere. qdel(src) diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index dee88f176f..5b84608fad 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -67,7 +67,7 @@ teleloc = target.loc for(var/atom/movable/stuff in teleloc) if(!stuff.anchored && stuff.loc) - if(do_teleport(stuff, stuff, 10)) + if(do_teleport(stuff, stuff, 10, channel = TELEPORT_CHANNEL_MAGIC)) teleammount++ var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(max(round(4 - teleammount),0), stuff.loc) //Smoke drops off if a lot of stuff is moved for the sake of sanity diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 211fddca26..a46a4d61e4 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -2076,7 +2076,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/blazaam/on_mob_life(mob/living/carbon/M) if(M.drunkenness > 40) if(stored_teleports) - do_teleport(M, get_turf(M), rand(1,3)) + do_teleport(M, get_turf(M), rand(1,3), channel = TELEPORT_CHANNEL_WORMHOLE) stored_teleports-- if(prob(10)) stored_teleports += rand(2,6) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 840a57055c..db927411c0 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -346,7 +346,7 @@ //We only get 30u to start with... /datum/reagent/fuel/holyoil/reaction_obj(obj/O, reac_volume) - . = ..() + . = ..() if(istype(O, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = O reac_volume = min(reac_volume, M.amount) @@ -989,7 +989,7 @@ /datum/reagent/bluespace/reaction_mob(mob/living/M, method=TOUCH, reac_volume) if(method == TOUCH || method == VAPOR) - do_teleport(M, get_turf(M), (reac_volume / 5), asoundin = 'sound/effects/phasein.ogg') //4 tiles per crystal + do_teleport(M, get_turf(M), (reac_volume / 5), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //4 tiles per crystal ..() /datum/reagent/bluespace/on_mob_life(mob/living/carbon/M) @@ -1001,7 +1001,7 @@ ..() /mob/living/proc/bluespace_shuffle() - do_teleport(src, get_turf(src), 5, asoundin = 'sound/effects/phasein.ogg') + do_teleport(src, get_turf(src), 5, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) /datum/reagent/aluminium name = "Aluminium" diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 59df0f6e85..d27c876f88 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -460,6 +460,16 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/quantum_keycard + name = "Quantum Keycard" + desc = "Allows for the construction of a quantum keycard." + id = "quantum_keycard" + build_type = PROTOLATHE + materials = list(MAT_GLASS = 500, MAT_METAL = 500, MAT_SILVER = 500, MAT_BLUESPACE = 1000) + build_path = /obj/item/quantum_keycard + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + /datum/design/anomaly_neutralizer name = "Anomaly Neutralizer" desc = "An advanced tool capable of instantly neutralizing anomalies, designed to capture the fleeting aberrations created by the engine." diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index ebd386513e..e56350a280 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -651,7 +651,7 @@ if(loc == user && !is_centcom_level(userturf.z)) //Because Nuke Ops bringing this back on their shuttle, then looting the ERT area is 2fun4you! visible_message("[src] twists and bends, relocating itself!") throwSmoke(userturf) - do_teleport(user, userturf, 8, asoundin = 'sound/effects/phasein.ogg') + do_teleport(user, userturf, 8, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) throwSmoke(get_turf(user)) warn_admins(user, "Teleport", 0) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index c6487c92f0..1cbe3f0dea 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -227,33 +227,42 @@ display_name = "Basic Bluespace Theory" description = "Basic studies into the mysterious alternate dimension known as bluespace." prereq_ids = list("base", "datatheory") - design_ids = list("beacon", "xenobioconsole", "telesci_gps") + design_ids = list("beacon", "xenobioconsole", "telesci_gps", "bluespace_crystal", "xenobio_monkeys") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 +/datum/techweb_node/bluespace_travel + id = "bluespace_travel" + display_name = "Bluespace Travel" + description = "Application of Bluespace for static teleportation technology." + prereq_ids = list("practical_bluespace") + design_ids = list("tele_station", "tele_hub", "quantumpad", "launchpad", "launchpad_console", "bluespace_pod") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +/datum/techweb_node/micro_bluespace + id = "micro_bluespace" + display_name = "Miniaturized Bluespace Research" + description = "Extreme reduction in space required for bluespace engines, leading to portable bluespace technology." + prereq_ids = list("bluespace_travel", "practical_bluespace", "high_efficiency") + design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bag_holding", "quantum_keycard", "wormholeprojector", "xenobio_slimeadv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + export_price = 5000 + /datum/techweb_node/practical_bluespace id = "practical_bluespace" display_name = "Applied Bluespace Research" description = "Using bluespace to make things faster and better." prereq_ids = list("bluespace_basic", "engineering") - design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart") + design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) export_price = 5000 -/datum/techweb_node/adv_bluespace - id = "adv_bluespace" - display_name = "Advanced Bluespace Research" - description = "Deeper understanding of how the Bluespace dimension works" - prereq_ids = list("practical_bluespace", "high_efficiency") - design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - export_price = 5000 - /datum/techweb_node/bluespace_power id = "bluespace_power" display_name = "Bluespace Power Technology" description = "Even more powerful.. power!" - prereq_ids = list("adv_power", "adv_bluespace") + prereq_ids = list("adv_power", "practical_bluespace") design_ids = list("bluespace_cell", "quadratic_capacitor") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index ad5bfa27dc..b9e7122d07 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -680,7 +680,7 @@ datum/status_effect/stabilized/blue/on_remove() if(!F) F = get_turf(owner) range = 50 - if(do_teleport(owner, F, range)) + if(do_teleport(owner, F, range, channel = TELEPORT_CHANNEL_BLUESPACE)) to_chat(owner, "[linked_extract] will take some time to re-align you on the bluespace axis.") do_sparks(5,FALSE,owner) owner.apply_status_effect(/datum/status_effect/bluespacestabilization) diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 38362e6d64..363331e12d 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -144,7 +144,7 @@ Burning extracts: user.visible_message("[src] sparks, and lets off a shockwave of bluespace energy!") for(var/mob/living/L in range(1, get_turf(user))) if(L != user) - do_teleport(L, get_turf(L), 6, asoundin = 'sound/effects/phasein.ogg') //Somewhere between the effectiveness of fake and real BS crystal + do_teleport(L, get_turf(L), 6, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //Somewhere between the effectiveness of fake and real BS crystal new /obj/effect/particle_effect/sparks(get_turf(L)) playsound(get_turf(L), "sparks", 50, 1) ..() diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm index b51a7b2553..0b2d60da8c 100644 --- a/code/modules/research/xenobiology/crossbreeding/consuming.dm +++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm @@ -232,7 +232,7 @@ Consuming extracts: L.Cut(I,I+1) if(target) - do_teleport(M, target, 0, asoundin = 'sound/effects/phasein.ogg') + do_teleport(M, target, 0, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) new /obj/effect/particle_effect/sparks(get_turf(M)) playsound(get_turf(M), "sparks", 50, 1) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index ce36be8e42..7acbaaac1c 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -494,7 +494,7 @@ to_chat(user, "You feel your body vibrating...") if(do_after(user, 25, target = user)) to_chat(user, "You teleport!") - do_teleport(user, get_turf(user), 6, asoundin = 'sound/weapons/emitter2.ogg') + do_teleport(user, get_turf(user), 6, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) return 300 if(SLIME_ACTIVATE_MAJOR) @@ -510,7 +510,7 @@ if(teleport_x && teleport_y && teleport_z) var/turf/T = locate(teleport_x, teleport_y, teleport_z) to_chat(user, "You snap back to your anchor point!") - do_teleport(user, T, asoundin = 'sound/weapons/emitter2.ogg') + do_teleport(user, T, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) return 450 diff --git a/code/modules/spells/spell_types/area_teleport.dm b/code/modules/spells/spell_types/area_teleport.dm index ab399f4e2a..7bede9f8be 100644 --- a/code/modules/spells/spell_types/area_teleport.dm +++ b/code/modules/spells/spell_types/area_teleport.dm @@ -58,7 +58,7 @@ var/success = 0 while(tempL.len) attempt = pick(tempL) - target.Move(attempt) + do_teleport(target, attempt, channel = TELEPORT_CHANNEL_MAGIC) if(get_turf(target) == attempt) success = 1 break @@ -66,7 +66,7 @@ tempL.Remove(attempt) if(!success) - target.forceMove(L) + do_teleport(target, L, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC) playsound(get_turf(user), sound2, 50,1) return diff --git a/code/modules/spells/spell_types/turf_teleport.dm b/code/modules/spells/spell_types/turf_teleport.dm index 093285b74d..8a45f2be22 100644 --- a/code/modules/spells/spell_types/turf_teleport.dm +++ b/code/modules/spells/spell_types/turf_teleport.dm @@ -40,6 +40,5 @@ if(!picked || !isturf(picked)) return - if(!target.Move(picked)) - target.forceMove(picked) - playsound(get_turf(user), sound2, 50,1) + if(do_teleport(user, picked, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC)) + playsound(get_turf(user), sound1, 50,1) diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 29086033c8..e13ce10347 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 55c33e5e83..032b0c27ad 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/modular_citadel/code/modules/research/techweb/all_nodes.dm b/modular_citadel/code/modules/research/techweb/all_nodes.dm index c0ddaceaf7..55b3a55736 100644 --- a/modular_citadel/code/modules/research/techweb/all_nodes.dm +++ b/modular_citadel/code/modules/research/techweb/all_nodes.dm @@ -1,15 +1,3 @@ -/datum/techweb_node/bluespace_basic/New() - . = ..() - design_ids += "xenobio_monkeys" - -/datum/techweb_node/practical_bluespace/New() - . = ..() - design_ids += "xenobio_slimebasic" - -/datum/techweb_node/adv_bluespace/New() - . = ..() - design_ids += "xenobio_slimeadv" - /datum/techweb_node/ballistic_weapons/New() . = ..() design_ids += "mag_oldsmg_rubber" diff --git a/tgstation.dme b/tgstation.dme index 24477d885b..ab360ad73d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -861,6 +861,7 @@ #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\pressureplates.dm" +#include "code\game\objects\items\devices\quantum_keycard.dm" #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"