diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index 54fe2d6943a..089f1e95a82 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -104,6 +104,10 @@ else to_chat(user, span_warning("Both devices must be in attachable mode to be attached together.")) return + if(istype(W, /obj/item/assembly_holder)) + if(!secured) + var/obj/item/assembly_holder/added_to_holder = W + added_to_holder.add_assembly(src, user) ..() /obj/item/assembly/screwdriver_act(mob/living/user, obj/item/I) diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index f2d504d5942..d033f862b88 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -115,7 +115,11 @@ //Bomb assembly proc. This turns assembly+tank into a bomb /obj/item/tank/proc/bomb_assemble(obj/item/assembly_holder/assembly, mob/living/user) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it - if(isigniter(assembly.a_left) == isigniter(assembly.a_right)) + var/igniter_count = 0 + for(var/obj/item/assembly/attached_assembly as anything in assembly.assemblies) + if(isigniter(attached_assembly)) + igniter_count += 1 + if(LAZYLEN(assembly.assemblies) == igniter_count) return if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src)) diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 6ea9b5f8511..32191f31da5 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -10,25 +10,20 @@ w_class = WEIGHT_CLASS_SMALL throw_speed = 2 throw_range = 7 - - var/obj/item/assembly/a_left = null - var/obj/item/assembly/a_right = null + /// used to store the list of assemblies making up our assembly holder + var/list/obj/item/assembly/assemblies /obj/item/assembly_holder/Initialize(mapload) . = ..() AddComponent(/datum/component/simple_rotation) /obj/item/assembly_holder/Destroy() - QDEL_NULL(a_left) - QDEL_NULL(a_right) + QDEL_LAZYLIST(assemblies) return ..() /obj/item/assembly_holder/Exited(atom/movable/gone, direction) . = ..() - if(gone == a_left) - a_left = null - else if(gone == a_right) - a_right = null + LAZYREMOVE(assemblies, gone) /obj/item/assembly_holder/IsAssemblyHolder() return TRUE @@ -41,6 +36,23 @@ update_appearance() SSblackbox.record_feedback("tally", "assembly_made", 1, "[initial(A.name)]-[initial(A2.name)]") +/** + * Adds an assembly to the assembly holder + * + * This proc is used to add an assembly to the assembly holder, update the appearance, and the name of it. + * Arguments: + * * attached_assembly - assembly we are adding to the assembly holder + * * user - user we pass into attach() + */ +/obj/item/assembly_holder/proc/add_assembly(obj/item/assembly/attached_assembly, mob/user) + attach(attached_assembly, user) + name = "" + for(var/obj/item/assembly/assembly as anything in assemblies) + name += "[assembly.name]-" + name = splicetext(name, length(name), length(name) + 1, "") + name += " assembly" + update_appearance() + /obj/item/assembly_holder/proc/attach(obj/item/assembly/A, mob/user) if(!A.remove_item_from_storage(src)) if(user) @@ -49,10 +61,7 @@ A.forceMove(src) A.holder = src A.toggle_secure() - if(!a_left) - a_left = A - else - a_right = A + LAZYADD(assemblies, A) A.holder_movement() A.on_attach() @@ -62,96 +71,88 @@ /obj/item/assembly_holder/update_overlays() . = ..() - if(a_left) - . += "[a_left.icon_state]_left" - for(var/left_overlay in a_left.attached_overlays) - . += "[left_overlay]_l" - - if(!a_right) - return - - if(a_right.is_position_sensitive) - . += "[a_right.icon_state]_right" - for(var/right_overlay in a_right.attached_overlays) - . += "[right_overlay]_r" - return - - var/mutable_appearance/right = mutable_appearance(icon, "[a_right.icon_state]_left") - right.transform = matrix(-1, 0, 0, 0, 1, 0) - for(var/right_overlay in a_right.attached_overlays) - right.add_overlay("[right_overlay]_l") - . += right + for(var/i in 1 to LAZYLEN(assemblies)) + if(i % 2 == 1) + var/obj/item/assembly/assembly = assemblies[i] + . += "[assembly.icon_state]_left" + for(var/left_overlay in assembly.attached_overlays) + . += "[left_overlay]_l" + if(i % 2 == 0) + var/obj/item/assembly/assembly = assemblies[i] + var/mutable_appearance/right = mutable_appearance(icon, "[assembly.icon_state]_left") + right.transform = matrix(-1, 0, 0, 0, 1, 0) + for(var/right_overlay in assembly.attached_overlays) + right.add_overlay("[right_overlay]_l") + . += right /obj/item/assembly_holder/on_found(mob/finder) - if(a_left) - a_left.on_found(finder) - if(a_right) - a_right.on_found(finder) + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.on_found(finder) /obj/item/assembly_holder/setDir() . = ..() - if(a_left) - a_left.holder_movement() - if(a_right) - a_right.holder_movement() + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.holder_movement() /obj/item/assembly_holder/dropped(mob/user) . = ..() - if(a_left) - a_left.dropped() - if(a_right) - a_right.dropped() + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.dropped() /obj/item/assembly_holder/attack_hand(mob/living/user, list/modifiers)//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess . = ..() if(.) return - if(a_left) - a_left.attack_hand() - if(a_right) - a_right.attack_hand() + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.attack_hand() +/obj/item/assembly_holder/attackby(obj/item/weapon, mob/user, params) + if(isassembly(weapon)) + var/obj/item/assembly/attached_assembly = weapon + if(!attached_assembly.secured) + add_assembly(attached_assembly, user) + balloon_alert(user, "part added") + return + return ..() /obj/item/assembly_holder/AltClick(mob/user) return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool) if(..()) return TRUE - to_chat(user, span_notice("You disassemble [src]!")) - if(a_left) - a_left.on_detach() - a_left = null - if(a_right) - a_right.on_detach() - a_right = null + balloon_alert(user, "disassembled") + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.on_detach() + LAZYREMOVE(assemblies, assembly) qdel(src) return TRUE /obj/item/assembly_holder/attack_self(mob/user) src.add_fingerprint(user) - if(!a_left || !a_right) - to_chat(user, span_danger("Assembly part missing!")) + if(LAZYLEN(assemblies) == 1) + balloon_alert(user, "part missing!") return - if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code - switch(tgui_alert(usr,"Which side would you like to use?",,list("Left","Right"))) - if("Left") - a_left.attack_self(user) - if("Right") - a_right.attack_self(user) - return - else - a_left.attack_self(user) - a_right.attack_self(user) + for(var/obj/item/assembly/assembly as anything in assemblies) + assembly.attack_self(user) -/obj/item/assembly_holder/proc/process_activation(obj/D, normal = 1, special = 1) - if(!D) +/** + * this proc is used to process the activation of the assembly holder + * + * This proc is usually called by signalers, timers, or anything that can trigger and + * send a pulse to the assembly holder, which then calls this proc that actually activates the assemblies + * Arguments: + * * /obj/device - the device we sent the pulse from which called this proc + * * normal - if this is a normal activation + * * special - if this is a special activation + */ +/obj/item/assembly_holder/proc/process_activation(obj/device, normal = TRUE, special = TRUE) + if(!device) return FALSE - if((normal) && (a_right) && (a_left)) - if(a_right != D) - a_right.pulsed(FALSE) - if(a_left != D) - a_left.pulsed(FALSE) + if(normal && LAZYLEN(assemblies) >= 2) + for(var/obj/item/assembly/assembly as anything in assemblies) + if(LAZYACCESS(assemblies, assembly) != device) + assembly.pulsed(FALSE) if(master) master.receive_signal() return TRUE diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index ca35ced6c6b..60f863176ff 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -101,8 +101,7 @@ for(var/i in 1 to maxlength) var/obj/effect/beam/i_beam/I = new(T) if(istype(holder, /obj/item/assembly_holder)) - var/obj/item/assembly_holder/assembly_holder = holder - I.icon_state = "[initial(I.icon_state)]_[(assembly_holder.a_left == src) ? "l":"r"]" //Sync the offset of the beam with the position of the sensor. + I.icon_state = "[initial(I.icon_state)]_l" //Sync the offset of the beam with the position of the sensor. else if(istype(holder, /obj/item/transfer_valve)) I.icon_state = "[initial(I.icon_state)]_ttv" I.set_density(TRUE) diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 21886c1eb74..b148f51b408 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -123,6 +123,19 @@ to_chat(user, "You transfer the frequency and code of \the [signaler2.name] to \the [name]") ..() +/obj/item/assembly/signaler/attack_self_secondary(mob/user, modifiers) + . = ..() + if(!can_interact(user)) + return + if(!ishuman(user)) + return + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_SIGNALLER_SEND)) + balloon_alert(user, "still recharging...") + return + TIMER_COOLDOWN_START(src, COOLDOWN_SIGNALLER_SEND, 1 SECONDS) + INVOKE_ASYNC(src, .proc/signal) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + /obj/item/assembly/signaler/proc/signal() if(!radio_connection) return