diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 071dab20b1..362b099829 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -536,3 +536,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define LOOT_RESTRICTION_CKEY_PILE 4 //Idem #define WANTED_FILE "wanted_message.json" + +#define UTF8HEADER "" //I WOULD LOVE TO DEFINE THIS IN SANDCODE BUT FREAKING CODE DOESN'T GET IT THEN diff --git a/code/modules/integrated_electronics/core/analyzer.dm b/code/modules/integrated_electronics/core/analyzer.dm index 7e30529bf4..c3851cdb32 100644 --- a/code/modules/integrated_electronics/core/analyzer.dm +++ b/code/modules/integrated_electronics/core/analyzer.dm @@ -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, "[A] is currently identity-locked and can't be analyzed.") + return FALSE + var/saved = "[A.name] analyzed! On circuit printers with cloning enabled, you may use the code below to clone the circuit:

[SScircuit.save_electronic_assembly(A)]" if(saved) to_chat(user, "You scan [A].") diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index c3e0a7abcc..007caa7c06 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -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 scan 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 += "[name]" - - HTML += "\[Refresh\] | \[Rename\]
" - HTML += "[total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.
" - HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.
" + var/HTML = "[UTF8HEADER][name]\ + \ + Refresh | Rename
\ + [total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.
\ + [total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.
" if(battery) - HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. \[Remove\]" + HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. Remove" else HTML += "No power cell detected!" - HTML += "

" + HTML += "" + //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 += "
Components:
" 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 += "\[R\] | " - builtin_components += "[circuit.displayed_name]" - builtin_components += "
" + if(circuit == circuit_pins) + builtin_components += "[circuit.displayed_name]
" + else + builtin_components += "[circuit.displayed_name]
" + + // Non-inbuilt circuits come after inbuilt circuits + else + removables += "[remove_num]. | " + if(circuit == circuit_pins) + removables += "[circuit.displayed_name]
" + else + removables += "[circuit.displayed_name]
" + remove_num++ // Put removable circuits (if any) in separate categories from non-removable if(builtin_components) - HTML += "
" - HTML += "Built in:
" - HTML += builtin_components - HTML += "
" - HTML += "Removable:" + HTML += "
Built in:
[builtin_components]
Removable:
" - HTML += "
" + HTML += removables - for(var/c in assembly_components) - var/obj/item/integrated_circuit/circuit = c - if(circuit.removable) - HTML += " " - HTML += " " - HTML += " " - HTML += " | " - HTML += "\[R\] | " - HTML += "\[-\] | " - HTML += "[circuit.displayed_name]" - HTML += "
" + HTML += "
" - 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 += "
[circuit_pins.displayed_name]
" + + HTML += "Refresh | \ + Rename | \ + Copy Ref | \ + Interact" + if(circuit_pins.removable) + HTML += " | Remove" + HTML += "

" + + var/table_edge_width = "30%" + var/table_middle_width = "40%" + + HTML += "\ + \ + \ + \ + " + + 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 += "" + 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 += "[io.display_pin_type()] [io.name] \ + [io.display_data(io.data)]
" + if(io.linked.len) + words += "" + + if(circuit_pins.outputs.len > circuit_pins.inputs.len) + height = 1 + if(2) + if(i == 1) + words += "[circuit_pins.displayed_name]
[circuit_pins.name != circuit_pins.displayed_name ? "([circuit_pins.name])":""]
[circuit_pins.desc]" + height = row_height + else + continue + if(3) + io = circuit_pins.get_pin_ref(IC_OUTPUT, i) + if(io) + words += "[io.display_pin_type()] [io.name] \ + [io.display_data(io.data)]
" + if(io.linked.len) + words += "" + + if(circuit_pins.inputs.len > circuit_pins.outputs.len) + height = 1 + HTML += "" + HTML += "" + + for(var/activator in circuit_pins.activators) + var/datum/integrated_io/io = activator + var/words = "" + + words += "[io] \ + [io.data?"\":"\"]
" + if(io.linked.len) + words += "" + + HTML += "" + + HTML += "\ +
Complexity: [circuit_pins.complexity]\ +
Cooldown per use: [circuit_pins.cooldown_per_use/10] sec" + if(circuit_pins.ext_cooldown) + HTML += "
External manipulation cooldown: [circuit_pins.ext_cooldown/10] sec" + if(circuit_pins.power_draw_idle) + HTML += "
Power Draw: [circuit_pins.power_draw_idle] W (Idle)" + if(circuit_pins.power_draw_per_use) + HTML += "
Power Draw: [circuit_pins.power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input. + HTML += "
[circuit_pins.extended_desc]
[words]
[words]
" + + + 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, "The debugger's 'ref scanner' needs to be on.") 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, "You need a debugger set to 'ref' mode to do that.") - // 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,"The assembly is sealed. Any attempt to force it open would break it.") + 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,"You fix the dents and scratches of the assembly.") + to_chat(world,user) + return TRUE + + else + to_chat(user,"The assembly is already in impeccable condition.") + return FALSE + + if("seal") + if(!opened) + sealed = TRUE + if(I.use_tool(src, user, 50, volume=100, amount=3)) + to_chat(user,"You seal the assembly, making it impossible to be opened.") + return TRUE + + else + to_chat(user,"You need to close the assembly first before sealing it indefinitely!") + return FALSE + + if("unseal") + to_chat(user,"You start unsealing the assembly carefully...") + 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,"You unsealed the assembly.") + 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,"You lock \the [src].") + + //if locked, unlock if ids match + else + if(idlock.resolve() == debugger.idlock.resolve()) + idlock = null + to_chat(user,"You unlock \the [src].") + + else + to_chat(user,"The scanned ID doesn't match with \the [src]'s lock.") + + 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, "[src]'s hatch is closed, so you can't access \the [src]'s power supplier.") @@ -478,10 +679,12 @@ playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You slot the [I] inside \the [src]'s power supplier.") 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" diff --git a/code/modules/integrated_electronics/core/debugger.dm b/code/modules/integrated_electronics/core/debugger.dm index e3fded3a82..4b50af56c3 100644 --- a/code/modules/integrated_electronics/core/debugger.dm +++ b/code/modules/integrated_electronics/core/debugger.dm @@ -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, "You turn \the [src]'s ref scanner on. Slide it across \ an object for a ref of that object to save it in memory.") if("copy") accepting_refs = FALSE copy_values = TRUE + copy_id = FALSE to_chat(user, "You turn \the [src]'s value copier on. Use it on a pin \ to save its current value in memory.") if("null") data_to_write = null copy_values = FALSE to_chat(user, "You set \the [src]'s memory to absolutely nothing.") + if("id lock") + accepting_refs = FALSE + copy_values = FALSE + copy_id = TRUE + to_chat(user, "You turn \the [src]'s id card scanner on. Use your own card \ + to store the identity and id-lock an assembly.") /obj/item/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity) . = ..() @@ -56,6 +68,18 @@ now off.") accepting_refs = FALSE + else if(copy_id && proximity) + if(istype(target,/obj/item/card/id)) + idlock = WEAKREF(target) + to_chat(user, "You set \the [src]'s card memory to [target.name]. The id card scanner is \ + now off.") + + else + to_chat(user, "You turn the id card scanner is off.") + + 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) diff --git a/code/modules/integrated_electronics/core/detailer.dm b/code/modules/integrated_electronics/core/detailer.dm index 9720bccfe5..653992c0d3 100644 --- a/code/modules/integrated_electronics/core/detailer.dm +++ b/code/modules/integrated_electronics/core/detailer.dm @@ -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 diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index 5567683006..172b14eba4 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -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 - diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index f90b584d76..f391ceae26 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -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 += "[src.displayed_name]" - HTML += "
" - 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') + + var/HTML = "[UTF8HEADER][src.displayed_name] \ +
\ +
" if(assembly) - HTML += "\[Return to Assembly\]
" + HTML += "Return to Assembly
" + + HTML += "Refresh | \ + Rename | \ + Copy Ref" - HTML += "\[Refresh\] | " - HTML += "\[Rename\] | " - HTML += "\[Copy Ref\]" if(assembly && removable) - HTML += " | \[Remove\]" - HTML += "
" + HTML += " | Remove" - HTML += "" - HTML += "" - HTML += "" - HTML += "" - HTML += "" + HTML += "
\ + \ + \ + \ + " 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 += "" 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 += "[io.display_pin_type()] [io.name] \ - [io.display_data(io.data)]
" + [io.display_data(io.data)]
" if(io.linked.len) - for(var/k in 1 to io.linked.len) - var/datum/integrated_io/linked = io.linked[k] - words += "[linked] \ - @ [linked.holder.displayed_name]
" + words += "" if(outputs.len > inputs.len) height = 1 if(2) if(i == 1) - words += "[src.displayed_name]
[src.name != src.displayed_name ? "([src.name])":""]
[src.desc]" + words += "[displayed_name]
[name != displayed_name ? "([name])":""]
[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 += "[io.display_pin_type()] [io.name] \ - [io.display_data(io.data)]
" + [io.display_data(io.data)]
" if(io.linked.len) - for(var/k in 1 to io.linked.len) - var/datum/integrated_io/linked = io.linked[k] - words += "[linked] \ - @ [linked.holder.displayed_name]
" + words += "" if(inputs.len > outputs.len) height = 1 - HTML += "" + HTML += "" HTML += "" for(var/activator in activators) var/datum/integrated_io/io = activator - var/words = list() + var/words + + words += "[io] \ + [io.data?"\":"\"]
" - words += "[io] " - words += "[io.data?"\":"\"]
" if(io.linked.len) - for(var/k in 1 to io.linked.len) - var/datum/integrated_io/linked = io.linked[k] - words += "[linked] \ - @ [linked.holder.displayed_name]
" + words += "" - HTML += "" - HTML += "" + HTML += "" - HTML += "
[jointext(words, null)][words]
[jointext(words, null)]
[words]
" - HTML += "
" + HTML += " \ +
Complexity: [complexity] \ +
Cooldown per use: [cooldown_per_use/10] sec" - HTML += "
Complexity: [complexity]" - HTML += "
Cooldown per use: [cooldown_per_use/10] sec" if(ext_cooldown) - HTML += "
External manipulation cooldown: [ext_cooldown/10] sec" + HTML += "
External manipulation cooldown: [ext_cooldown/10] sec" if(power_draw_idle) - HTML += "
Power Draw: [power_draw_idle] W (Idle)" + HTML += "
Power Draw: [power_draw_idle] W (Idle)" if(power_draw_per_use) - HTML += "
Power Draw: [power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input. - HTML += "
[extended_desc]" + HTML += "
Power Draw: [power_draw_per_use] W (Active)" // Borgcode says that powercells' checked_use() takes joules as input. - 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 += "
[extended_desc]" - 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, "You can't do a whole lot without the proper tools.") 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() diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index c1bbb900fa..eaeeeb6dfd 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -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 diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm index 5f6440bffb..b3e5a122b3 100644 --- a/code/modules/integrated_electronics/core/printer.dm +++ b/code/modules/integrated_electronics/core/printer.dm @@ -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("[src] has finished printing its assembly!") 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, "You set \the [src] to print out id-locked assemblies only.") + return + + if(debugger.idlock.resolve() == idlock.resolve()) + idlock = null + debugger.idlock = null + to_chat(user, "You reset \the [src]'s protection settings.") + 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].

" + HTML += "Identity-lock: " + if(idlock) + var/obj/item/card/id = idlock.resolve() + HTML+= "[id.name] | Reset
" + else + HTML += "None | Reset
" + if(CONFIG_GET(flag/ic_printing) || debug) HTML += "Assembly cloning: [can_clone ? (fast_clone ? "Instant" : "Available") : "Unavailable"].
" @@ -136,7 +162,7 @@ if((can_clone && CONFIG_GET(flag/ic_printing)) || debug) HTML += "Here you can load script for your assembly.
" if(!cloning) - HTML += " {Load Program} " + HTML += " Load Program " 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 += " \[[category]\] " + HTML += " [category] " else // Bold the button if it's already selected. - HTML += " \[[category]\] " + HTML += " [category] " HTML += "
" HTML += "

[current_category]

" @@ -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"] diff --git a/code/modules/integrated_electronics/core/saved_circuits.dm b/code/modules/integrated_electronics/core/saved_circuits.dm index 61ada24b25..3bbf05ea25 100644 --- a/code/modules/integrated_electronics/core/saved_circuits.dm +++ b/code/modules/integrated_electronics/core/saved_circuits.dm @@ -361,4 +361,3 @@ assembly.forceMove(loc) return assembly - diff --git a/code/modules/integrated_electronics/core/special_pins/color_pin.dm b/code/modules/integrated_electronics/core/special_pins/color_pin.dm index 64e4114357..7d4a01b169 100644 --- a/code/modules/integrated_electronics/core/special_pins/color_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/color_pin.dm @@ -46,4 +46,4 @@ /datum/integrated_io/color/display_data(var/input) if(!isnull(data)) return "([data])" - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/integrated_electronics/core/wirer.dm b/code/modules/integrated_electronics/core/wirer.dm index 95f46564cb..ed27354b6c 100644 --- a/code/modules/integrated_electronics/core/wirer.dm +++ b/code/modules/integrated_electronics/core/wirer.dm @@ -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) diff --git a/html/browser/assembly_ui.css b/html/browser/assembly_ui.css new file mode 100644 index 0000000000..02d32c7394 --- /dev/null +++ b/html/browser/assembly_ui.css @@ -0,0 +1,29 @@ +div.scrollleft +{ + bottom: 0; + margin: 0; + overflow: scroll; + overflow-x: auto; + position: absolute; + text-indent: 15px; + top: 120px; + width: 200px; +} + +div.scrollright +{ + bottom: 0; + left: 210px; + margin: 0; + right: 0; + overflow: scroll; + overflow-x: auto; + position: absolute; + text-indent: 15px; + top: 120px; +} + +font.lowtext +{ + bottom: 0; +}