New Circuitry Menu #27

This commit is contained in:
Enric Gabriel
2020-07-22 15:36:59 -03:00
committed by GitHub
parent fc49be591b
commit a5ef1123ca
13 changed files with 486 additions and 207 deletions
@@ -9,6 +9,11 @@
/obj/item/integrated_electronics/analyzer/afterattack(var/atom/A, var/mob/living/user)
. = ..()
if(istype(A, /obj/item/electronic_assembly))
var/obj/item/electronic_assembly/EA = A
if(EA.idlock)
to_chat(user, "<span class='notice'>[A] is currently identity-locked and can't be analyzed.</span>")
return FALSE
var/saved = "[A.name] analyzed! On circuit printers with cloning enabled, you may use the code below to clone the circuit:<br><br><code>[SScircuit.save_electronic_assembly(A)]</code>"
if(saved)
to_chat(user, "<span class='notice'>You scan [A].</span>")
@@ -33,6 +33,9 @@
var/prefered_hud_icon = "hudstat" // Used by the AR circuit to change the hud icon.
var/creator // circuit creator if any
var/static/next_assembly_id = 0
var/sealed = FALSE
var/datum/weakref/idlock = null
hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD, DIAG_CIRCUIT_HUD) //diagnostic hud overlays
max_integrity = 50
pass_flags = 0
@@ -65,7 +68,7 @@
src.max_complexity = round(max_complexity)
/obj/item/electronic_assembly/GenerateTag()
tag = "assembly_[next_assembly_id++]"
tag = "assembly_[next_assembly_id++]"
/obj/item/electronic_assembly/examine(mob/user)
. = ..()
@@ -77,15 +80,14 @@
if((isobserver(user) && ckeys_allowed_to_scan[user.ckey]) || IsAdminGhost(user))
. += "You can <a href='?src=[REF(src)];ghostscan=1'>scan</a> this circuit."
for(var/I in assembly_components)
var/obj/item/integrated_circuit/IC = I
var/text = IC.external_examine(user)
if(text)
. += text
for(var/obj/item/integrated_circuit/I in assembly_components)
I.external_examine(user)
if(opened)
interact(user)
/obj/item/electronic_assembly/proc/check_interactivity(mob/user)
if(!istype(user, /mob))
return
return user.canUseTopic(src, BE_CLOSE)
/obj/item/electronic_assembly/Bump(atom/AM)
@@ -128,77 +130,185 @@
diag_hud_set_circuitcell()
/obj/item/electronic_assembly/proc/handle_idle_power()
// First we generate power.
for(var/obj/item/integrated_circuit/passive/power/P in assembly_components)
P.make_energy()
// Now spend it.
for(var/I in assembly_components)
var/obj/item/integrated_circuit/IC = I
if(IC.power_draw_idle)
if(!draw_power(IC.power_draw_idle))
IC.power_fail()
for(var/obj/item/integrated_circuit/I in assembly_components)
if(I.power_draw_idle)
if(!draw_power(I.power_draw_idle))
I.power_fail()
/obj/item/electronic_assembly/interact(mob/user)
ui_interact(user)
/obj/item/electronic_assembly/interact(mob/user, circuit)
ui_interact(user, circuit)
/obj/item/electronic_assembly/ui_interact(mob/user)
/obj/item/electronic_assembly/ui_interact(mob/user, obj/item/integrated_circuit/circuit_pins)
. = ..()
if(!check_interactivity(user))
return
var/total_part_size = return_total_size()
var/total_complexity = return_total_complexity()
var/HTML = ""
var/datum/browser/popup = new(user, "scannernew", name, 800, 630) // Set up the popup browser window
popup.add_stylesheet("scannernew", 'html/browser/assembly_ui.css')
HTML += "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[name]</title></head><body>"
HTML += "<a href='?src=[REF(src)]'>\[Refresh\]</a> | <a href='?src=[REF(src)];rename=1'>\[Rename\]</a><br>"
HTML += "[total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
var/HTML = "<html><head>[UTF8HEADER]<title>[name]</title></head>\
<body><table><thead><tr> \
<a href='?src=[REF(src)]'>Refresh</a> | <a href='?src=[REF(src)];rename=1'>Rename</a><br> \
[total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.<br> \
[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=[REF(src)];remove_cell=1'>\[Remove\]</a>"
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=[REF(src)];remove_cell=1'>Remove</a>"
else
HTML += "<span class='danger'>No power cell detected!</span>"
HTML += "<br><br>"
HTML += "</tr></thead>"
//Getting the newest viewed circuit to compare with new circuit list
if(!circuit_pins || !istype(circuit_pins,/obj/item/integrated_circuit) || !(circuit_pins in assembly_components))
if(assembly_components.len > 0)
circuit_pins = assembly_components[1]
HTML += "Components:"
HTML += "<tr><td width=200px><div class=scrollleft>Components:<br><nobr>"
var/builtin_components = ""
var/removables = ""
var/remove_num = 1
for(var/c in assembly_components)
var/obj/item/integrated_circuit/circuit = c
for(var/obj/item/integrated_circuit/circuit in assembly_components)
if(!circuit.removable)
builtin_components += "<a href='?src=[REF(circuit)];rename=1;return=1'>\[R\]</a> | "
builtin_components += "<a href='?src=[REF(circuit)]'>[circuit.displayed_name]</a>"
builtin_components += "<br>"
if(circuit == circuit_pins)
builtin_components += "[circuit.displayed_name]<br>"
else
builtin_components += "<a href='?src=[REF(src)]'>[circuit.displayed_name]</a><br>"
// Non-inbuilt circuits come after inbuilt circuits
else
removables += "<a href='?src=[REF(src)];component=[REF(circuit)];change_pos=1' style='text-decoration:none;'>[remove_num].</a> | "
if(circuit == circuit_pins)
removables += "[circuit.displayed_name]<br>"
else
removables += "<a href='?src=[REF(src)];component=[REF(circuit)]'>[circuit.displayed_name]</a><br>"
remove_num++
// Put removable circuits (if any) in separate categories from non-removable
if(builtin_components)
HTML += "<hr>"
HTML += "Built in:<br>"
HTML += builtin_components
HTML += "<hr>"
HTML += "Removable:"
HTML += "<hr> Built in:<br> [builtin_components] <hr> Removable: <br>"
HTML += "<br>"
HTML += removables
for(var/c in assembly_components)
var/obj/item/integrated_circuit/circuit = c
if(circuit.removable)
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];up=1' style='text-decoration:none;'>&#8593;</a> "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];down=1' style='text-decoration:none;'>&#8595;</a> "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];top=1' style='text-decoration:none;'>&#10514;</a> "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];bottom=1' style='text-decoration:none;'>&#10515;</a> | "
HTML += "<a href='?src=[REF(circuit)];component=[REF(circuit)];rename=1;return=1'>\[R\]</a> | "
HTML += "<a href='?src=[REF(src)];component=[REF(circuit)];remove=1'>\[-\]</a> | "
HTML += "<a href='?src=[REF(circuit)]'>[circuit.displayed_name]</a>"
HTML += "<br>"
HTML += "</nobr></div></td><td valign='top'><div class=scrollright>"
HTML += "</body></html>"
user << browse(HTML, "window=assembly-[REF(src)];size=655x350;border=1;can_resize=1;can_close=1;can_minimize=1")
//Getting the newest circuit's pin
if(!circuit_pins || !istype(circuit_pins,/obj/item/integrated_circuit))
if(assembly_components.len > 0)
circuit_pins = assembly_components[1]
if(circuit_pins)
HTML += "<div valign='middle'>[circuit_pins.displayed_name]<br>"
HTML += "<a href='?src=[REF(src)];component=[REF(circuit_pins)]'>Refresh</a> | \
<a href='?src=[REF(src)];component=[REF(circuit_pins)];rename_component=1'>Rename</a> | \
<a href='?src=[REF(src)];component=[REF(circuit_pins)];scan=1'>Copy Ref</a> | \
<a href='?src=[REF(src)];component=[REF(circuit_pins)];interact=1'>Interact</a>"
if(circuit_pins.removable)
HTML += " | <a href='?src=[REF(src)];component=[REF(circuit_pins)];remove=1'>Remove</a>"
HTML += "</div><br>"
var/table_edge_width = "30%"
var/table_middle_width = "40%"
HTML += "<table border='1' style='undefined;table-layout: fixed; position: absolute; left: 210; right: 2;'><colgroup>\
<col style='width: [table_edge_width]'>\
<col style='width: [table_middle_width]'>\
<col style='width: [table_edge_width]'>\
</colgroup>"
var/column_width = 3
var/row_height = max(circuit_pins.inputs.len, circuit_pins.outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = ""
var/height = 1
switch(j)
if(1)
io = circuit_pins.get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href='?src=[REF(circuit_pins)];act=wire;pin=[REF(io)]'>[io.display_pin_type()] [io.name]</a> \
<a href='?src=[REF(circuit_pins)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(circuit_pins)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "</ul>"
if(circuit_pins.outputs.len > circuit_pins.inputs.len)
height = 1
if(2)
if(i == 1)
words += "[circuit_pins.displayed_name]<br>[circuit_pins.name != circuit_pins.displayed_name ? "([circuit_pins.name])":""]<hr>[circuit_pins.desc]"
height = row_height
else
continue
if(3)
io = circuit_pins.get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href='?src=[REF(circuit_pins)];act=wire;pin=[REF(io)]'>[io.display_pin_type()] [io.name]</a> \
<a href='?src=[REF(circuit_pins)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(circuit_pins)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "</ul>"
if(circuit_pins.inputs.len > circuit_pins.outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[words]</td>"
HTML += "</tr>"
for(var/activator in circuit_pins.activators)
var/datum/integrated_io/io = activator
var/words = ""
words += "<b><a href='?src=[REF(circuit_pins)];act=wire;pin=[REF(io)]'>[io]</a> \
<a href='?src=[REF(circuit_pins)];act=data;pin=[REF(io)]'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</a></b><br>"
if(io.linked.len)
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(circuit_pins)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "</ul>"
HTML += "<tr><td colspan='3' align='center'>[words]</td></tr>"
HTML += "<tr>\
<br><font color='FFFFFF' class=lowtext>Complexity: [circuit_pins.complexity]\
<br>Cooldown per use: [circuit_pins.cooldown_per_use/10] sec"
if(circuit_pins.ext_cooldown)
HTML += "<br>External manipulation cooldown: [circuit_pins.ext_cooldown/10] sec"
if(circuit_pins.power_draw_idle)
HTML += "<br>Power Draw: [circuit_pins.power_draw_idle] W (Idle)"
if(circuit_pins.power_draw_per_use)
HTML += "<br>Power Draw: [circuit_pins.power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br>[circuit_pins.extended_desc]</font></tr></table></div>"
HTML += "</div></td></tr></table></body></html>"
popup.set_content(HTML)
popup.open()
/obj/item/electronic_assembly/Topic(href, href_list)
if(..())
@@ -229,49 +339,70 @@
battery = null
diag_hud_set_circuitstat() //update diagnostic hud
var/obj/item/integrated_circuit/component
if(href_list["component"])
var/obj/item/integrated_circuit/component = locate(href_list["component"]) in assembly_components
if(component)
// Builtin components are not supposed to be removed or rearranged
if(!component.removable)
return
component = locate(href_list["component"]) in assembly_components
add_allowed_scanner(usr.ckey)
if(!component)
return
var/current_pos = assembly_components.Find(component)
// Find the position of a first removable component
var/first_removable_pos
for(var/i in 1 to assembly_components.len)
var/obj/item/integrated_circuit/temp_component = assembly_components[i]
if(temp_component.removable)
first_removable_pos = i
break
if(href_list["remove"])
try_remove_component(component, usr)
if(href_list["scan"])
var/obj/held_item = usr.get_active_held_item()
if(istype(held_item, /obj/item/integrated_electronics/debugger))
var/obj/item/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(component, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The debugger's 'ref scanner' needs to be on.</span>")
else
// Adjust the position
if(href_list["up"])
current_pos--
else if(href_list["down"])
current_pos++
else if(href_list["top"])
current_pos = first_removable_pos
else if(href_list["bottom"])
current_pos = assembly_components.len
to_chat(usr, "<span class='warning'>You need a debugger set to 'ref' mode to do that.</span>")
// Wrap around nicely
if(current_pos < first_removable_pos)
current_pos = assembly_components.len
else if(current_pos > assembly_components.len)
current_pos = first_removable_pos
// Builtin components are not supposed to be removed or rearranged
if(!component.removable)
return
assembly_components.Remove(component)
assembly_components.Insert(current_pos, component)
add_allowed_scanner(usr.ckey)
interact(usr) // To refresh the UI.
// Find the position of a first removable component
var/first_removable_pos = 0
for(var/i in assembly_components)
first_removable_pos++
var/obj/item/integrated_circuit/temp_component = i
if(temp_component.removable)
break
if(href_list["remove"])
if(try_remove_component(component, usr))
component = null
if(href_list["rename_component"])
component.rename_component(usr)
if(component.assembly)
component.assembly.add_allowed_scanner(usr.ckey)
if(href_list["interact"])
var/obj/item/I = usr.get_active_held_item()
if(istype(I))
I.melee_attack_chain(usr, component)
else
component.attack_hand(usr)
// Adjust the position
if(href_list["change_pos"])
var/new_pos = max(input(usr,"Write the new number","New position") as num,1)
if(new_pos > assembly_components.len)
new_pos = assembly_components.len
if(new_pos < first_removable_pos)
new_pos = first_removable_pos
assembly_components.Remove(component)
assembly_components.Insert(new_pos, component)
interact(usr, component) // To refresh the UI.
/obj/item/electronic_assembly/pickup(mob/living/user)
. = ..()
@@ -307,31 +438,29 @@
/obj/item/electronic_assembly/proc/can_move()
return FALSE
/obj/item/electronic_assembly/update_icon_state()
/obj/item/electronic_assembly/update_icon()
if(opened)
icon_state = initial(icon_state) + "-open"
else
icon_state = initial(icon_state)
/obj/item/electronic_assembly/update_overlays()
. = ..()
cut_overlays()
if(detail_color == COLOR_ASSEMBLY_BLACK) //Black colored overlay looks almost but not exactly like the base sprite, so just cut the overlay and avoid it looking kinda off.
return
. += mutable_appearance('icons/obj/assemblies/electronic_setups.dmi', "[icon_state]-color", color = detail_color)
var/mutable_appearance/detail_overlay = mutable_appearance('icons/obj/assemblies/electronic_setups.dmi', "[icon_state]-color")
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/electronic_assembly/proc/return_total_complexity()
. = 0
var/obj/item/integrated_circuit/part
for(var/p in assembly_components)
part = p
. += part.complexity
var/returnvalue = 0
for(var/obj/item/integrated_circuit/part in assembly_components)
returnvalue += part.complexity
return(returnvalue)
/obj/item/electronic_assembly/proc/return_total_size()
. = 0
var/obj/item/integrated_circuit/part
for(var/p in assembly_components)
part = p
. += part.size
var/returnvalue = 0
for(var/obj/item/integrated_circuit/part in assembly_components)
returnvalue += part.size
return(returnvalue)
// Returns true if the circuit made it inside.
/obj/item/electronic_assembly/proc/try_add_component(obj/item/integrated_circuit/IC, mob/user)
@@ -411,9 +540,10 @@
component.disconnect_all()
component.forceMove(drop_location())
component.assembly = null
assembly_components.Remove(component)
//decriment numbers for diagnostic hud
assembly_components -= component
//decrement numbers for diagnostic hud
if(component.action_flags & IC_ACTION_COMBAT)
combat_circuits -= 1;
if(component.action_flags & IC_ACTION_LONG_RANGE)
@@ -432,6 +562,9 @@
/obj/item/electronic_assembly/screwdriver_act(mob/living/user, obj/item/I)
if(sealed)
to_chat(user,"<span class='notice'>The assembly is sealed. Any attempt to force it open would break it.</span>")
return FALSE
if(..())
return TRUE
I.play_tool_sound(src)
@@ -440,9 +573,75 @@
update_icon()
return TRUE
/obj/item/electronic_assembly/welder_act(mob/living/user, obj/item/I)
var/type_to_use
if(!sealed)
type_to_use = input("What would you like to do?","[src] type setting") as null|anything in list("repair", "seal")
else
type_to_use = input("What would you like to do?","[src] type setting") as null|anything in list("repair", "unseal")
switch(type_to_use)
if("repair")
to_chat(world,"Integrity: [obj_integrity] / [max_integrity]")
if(obj_integrity < max_integrity)
obj_integrity = min(obj_integrity + 20,max_integrity)
to_chat(world,"Integrity: [obj_integrity] / [max_integrity]")
to_chat(user,"<span class='notice'>You fix the dents and scratches of the assembly.</span>")
to_chat(world,user)
return TRUE
else
to_chat(user,"<span class='notice'>The assembly is already in impeccable condition.</span>")
return FALSE
if("seal")
if(!opened)
sealed = TRUE
if(I.use_tool(src, user, 50, volume=100, amount=3))
to_chat(user,"<span class='notice'>You seal the assembly, making it impossible to be opened.</span>")
return TRUE
else
to_chat(user,"<span class='notice'>You need to close the assembly first before sealing it indefinitely!</span>")
return FALSE
if("unseal")
to_chat(user,"<span class='notice'>You start unsealing the assembly carefully...</span>")
if(I.use_tool(src, user, 50, volume=250, amount=3))
for(var/obj/item/integrated_circuit/IC in assembly_components)
if(prob(50))
IC.disconnect_all()
to_chat(user,"<span class='notice'>You unsealed the assembly.</span>")
sealed = FALSE
return TRUE
/obj/item/electronic_assembly/attackby(obj/item/I, mob/living/user)
if(can_anchor && default_unfasten_wrench(user, I, 20))
return
// ID-Lock part: check if we have an id-lock and only lock if we're not trying to get values from it, to prevent accidents
if(istype(I, /obj/item/integrated_electronics/debugger))
var/obj/item/integrated_electronics/debugger/debugger = I
if(debugger.idlock)
// check if unlocked to lock
if(!idlock)
idlock = debugger.idlock
to_chat(user,"<span class='notice'>You lock \the [src].</span>")
//if locked, unlock if ids match
else
if(idlock.resolve() == debugger.idlock.resolve())
idlock = null
to_chat(user,"<span class='notice'>You unlock \the [src].</span>")
else
to_chat(user,"<span class='notice'>The scanned ID doesn't match with \the [src]'s lock.</span>")
debugger.idlock = null
return
if(istype(I, /obj/item/integrated_circuit))
if(!user.canUnEquip(I))
return FALSE
@@ -452,6 +651,7 @@
for(var/obj/item/integrated_circuit/input/S in assembly_components)
S.attackby_react(I,user,user.a_intent)
return ..()
else if(istype(I, /obj/item/multitool) || istype(I, /obj/item/integrated_electronics/wirer) || istype(I, /obj/item/integrated_electronics/debugger))
if(opened)
interact(user)
@@ -461,6 +661,7 @@
for(var/obj/item/integrated_circuit/input/S in assembly_components)
S.attackby_react(I,user,user.a_intent)
return ..()
else if(istype(I, /obj/item/stock_parts/cell))
if(!opened)
to_chat(user, "<span class='warning'>[src]'s hatch is closed, so you can't access \the [src]'s power supplier.</span>")
@@ -478,10 +679,12 @@
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "<span class='notice'>You slot the [I] inside \the [src]'s power supplier.</span>")
return TRUE
else if(istype(I, /obj/item/integrated_electronics/detailer))
var/obj/item/integrated_electronics/detailer/D = I
detail_color = D.detail_color
update_icon()
else
if(user.a_intent != INTENT_HELP)
return ..()
@@ -492,7 +695,7 @@
var/i = 0
//Check if there is another component with the same name and append a number for identification
for(var/s in input_selection)
var/obj/item/integrated_circuit/s_circuit = input_selection[s]
var/obj/item/integrated_circuit/s_circuit = input_selection[s] //The for-loop iterates the keys of the associative list.
if(s_circuit.name == input.name && s_circuit.displayed_name == input.displayed_name && s_circuit != input)
i++
var/disp_name= "[input.displayed_name] \[[input]\]"
@@ -531,7 +734,7 @@
var/i = 0
//Check if there is another component with the same name and append a number for identification
for(var/s in input_selection)
var/obj/item/integrated_circuit/s_circuit = input_selection[s]
var/obj/item/integrated_circuit/s_circuit = input_selection[s] //The for-loop iterates the keys of an associative list.
if(s_circuit.name == input.name && s_circuit.displayed_name == input.displayed_name && s_circuit != input)
i++
var/disp_name= "[input.displayed_name] \[[input]\]"
@@ -617,11 +820,6 @@
return
..()
/obj/item/electronic_assembly/can_trigger_gun(mob/living/user) //sanity checks against pocket death weapon circuits
if(!can_fire_equipped || !user.is_holding(src))
return FALSE
return ..()
/obj/item/electronic_assembly/default //The /default electronic_assemblys are to allow the introduction of the new naming scheme without breaking old saves.
name = "type-a electronic assembly"
@@ -736,7 +934,6 @@
icon_state = "setup_dildo_large"
desc = "It's a case, for building medium-sized electronics with. This one has a phallic design."
/obj/item/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
@@ -10,9 +10,11 @@
var/data_to_write = null
var/accepting_refs = FALSE
var/copy_values = FALSE
var/copy_id = FALSE
var/datum/weakref/idlock = null
/obj/item/integrated_electronics/debugger/attack_self(mob/user)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref","copy","null")
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref","copy","null","id lock")
if(!user.IsAdvancedToolUser())
return
@@ -21,6 +23,7 @@
if("string")
accepting_refs = FALSE
copy_values = FALSE
copy_id = FALSE
new_data = stripped_input(user, "Now type in a string.","[src] string writing", no_trim = TRUE)
if(istext(new_data) && user.IsAdvancedToolUser())
data_to_write = new_data
@@ -28,6 +31,7 @@
if("number")
accepting_refs = FALSE
copy_values = FALSE
copy_id = FALSE
new_data = input(user, "Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && user.IsAdvancedToolUser())
data_to_write = new_data
@@ -35,17 +39,25 @@
if("ref")
accepting_refs = TRUE
copy_values = FALSE
copy_id = FALSE
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
an object for a ref of that object to save it in memory.</span>")
if("copy")
accepting_refs = FALSE
copy_values = TRUE
copy_id = FALSE
to_chat(user, "<span class='notice'>You turn \the [src]'s value copier on. Use it on a pin \
to save its current value in memory.</span>")
if("null")
data_to_write = null
copy_values = FALSE
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
if("id lock")
accepting_refs = FALSE
copy_values = FALSE
copy_id = TRUE
to_chat(user, "<span class='notice'>You turn \the [src]'s id card scanner on. Use your own card \
to store the identity and id-lock an assembly.</span>")
/obj/item/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity)
. = ..()
@@ -56,6 +68,18 @@
now off.</span>")
accepting_refs = FALSE
else if(copy_id && proximity)
if(istype(target,/obj/item/card/id))
idlock = WEAKREF(target)
to_chat(user, "<span class='notice'>You set \the [src]'s card memory to [target.name]. The id card scanner is \
now off.</span>")
else
to_chat(user, "<span class='notice'>You turn the id card scanner is off.</span>")
copy_id = FALSE
return
/obj/item/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
//If the pin can take data:
if(io.io_type == DATA_CHANNEL)
@@ -34,10 +34,11 @@
.=..()
update_icon()
/obj/item/integrated_electronics/detailer/update_overlays()
. = ..()
. += mutable_appearance('icons/obj/assemblies/electronic_tools.dmi', "detailer-color", color = detail_color)
/obj/item/integrated_electronics/detailer/update_icon()
cut_overlays()
var/mutable_appearance/detail_overlay = mutable_appearance('icons/obj/assemblies/electronic_tools.dmi', "detailer-color")
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/integrated_electronics/detailer/attack_self(mob/user)
var/color_choice = input(user, "Select color.", "Assembly Detailer") as null|anything in color_list
@@ -140,4 +140,3 @@
for(var/i = 1 to length(string))
r += ascii2text(text2ascii(string,i) ^ text2ascii(key,(i-1)%length(string)+1))
return r
@@ -35,10 +35,8 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/examine(mob/user)
interact(user)
external_examine(user)
. = ..()
var/text = external_examine(user)
if(text)
. += text
// Can be called via electronic_assembly/attackby()
/obj/item/integrated_circuit/proc/additem(var/obj/item/I, var/mob/living/user)
@@ -47,24 +45,24 @@ a creative player the means to solve many problems. Circuits are held inside an
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
for(var/k in inputs)
var/datum/integrated_io/I = k
if(I.linked.len)
to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].")
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
for(var/k in outputs)
var/datum/integrated_io/O = k
if(O.linked.len)
to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].")
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
for(var/k in activators)
var/datum/integrated_io/activate/A = k
if(A.linked.len)
to_chat(user, "The '[A]' is connected to [A.get_linked_to_desc()].")
to_chat(user, any_examine(user))
any_examine(user)
interact(user)
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
/obj/item/integrated_circuit/proc/external_examine(mob/user)
return any_examine(user)
any_examine(user)
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
@@ -99,14 +97,14 @@ a creative player the means to solve many problems. Circuits are held inside an
. = ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
for(var/k in inputs)
var/datum/integrated_io/I = k
I.scramble()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
for(var/k in outputs)
var/datum/integrated_io/O = k
O.scramble()
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
for(var/k in activators)
var/datum/integrated_io/activate/A = k
A.scramble()
@@ -134,32 +132,35 @@ a creative player the means to solve many problems. Circuits are held inside an
if(!check_interactivity(user))
return
var/window_height = 350
var/window_width = 655
if(assembly)
assembly.ui_interact(user, src)
return
var/table_edge_width = "30%"
var/table_middle_width = "40%"
var/HTML = ""
HTML += "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[src.displayed_name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
var/datum/browser/popup = new(user, "scannernew", name, 800, 630) // Set up the popup browser window
popup.add_stylesheet("scannernew", 'html/browser/assembly_ui.css')
var/HTML = "<html><head>[UTF8HEADER]<title>[src.displayed_name]</title></head><body> \
<div align='center'> \
<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
if(assembly)
HTML += "<a href='?src=[REF(src)];return=1'>\[Return to Assembly\]</a><br>"
HTML += "<a href='?src=[REF(src)];return=1'>Return to Assembly</a><br>"
HTML += "<a href='?src=[REF(src)]'>Refresh</a> | \
<a href='?src=[REF(src)];rename=1'>Rename</a> | \
<a href='?src=[REF(src)];scan=1'>Copy Ref</a>"
HTML += "<a href='?src=[REF(src)]'>\[Refresh\]</a> | "
HTML += "<a href='?src=[REF(src)];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=[REF(src)];scan=1'>\[Copy Ref\]</a>"
if(assembly && removable)
HTML += " | <a href='?src=[REF(assembly)];component=[REF(src)];remove=1'>\[Remove\]</a>"
HTML += "<br>"
HTML += " | <a href='?src=[REF(assembly)];component=[REF(src)];remove=1'>Remove</a>"
HTML += "<colgroup>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
HTML += "<br><colgroup> \
<col style='width: [table_edge_width]'> \
<col style='width: [table_middle_width]'> \
<col style='width: [table_edge_width]'> \
</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
@@ -168,25 +169,27 @@ a creative player the means to solve many problems. Circuits are held inside an
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/words
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href='?src=[REF(src)];act=wire;pin=[REF(io)]'>[io.display_pin_type()] [io.name]</a> \
<a href='?src=[REF(src)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
<a href='?src=[REF(src)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
words += "<a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a><br>"
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "</ul>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
words += "[displayed_name]<br>[name != displayed_name ? "([name])":""]<hr>[desc]"
height = row_height
else
continue
@@ -194,54 +197,52 @@ a creative player the means to solve many problems. Circuits are held inside an
io = get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href='?src=[REF(src)];act=wire;pin=[REF(io)]'>[io.display_pin_type()] [io.name]</a> \
<a href='?src=[REF(src)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
<a href='?src=[REF(src)];act=data;pin=[REF(io)]'>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
words += "<a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a><br>"
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "</ul>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "<td align='center' rowspan='[height]'>[words]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
var/words
words += "<b><a href='?src=[REF(src)];act=wire;pin=[REF(io)]'>[io]</a> \
<a href='?src=[REF(src)];act=data;pin=[REF(io)]'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</a></b><br>"
words += "<b><a href='?src=[REF(src)];act=wire;pin=[REF(io)]'><font color='FF0000'>[io]</font></a> "
words += "<a href='?src=[REF(src)];act=data;pin=[REF(io)]'><font color='FF0000'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</font></a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
words += "<a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'><font color='FF0000'>[linked]</font></a> \
@ <a href='?src=[REF(linked.holder)]'><font color='FF0000'>[linked.holder.displayed_name]</font></a><br>"
words += "<ul>"
for(var/k in io.linked)
var/datum/integrated_io/linked = k
words += "<li><a href='?src=[REF(src)];act=unwire;pin=[REF(io)];link=[REF(linked)]'>[linked]</a> \
@ <a href='?src=[REF(linked.holder)]'>[linked.holder.displayed_name]</a></li>"
words += "<ul>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "<tr><td colspan='3' align='center'>[words]</td></tr>"
HTML += "</table>"
HTML += "</div>"
HTML += "</table></div> \
<br>Complexity: [complexity] \
<br>Cooldown per use: [cooldown_per_use/10] sec"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
HTML += "<br><font color='0000AA'>Cooldown per use: [cooldown_per_use/10] sec</font>"
if(ext_cooldown)
HTML += "<br><font color='0000AA'>External manipulation cooldown: [ext_cooldown/10] sec</font>"
HTML += "<br>External manipulation cooldown: [ext_cooldown/10] sec"
if(power_draw_idle)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_idle] W (Idle)</font>"
HTML += "<br>Power Draw: [power_draw_idle] W (Idle)"
if(power_draw_per_use)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_per_use] W (Active)</font>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "<br>Power Draw: [power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "</body></html>"
if(assembly)
user << browse(HTML, "window=assembly-[REF(assembly)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
else
user << browse(HTML, "window=circuit-[REF(src)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
HTML += "<br>[extended_desc]</body></html>"
onclose(user, "assembly-[REF(src.assembly)]")
popup.set_content(HTML)
popup.open()
/obj/item/integrated_circuit/Topic(href, href_list)
if(!check_interactivity(usr))
@@ -268,7 +269,7 @@ a creative player the means to solve many problems. Circuits are held inside an
linked = locate(href_list["link"]) in pin.linked
if(istype(held_item, /obj/item/integrated_electronics) || istype(held_item, /obj/item/multitool))
pin.handle_wire(linked, held_item, href_list["act"], usr)
update_to_assembly = pin.handle_wire(linked, held_item, href_list["act"], usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
success = FALSE
@@ -291,18 +292,18 @@ a creative player the means to solve many problems. Circuits are held inside an
if(update)
if(assembly && update_to_assembly)
assembly.interact(usr)
assembly.interact(usr, src)
else
interact(usr) // To refresh the UI.
/obj/item/integrated_circuit/proc/push_data()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
for(var/k in outputs)
var/datum/integrated_io/O = k
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
for(var/k in inputs)
var/datum/integrated_io/I = k
I.push_data()
/obj/item/integrated_circuit/proc/draw_idle_power()
@@ -1,22 +1,15 @@
/*
Pins both hold data for circuits, as well move data between them. Some also cause circuits to do their function. DATA_CHANNEL pins are the data holding/moving kind,
where as PULSE_CHANNEL causes circuits to work() when their pulse hits them.
A visualization of how pins work is below. Imagine the below image involves an addition circuit.
When the bottom pin, the activator, receives a pulse, all the numbers on the left (input) get added, and the answer goes on the right side (output).
Inputs Outputs
A [2]\ /[8] result
B [1]-\|++|/
C [4]-/|++|
D [1]/ ||
||
Activator
*/
/datum/integrated_io
var/name = "input/output"
@@ -29,7 +22,7 @@ D [1]/ ||
/datum/integrated_io/New(loc, _name, _data, _pin_type,_ord)
name = _name
if(_data)
if(!isnull(_data))
data = _data
if(_pin_type)
pin_type = _pin_type
@@ -14,6 +14,7 @@
var/cloning = FALSE // If the printer is currently creating a circuit
var/recycling = FALSE // If an assembly is being emptied into this printer
var/list/program // Currently loaded save, in form of list
var/datum/weakref/idlock = null
/obj/item/integrated_circuit_printer/proc/check_interactivity(mob/user)
return user.canUseTopic(src, BE_CLOSE)
@@ -33,8 +34,7 @@
/obj/item/integrated_circuit_printer/Initialize()
. = ..()
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(/datum/material/iron), MINERAL_MATERIAL_AMOUNT * 25, TRUE, list(/obj/item/stack, /obj/item/integrated_circuit, /obj/item/electronic_assembly))
materials.precise_insertion = TRUE
AddComponent(/datum/component/material_container, list(/datum/material/iron), MINERAL_MATERIAL_AMOUNT * 25, TRUE, list(/obj/item/stack, /obj/item/integrated_circuit, /obj/item/electronic_assembly))
/obj/item/integrated_circuit_printer/proc/print_program(mob/user)
if(!cloning)
@@ -43,6 +43,8 @@
visible_message("<span class='notice'>[src] has finished printing its assembly!</span>")
playsound(src, 'sound/items/poster_being_created.ogg', 50, TRUE)
var/obj/item/electronic_assembly/assembly = SScircuit.load_electronic_assembly(get_turf(src), program)
if(idlock)
assembly.idlock = idlock
assembly.creator = key_name(user)
assembly.investigate_log("was printed by [assembly.creator].", INVESTIGATE_CIRCUIT)
cloning = FALSE
@@ -102,13 +104,30 @@
recycling = FALSE
return TRUE
if(istype(O, /obj/item/integrated_electronics/debugger))
var/obj/item/integrated_electronics/debugger/debugger = O
if(!debugger.idlock)
return
if(!idlock)
idlock = debugger.idlock
debugger.idlock = null
to_chat(user, "<span class='notice'>You set \the [src] to print out id-locked assemblies only.</span>")
return
if(debugger.idlock.resolve() == idlock.resolve())
idlock = null
debugger.idlock = null
to_chat(user, "<span class='notice'>You reset \the [src]'s protection settings.</span>")
return
return ..()
/obj/item/integrated_circuit_printer/attack_self(mob/user)
interact(user)
/obj/item/integrated_circuit_printer/interact(mob/user)
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
if(!(in_range(src, user) || issilicon(user)))
return
if(isnull(current_category))
@@ -125,6 +144,13 @@
else
HTML += "Metal: [materials.total_amount]/[materials.max_amount].<br><br>"
HTML += "Identity-lock: "
if(idlock)
var/obj/item/card/id = idlock.resolve()
HTML+= "[id.name] | <A href='?src=[REF(src)];id-lock=TRUE'>Reset</a><br>"
else
HTML += "None | Reset<br>"
if(CONFIG_GET(flag/ic_printing) || debug)
HTML += "Assembly cloning: [can_clone ? (fast_clone ? "Instant" : "Available") : "Unavailable"].<br>"
@@ -136,7 +162,7 @@
if((can_clone && CONFIG_GET(flag/ic_printing)) || debug)
HTML += "Here you can load script for your assembly.<br>"
if(!cloning)
HTML += " <A href='?src=[REF(src)];print=load'>{Load Program}</a> "
HTML += " <A href='?src=[REF(src)];print=load'>Load Program</a> "
else
HTML += " Load Program"
if(!program)
@@ -150,9 +176,9 @@
HTML += "Categories:"
for(var/category in SScircuit.circuit_fabricator_recipe_list)
if(category != current_category)
HTML += " <a href='?src=[REF(src)];category=[category]'>\[[category]\]</a> "
HTML += " <a href='?src=[REF(src)];category=[category]'>[category]</a> "
else // Bold the button if it's already selected.
HTML += " <b>\[[category]\]</b> "
HTML += " <b>[category]</b> "
HTML += "<hr>"
HTML += "<center><h4>[current_category]</h4></center>"
@@ -179,6 +205,9 @@
return TRUE
add_fingerprint(usr)
if(href_list["id-lock"])
idlock = null
if(href_list["category"])
current_category = href_list["category"]
@@ -361,4 +361,3 @@
assembly.forceMove(loc)
return assembly
@@ -46,4 +46,4 @@
/datum/integrated_io/color/display_data(var/input)
if(!isnull(data))
return "(<font color='[data]'>[data]</font>)"
return ..()
return ..()
@@ -15,7 +15,7 @@
var/datum/integrated_io/selected_io = null
var/mode = WIRE
/obj/item/integrated_electronics/wirer/update_icon_state()
/obj/item/integrated_electronics/wirer/update_icon()
icon_state = "wirer-[mode]"
/obj/item/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)