Allows more than two assemblies to be connected together (#65240)

This PR changes how assemblies and assembly holders work, and allows you to connect more than just a signaler and an igniter together. You could have a signaler, a repeating timer, and an igniter together to constantly produce sparks. Making the assembly holder is the same as before, but now you can add assemblies to it. This also allows signalers to be triggered via right clicking them while holding them in your active hand.
This commit is contained in:
MacBlaze1
2022-03-17 13:52:26 -05:00
committed by GitHub
parent 82a3406b3f
commit 720e833d58
5 changed files with 98 additions and 77 deletions
+4
View File
@@ -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)
+5 -1
View File
@@ -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))
+75 -74
View File
@@ -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
+1 -2
View File
@@ -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)
+13
View File
@@ -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