From 1caf39230ad7503ecdc135dfb768caf160cd8da4 Mon Sep 17 00:00:00 2001 From: FalseIncarnate Date: Tue, 29 Mar 2016 03:11:42 -0400 Subject: [PATCH] Logic Gates WIP 3 Allows mass driver buttons to send logic signals - They send LOGIC_FLICKER, since they are only on when pressed, then turn off when released - Can send logic signals to a different ID tag than their associated driver/door ID tag, configurable from the multitool menu Allows light switches to send logic signals - Will send LOGIC_ON or LOGIC_OFF signals to match their current state - Send both when toggled and on the process() cycle - Light control can be toggled via the multitool menu, so you can use them as purely light switches, purely logic switches, or as dual switches Allows light switches to be made from metal sheets, just like mass driver buttons (1 sheet per button) - Fixes a resource duplication bug where driver buttons can be disassembled for more metal than it takes to build them Begins to move some code for various button types into the buttons.dm file, rather than being scattered across multiple files - Driver buttons code moved from door_control.dm - Ignition switch code moved from igniter.dm Renames driver_button.dm to buttons_switches.dm - This is the file that contained the mountable frames for driver buttons, and now also contains the frame for light switches. --- code/game/machinery/buttons.dm | 164 ++++++++++++++++++ code/game/machinery/door_control.dm | 115 ------------ code/game/machinery/igniter.dm | 36 ---- code/game/machinery/lightswitch.dm | 119 ++++++++++++- .../mountable_frames/buttons_switches.dm | 23 +++ .../items/mountable_frames/driver_button.dm | 10 -- .../items/stacks/sheets/sheet_types.dm | 1 + code/modules/logic/logic_base.dm | 7 + paradise.dme | 2 +- 9 files changed, 306 insertions(+), 171 deletions(-) create mode 100644 code/game/objects/items/mountable_frames/buttons_switches.dm delete mode 100644 code/game/objects/items/mountable_frames/driver_button.dm 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 {" + "} + +/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 {" - "} - -/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"