From 90b67b0541413ba47603947ccabf974ee3544d88 Mon Sep 17 00:00:00 2001 From: Y0SH1M4S73R Date: Sun, 19 Jan 2025 13:40:23 -0500 Subject: [PATCH] A Small Circuit Expansion: Wallmounts, Undertiles, and Wire Bundles (#89122) ## About The Pull Request This PR adds several circuit features, and changes several assembly-related features to make them a bit more logical in how they work. Included are the following changes/additions: - Assemblies and wires have been refactored with vars that describe their behavior: - Assemblies have an `assembly_behavior` bitflag instead of a `attachable` var. This var has 3 flags: - `ASSEMBLY_INPUT`: The assembly is able to pulse the wire it is attached to. - `ASSEMBLY_TOGGLE_ARMED`: On activation, the assembly toggles whether it can pulse the wire it is attached to. - `ASSEMBLY_FUNCTIONAL_OUTPUT`: On activation, the assembly does something other than just toggling whether it's armed. - Wires have a `wires_behavior` bitflag with 3 flags: - `WIRES_INPUT`: The object the wires are attached to does something when the wires are pulsed. - `WIRES_TOGGLE_ARMED`: The object the wires are attached to can activate assemblies attached to those wires, and is fine if all that activating that assembly does is toggle whether it's armed. - `WIRES_FUNCTIONAL_OUTPUT`: The object the wires are attached to expects that assemblies attached to its wires do something other than toggling themselves when activated. - Buttons can only accept assemblies with `ASSEMBLY_FUNCTIONAL_OUTPUT`. - Pressure plates can now accept any assembly with `ASSEMBLY_FUNCTIONAL_OUTPUT`, not just signalers. Assembly shells attached to pressure plates will draw power from the powernet if the pressure plate is under a tile. - Adds a new circuit component - the wire bundle. - This component gives the circuit a number of wires corresponding to the size of the shell. - Each wire has a corresponding port on the component that can pulse, and receive pulses from, that wire. - A circuit can only have one wire bundle component. - Assembly shells cannot be attached to these wires, and no wires will be created if the component is added to an assembly shell. - Available with roundstart tech. - Adds two new shells. - The wallmounted shell is a large shell that can be hung on walls, and uses power from the area it's placed in. - Frame icon: ![image](https://github.com/user-attachments/assets/2fe9297d-44a9-4ceb-b803-a758e59b807d) - Constructed icon: ![image](https://github.com/user-attachments/assets/34c3ffcb-53cb-415f-952f-aec5de63cf17) - The undertile shell is a small shell that only works when fit under a floor tile, but uses power from the area it's placed in. ![image](https://github.com/user-attachments/assets/11ea150d-08be-4ce9-bf44-35a9d6e2d94f) - Both shells support usb cables. - The above shells are available with the Advanced Shells techweb node. ## Why It's Good For The Game The wire bundle component complements the functionality of the assembly shell by allowing circuits to use assemblies directly in their logic. The wallmounted and undertile shells provide ways of placing circuits that don't necessarily take up space for machines. The undertile shell is particularly useful for relaying usb component data over wirenets. Pressure plates being able to accept assemblies other than signalers expands their uses significantly. ## Changelog :cl: refactor: Wires and assemblies have been refactored to have directionality to them. This mostly makes it so that assemblies can only be attached to wires it would make sense for them to be attached to. qol: Pressure plates can now also accept igniters, condensers, flashes, assembly shells, and door controllers. add: Undertile circuit shells. They only work when placed under floor tiles, but support USB cables and use APC power instead of cell power. add: Wallmounted circuit shells. Large shells that support USB cables and use APC power instead of cell power. add: Wire bundle component. Adds a number of wires to the circuit proportional to the capacity of the shell, allowing you to use assemblies in circuit logic. /:cl: --- code/__DEFINES/dcs/signals/signals_object.dm | 16 ++- code/__DEFINES/traits/declarations.dm | 3 + code/__DEFINES/wires.dm | 26 ++++ code/_globalvars/traits/_traits.dm | 1 + code/datums/wires/_wires.dm | 16 +-- code/datums/wires/scanner_gate.dm | 1 + code/datums/wires/wire_bundle_component.dm | 24 ++++ code/game/machinery/buttons.dm | 3 + .../objects/items/devices/pressureplates.dm | 42 ++++--- code/game/objects/items/puzzle_pieces.dm | 2 +- code/modules/assembly/assembly.dm | 4 +- code/modules/assembly/doorcontrol.dm | 1 - code/modules/assembly/health.dm | 2 +- code/modules/assembly/mousetrap.dm | 2 +- code/modules/assembly/proximity.dm | 2 +- code/modules/assembly/signaler.dm | 2 +- code/modules/assembly/timer.dm | 2 +- code/modules/assembly/voice.dm | 2 +- .../research/designs/wiremod_designs.dm | 34 ++++++ .../research/techweb/nodes/circuit_nodes.dm | 3 + .../wiremod/components/utility/wire_bundle.dm | 115 ++++++++++++++++++ code/modules/wiremod/shell/assembly.dm | 33 +++-- code/modules/wiremod/shell/undertile.dm | 13 ++ code/modules/wiremod/shell/wallmount.dm | 33 +++++ icons/obj/science/circuits.dmi | Bin 20554 -> 22989 bytes tgstation.dme | 4 + 26 files changed, 342 insertions(+), 44 deletions(-) create mode 100644 code/datums/wires/wire_bundle_component.dm create mode 100644 code/modules/wiremod/components/utility/wire_bundle.dm create mode 100644 code/modules/wiremod/shell/undertile.dm create mode 100644 code/modules/wiremod/shell/wallmount.dm diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 2044aab51e2..4d9c6e9c00b 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -558,19 +558,29 @@ #define COMSIG_ASSEMBLY_DETACHED "assembly_detached" /* - * The following two signals are separate from the above two because buttons don't set the holder of the inserted assembly. + * The following four signals are separate from the above two because buttons and pressure plates don't set the holder of the inserted assembly. * This causes subtle behavioral differences that future handlers for these signals may need to account for, * even if none of the currently implemented handlers do. */ -/// Sent from /obj/machinery/button/assembly_act(obj/machinery/button/button, mob/user) +/// Sent when an assembly is added to a button : (obj/machinery/button/button, mob/user) #define COMSIG_ASSEMBLY_ADDED_TO_BUTTON "assembly_added_to_button" -/// Sent from /obj/machinery/button/remove_assembly(obj/machinery/button/button, mob/user) +/// Sent when an assembly is removed from a button : (obj/machinery/button/button, mob/user) #define COMSIG_ASSEMBLY_REMOVED_FROM_BUTTON "assembly_removed_from_button" +/// Sent when an assembly is added to a pressure plate : (obj/item/pressureplate/pressure_plate, mob/user) +#define COMSIG_ASSEMBLY_ADDED_TO_PRESSURE_PLATE "assembly_added_to_pressure_plate" + +/// Sent when an assembly is removed from a pressure plate : (obj/item/pressureplate/pressure_plate, mob/user) +#define COMSIG_ASSEMBLY_REMOVED_FROM_PRESSURE_PLATE "assembly_removed_from_pressure_playe" + /// Sent from /datum/powernet/add_cable() #define COMSIG_CABLE_ADDED_TO_POWERNET "cable_added_to_powernet" /// Sent from /datum/powernet/remove_cable() #define COMSIG_CABLE_REMOVED_FROM_POWERNET "cable_removed_from_powernet" + +/// Sent from /datum/wires/attach_assembly() : (atom/holder) +#define COMSIG_ASSEMBLY_PRE_ATTACH "assembly_pre_attach" + #define COMPONENT_CANCEL_ATTACH (1<<0) diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index dc3d6fa0c1d..5d35a7fcb87 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1424,4 +1424,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Mob doesn't get closed eyelids overlay when it gets knocked out cold or dies #define TRAIT_NO_EYELIDS "no_eyelids" +/// Trait applied when the wire bundle component is added to an [/obj/item/integrated_circuit] +#define TRAIT_COMPONENT_WIRE_BUNDLE "component_wire_bundle" + // END TRAIT DEFINES diff --git a/code/__DEFINES/wires.dm b/code/__DEFINES/wires.dm index 4926996f26b..034bb8897e6 100644 --- a/code/__DEFINES/wires.dm +++ b/code/__DEFINES/wires.dm @@ -2,6 +2,30 @@ #define COMSIG_CUT_WIRE(wire) "cut_wire [wire]" #define COMSIG_MEND_WIRE(wire) "mend_wire [wire]" +/// from base of /datum/wires/proc/on_pulse : (wire, mob/user) +#define COMSIG_PULSE_WIRE "pulse_wire" + +// Directionality of wire pulses + +/// The wires interact with their holder when pulsed +#define WIRES_INPUT (1<<0) +/// The wires have a reason to toggle whether attached assemblies are armed +#define WIRES_TOGGLE_ARMED (1<<1) +/// The wires only want to activate assemblies that do something other than (dis)arming themselves +#define WIRES_FUNCTIONAL_OUTPUT (1<<2) +/// The holder can both pulse its wires and be affected by its wires getting pulsed +#define WIRES_ALL (WIRES_INPUT | WIRES_TOGGLE_ARMED | WIRES_FUNCTIONAL_OUTPUT) + +/// The assembly can pulse a wire it is attached to +#define ASSEMBLY_INPUT (1<<0) +/// The assembly toggles whether it will pulse the attached wire when it is pulsed by the attached wire +#define ASSEMBLY_TOGGLE_ARMED (1<<1) +/// The assembly does something other than just (dis)arming itself when it is pulsed by the wire it is attached to +#define ASSEMBLY_FUNCTIONAL_OUTPUT (1<<2) +/// The assembly can both pulse the wire it is attached to, and (dis)arms itself when pulsed by the wire +#define ASSEMBLY_TOGGLEABLE_INPUT (ASSEMBLY_INPUT | ASSEMBLY_TOGGLE_ARMED) +#define ASSEMBLY_ALL (ASSEMBLY_TOGGLEABLE_INPUT | ASSEMBLY_FUNCTIONAL_OUTPUT) + //retvals for attempt_wires_interaction #define WIRE_INTERACTION_FAIL 0 #define WIRE_INTERACTION_SUCCESSFUL 1 @@ -72,3 +96,5 @@ #define AI_WIRE_DISABLED 1 #define AI_WIRE_HACKED 2 #define AI_WIRE_DISABLED_HACKED -1 + +#define MAX_WIRE_COUNT 17 diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 4edc46bb503..e351e155dc1 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -687,6 +687,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CIRCUIT_UI_OPEN" = TRAIT_CIRCUIT_UI_OPEN, "TRAIT_CIRCUIT_UNDUPABLE" = TRAIT_CIRCUIT_UNDUPABLE, "TRAIT_COMPONENT_MMI" = TRAIT_COMPONENT_MMI, + "TRAIT_COMPONENT_WIRE_BUNDLE" = TRAIT_COMPONENT_WIRE_BUNDLE, ), /obj/item/modular_computer = list( "TRAIT_MODPC_HALVED_DOWNLOAD_SPEED" = TRAIT_MODPC_HALVED_DOWNLOAD_SPEED, diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index 73bdc511ee4..13b9420d836 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -7,16 +7,14 @@ if(I.tool_behaviour == TOOL_WIRECUTTER || I.tool_behaviour == TOOL_MULTITOOL) return TRUE if(isassembly(I)) - var/obj/item/assembly/A = I - if(A.attachable) - return TRUE + return TRUE /atom/proc/attempt_wire_interaction(mob/user) if(!wires) return WIRE_INTERACTION_FAIL if(!user.CanReach(src)) return WIRE_INTERACTION_FAIL - wires.interact(user) + INVOKE_ASYNC(wires, TYPE_PROC_REF(/datum/wires, interact), user) return WIRE_INTERACTION_BLOCK /datum/wires @@ -29,6 +27,9 @@ /// The display name for the wire set shown in station blueprints. Not shown in blueprints if randomize is TRUE or it's an item NT wouldn't know about (Explosives/Nuke). Also used in the hacking interface. var/proper_name = "Unknown" + /// Whether pulsed wires affect the holder, and/or the holder pulses its wires + var/wire_behavior = WIRES_INPUT + /// List of all wires. var/list/wires = list() /// List of cut wires. @@ -179,6 +180,7 @@ /datum/wires/proc/pulse(wire, user, force=FALSE) if(!force && is_cut(wire)) return + SEND_SIGNAL(src, COMSIG_PULSE_WIRE, wire, user) on_pulse(wire, user) /datum/wires/proc/pulse_color(color, mob/living/user, force=FALSE) @@ -191,7 +193,7 @@ return TRUE /datum/wires/proc/attach_assembly(color, obj/item/assembly/S) - if(S && istype(S) && S.attachable && !is_attached(color)) + if(S && istype(S) && S.assembly_behavior && !is_attached(color) && !(SEND_SIGNAL(S, COMSIG_ASSEMBLY_PRE_ATTACH, holder) & COMPONENT_CANCEL_ATTACH)) assemblies[color] = S S.forceMove(holder) S.connected = src @@ -384,13 +386,13 @@ I = L.get_active_held_item() if(isassembly(I)) var/obj/item/assembly/A = I - if(A.attachable) + if(A.assembly_behavior & wire_behavior) if(!L.temporarilyRemoveItemFromInventory(A)) return if(!attach_assembly(target_wire, A)) A.forceMove(L.drop_location()) . = TRUE else - to_chat(L, span_warning("You need an attachable assembly!")) + to_chat(L, span_warning("You cannot attach this assembly to these wires!")) #undef MAXIMUM_EMP_WIRES diff --git a/code/datums/wires/scanner_gate.dm b/code/datums/wires/scanner_gate.dm index 14752ec6795..cb363d68f95 100644 --- a/code/datums/wires/scanner_gate.dm +++ b/code/datums/wires/scanner_gate.dm @@ -2,6 +2,7 @@ holder_type = /obj/machinery/scanner_gate proper_name = "Scanner Gate" wires = list(WIRE_ACCEPT, WIRE_DENY, WIRE_DISABLE) + wire_behavior = WIRES_FUNCTIONAL_OUTPUT /datum/wires/scanner_gate/on_pulse(wire, user) . = ..() diff --git a/code/datums/wires/wire_bundle_component.dm b/code/datums/wires/wire_bundle_component.dm new file mode 100644 index 00000000000..5cd4ffa2af6 --- /dev/null +++ b/code/datums/wires/wire_bundle_component.dm @@ -0,0 +1,24 @@ +#define CAPACITY_PER_WIRE 10 + +/datum/wires/wire_bundle_component + holder_type = /atom //Anything that can have a shell component, really. + randomize = TRUE + wire_behavior = WIRES_ALL + +/datum/wires/wire_bundle_component/New(atom/holder) + var/datum/component/shell/shell_comp = holder.GetComponent(/datum/component/shell) + if(!istype(shell_comp)) + CRASH("Holder does not have a shell component!") + var/wire_count = clamp(round(shell_comp.capacity / CAPACITY_PER_WIRE, 1), 1, MAX_WIRE_COUNT) + for(var/index in 1 to wire_count) + wires += "Port [index]" + ..() + +/datum/wires/wire_bundle_component/always_reveal_wire(color) + return TRUE // Let's not make wiring up this stuff confusing - just give them what wires correspond to what ports. + +/datum/wires/wire_bundle_component/ui_data(mob/user) + proper_name = holder.name + . = ..() + +#undef CAPACITY_PER_WIRE diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index c8aba44ef47..66f1b64795a 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -140,6 +140,9 @@ if(device) to_chat(user, span_warning("The button already contains a device!")) return ITEM_INTERACT_BLOCKING + if(!(new_device.assembly_behavior & ASSEMBLY_FUNCTIONAL_OUTPUT)) + to_chat(user, span_warning("\The [new_device] won't really do anything meaningful inside of the button...")) + return ITEM_INTERACT_BLOCKING if(!user.transferItemToLoc(new_device, src, silent = FALSE)) to_chat(user, span_warning("\The [new_device] is stuck to you!")) return ITEM_INTERACT_BLOCKING diff --git a/code/game/objects/items/devices/pressureplates.dm b/code/game/objects/items/devices/pressureplates.dm index 17f324d109f..ea27894d829 100644 --- a/code/game/objects/items/devices/pressureplates.dm +++ b/code/game/objects/items/devices/pressureplates.dm @@ -14,12 +14,12 @@ var/specific_item = null var/trigger_silent = FALSE var/sound/trigger_sound = 'sound/effects/pressureplate.ogg' - var/obj/item/assembly/signaler/sigdev = null + var/obj/item/assembly/assembly = null var/roundstart_signaller = FALSE var/roundstart_signaller_freq = FREQ_PRESSURE_PLATE var/roundstart_signaller_code = 30 var/roundstart_hide = FALSE - var/removable_signaller = TRUE + var/removable_assembly = TRUE var/active = FALSE var/image/tile_overlay = null var/can_trigger = TRUE @@ -31,9 +31,10 @@ . = ..() tile_overlay = image(icon = 'icons/turf/floors.dmi', icon_state = "pp_overlay") if(roundstart_signaller) - sigdev = new - sigdev.code = roundstart_signaller_code - sigdev.set_frequency(roundstart_signaller_freq) + var/obj/item/assembly/signaler/signaller = new(src) + signaller.code = roundstart_signaller_code + signaller.set_frequency(roundstart_signaller_freq) + assembly = signaller if(undertile_pressureplate) AddElement(/datum/element/undertile, tile_overlay = tile_overlay, use_anchor = TRUE) @@ -59,21 +60,28 @@ /obj/item/pressure_plate/proc/trigger() can_trigger = TRUE - if(istype(sigdev)) - sigdev.signal() + if(istype(assembly)) + assembly.activate() -/obj/item/pressure_plate/attackby(obj/item/I, mob/living/L) - if(issignaler(I) && !istype(sigdev) && removable_signaller && L.transferItemToLoc(I, src)) - sigdev = I - to_chat(L, span_notice("You attach [I] to [src]!")) +/obj/item/pressure_plate/attackby(obj/item/item, mob/living/L) + if(isassembly(item) && !istype(assembly) && removable_assembly) + var/obj/item/assembly/new_assembly = item + if(!(new_assembly.assembly_behavior & ASSEMBLY_FUNCTIONAL_OUTPUT)) + to_chat(L, span_warning("\The [item] doesn't seem like it would do much of anything inside of [src]...")) + return + if(L.transferItemToLoc(item, src)) + assembly = item + SEND_SIGNAL(item, COMSIG_ASSEMBLY_ADDED_TO_PRESSURE_PLATE, src, L) + to_chat(L, span_notice("You attach [item] to [src]!")) return ..() /obj/item/pressure_plate/attack_self(mob/living/L) - if(removable_signaller && istype(sigdev)) - to_chat(L, span_notice("You remove [sigdev] from [src].")) - if(!L.put_in_hands(sigdev)) - sigdev.forceMove(get_turf(src)) - sigdev = null + if(removable_assembly && istype(assembly)) + to_chat(L, span_notice("You remove [assembly] from [src].")) + SEND_SIGNAL(assembly, COMSIG_ASSEMBLY_REMOVED_FROM_PRESSURE_PLATE, src, L) + if(!L.put_in_hands(assembly)) + assembly.forceMove(get_turf(src)) + assembly = null return ..() /obj/item/pressure_plate/item_ctrl_click(mob/user) @@ -97,7 +105,7 @@ protected = TRUE anchored = TRUE //this prevents us from being picked up active = TRUE - removable_signaller = FALSE + removable_assembly = FALSE /// puzzle id we send if stepped on var/puzzle_id /// queue size must match diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index a7bd4da85ae..f5e3cf6da68 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -168,7 +168,7 @@ trigger_mob = FALSE trigger_item = TRUE specific_item = /obj/structure/holobox - removable_signaller = FALSE //Being a pressure plate subtype, this can also use signals. + removable_assembly = FALSE //Being a pressure plate subtype, this can also use signals. roundstart_signaller_freq = FREQ_HOLOGRID_SOLUTION //Frequency is kept on its own default channel however. active = TRUE trigger_delay = 10 diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index dbd5a704614..0ac5993aecc 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -23,7 +23,7 @@ var/secured = TRUE var/list/attached_overlays = null var/obj/item/assembly_holder/holder = null - var/attachable = FALSE // can this be attached to wires + var/assembly_behavior = ASSEMBLY_FUNCTIONAL_OUTPUT // how does the assembly behave with respect to what it's connected to var/datum/wires/connected = null var/next_activate = 0 //When we're next allowed to activate - for spam control @@ -126,7 +126,7 @@ balloon_alert(user, "can't attach another of that!") return if(new_assembly.secured || secured) - balloon_alert(user, "both devices not attachable!") + balloon_alert(user, "both devices not assembly_behavior!") return holder = new /obj/item/assembly_holder(drop_location()) diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm index 31584976ced..33610283502 100644 --- a/code/modules/assembly/doorcontrol.dm +++ b/code/modules/assembly/doorcontrol.dm @@ -2,7 +2,6 @@ name = "blast door controller" desc = "A small electronic device able to control a blast door remotely." icon_state = "control" - attachable = TRUE /// The ID of the blast door electronics to match to the ID of the blast door being used. var/id = null /// Cooldown of the door's controller. Updates when pressed (activate()) diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm index ad2c6ac1764..d4635ac159f 100644 --- a/code/modules/assembly/health.dm +++ b/code/modules/assembly/health.dm @@ -3,7 +3,7 @@ desc = "Used for scanning and monitoring health." icon_state = "health" custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*8, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 2) - attachable = TRUE + assembly_behavior = ASSEMBLY_TOGGLEABLE_INPUT var/scanning = FALSE var/health_scan diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 187a161df80..2b2065a67a0 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -4,7 +4,7 @@ icon_state = "mousetrap" inhand_icon_state = "mousetrap" custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT) - attachable = TRUE + assembly_behavior = ASSEMBLY_TOGGLEABLE_INPUT var/armed = FALSE drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index 6ba2a7a6342..9b7ccad9aef 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -3,7 +3,7 @@ desc = "Used for scanning and alerting when someone enters a certain proximity." icon_state = "prox" custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*8, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 2) - attachable = TRUE + assembly_behavior = ASSEMBLY_TOGGLEABLE_INPUT drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' var/scanning = FALSE diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 4e265384ace..b5346386d7d 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -6,7 +6,7 @@ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 4, /datum/material/glass=SMALL_MATERIAL_AMOUNT*1.2) - attachable = TRUE + assembly_behavior = ASSEMBLY_ALL drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index 09cbfd9b0dc..b25d30e1b4b 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -3,7 +3,7 @@ desc = "Used to time things. Works well with contraptions which has to count down. Tick tock." icon_state = "timer" custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*5, /datum/material/glass=SMALL_MATERIAL_AMOUNT*0.5) - attachable = TRUE + assembly_behavior = ASSEMBLY_TOGGLEABLE_INPUT drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm index de0954c960e..106b8127307 100644 --- a/code/modules/assembly/voice.dm +++ b/code/modules/assembly/voice.dm @@ -8,7 +8,7 @@ desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated." icon_state = "voice" custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*5, /datum/material/glass=SMALL_MATERIAL_AMOUNT*0.5) - attachable = TRUE + assembly_behavior = ASSEMBLY_TOGGLEABLE_INPUT verb_say = "beeps" verb_ask = "beeps" verb_exclaim = "beeps" diff --git a/code/modules/research/designs/wiremod_designs.dm b/code/modules/research/designs/wiremod_designs.dm index f8732cc332b..526e8d2a54a 100644 --- a/code/modules/research/designs/wiremod_designs.dm +++ b/code/modules/research/designs/wiremod_designs.dm @@ -477,6 +477,11 @@ id = "comp_assoc_list_pick" build_path = /obj/item/circuit_component/list_pick/assoc +/datum/design/component/wire_bundle + name = "Wire Bundle" + id = "comp_wire_bundle" + build_path = /obj/item/circuit_component/wire_bundle + /datum/design/component/wirenet_receive name = "Wirenet Receiver Component" id = "comp_wirenet_receive" @@ -691,3 +696,32 @@ category = list( RND_CATEGORY_CIRCUITRY + RND_SUBCATEGORY_CIRCUITRY_SHELLS ) + +/datum/design/undertile_shell + name = "Under-tile Shell" + desc = "A small shell that can fit under the floor." + id = "undertile_shell" + materials = list( + /datum/material/glass=HALF_SHEET_MATERIAL_AMOUNT, + /datum/material/iron=SHEET_MATERIAL_AMOUNT*2.5, + ) + build_path = /obj/item/undertile_circuit + build_type = COMPONENT_PRINTER + category = list( + RND_CATEGORY_CIRCUITRY + RND_SUBCATEGORY_CIRCUITRY_SHELLS + ) + + +/datum/design/wallmount_shell + name = "Wall-mounted Shell" + desc = "A large shell that can be mounted on a wall." + id = "wallmount_shell" + materials = list( + /datum/material/glass=SHEET_MATERIAL_AMOUNT, + /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, + ) + build_path = /obj/item/wallframe/circuit + build_type = COMPONENT_PRINTER + category = list( + RND_CATEGORY_CIRCUITRY + RND_SUBCATEGORY_CIRCUITRY_SHELLS + ) diff --git a/code/modules/research/techweb/nodes/circuit_nodes.dm b/code/modules/research/techweb/nodes/circuit_nodes.dm index 109873c3851..9ef3b929ac4 100644 --- a/code/modules/research/techweb/nodes/circuit_nodes.dm +++ b/code/modules/research/techweb/nodes/circuit_nodes.dm @@ -86,6 +86,7 @@ "comp_typecast", "comp_typecheck", "comp_view_sensor", + "comp_wire_bundle", "comp_wirenet_receive", "comp_wirenet_send", "comp_wirenet_send_literal", @@ -108,6 +109,8 @@ "money_bot_shell", "scanner_gate_shell", "scanner_shell", + "undertile_shell", + "wallmount_shell", "comp_equip_action", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) diff --git a/code/modules/wiremod/components/utility/wire_bundle.dm b/code/modules/wiremod/components/utility/wire_bundle.dm new file mode 100644 index 00000000000..7e0355e8948 --- /dev/null +++ b/code/modules/wiremod/components/utility/wire_bundle.dm @@ -0,0 +1,115 @@ +/obj/item/circuit_component/wire_bundle + display_name = "Wire Bundle" + desc = "A bundle of exposed wires that assemblies can be attached to. Ports will only show up once the circuit is inserted into a shell." + category = "Utility" + circuit_flags = CIRCUIT_FLAG_REFUSE_MODULE + + var/datum/wires/wire_bundle_component/tracked_wires + + var/list/wire_input_ports = list() + var/list/wire_output_ports = list() + +/obj/item/circuit_component/wire_bundle/get_ui_notices() + . = ..() + . += create_ui_notice("Port count is proportional to shell capacity.", "orange", "plug") + . += create_ui_notice("Max port count: [MAX_WIRE_COUNT]", "orange", "plug") + . += create_ui_notice("Incompatible with assembly shell.", "red", "plug-circle-xmark") + +/obj/item/circuit_component/wire_bundle/register_shell(atom/movable/shell) + . = ..() + if(isassembly(shell) && !parent.admin_only) + return + if(shell.wires) // Don't add wires to shells that already have some. + return + tracked_wires = new(shell) + shell.set_wires(tracked_wires) + for(var/wire in tracked_wires.wires) + wire_input_ports[add_input_port("Pulse [wire]", PORT_TYPE_SIGNAL)] = wire + wire_output_ports[wire] = add_output_port("[wire] Pulsed", PORT_TYPE_SIGNAL) + RegisterSignal(tracked_wires, COMSIG_PULSE_WIRE, PROC_REF(on_pulse_wire)) + RegisterSignal(shell, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_shell_requesting_context)) + RegisterSignal(shell, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY, PROC_REF(on_shell_secondary_interaction)) + +/obj/item/circuit_component/wire_bundle/unregister_shell(atom/movable/shell) + . = ..() + if(shell.wires != tracked_wires) + return + UnregisterSignal(shell, list(COMSIG_ATOM_ITEM_INTERACTION_SECONDARY, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM)) + for(var/color in tracked_wires.colors) + var/obj/item/assembly/assembly = tracked_wires.detach_assembly(color) + if(assembly) + assembly.forceMove(drop_location()) + shell.set_wires(null) + QDEL_NULL(tracked_wires) + for(var/datum/port/input/in_port in wire_input_ports) + remove_input_port(in_port) + for(var/wire in wire_output_ports) + var/datum/port/output/out_port = wire_output_ports[wire] + remove_output_port(out_port) + wire_input_ports.Cut() + wire_output_ports.Cut() + +/obj/item/circuit_component/wire_bundle/add_to(obj/item/integrated_circuit/added_to) + . = ..() + if(HAS_TRAIT(added_to, TRAIT_COMPONENT_WIRE_BUNDLE)) + return FALSE + ADD_TRAIT(added_to, TRAIT_COMPONENT_WIRE_BUNDLE, REF(src)) + +/obj/item/circuit_component/wire_bundle/removed_from(obj/item/integrated_circuit/removed_from) + . = ..() + REMOVE_TRAIT(removed_from, TRAIT_COMPONENT_WIRE_BUNDLE, REF(src)) + return ..() + +/obj/item/circuit_component/wire_bundle/input_received(datum/port/input/port) + . = ..() + if(!port) + return + var/wire = wire_input_ports[port] + if(!wire) + return + if(tracked_wires.is_cut(wire)) + return + var/color = tracked_wires.get_color_of_wire(wire) + var/obj/item/assembly/attached = tracked_wires.get_attached(color) + attached?.activate() + +/obj/item/circuit_component/wire_bundle/proc/on_pulse_wire(source, wire) + SIGNAL_HANDLER + if(tracked_wires.is_cut(wire)) + return + var/datum/port/output/port = wire_output_ports[wire] + if(!istype(port)) + return + port.set_output(COMPONENT_SIGNAL) + +/obj/item/circuit_component/wire_bundle/proc/can_access_wires(atom/source) + if(ismachinery(source)) + var/obj/machinery/machine = source + return machine.panel_open + return TRUE + +/obj/item/circuit_component/wire_bundle/proc/on_shell_requesting_context(atom/source, list/context, obj/item/item, mob/user) + SIGNAL_HANDLER + . = NONE + + if(!is_wire_tool(item)) + return + if(!can_access_wires(source)) + return + context[SCREENTIP_CONTEXT_RMB] = "Interact with wires" + return CONTEXTUAL_SCREENTIP_SET + +/obj/item/circuit_component/wire_bundle/proc/on_shell_secondary_interaction(atom/source, mob/user, obj/item/tool) + SIGNAL_HANDLER + if(!is_wire_tool(tool)) + return + if(!can_access_wires(source)) + return + var/datum/component/shell/shell_comp = source.GetComponent(/datum/component/shell) + if(shell_comp.locked) + source.balloon_alert(user, "locked!") + return ITEM_INTERACT_FAILURE + if(source.attempt_wire_interaction(user) == WIRE_INTERACTION_BLOCK) + return ITEM_INTERACT_BLOCKING + + diff --git a/code/modules/wiremod/shell/assembly.dm b/code/modules/wiremod/shell/assembly.dm index 3e69331c4c8..033808c8454 100644 --- a/code/modules/wiremod/shell/assembly.dm +++ b/code/modules/wiremod/shell/assembly.dm @@ -7,13 +7,13 @@ name = "circuit assembly" desc = "A small electronic device that can house an integrated circuit." icon_state = "wiremod" - attachable = TRUE + assembly_behavior = ASSEMBLY_ALL /// A reference to any holder to use power from instead of the circuit's own cell var/atom/movable/power_use_proxy /// Valid types for `power_use_proxy` to be - var/static/list/power_use_override_types = list(/obj/machinery, /obj/vehicle/sealed/mecha, /obj/item/mod/control, /mob/living/silicon/robot) + var/static/list/power_use_override_types = list(/obj/machinery, /obj/vehicle/sealed/mecha, /obj/item/mod/control, /obj/item/pressure_plate, /mob/living/silicon/robot) /obj/item/assembly/wiremod/Initialize(mapload) . = ..() @@ -23,10 +23,11 @@ ), SHELL_CAPACITY_SMALL) RegisterSignal(shell, COMSIG_SHELL_CIRCUIT_ATTACHED, PROC_REF(on_circuit_attached)) RegisterSignal(shell, COMSIG_SHELL_CIRCUIT_REMOVED, PROC_REF(on_circuit_removed)) - RegisterSignals(src, list(COMSIG_ASSEMBLY_ATTACHED, COMSIG_ASSEMBLY_ADDED_TO_BUTTON), PROC_REF(on_attached)) - RegisterSignals(src, list(COMSIG_ASSEMBLY_DETACHED, COMSIG_ASSEMBLY_REMOVED_FROM_BUTTON), PROC_REF(on_detached)) + RegisterSignal(src, COMSIG_ASSEMBLY_PRE_ATTACH, PROC_REF(on_pre_attach)) + RegisterSignals(src, list(COMSIG_ASSEMBLY_ATTACHED, COMSIG_ASSEMBLY_ADDED_TO_BUTTON, COMSIG_ASSEMBLY_ADDED_TO_PRESSURE_PLATE), PROC_REF(on_attached)) + RegisterSignals(src, list(COMSIG_ASSEMBLY_DETACHED, COMSIG_ASSEMBLY_REMOVED_FROM_BUTTON, COMSIG_ASSEMBLY_REMOVED_FROM_PRESSURE_PLATE), PROC_REF(on_detached)) -/obj/item/assembly/wiremod/proc/on_circuit_attached(_source, obj/item/integrated_circuit/circuit) +/obj/item/assembly/wiremod/proc/on_circuit_attached(source, obj/item/integrated_circuit/circuit) SIGNAL_HANDLER RegisterSignal(circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE, PROC_REF(override_circuit_power_usage)) @@ -34,12 +35,24 @@ SIGNAL_HANDLER UnregisterSignal(source.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE) -/obj/item/assembly/wiremod/proc/on_attached(_source, atom/movable/holder) +/obj/item/assembly/wiremod/proc/on_pre_attach(obj/item/circuit_component/wire_bundle/source, atom/holder) + SIGNAL_HANDLER + if(!istype(source)) + return + if(source.parent.admin_only) + return + if(istype(holder.wires, /datum/wires/wire_bundle_component)) + var/datum/component/shell/shell_comp = GetComponent(/datum/component/shell) + if(shell_comp.attached_circuit.admin_only) + return + return COMPONENT_CANCEL_ATTACH + +/obj/item/assembly/wiremod/proc/on_attached(source, atom/movable/holder) SIGNAL_HANDLER if(is_type_in_list(holder, power_use_override_types)) power_use_proxy = holder -/obj/item/assembly/wiremod/proc/on_detached(_source) +/obj/item/assembly/wiremod/proc/on_detached(source) SIGNAL_HANDLER power_use_proxy = null @@ -59,6 +72,12 @@ var/obj/item/mod/control/modsuit = power_use_proxy if(modsuit.subtract_charge(power_to_use)) return COMPONENT_OVERRIDE_POWER_USAGE + if(istype(power_use_proxy, /obj/item/pressure_plate)) + if(!power_use_proxy.anchored) + return + var/area/our_area = get_area(power_use_proxy) + if(our_area.apc?.use_energy(power_to_use, AREA_USAGE_EQUIP)) + return COMPONENT_OVERRIDE_POWER_USAGE if(iscyborg(power_use_proxy)) var/mob/living/silicon/robot/borg = power_use_proxy if(borg.cell?.use(power_to_use, force = TRUE)) diff --git a/code/modules/wiremod/shell/undertile.dm b/code/modules/wiremod/shell/undertile.dm new file mode 100644 index 00000000000..69ef66b61c0 --- /dev/null +++ b/code/modules/wiremod/shell/undertile.dm @@ -0,0 +1,13 @@ +/obj/item/undertile_circuit + name = "circuit panel" + desc = "A panel for an integrated circuit. It needs to be fit under a floor tile to operate." + icon = 'icons/obj/science/circuits.dmi' + inhand_icon_state = "flashtool" + lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' + icon_state = "undertile" + +/obj/item/undertile_circuit/Initialize(mapload) + . = ..() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE) + AddComponent(/datum/component/shell, null, SHELL_CAPACITY_SMALL, SHELL_FLAG_REQUIRE_ANCHOR|SHELL_FLAG_USB_PORT) diff --git a/code/modules/wiremod/shell/wallmount.dm b/code/modules/wiremod/shell/wallmount.dm new file mode 100644 index 00000000000..d461f696da1 --- /dev/null +++ b/code/modules/wiremod/shell/wallmount.dm @@ -0,0 +1,33 @@ +/obj/structure/wallmount_circuit + name = "circuit box" + desc = "A wall-mounted box suitable for the installation of integrated circuits." + icon = 'icons/obj/science/circuits.dmi' + icon_state = "wallmount" + layer = BELOW_OBJ_LAYER + anchored = TRUE + + resistance_flags = LAVA_PROOF | FIRE_PROOF + +/obj/structure/wallmount_circuit/Initialize(mapload) + . = ..() + AddComponent(/datum/component/shell, null, SHELL_CAPACITY_LARGE, SHELL_FLAG_REQUIRE_ANCHOR|SHELL_FLAG_USB_PORT) + +/obj/structure/wallmount_circuit/wrench_act(mob/living/user, obj/item/tool) + var/datum/component/shell/shell_comp = GetComponent(/datum/component/shell) + if(shell_comp.locked) + balloon_alert(user, "locked!") + return ITEM_INTERACT_FAILURE + to_chat(user, span_notice("You start unsecuring the circuit box...")) + if(tool.use_tool(src, user, 40, volume=50)) + to_chat(user, span_notice("You unsecure the circuit box.")) + playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/item/wallframe/circuit + name = "circuit box frame" + desc = "A box that can be mounted on a wall and have circuits installed." + icon = 'icons/obj/science/circuits.dmi' + icon_state = "wallmount_assembly" + result_path = /obj/structure/wallmount_circuit + pixel_shift = 32 diff --git a/icons/obj/science/circuits.dmi b/icons/obj/science/circuits.dmi index 1d50c67823bb2fc9afac7e40e397772f11f83794..e91025ae61365e780a5bac27a325fc62858f451b 100644 GIT binary patch literal 22989 zcmZs@1z1$wyEeWDkdPQsK)OVw1q5l3PC*H2Md^}ukdzRRmhO^}?ruZ`rMm@$p(ICo zzQy~V-*?Xc|DEg7YuI~sti9J-&wW4lbFT?`qOL%A^Y%>$f(VrqWwjs(CUyNE7aQ#P z5tUa2HgXWp^ju_LJDWLKIl5Rm*h7#KT7MM#%12TOu8 z&7)U2efS$6nD${cs*cqP3BQ+#t}Hl;LVh+6l)#(mcSt#oG~is@Yu ziCIuo&%i*$;|re0R+^eFgaKaW!s$M&8FE}Y*`#b780pndr?p<$QHw5G(0)ud4pA=d z&RF5UFRiOiRqV!l>|qqU;Y9rT=a5i(^$uPPim3C{J~6I9_E=~j<0iS0ohK&uyu9vY zQ^vB^DmlHY&~d6!d+tF;ljgBVlYhT~=n1^3@nu!#8H>KlJ)2(%TW6&K<-kA@k1yL!&77t;{81ni z@*Ng_>vYK}c%!Y*gKvkU>ZVjv5X1;6$x1)-NZo1iawMNj`+J_IM&KVU@E}H-I9Ibh zeiwr@B8~)A#Y(^SmB}rW7RO50+?ne&N2h_u4|Br2xq}*8>Wh;*T zJdN2&A-!|!Ro7JHTMudu8>JvIe_v`mvkqlm7AC7HTl+;xg!&*d-P-My{6yVv7-2z>R&lAbls|TSWMS}&)T1>Ley2*S>AtQI^o4cLsr?t8>yA( z=LUmc6Uk_W9eq=hl7y?>&mhSnBW z*0)LT+;JojeSuLB`}M2*<5G78h2CPXCl==Bj(cd)0&4q}0r}xG9Gi(HX$XDml=K3+ z+Br#B@_|l9RuedT@1=}nM2jRso0%0A(O-&-W!2RqO7|-C2*Sg|=WM-jDLM6`SnZXU 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