diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index e8981ed68523..fa6b066e95c7 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -849,11 +849,11 @@
The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
is only triggered if it hears someone speaking a language other than Galactic Common."
icon_state = "recorder"
- complexity = 8
+ complexity = 4 //cuts complexity in half, you'll need to use a ref to string for the name
inputs = list()
flags_1 = CONDUCT_1 | HEAR_1
outputs = list(
- "speaker" = IC_PINTYPE_STRING,
+ "speaker" = IC_PINTYPE_REF,
"message" = IC_PINTYPE_STRING
)
activators = list("on message received" = IC_PINTYPE_PULSE_OUT, "on translation" = IC_PINTYPE_PULSE_OUT)
@@ -867,7 +867,7 @@
if(raw_message)
if(message_langs != get_selected_language())
translated = TRUE
- set_pin_data(IC_OUTPUT, 1, speaker.GetVoice())
+ set_pin_data(IC_OUTPUT, 1, speaker)
set_pin_data(IC_OUTPUT, 2, raw_message)
push_data()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f028ffc1c9ba..ef8d0f326cc1 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -370,10 +370,19 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
var/msg = "[src] makes eye contact with you."
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3)
-//same as above
-//note: ghosts can point, this is intended
-//visible_message will handle invisibility properly
-//overridden here and in /mob/dead/observer for different point span classes and sanity checks
+/**
+ * Point at an atom
+ *
+ * mob verbs are faster than object verbs. See
+ * [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716)
+ * for why this isn't atom/verb/pointed()
+ *
+ * note: ghosts can point, this is intended
+ *
+ * visible_message will handle invisibility properly
+ *
+ * overridden here and in /mob/dead/observer for different point span classes and sanity checks
+ */
/mob/verb/pointed(atom/A as mob|obj|turf in fov_view())
set name = "Point To"
set category = "Object"
@@ -383,12 +392,15 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(istype(A, /obj/effect/temp_visual/point))
return FALSE
- var/tile = get_turf(A)
+ var/turf/tile = get_turf(A)
if (!tile)
return FALSE
- new /obj/effect/temp_visual/point(A,invisibility)
+ var/turf/our_tile = get_turf(src)
+ var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility)
+ animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, time = 1.7, easing = EASE_OUT)
SEND_SIGNAL(src, COMSIG_MOB_POINTED, A)
+
return TRUE
/mob/proc/can_resist()
diff --git a/sandcode/code/_globalvars/lists/misc.dm b/sandcode/code/_globalvars/lists/misc.dm
new file mode 100644
index 000000000000..e2265f339d29
--- /dev/null
+++ b/sandcode/code/_globalvars/lists/misc.dm
@@ -0,0 +1 @@
+GLOBAL_VAR_INIT(remote_control, TRUE)
diff --git a/sandcode/code/_globalvars/lists/objects.dm b/sandcode/code/_globalvars/lists/objects.dm
new file mode 100644
index 000000000000..dd737fbe73e9
--- /dev/null
+++ b/sandcode/code/_globalvars/lists/objects.dm
@@ -0,0 +1,2 @@
+GLOBAL_LIST_EMPTY(ic_jammers)
+GLOBAL_LIST_EMPTY(ic_speakers)
diff --git a/sandcode/code/game/machinery/computer/arcade/tetris.dm b/sandcode/code/game/machinery/computer/arcade/tetris.dm
index 4551314216f9..8bf9c0ac7834 100644
--- a/sandcode/code/game/machinery/computer/arcade/tetris.dm
+++ b/sandcode/code/game/machinery/computer/arcade/tetris.dm
@@ -33,8 +33,8 @@
return
if(user.client)
- var/datum/asset/simple/C = new/datum/asset/simple/tetris()
- SSassets.transport.send_assets(user.client, C.assets)
+ var/datum/asset/assets = get_asset_datum(/datum/asset/simple/tetris)
+ assets.send(user)
var/dat = {"
diff --git a/sandcode/code/game/machinery/telecomms/machine_interactions.dm b/sandcode/code/game/machinery/telecomms/machine_interactions.dm
new file mode 100644
index 000000000000..ed24093d15b8
--- /dev/null
+++ b/sandcode/code/game/machinery/telecomms/machine_interactions.dm
@@ -0,0 +1,10 @@
+// Additional Options for certain machines. Use this when you want to add an option to a specific machine.
+// Example of how to use below.
+
+/obj/machinery/telecomms/proc/Options_Menu()
+ return ""
+
+// The topic for Additional Options. Use this for checking href links for your specific option.
+// Example of how to use below.
+/obj/machinery/telecomms/proc/Options_Topic(href, href_list)
+ return
diff --git a/sandcode/code/game/machinery/telecomms/machines/receiver.dm b/sandcode/code/game/machinery/telecomms/machines/receiver.dm
new file mode 100644
index 000000000000..f1f313d3a27c
--- /dev/null
+++ b/sandcode/code/game/machinery/telecomms/machines/receiver.dm
@@ -0,0 +1,46 @@
+//Code for the interceptor circuit
+/obj/machinery/telecomms/receiver/Options_Menu()
+ var/dat = "
Remote control: [GLOB.remote_control ? "ENABLED" : "DISABLED"]"
+ dat += "
Broadcasting signals: "
+ for(var/i in GLOB.ic_speakers)
+ var/obj/item/integrated_circuit/I = i
+ var/obj/item/O = I.get_object()
+ if(get_area(O)) //if it isn't in nullspace, can happen due to printer newing all possible circuits to fetch list data
+ dat += "
[O.name] = [O.x], [O.y], [O.z], [get_area(O)]"
+ dat += "
Circuit jammer signals: "
+ for(var/i in GLOB.ic_jammers)
+ var/obj/item/integrated_circuit/I = i
+ var/obj/item/O = I.get_object()
+ if(get_area(O)) //if it isn't in nullspace, can happen due to printer newing all possible circuits to fetch list data
+ dat += "
[O.name] = [O.x], [O.y], [O.z], [get_area(O)]"
+ return dat
+
+/obj/machinery/telecomms/receiver/Options_Topic(href, href_list)
+ if(href_list["toggle_remote_control"])
+ GLOB.remote_control = !GLOB.remote_control
+
+/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal)
+ if(LAZYLEN(GLOB.ic_jammers) && GLOB.remote_control)
+ for(var/i in GLOB.ic_jammers)
+ var/obj/item/integrated_circuit/input/tcomm_interceptor/T = i
+ var/obj/item/O = T.get_object()
+ if(is_station_level(O.z)&& (!istype(get_area(O), /area/space)))
+ if(!istype(signal.source, /obj/item/radio/headset/integrated))
+ signal.data["reject"] = TRUE
+ break
+ ..()
+
+//makeshift receiver used for the circuit, so that we don't
+//have to edit radio.dm and other shit
+/obj/machinery/telecomms/receiver/circuit
+ idle_power_usage = 0
+ var/obj/item/integrated_circuit/input/tcomm_interceptor/holder
+
+/obj/machinery/telecomms/receiver/circuit/receive_signal(datum/signal/signal)
+ if(!holder.get_pin_data(IC_INPUT, 1))
+ return
+ if(!signal)
+ return
+ holder.receive_signal(signal)
+
+// End
diff --git a/sandcode/code/modules/integrated_electronics/subtypes/input.dm b/sandcode/code/modules/integrated_electronics/subtypes/input.dm
new file mode 100644
index 000000000000..c867f905602a
--- /dev/null
+++ b/sandcode/code/modules/integrated_electronics/subtypes/input.dm
@@ -0,0 +1,88 @@
+//Interceptor
+//Intercepts a telecomms signal, aka a radio message (;halp getting griff)
+//Inputs:
+//On (Boolean): If on, the circuit intercepts radio signals. Otherwise it does not. This doesn't affect no pass!
+//No pass (Boolean): Decides if the signal will be silently intercepted
+// (false) or also blocked from being sent on the radio (true)
+//Outputs:
+//Source: name of the mob
+//Job: job of the mob
+//content: the actual message
+//spans: a list of spans, there's not much info about this but stuff like robots will have "robot" span
+/obj/item/integrated_circuit/input/tcomm_interceptor
+ name = "telecommunication interceptor"
+ desc = "This circuit allows for telecomms signals \
+ to be fetched prior to being broadcasted."
+ extended_desc = "Similar \
+ to the old NTSL system of realtime signal modification, \
+ the circuit connects to telecomms and fetches data \
+ for each signal, which can be sent normally or blocked, \
+ for cases such as other circuits modifying certain data. \
+ Beware, this cannot stop signals from unreachable areas, such \
+ as space or zlevels other than station's one."
+ complexity = 30
+ cooldown_per_use = 0.1
+ w_class = WEIGHT_CLASS_SMALL
+ inputs = list(
+ "intercept" = IC_PINTYPE_BOOLEAN,
+ "no pass" = IC_PINTYPE_BOOLEAN
+ )
+ outputs = list(
+ "source" = IC_PINTYPE_STRING,
+ "job" = IC_PINTYPE_STRING,
+ "content" = IC_PINTYPE_STRING,
+ "spans" = IC_PINTYPE_LIST,
+ "frequency" = IC_PINTYPE_NUMBER
+ )
+ activators = list(
+ "on intercept" = IC_PINTYPE_PULSE_OUT
+ )
+ power_draw_idle = 0
+ spawn_flags = IC_SPAWN_RESEARCH
+ var/obj/machinery/telecomms/receiver/circuit/receiver
+ var/list/freq_blacklist = list(FREQ_CENTCOM,FREQ_SYNDICATE,FREQ_CTF_RED,FREQ_CTF_BLUE)
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/Initialize()
+ . = ..()
+ receiver = new(src)
+ receiver.holder = src
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/Destroy()
+ qdel(receiver)
+ GLOB.ic_jammers -= src
+ ..()
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/receive_signal(datum/signal/signal)
+ if((signal.transmission_method == TRANSMISSION_SUBSPACE) && get_pin_data(IC_INPUT, 1))
+ if(signal.frequency in freq_blacklist)
+ return
+ set_pin_data(IC_OUTPUT, 1, signal.data["name"])
+ set_pin_data(IC_OUTPUT, 2, signal.data["job"])
+ set_pin_data(IC_OUTPUT, 3, signal.data["message"])
+ set_pin_data(IC_OUTPUT, 4, signal.data["spans"])
+ set_pin_data(IC_OUTPUT, 5, signal.frequency)
+ push_data()
+ activate_pin(1)
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/on_data_written()
+ if(get_pin_data(IC_INPUT, 2))
+ GLOB.ic_jammers |= src
+ if(get_pin_data(IC_INPUT, 1))
+ power_draw_idle = 200
+ else
+ power_draw_idle = 100
+ else
+ GLOB.ic_jammers -= src
+ if(get_pin_data(IC_INPUT, 1))
+ power_draw_idle = 100
+ else
+ power_draw_idle = 0
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/power_fail()
+ set_pin_data(IC_INPUT, 1, 0)
+ set_pin_data(IC_INPUT, 2, 0)
+
+/obj/item/integrated_circuit/input/tcomm_interceptor/disconnect_all()
+ set_pin_data(IC_INPUT, 1, 0)
+ set_pin_data(IC_INPUT, 2, 0)
+ ..()
diff --git a/sandcode/code/modules/integrated_electronics/subtypes/manipulation.dm b/sandcode/code/modules/integrated_electronics/subtypes/manipulation.dm
new file mode 100644
index 000000000000..936d66df2268
--- /dev/null
+++ b/sandcode/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -0,0 +1,50 @@
+/obj/item/integrated_circuit/manipulation/activator
+ name = "activator"
+ desc = "Circuit which can activate things remotely!"
+ icon_state = "pull_claw"
+ extended_desc = "This circuit needs a reference to a thing to activate, it also needs to know who is activating said item."
+ w_class = WEIGHT_CLASS_SMALL
+ size = 3
+ cooldown_per_use = 1
+ complexity = 10
+ inputs = list("target" = IC_PINTYPE_REF, "person" = IC_PINTYPE_REF)
+ activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ power_draw_per_use = 50
+ ext_cooldown = 1
+
+/obj/item/integrated_circuit/manipulation/activator/do_work(ord)
+ var/obj/acting_object = get_pin_data_as_type(IC_INPUT, 1, /obj/)
+ var/mob/person = get_pin_data_as_type(IC_INPUT, 2, /mob/)
+ acting_object.interact(person)
+ activate_pin(1)
+
+
+/obj/item/integrated_circuit/manipulation/advactivator
+ name = "advactivator"
+ desc = "Circuit which can UI elements remotely!"
+ icon_state = "pull_claw"
+ extended_desc = "This circuit needs a reference to a to activate, as well as action and parems to pass! Use mode 1 for lists or 0 for single values."
+ w_class = WEIGHT_CLASS_SMALL
+ size = 3
+ cooldown_per_use = 1
+ complexity = 10
+
+ //inputs = list("target" = IC_PINTYPE_REF, "action" = IC_PINTYPE_STRING, "params" = IC_PINTYPE_STRING)
+ inputs = list("target" = IC_PINTYPE_REF, "action" = IC_PINTYPE_STRING, "mode" = IC_PINTYPE_NUMBER, "params" = IC_PINTYPE_STRING, "listparams" = IC_PINTYPE_LIST)
+ activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_RESEARCH
+ power_draw_per_use = 50
+ ext_cooldown = 1
+ var/max_grab = GRAB_PASSIVE
+
+/obj/item/integrated_circuit/manipulation/advactivator/do_work(ord)
+ var/obj/acting_object = get_pin_data_as_type(IC_INPUT, 1, /obj/)
+ var/action = get_pin_data(IC_INPUT, 2)
+ var/mode = get_pin_data(IC_INPUT, 3)
+ var/params = get_pin_data(IC_INPUT, 4)
+ if(mode == 1)
+ params = get_pin_data(IC_INPUT, 5)
+
+ acting_object.ui_act(action, params)
+ activate_pin(1)
diff --git a/sandcode/code/modules/integrated_electronics/subtypes/output.dm b/sandcode/code/modules/integrated_electronics/subtypes/output.dm
index 84ef309ee144..85a99c056af3 100644
--- a/sandcode/code/modules/integrated_electronics/subtypes/output.dm
+++ b/sandcode/code/modules/integrated_electronics/subtypes/output.dm
@@ -24,9 +24,11 @@
. = ..()
radio = new(src)
radio.frequency = FREQ_COMMON
+ GLOB.ic_speakers += src
/obj/item/integrated_circuit/output/text_to_radio/Destroy()
qdel(radio)
+ GLOB.ic_speakers -= src
..()
/obj/item/integrated_circuit/output/text_to_radio/on_data_written()
@@ -79,3 +81,41 @@
to_chat(user, "There are no encryption keys to remove from the mechanism.")
/obj/item/radio/headset/integrated
+
+//sandstorm original - pointer
+/obj/item/integrated_circuit/output/pointer
+ name = "pointer circuit"
+ desc = "Takes a reference and points to it upon activation."
+ extended_desc = "This machine points at something for everyone to see."
+ icon_state = "pull_claw"
+ complexity = 2
+ inputs = list("target" = IC_PINTYPE_REF)
+ activators = list("point" = IC_PINTYPE_PULSE_IN, "on pointed" = IC_PINTYPE_PULSE_OUT, "on failure" = IC_PINTYPE_PULSE_OUT)
+ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+ power_draw_per_use = 10
+ cooldown_per_use = 0.1
+
+/obj/item/integrated_circuit/output/pointer/do_work()
+ if(!get_pin_data(IC_INPUT, 1))
+ activate_pin(3)
+ return
+ else
+ assembly.point(get_pin_data(IC_INPUT, 1))
+ activate_pin(2)
+
+/obj/item/electronic_assembly/proc/point(atom/A as mob|obj|turf in view())
+ if(!src || !(A in view(src.loc)))
+ return FALSE
+ if(istype(A, /obj/effect/temp_visual/point))
+ return FALSE
+
+ var/turf/tile = get_turf(A)
+ if(!tile)
+ return FALSE
+
+ var/turf/our_tile = get_turf(src)
+ var/obj/visual = new /obj/effect/temp_visual/point(our_tile, invisibility)
+ animate(visual, pixel_x = (tile.x - our_tile.x) * world.icon_size + A.pixel_x, pixel_y = (tile.y - our_tile.y) * world.icon_size + A.pixel_y, time = 1.7, easing = EASE_OUT)
+ SEND_SIGNAL(src, COMSIG_MOB_POINTED, A)
+
+ return TRUE
diff --git a/tgstation.dme b/tgstation.dme
index 7d30d694b0ce..36cf9853c572 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3614,6 +3614,8 @@
#include "sandcode\code\__DEFINES\status_effects.dm"
#include "sandcode\code\__DEFINES\traits.dm"
#include "sandcode\code\__DEFINES\wires.dm"
+#include "sandcode\code\_globalvars\lists\misc.dm"
+#include "sandcode\code\_globalvars\lists\objects.dm"
#include "sandcode\code\_onclick\hud\screen_objects.dm"
#include "sandcode\code\datums\action.dm"
#include "sandcode\code\datums\ai_laws.dm"
@@ -3645,6 +3647,8 @@
#include "sandcode\code\game\machinery\posialert.dm"
#include "sandcode\code\game\machinery\computer\arcade\tetris.dm"
#include "sandcode\code\game\machinery\pipe\construction.dm"
+#include "sandcode\code\game\machinery\telecomms\machine_interactions.dm"
+#include "sandcode\code\game\machinery\telecomms\machines\receiver.dm"
#include "sandcode\code\game\mecha\mecha_construction_paths.dm"
#include "sandcode\code\game\mecha\mecha_parts.dm"
#include "sandcode\code\game\objects\effects\contraband.dm"
@@ -3684,6 +3688,8 @@
#include "sandcode\code\modules\crafting\recipes\recipes_misc.dm"
#include "sandcode\code\modules\hydroponics\grown\misc.dm"
#include "sandcode\code\modules\integrated_electronics\core\assemblies.dm"
+#include "sandcode\code\modules\integrated_electronics\subtypes\input.dm"
+#include "sandcode\code\modules\integrated_electronics\subtypes\manipulation.dm"
#include "sandcode\code\modules\integrated_electronics\subtypes\output.dm"
#include "sandcode\code\modules\keybindings\keybind\carbon.dm"
#include "sandcode\code\modules\language\dragon.dm"
diff --git a/tgui/src/interfaces/tetris/tetris.js b/tgui/src/interfaces/tetris/tetris.js
index 965c4cab1580..0abb6a8614ef 100644
--- a/tgui/src/interfaces/tetris/tetris.js
+++ b/tgui/src/interfaces/tetris/tetris.js
@@ -5,17 +5,17 @@ Delay=new Array(828,620,464,348,260,196,148,112,84,64,48,36,27);
Fld = new Array(MaxX);
for (i=0; i < MaxX; i++)
{ Fld[i]=new Array(MaxY);
-}
+}
RFld=new Array(MaxY);
Pic= new Array(8);
for (i=0; i<8; i++)
-{ Pic[i] = new Image();
- Pic[i].src = "tetris_"+i+".gif";
+{ Pic[i] = new Image();
+ Pic[i].src = "tetris_"+i+".gif";
}
PrePic= new Array(8);
for (i=0; i<8; i++)
-{ PrePic[i] = new Image();
- PrePic[i].src = "tetrisp"+i+".gif";
+{ PrePic[i] = new Image();
+ PrePic[i].src = "tetrisp"+i+".gif";
}
PatternX=new Array(7);
PatternY=new Array(7);
@@ -53,7 +53,7 @@ function KeyDown(whichkey)
if (whichkey == 65461) Down();
if (whichkey == 65462) Right();
if (whichkey == 65464) Rotate();
-}
+}
function Pause()
{ IsOver=true;
alert("Click OK to continue!");
@@ -108,15 +108,15 @@ function Go()
for (nn=0; nn<4; nn++)
{ Fld[PosX[nn]][PosY[nn]]=Col+1;
document.images[PosX[nn]+MaxX*PosY[nn]].src = Pic[Col+1].src;
- }
+ }
}
else
{ for (nn=0; nn<4; nn++)
Fld[PosX[nn]][PosY[nn]]=0;
- if (CanShift(0,1))
+ if (CanShift(0,1))
{ for (nn=0; nn<4; nn++)
Fld[PosX[nn]][PosY[nn]]=Col+1;
- Shift(0,1);
+ Shift(0,1);
}
else
{ for (nn=0; nn<4; nn++)
@@ -139,7 +139,7 @@ function CanShift(xx, yy)
if (PosY[nn]+yy>=MaxY) return(false);
if (Fld[PosX[nn]+xx][PosY[nn]+yy]>0) return(false);
}
- return(true);
+ return(true);
}
function GetFld(xx, yy)
{ if (xx<0) return(-1);
@@ -158,7 +158,7 @@ function Rotate()
{ for (nn=0; nn<4; nn++)
Fld[PosX[nn]][PosY[nn]]=Col+1;
return;
- }
+ }
for (nn=0; nn<4; nn++)
document.images[PosX[nn]+MaxX*PosY[nn]].src = Pic[0].src;
if (Col==0)
@@ -191,11 +191,11 @@ function Rotate()
PosX[0]=PosX[1]-nn;
nn=PosY[1]-PosY[2];
PosY[2]=PosY[1]+(PosX[1]-PosX[2]);
- PosX[2]=PosX[1]-nn;
+ PosX[2]=PosX[1]-nn;
nn=PosY[1]-PosY[3];
PosY[3]=PosY[1]+(PosX[1]-PosX[3]);
- PosX[3]=PosX[1]-nn;
- }
+ PosX[3]=PosX[1]-nn;
+ }
for (nn=0; nn<4; nn++)
document.images[PosX[nn]+MaxX*PosY[nn]].src = Pic[Col+1].src;
}
@@ -203,19 +203,19 @@ function CanRotate()
{ var ii, jj, iim, jjm, dd=3;
if (Col==3) return(false);
if (Col==0)
- { iim=PosX[2]-2;
+ { iim=PosX[2]-2;
jjm=PosY[2]-1;
dd=4;
}
else
- { iim=PosX[1]-1;
+ { iim=PosX[1]-1;
jjm=PosY[1]-1;
}
for (ii=iim; ii