mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-23 15:38:08 +00:00
🆑 coiax add: The cyborg reset module wire has a star symbol marking, allowing a trained Roboticist to easily provide resets without altering any other cyborg settings. /🆑 When I removed cyborg module reset modules, it was pulse-to-reset, which when applied to all the wires on a cyborg, had no real side effects if there was only one AI. Now that it's a cut-to-reset wire, cutting all the wires will invariably desync the cyborg from its parent AI, given that all cyborg wires are randomised. My intention was never for the reset wire to be "found" just like door wires, just to make it cheaper and possible to reset a borg module "in the field". Someone who hasn't read the wiki or knows what a "star symbol" means, will have to be told what to look for, so I chose this method of signaling rather than just "the module reset wire is X". Also, it's a Keep Talking And No One Explodes reference.
301 lines
7.5 KiB
Plaintext
301 lines
7.5 KiB
Plaintext
#define MAXIMUM_EMP_WIRES 3
|
|
|
|
/proc/is_wire_tool(obj/item/I)
|
|
if(!I)
|
|
return
|
|
|
|
if(I.tool_behaviour == TOOL_WIRECUTTER || I.tool_behaviour == TOOL_MULTITOOL)
|
|
return TRUE
|
|
if(istype(I, /obj/item/assembly))
|
|
var/obj/item/assembly/A = I
|
|
if(A.attachable)
|
|
return TRUE
|
|
|
|
/atom
|
|
var/datum/wires/wires = null
|
|
|
|
/atom/proc/attempt_wire_interaction(mob/user)
|
|
if(!wires)
|
|
return WIRE_INTERACTION_FAIL
|
|
if(!user.CanReach(src))
|
|
return WIRE_INTERACTION_FAIL
|
|
wires.interact(user)
|
|
return WIRE_INTERACTION_BLOCK
|
|
|
|
/datum/wires
|
|
var/atom/holder = null // The holder (atom that contains these wires).
|
|
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
|
|
var/proper_name = "Unknown" // The display name for the wire set shown in station blueprints. Not used if randomize is true or it's an item NT wouldn't know about (Explosives/Nuke)
|
|
|
|
var/list/wires = list() // List of wires.
|
|
var/list/cut_wires = list() // List of wires that have been cut.
|
|
var/list/colors = list() // Dictionary of colors to wire.
|
|
var/list/assemblies = list() // List of attached assemblies.
|
|
var/randomize = 0 // If every instance of these wires should be random.
|
|
// Prevents wires from showing up in station blueprints
|
|
|
|
/datum/wires/New(atom/holder)
|
|
..()
|
|
if(!istype(holder, holder_type))
|
|
CRASH("Wire holder is not of the expected type!")
|
|
return
|
|
|
|
src.holder = holder
|
|
if(randomize)
|
|
randomize()
|
|
else
|
|
if(!GLOB.wire_color_directory[holder_type])
|
|
randomize()
|
|
GLOB.wire_color_directory[holder_type] = colors
|
|
GLOB.wire_name_directory[holder_type] = proper_name
|
|
else
|
|
colors = GLOB.wire_color_directory[holder_type]
|
|
|
|
/datum/wires/Destroy()
|
|
holder = null
|
|
assemblies = list()
|
|
return ..()
|
|
|
|
/datum/wires/proc/add_duds(duds)
|
|
while(duds)
|
|
var/dud = WIRE_DUD_PREFIX + "[--duds]"
|
|
if(dud in wires)
|
|
continue
|
|
wires += dud
|
|
|
|
/datum/wires/proc/randomize()
|
|
var/static/list/possible_colors = list(
|
|
"blue",
|
|
"brown",
|
|
"crimson",
|
|
"cyan",
|
|
"gold",
|
|
"grey",
|
|
"green",
|
|
"magenta",
|
|
"orange",
|
|
"pink",
|
|
"purple",
|
|
"red",
|
|
"silver",
|
|
"violet",
|
|
"white",
|
|
"yellow"
|
|
)
|
|
|
|
var/list/my_possible_colors = possible_colors.Copy()
|
|
|
|
for(var/wire in shuffle(wires))
|
|
colors[pick_n_take(my_possible_colors)] = wire
|
|
|
|
/datum/wires/proc/shuffle_wires()
|
|
colors.Cut()
|
|
randomize()
|
|
|
|
/datum/wires/proc/repair()
|
|
cut_wires.Cut()
|
|
|
|
/datum/wires/proc/get_wire(color)
|
|
return colors[color]
|
|
|
|
/datum/wires/proc/get_color_of_wire(wire_type)
|
|
for(var/color in colors)
|
|
var/other_type = colors[color]
|
|
if(wire_type == other_type)
|
|
return color
|
|
|
|
/datum/wires/proc/get_attached(color)
|
|
if(assemblies[color])
|
|
return assemblies[color]
|
|
return null
|
|
|
|
/datum/wires/proc/is_attached(color)
|
|
if(assemblies[color])
|
|
return TRUE
|
|
|
|
/datum/wires/proc/is_cut(wire)
|
|
return (wire in cut_wires)
|
|
|
|
/datum/wires/proc/is_color_cut(color)
|
|
return is_cut(get_wire(color))
|
|
|
|
/datum/wires/proc/is_all_cut()
|
|
if(cut_wires.len == wires.len)
|
|
return TRUE
|
|
|
|
/datum/wires/proc/is_dud(wire)
|
|
return dd_hasprefix(wire, WIRE_DUD_PREFIX)
|
|
|
|
/datum/wires/proc/is_dud_color(color)
|
|
return is_dud(get_wire(color))
|
|
|
|
/datum/wires/proc/cut(wire)
|
|
if(is_cut(wire))
|
|
cut_wires -= wire
|
|
on_cut(wire, mend = TRUE)
|
|
else
|
|
cut_wires += wire
|
|
on_cut(wire, mend = FALSE)
|
|
|
|
/datum/wires/proc/cut_color(color)
|
|
cut(get_wire(color))
|
|
|
|
/datum/wires/proc/cut_random()
|
|
cut(wires[rand(1, wires.len)])
|
|
|
|
/datum/wires/proc/cut_all()
|
|
for(var/wire in wires)
|
|
cut(wire)
|
|
|
|
/datum/wires/proc/pulse(wire, user)
|
|
if(is_cut(wire))
|
|
return
|
|
on_pulse(wire, user)
|
|
|
|
/datum/wires/proc/pulse_color(color, mob/living/user)
|
|
pulse(get_wire(color), user)
|
|
|
|
/datum/wires/proc/pulse_assembly(obj/item/assembly/S)
|
|
for(var/color in assemblies)
|
|
if(S == assemblies[color])
|
|
pulse_color(color)
|
|
return TRUE
|
|
|
|
/datum/wires/proc/attach_assembly(color, obj/item/assembly/S)
|
|
if(S && istype(S) && S.attachable && !is_attached(color))
|
|
assemblies[color] = S
|
|
S.forceMove(holder)
|
|
S.connected = src
|
|
return S
|
|
|
|
/datum/wires/proc/detach_assembly(color)
|
|
var/obj/item/assembly/S = get_attached(color)
|
|
if(S && istype(S))
|
|
assemblies -= color
|
|
S.connected = null
|
|
S.forceMove(holder.drop_location())
|
|
return S
|
|
|
|
/datum/wires/proc/emp_pulse()
|
|
var/list/possible_wires = shuffle(wires)
|
|
var/remaining_pulses = MAXIMUM_EMP_WIRES
|
|
|
|
for(var/wire in possible_wires)
|
|
if(prob(33))
|
|
pulse(wire)
|
|
remaining_pulses--
|
|
if(!remaining_pulses)
|
|
break
|
|
|
|
// Overridable Procs
|
|
/datum/wires/proc/interactable(mob/user)
|
|
return TRUE
|
|
|
|
/datum/wires/proc/get_status()
|
|
return list()
|
|
|
|
/datum/wires/proc/on_cut(wire, mend = FALSE)
|
|
return
|
|
|
|
/datum/wires/proc/on_pulse(wire, user)
|
|
return
|
|
// End Overridable Procs
|
|
|
|
/datum/wires/proc/interact(mob/user)
|
|
if(!interactable(user))
|
|
return
|
|
ui_interact(user)
|
|
for(var/A in assemblies)
|
|
var/obj/item/I = assemblies[A]
|
|
if(istype(I) && I.on_found(user))
|
|
return
|
|
|
|
/datum/wires/ui_host()
|
|
return holder
|
|
|
|
/datum/wires/ui_status(mob/user)
|
|
if(interactable(user))
|
|
return ..()
|
|
return UI_CLOSE
|
|
|
|
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \
|
|
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
|
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
|
if (!ui)
|
|
ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state)
|
|
ui.open()
|
|
|
|
/datum/wires/ui_data(mob/user)
|
|
var/list/data = list()
|
|
var/list/payload = list()
|
|
var/reveal_wires = FALSE
|
|
|
|
// Admin ghost can see a purpose of each wire.
|
|
if(IsAdminGhost(user))
|
|
reveal_wires = TRUE
|
|
|
|
// Same for anyone with an abductor multitool.
|
|
else if(user.is_holding_item_of_type(/obj/item/multitool/abductor))
|
|
reveal_wires = TRUE
|
|
|
|
// Station blueprints do that too, but only if the wires are not randomized.
|
|
else if(user.is_holding_item_of_type(/obj/item/areaeditor/blueprints) && !randomize)
|
|
reveal_wires = TRUE
|
|
|
|
for(var/color in colors)
|
|
payload.Add(list(list(
|
|
"color" = color,
|
|
"wire" = ((reveal_wires && !is_dud_color(color)) ? get_wire(color) : null),
|
|
"cut" = is_color_cut(color),
|
|
"attached" = is_attached(color)
|
|
)))
|
|
data["wires"] = payload
|
|
data["status"] = get_status()
|
|
return data
|
|
|
|
/datum/wires/ui_act(action, params)
|
|
if(..() || !interactable(usr))
|
|
return
|
|
var/target_wire = params["wire"]
|
|
var/mob/living/L = usr
|
|
var/obj/item/I
|
|
switch(action)
|
|
if("cut")
|
|
I = L.is_holding_tool_quality(TOOL_WIRECUTTER)
|
|
if(I || IsAdminGhost(usr))
|
|
if(I && holder)
|
|
I.play_tool_sound(holder, 20)
|
|
cut_color(target_wire)
|
|
. = TRUE
|
|
else
|
|
to_chat(L, "<span class='warning'>You need wirecutters!</span>")
|
|
if("pulse")
|
|
I = L.is_holding_tool_quality(TOOL_MULTITOOL)
|
|
if(I || IsAdminGhost(usr))
|
|
if(I && holder)
|
|
I.play_tool_sound(holder, 20)
|
|
pulse_color(target_wire, L)
|
|
. = TRUE
|
|
else
|
|
to_chat(L, "<span class='warning'>You need a multitool!</span>")
|
|
if("attach")
|
|
if(is_attached(target_wire))
|
|
I = detach_assembly(target_wire)
|
|
if(I)
|
|
L.put_in_hands(I)
|
|
. = TRUE
|
|
else
|
|
I = L.get_active_held_item()
|
|
if(istype(I, /obj/item/assembly))
|
|
var/obj/item/assembly/A = I
|
|
if(A.attachable)
|
|
if(!L.temporarilyRemoveItemFromInventory(A))
|
|
return
|
|
if(!attach_assembly(target_wire, A))
|
|
A.forceMove(L.drop_location())
|
|
. = TRUE
|
|
else
|
|
to_chat(L, "<span class='warning'>You need an attachable assembly!</span>")
|
|
|
|
#undef MAXIMUM_EMP_WIRES
|