diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 8dcb8a9ce63..0934959d20f 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -1,3 +1,8 @@
+
+//////////////////////////////////////
+// Driver Button //
+//////////////////////////////////////
+
/obj/machinery/driver_button
name = "mass driver button"
icon = 'icons/obj/objects.dmi'
@@ -31,6 +36,121 @@
if(radio_controller)
set_frequency(frequency)
+/obj/machinery/driver_button/initialize()
+ ..()
+ set_frequency(frequency)
+
+/obj/machinery/driver_button/proc/set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_LOGIC)
+ return
+
+/obj/machinery/driver_button/Destroy()
+ if(radio_controller)
+ radio_controller.remove_object(src,frequency)
+ return ..()
+
+
+/obj/machinery/driver_button/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/driver_button/attackby(obj/item/weapon/W, mob/user as mob, params)
+
+ if(istype(W, /obj/item/device/detective_scanner))
+ return
+
+ if(istype(W, /obj/item/device/multitool))
+ update_multitool_menu(user)
+ return 1
+
+ if(istype(W, /obj/item/weapon/wrench))
+ playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ if(do_after(user, 30, target = src))
+ user << "You detach \the [src] from the wall."
+ new/obj/item/mounted/frame/driver_button(get_turf(src))
+ qdel(src)
+ return 1
+
+ return src.attack_hand(user)
+
+/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/device/multitool/P)
+ return {"
+
+ - ID Tag: [format_tag("ID Tag","id_tag")]
+ - Logic Connection: [logic_connect ? "On" : "Off"]
+ - Logic ID Tag: [format_tag("Logic ID Tag", "logic_id_tag")]
+
"}
+
+/obj/machinery/driver_button/attack_hand(mob/user as mob)
+
+ src.add_fingerprint(usr)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(active)
+ return
+ add_fingerprint(user)
+
+ use_power(5)
+
+ launch_sequence()
+
+ return
+
+/obj/machinery/driver_button/proc/launch_sequence()
+ active = 1
+ icon_state = "launcheract"
+
+ if(logic_connect)
+ if(!radio_connection) //can't output without this
+ return
+
+ if(logic_id_tag == null) //Don't output to an undefined id_tag
+ return
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_FLICKER, //Buttons are a FLICKER source, since they only register as ON when you press it, then turn OFF after you release
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
+
+ for(var/obj/machinery/door/poddoor/M in range(src,range))
+ if (M.id_tag == src.id_tag && !M.protected)
+ spawn()
+ M.open()
+
+ sleep(20)
+
+ for(var/obj/machinery/mass_driver/M in range(src,range))
+ if(M.id_tag == src.id_tag)
+ M.drive()
+
+ sleep(50)
+
+ for(var/obj/machinery/door/poddoor/M in range(src,range))
+ if (M.id_tag == src.id_tag && !M.protected)
+ spawn()
+ M.close()
+ return
+
+ icon_state = "launcherbtt"
+ active = 0
+
+/obj/machinery/driver_button/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
+ ..()
+ if("toggle_logic" in href_list)
+ logic_connect = !logic_connect
+
+//////////////////////////////////////
+// Ignition Switch //
+//////////////////////////////////////
+
/obj/machinery/ignition_switch
name = "ignition switch"
icon = 'icons/obj/objects.dmi'
@@ -43,6 +163,46 @@
idle_power_usage = 2
active_power_usage = 4
+/obj/machinery/ignition_switch/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user as mob, params)
+ return src.attack_hand(user)
+
+/obj/machinery/ignition_switch/attack_hand(mob/user as mob)
+
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(active)
+ return
+
+ use_power(5)
+
+ active = 1
+ icon_state = "launcheract"
+
+ for(var/obj/machinery/sparker/M in world)
+ if (M.id == src.id)
+ spawn( 0 )
+ M.spark()
+
+ for(var/obj/machinery/igniter/M in world)
+ if(M.id == src.id)
+ use_power(50)
+ M.on = !( M.on )
+ M.icon_state = text("igniter[]", M.on)
+
+ sleep(50)
+
+ icon_state = "launcherbtt"
+ active = 0
+
+ return
+
+//////////////////////////////////////
+// Flasher Button //
+//////////////////////////////////////
+
/obj/machinery/flasher_button
name = "flasher button"
desc = "A remote control switch for a mounted flasher."
@@ -55,6 +215,10 @@
idle_power_usage = 2
active_power_usage = 4
+//////////////////////////////////////
+// Crematorium Switch //
+//////////////////////////////////////
+
/obj/machinery/crema_switch
desc = "Burn baby burn!"
name = "crematorium igniter"
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index d8e7060d09a..0e6834a3229 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -131,118 +131,3 @@
icon_state = "doorctrl-p"
else
icon_state = "doorctrl0"
-
-//////////////////////////////////////
-// Driver Button //
-//////////////////////////////////////
-
-/obj/machinery/driver_button/initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/driver_button/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_LOGIC)
- return
-
-/obj/machinery/driver_button/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src,frequency)
- return ..()
-
-
-/obj/machinery/driver_button/attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/driver_button/attackby(obj/item/weapon/W, mob/user as mob, params)
-
- if(istype(W, /obj/item/device/detective_scanner))
- return
-
- if(istype(W, /obj/item/device/multitool))
- update_multitool_menu(user)
- return 1
-
- if(istype(W, /obj/item/weapon/wrench))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 30, target = src))
- user << "You detach \the [src] from the wall."
- new/obj/item/mounted/frame/driver_button(get_turf(src))
- qdel(src)
- return 1
-
- return src.attack_hand(user)
-
-/obj/machinery/driver_button/multitool_menu(var/mob/user, var/obj/item/device/multitool/P)
- return {"
-
- - ID Tag: [format_tag("ID Tag","id_tag")]
- - Logic Connection: [logic_connect ? "On" : "Off"]
- - Logic ID Tag: [format_tag("Logic ID Tag", "logic_id_tag")]
-
"}
-
-/obj/machinery/driver_button/attack_hand(mob/user as mob)
-
- src.add_fingerprint(usr)
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
- add_fingerprint(user)
-
- use_power(5)
-
- launch_sequence()
-
- return
-
-/obj/machinery/driver_button/proc/launch_sequence()
- active = 1
- icon_state = "launcheract"
-
- if(logic_connect)
- if(!radio_connection) //can't output without this
- return
-
- if(logic_id_tag == null) //Don't output to an undefined id_tag
- return
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = logic_id_tag,
- "sigtype" = "logic",
- "state" = LOGIC_FLICKER, //Buttons are a FLICKER source, since they only register as ON when you press it, then turn OFF after you release
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
-
- for(var/obj/machinery/door/poddoor/M in range(src,range))
- if (M.id_tag == src.id_tag && !M.protected)
- spawn()
- M.open()
-
- sleep(20)
-
- for(var/obj/machinery/mass_driver/M in range(src,range))
- if(M.id_tag == src.id_tag)
- M.drive()
-
- sleep(50)
-
- for(var/obj/machinery/door/poddoor/M in range(src,range))
- if (M.id_tag == src.id_tag && !M.protected)
- spawn()
- M.close()
- return
-
- icon_state = "launcherbtt"
- active = 0
-
-/obj/machinery/driver_button/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- if("toggle_logic" in href_list)
- logic_connect = !logic_connect
\ No newline at end of file
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 25989db9e0f..d6e41d29fa2 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -114,39 +114,3 @@
return
spark()
..(severity)
-
-/obj/machinery/ignition_switch/attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user as mob, params)
- return src.attack_hand(user)
-
-/obj/machinery/ignition_switch/attack_hand(mob/user as mob)
-
- if(stat & (NOPOWER|BROKEN))
- return
- if(active)
- return
-
- use_power(5)
-
- active = 1
- icon_state = "launcheract"
-
- for(var/obj/machinery/sparker/M in world)
- if (M.id == src.id)
- spawn( 0 )
- M.spark()
-
- for(var/obj/machinery/igniter/M in world)
- if(M.id == src.id)
- use_power(50)
- M.on = !( M.on )
- M.icon_state = text("igniter[]", M.on)
-
- sleep(50)
-
- icon_state = "launcherbtt"
- active = 0
-
- return
\ No newline at end of file
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 839c63a6bc9..47a3d48e19c 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -11,9 +11,27 @@
var/area/area = null
var/otherarea = null
// luminosity = 1
+ settagwhitelist = list("logic_id_tag")
+ var/light_connect = 1 //Allows the switch to control lights in its associated areas. When set to 0, using the switch won't affect the lights.
+ var/datum/radio_frequency/radio_connection
+ var/frequency = 0
+ var/logic_id_tag = "default" //Defines the ID tag to send logic signals to.
+ var/logic_connect = 0 //Set this to allow the switch to send out logic signals.
-/obj/machinery/light_switch/New()
+
+/obj/machinery/light_switch/New(turf/loc, var/w_dir=null)
..()
+ switch(w_dir)
+ if(NORTH)
+ pixel_y = 25
+ if(SOUTH)
+ pixel_y = -25
+ if(EAST)
+ pixel_x = 25
+ if(WEST)
+ pixel_x = -25
+ if(radio_controller)
+ set_frequency(frequency)
spawn(5)
src.area = src.loc.loc
@@ -26,7 +44,20 @@
src.on = src.area.lightswitch
updateicon()
+/obj/machinery/light_switch/initialize()
+ ..()
+ set_frequency(frequency)
+/obj/machinery/light_switch/proc/set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_LOGIC)
+ return
+
+/obj/machinery/light_switch/Destroy()
+ if(radio_controller)
+ radio_controller.remove_object(src,frequency)
+ return ..()
/obj/machinery/light_switch/proc/updateicon()
if(stat & NOPOWER)
@@ -41,22 +72,55 @@
if(..(user, 1))
user << "A light switch. It is [on? "on" : "off"]."
-
/obj/machinery/light_switch/attack_hand(mob/user)
on = !on
+ updateicon()
- area.lightswitch = on
- area.updateicon()
+ if(light_connect)
+ area.lightswitch = on
+ area.updateicon()
- for(var/obj/machinery/light_switch/L in area)
- L.on = on
- L.updateicon()
+ if(logic_connect && powered(LIGHT)) //Don't bother sending a signal if we aren't set to send them or we have no power to send with.
+ handle_output()
- area.power_change()
+ if(light_connect)
+ for(var/obj/machinery/light_switch/L in area)
+ L.on = on
+ L.updateicon()
+
+ area.power_change()
+
+/obj/machinery/light_switch/proc/handle_output()
+ if(!radio_connection) //can't output without this
+ return
+
+ if(logic_id_tag == null) //Don't output to an undefined id_tag
+ return
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ //Light switches are continuous signal sources, since they register as ON or OFF and stay that way until adjusted again
+ if(on)
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_ON,
+ )
+ else
+ signal.data = list(
+ "tag" = logic_id_tag,
+ "sigtype" = "logic",
+ "state" = LOGIC_OFF,
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
+ if(on)
+ use_power(5, LIGHT) //Use a tiny bit of power every time we send an ON signal. Draws from the local APC's lighting circuit, since this is a LIGHT switch.
/obj/machinery/light_switch/power_change()
-
if(!otherarea)
if(powered(LIGHT))
stat &= ~NOPOWER
@@ -71,3 +135,40 @@
return
power_change()
..(severity)
+
+/obj/machinery/light_switch/process()
+ if(logic_connect && powered(LIGHT)) //We won't send signals while unpowered, but the last signal will remain valid for anything that received it before we went dark
+ handle_output()
+
+/obj/machinery/light_switch/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
+ if(istype(W, /obj/item/device/detective_scanner))
+ return
+
+ if(istype(W, /obj/item/device/multitool))
+ update_multitool_menu(user)
+ return 1
+
+ if(istype(W, /obj/item/weapon/wrench))
+ playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ if(do_after(user, 30, target = src))
+ user << "You detach \the [src] from the wall."
+ new/obj/item/mounted/frame/light_switch(get_turf(src))
+ qdel(src)
+ return 1
+
+ return src.attack_hand(user)
+
+/obj/machinery/light_switch/multitool_menu(var/mob/user, var/obj/item/device/multitool/P)
+ return {"
+ "}
+
+/obj/machinery/light_switch/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
+ ..()
+ if("toggle_light_connect" in href_list)
+ light_connect = !light_connect
+ if("toggle_logic" in href_list)
+ logic_connect = !logic_connect
diff --git a/code/game/objects/items/mountable_frames/buttons_switches.dm b/code/game/objects/items/mountable_frames/buttons_switches.dm
new file mode 100644
index 00000000000..b1e3fabbb86
--- /dev/null
+++ b/code/game/objects/items/mountable_frames/buttons_switches.dm
@@ -0,0 +1,23 @@
+/obj/item/mounted/frame/driver_button
+ name = "mass driver button frame"
+ desc = "Used for repairing or building mass driver buttons"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "launcherbtt_frame"
+ mount_reqs = list("simfloor")
+ sheets_refunded = 1
+
+/obj/item/mounted/frame/driver_button/do_build(turf/on_wall, mob/user)
+ new /obj/machinery/driver_button(get_turf(user), get_dir(user, on_wall))
+ qdel(src)
+
+/obj/item/mounted/frame/light_switch
+ name = "light switch frame"
+ desc = "Used for repairing or building light switches"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "light-p"
+ mount_reqs = list("simfloor", "nospace")
+ sheets_refunded = 1
+
+/obj/item/mounted/frame/light_switch/do_build(turf/on_wall, mob/user)
+ new /obj/machinery/light_switch(get_turf(user), get_dir(user, on_wall))
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/items/mountable_frames/driver_button.dm b/code/game/objects/items/mountable_frames/driver_button.dm
deleted file mode 100644
index 7c888b48c95..00000000000
--- a/code/game/objects/items/mountable_frames/driver_button.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-/obj/item/mounted/frame/driver_button
- name = "mass driver button frame"
- desc = "Used for repairing or building mass driver buttons"
- icon = 'icons/obj/objects.dmi'
- icon_state = "launcherbtt_frame"
- mount_reqs = list("simfloor")
-
-/obj/item/mounted/frame/driver_button/do_build(turf/on_wall, mob/user)
- new /obj/machinery/driver_button(get_turf(user), get_dir(user, on_wall))
- qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 11db68ec671..a5f7575a34a 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -72,6 +72,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
), 4), \
null, \
new/datum/stack_recipe("mass driver button frame", /obj/item/mounted/frame/driver_button, 1, time = 50, one_per_turf = 0, on_floor = 1), \
+ new/datum/stack_recipe("light switch frame", /obj/item/mounted/frame/light_switch, 1, time = 50, one_per_turf = 0, on_floor = 1), \
null, \
new/datum/stack_recipe("grenade casing", /obj/item/weapon/grenade/chem_grenade), \
new/datum/stack_recipe("light fixture frame", /obj/item/mounted/frame/light_fixture, 2), \
diff --git a/code/modules/logic/logic_base.dm b/code/modules/logic/logic_base.dm
index 9e93942935f..129a243c37b 100644
--- a/code/modules/logic/logic_base.dm
+++ b/code/modules/logic/logic_base.dm
@@ -265,8 +265,15 @@
if(tamperproof)
//This is some top-level tamperproofing right here, that's for sure. It can even defy a singularity!
return 0
+ ..()
/obj/machinery/logic_gate/bullet_act()
if(tamperproof)
return 0
+ ..()
+
+/obj/machinery/logic_gate/tesla_act(var/power)
+ if(tamperproof)
+ tesla_zap(src, 3, power) //If we're tamperproof, we'll just bounce the full shock of the tesla zap we got hit by, so it continues on normally without diminishing
+ return 0
..()
\ No newline at end of file
diff --git a/paradise.dme b/paradise.dme
index c4c7bfc1545..2dea07e765d 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -684,7 +684,7 @@
#include "code\game\objects\items\devices\radio\radio.dm"
#include "code\game\objects\items\mountable_frames\air_alarm.dm"
#include "code\game\objects\items\mountable_frames\apc_frame.dm"
-#include "code\game\objects\items\mountable_frames\driver_button.dm"
+#include "code\game\objects\items\mountable_frames\buttons_switches.dm"
#include "code\game\objects\items\mountable_frames\fire_alarm.dm"
#include "code\game\objects\items\mountable_frames\frames.dm"
#include "code\game\objects\items\mountable_frames\intercom.dm"