diff --git a/code/__DEFINES/integrated_electronics.dm b/code/__DEFINES/integrated_electronics.dm index e2467af26879..8e9e1b7cea62 100644 --- a/code/__DEFINES/integrated_electronics.dm +++ b/code/__DEFINES/integrated_electronics.dm @@ -1,6 +1,6 @@ -#define IC_INPUT "input" -#define IC_OUTPUT "output" -#define IC_ACTIVATOR "activator" +#define IC_INPUT "I" +#define IC_OUTPUT "O" +#define IC_ACTIVATOR "A" // Pin functionality. #define DATA_CHANNEL "data channel" diff --git a/code/controllers/subsystem/processing/circuit.dm b/code/controllers/subsystem/processing/circuit.dm index cb10503a8011..73e9ee669df0 100644 --- a/code/controllers/subsystem/processing/circuit.dm +++ b/code/controllers/subsystem/processing/circuit.dm @@ -9,8 +9,12 @@ PROCESSING_SUBSYSTEM_DEF(circuit) var/list/all_exonet_connections = list() //Address = connection datum. var/list/obj/machinery/exonet_node/all_exonet_nodes = list() - var/list/all_circuits = list() // Associative list of [circuit_name]:[circuit_path] pairs + var/list/all_components = list() // Associative list of [component_name]:[component_path] pairs + var/list/cached_components = list() // Associative list of [component_path]:[component] pairs + var/list/all_assemblies = list() // Associative list of [assembly_name]:[assembly_path] pairs + var/list/cached_assemblies = list() // Associative list of [assembly_path]:[assembly] pairs var/list/circuit_fabricator_recipe_list = list() // Associative list of [category_name]:[list_of_circuit_paths] pairs + var/cost_multiplier = MINERAL_MATERIAL_AMOUNT / 10 // Each circuit cost unit is 200cm3 /datum/controller/subsystem/processing/circuit/Initialize(start_timeofday) SScircuit.cipherkey = random_string(2000+rand(0,10), GLOB.alphabet) @@ -19,12 +23,11 @@ PROCESSING_SUBSYSTEM_DEF(circuit) /datum/controller/subsystem/processing/circuit/proc/circuits_init() //Cached lists for free performance - var/list/all_circuits = src.all_circuits - var/list/circuit_fabricator_recipe_list = src.circuit_fabricator_recipe_list for(var/path in typesof(/obj/item/integrated_circuit)) var/obj/item/integrated_circuit/IC = path var/name = initial(IC.name) - all_circuits[name] = IC // Populating the complete list + all_components[name] = path // Populating the component lists + cached_components[IC] = new path if(!(initial(IC.spawn_flags) & (IC_SPAWN_DEFAULT | IC_SPAWN_RESEARCH))) continue @@ -35,13 +38,19 @@ PROCESSING_SUBSYSTEM_DEF(circuit) var/list/category_list = circuit_fabricator_recipe_list[category] category_list += IC // Populating the fabricator categories + for(var/path in typesof(/obj/item/device/electronic_assembly)) + var/obj/item/device/electronic_assembly/A = path + var/name = initial(A.name) + all_assemblies[name] = path + cached_assemblies[A] = new path + + circuit_fabricator_recipe_list["Assemblies"] = list( /obj/item/device/electronic_assembly, /obj/item/device/electronic_assembly/medium, /obj/item/device/electronic_assembly/large, /obj/item/device/electronic_assembly/drone - //new /obj/item/weapon/implant/integrated_circuit, - //new /obj/item/device/assembly/electronic_assembly + ///obj/item/weapon/implant/integrated_circuit ) circuit_fabricator_recipe_list["Tools"] = list( diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 5523e582dd4a..fa4a31cfc362 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -109,10 +109,7 @@ use_power(250 * recharge_coeff) using_power = 1 update_icon(using_power) - if(istype(charging, /obj/item/gun/energy)) - var/obj/item/gun/energy/E = charging - E.recharge_newshot() - return + if(istype(charging, /obj/item/ammo_box/magazine/recharge)) var/obj/item/ammo_box/magazine/recharge/R = charging if(R.stored_ammo.len < R.max_ammo) diff --git a/code/game/objects/items/inducer.dm b/code/game/objects/items/inducer.dm index e23b2e4a8d04..8f380772e216 100644 --- a/code/game/objects/items/inducer.dm +++ b/code/game/objects/items/inducer.dm @@ -119,7 +119,7 @@ user.visible_message("[user] starts recharging [A] with [src].","You start recharging [A] with [src].") while(C.charge < C.maxcharge) if(E) - E.chambered = null // Prevents someone from firing continuously while recharging the gun. + E.semicd = TRUE // Prevents someone from firing continuously while recharging the gun. if(do_after(user, 10, target = user) && cell.charge) done_any = TRUE induce(C, coefficient) @@ -129,7 +129,7 @@ else break if(E) - E.recharge_newshot() //We're done charging, so we'll let someone fire it now. + E.reset_semicd() //We're done charging, so we'll let someone fire it now. if(done_any) // Only show a message if we succeeded at least once user.visible_message("[user] recharged [A]!","You recharged [A]!") recharging = FALSE diff --git a/code/modules/integrated_electronics/core/analyzer.dm b/code/modules/integrated_electronics/core/analyzer.dm index 6365d7a69581..02b8c88accab 100644 --- a/code/modules/integrated_electronics/core/analyzer.dm +++ b/code/modules/integrated_electronics/core/analyzer.dm @@ -1,5 +1,3 @@ - - /obj/item/device/integrated_electronics/analyzer name = "circuit analyzer" desc = "This tool can scan an assembly and generate code necessary to recreate it in a circuit printer." @@ -7,92 +5,14 @@ icon_state = "analyzer" flags_1 = CONDUCT_1 w_class = WEIGHT_CLASS_SMALL - var/list/circuit_list = list() - var/list/assembly_list = list(/obj/item/device/electronic_assembly, - /obj/item/device/electronic_assembly/medium, - /obj/item/device/electronic_assembly/large, - /obj/item/device/electronic_assembly/drone) /obj/item/device/integrated_electronics/analyzer/afterattack(var/atom/A, var/mob/living/user) - visible_message( "attempt to scan") - if(ispath(A.type,/obj/item/device/electronic_assembly)) - var/i = 0 - var/j = 0 - var/HTML ="start.assembly{{*}}" //1-st in chapters.1-st block is just to secure start of program from excess symbols.{{*}} is delimeter for chapters. - visible_message( "start of scan") - for(var/ix in 1 to assembly_list.len) - var/obj/item/I = assembly_list[ix] - if( A.type == I ) - HTML += initial(I.name) +"=-="+A.name //2-nd block.assembly type and name. Maybe in future there will also be color and accesories. - break - - HTML += "{{*}}components" //3-rd block.components. First element is useless.delimeter for elements is ^%^.In element first circuit's default name.Second is user given name.delimiter is =-= - - for(var/obj/item/integrated_circuit/IC in A.contents) - i =i + 1 - HTML += "^%^"+IC.name+"=-="+IC.displayed_name - if(i == 0) - return - HTML += "{{*}}values" //4-th block.values. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second is data type.third is value.delimiter is :+: - - i = 0 - var/val - var/list/inp=list() - var/list/out=list() - var/list/act=list() - var/list/ioa=list() - for(var/obj/item/integrated_circuit/IC in A.contents) - i += 1 - if(IC.inputs && IC.inputs.len) - for(j in 1 to IC.inputs.len) - var/datum/integrated_io/IN =IC.inputs[j] - inp[IN] = "[i]i[j]" - if(islist(IN.data)) - val = list2params(IN.data) - HTML += "^%^"+"[i]i[j]:+:list:+:[val]" - else if(isnum(IN.data)) - val= IN.data - HTML += "^%^"+"[i]i[j]:+:num:+:[val]" - else if(istext(IN.data)) - val = IN.data - HTML += "^%^"+"[i]i[j]:+:text:+:[val]" - if(IC.outputs && IC.outputs.len) - for(j in 1 to IC.outputs.len) //Also this block uses for setting all i/o id's - var/datum/integrated_io/OUT = IC.outputs[j] - out[OUT] = "[i]o[j]" - if(IC.activators && IC.activators.len) - for(j in 1 to IC.activators.len) - var/datum/integrated_io/ACT = IC.activators[j] - act[ACT] = "[i]a[j]" - ioa.Add(inp) - ioa.Add(out) - ioa.Add(act) - HTML += "{{*}}wires" - if(inp && inp.len) - for(i in 1 to inp.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-= - var/datum/integrated_io/P = inp[i] - for(j in 1 to P.linked.len) - var/datum/integrated_io/C = P.linked[j] - HTML += "^%^"+inp[P]+"=-="+ioa[C] - if(out && out.len) - for(i in 1 to out.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-= - var/datum/integrated_io/P = out[i] - for(j in 1 to P.linked.len) - var/datum/integrated_io/C = P.linked[j] - HTML += "^%^"+out[P]+"=-="+ioa[C] - if(act && act.len) - for(i in 1 to act.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-= - var/datum/integrated_io/P = act[i] - for(j in 1 to P.linked.len) - var/datum/integrated_io/C = P.linked[j] - HTML += "^%^"+act[P]+"=-="+ioa[C] - - HTML += "{{*}}end" //6 block.like 1. - visible_message( "[A] has been scanned,") - user << browse(jointext(HTML, null), "window=analyzer;size=[500]x[600];border=1;can_resize=1;can_close=1;can_minimize=1") + if(istype(A, /obj/item/device/electronic_assembly)) + var/saved = SScircuit.save_electronic_assembly(A) + if(saved) + to_chat(user, "You scan [A].") + user << browse(saved, "window=circuit_scan;size=500x600;border=1;can_resize=1;can_close=1;can_minimize=1") + else + to_chat(user, "[A] is not complete enough to be encoded!") else ..() - - - - diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index d992718bc745..6f552e1df447 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -8,6 +8,7 @@ icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "setup_small" flags_1 = NOBLUDGEON_1 + materials = list() // To be filled later var/max_components = IC_MAX_SIZE_BASE var/max_complexity = IC_COMPLEXITY_BASE var/opened = FALSE @@ -23,52 +24,12 @@ return user.canUseTopic(src,be_close = TRUE) -/obj/item/device/electronic_assembly/medium - name = "electronic mechanism" - icon_state = "setup_medium" - desc = "It's a case, for building medium-sized electronics with." - w_class = WEIGHT_CLASS_NORMAL - max_components = IC_MAX_SIZE_BASE * 2 - max_complexity = IC_COMPLEXITY_BASE * 2 - -/obj/item/device/electronic_assembly/large - name = "electronic machine" - icon_state = "setup_large" - desc = "It's a case, for building large electronics with." - w_class = WEIGHT_CLASS_BULKY - max_components = IC_MAX_SIZE_BASE * 4 - max_complexity = IC_COMPLEXITY_BASE * 4 - anchored = FALSE - -/obj/item/device/electronic_assembly/large/attackby(var/obj/item/O, var/mob/user) - if(default_unfasten_wrench(user, O, 20)) - return - ..() - -/obj/item/device/electronic_assembly/large/attack_tk(mob/user) - if(anchored) - return - ..() - -/obj/item/device/electronic_assembly/large/attack_hand(mob/user) - if(anchored) - attack_self(user) - return - ..() - -/obj/item/device/electronic_assembly/drone - name = "electronic drone" - icon_state = "setup_drone" - desc = "It's a case, for building mobile electronics with." - w_class = WEIGHT_CLASS_SMALL - max_components = IC_MAX_SIZE_BASE * 3 - max_complexity = IC_COMPLEXITY_BASE * 3 - - - /obj/item/device/electronic_assembly/Initialize() .=..() START_PROCESSING(SScircuit, src) + materials[MAT_METAL] = round((max_complexity + max_components) / 4) * SScircuit.cost_multiplier + + /obj/item/device/electronic_assembly/Destroy() STOP_PROCESSING(SScircuit, src) @@ -95,7 +56,7 @@ var/total_part_size = return_total_size() var/total_complexity = return_total_complexity() - var/HTML = list() + var/HTML = "" HTML += "[name]" HTML += "
\[Refresh\] | " @@ -105,25 +66,37 @@ if(battery) HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. \[Remove\]" else - HTML += "No powercell detected!" + HTML += "No power cell detected!" HTML += "

" - HTML += "Components:
" - HTML += "Built in:
" -//Put removable circuits in separate categories from non-removable - for(var/obj/item/integrated_circuit/circuit in contents) + + HTML += "Components:" + + var/list/components = return_all_components() + var/builtin_components = "" + + for(var/c in components) + var/obj/item/integrated_circuit/circuit = c if(!circuit.removable) - HTML += "[circuit.displayed_name] | " - HTML += "\[Rename\] | " - HTML += "\[Scan with Debugger\] | " - HTML += "\[Move to Bottom\]" - HTML += "
" + builtin_components += "[circuit.displayed_name] | " + builtin_components += "\[Rename\] | " + builtin_components += "\[Scan with Debugger\] | " + builtin_components += "\[Move to Bottom\]" + builtin_components += "
" - HTML += "
" - HTML += "Removable:
" + // Put removable circuits (if any) in separate categories from non-removable + if(builtin_components) + HTML += "
" + HTML += "Built in:
" + HTML += builtin_components + HTML += "
" + HTML += "Removable:" - for(var/obj/item/integrated_circuit/circuit in contents) + HTML += "
" + + for(var/c in components) + var/obj/item/integrated_circuit/circuit = c if(circuit.removable) HTML += "[circuit.displayed_name] | " HTML += "\[Rename\] | " @@ -133,9 +106,9 @@ HTML += "
" HTML += "" - user << browse(jointext(HTML,null), "window=assembly-\[REF(src)];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") + user << browse(HTML, "window=assembly-[REF(src)];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") -/obj/item/device/electronic_assembly/Topic(href, href_list[]) +/obj/item/device/electronic_assembly/Topic(href, href_list) if(..()) return 1 @@ -155,12 +128,11 @@ interact(usr) // To refresh the UI. /obj/item/device/electronic_assembly/proc/rename() - var/mob/M = usr if(!check_interactivity(M)) return - var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text,1) + var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text, TRUE) if(!check_interactivity(M)) return if(src && input) @@ -200,10 +172,15 @@ for(var/obj/item/integrated_circuit/part in contents) . += part.size +/obj/item/device/electronic_assembly/proc/return_all_components() + . = list() + for(var/obj/item/integrated_circuit/part in contents) + . += part + // Returns true if the circuit made it inside. /obj/item/device/electronic_assembly/proc/add_circuit(var/obj/item/integrated_circuit/IC, var/mob/user) if(!opened) - to_chat(user, "\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.") + to_chat(user, "\The [src]'s hatch is closed, you can't put anything inside.") return FALSE if(IC.w_class > w_class) @@ -245,7 +222,15 @@ visible_message(" [user] waves [src] around [target].") -/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user) + +/obj/item/device/electronic_assembly/screwdriver_act(mob/living/user, obj/item/S) + playsound(src, S.usesound, 50, 1) + opened = !opened + to_chat(user, "You [opened ? "open" : "close"] the maintenance hatch of [src].") + update_icon() + return TRUE + +/obj/item/device/electronic_assembly/attackby(obj/item/I, mob/living/user) if(istype(I, /obj/item/integrated_circuit)) if(!user.canUnEquip(I)) return FALSE @@ -254,24 +239,17 @@ playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) interact(user) return TRUE - else if(istype(I, /obj/item/crowbar)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - opened = !opened - to_chat(user, "You [opened ? "opened" : "closed"] [src].") - update_icon() - return TRUE - else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || istype(I, /obj/item/screwdriver)) + else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger)) if(opened) interact(user) else - to_chat(user, " [src] isn't opened, so you can't fiddle with the internal components. \ - Try using a crowbar.") + to_chat(user, "[src]'s hatch is closed, so you can't fiddle with the internal components.") else if(istype(I, /obj/item/stock_parts/cell)) if(!opened) - to_chat(user, " [src] isn't opened, so you can't put anything inside. Try using a crowbar.") + to_chat(user, "[src]'s hatch is closed, so you can't put anything inside.") return FALSE if(battery) - to_chat(user, " [src] already has \a [battery] inside. Remove it first if you want to replace it.") + to_chat(user, "[src] already has \a [battery] installed. Remove it first if you want to replace it.") return FALSE var/obj/item/stock_parts/cell = I user.transferItemToLoc(I, loc) @@ -340,3 +318,48 @@ /obj/item/device/electronic_assembly/Moved(oldLoc, dir) for(var/obj/item/integrated_circuit/IC in contents) IC.ext_moved(oldLoc, dir) + + + + + +/obj/item/device/electronic_assembly/medium + name = "electronic mechanism" + icon_state = "setup_medium" + desc = "It's a case, for building medium-sized electronics with." + w_class = WEIGHT_CLASS_NORMAL + max_components = IC_MAX_SIZE_BASE * 2 + max_complexity = IC_COMPLEXITY_BASE * 2 + +/obj/item/device/electronic_assembly/large + name = "electronic machine" + icon_state = "setup_large" + desc = "It's a case, for building large electronics with." + w_class = WEIGHT_CLASS_BULKY + max_components = IC_MAX_SIZE_BASE * 4 + max_complexity = IC_COMPLEXITY_BASE * 4 + anchored = FALSE + +/obj/item/device/electronic_assembly/large/attackby(obj/item/O, mob/user) + if(default_unfasten_wrench(user, O, 20)) + return + ..() + +/obj/item/device/electronic_assembly/large/attack_tk(mob/user) + if(anchored) + return + ..() + +/obj/item/device/electronic_assembly/large/attack_hand(mob/user) + if(anchored) + attack_self(user) + return + ..() + +/obj/item/device/electronic_assembly/drone + name = "electronic drone" + icon_state = "setup_drone" + desc = "It's a case, for building mobile electronics with." + w_class = WEIGHT_CLASS_SMALL + max_components = IC_MAX_SIZE_BASE * 3 + max_complexity = IC_COMPLEXITY_BASE * 3 diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index 45b48198c8ee..04137a4d052b 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -1,47 +1,44 @@ -/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type, var/list/io_default_list) +/obj/item/integrated_circuit/proc/setup_io(list/io_list, io_type, list/io_default_list, pin_type) var/list/io_list_copy = io_list.Copy() io_list.Cut() for(var/i in 1 to io_list_copy.len) var/io_entry = io_list_copy[i] var/default_data = null var/io_type_override = null + // Override the default data. - if(io_default_list && io_default_list.len) // List containing special pin types that need to be added. + if(length(io_default_list)) // List containing special pin types that need to be added. default_data = io_default_list["[i]"] // This is deliberately text because the index is a number in text form. + // Override the pin type. if(io_list_copy[io_entry]) io_type_override = io_list_copy[io_entry] if(io_type_override) - io_list.Add(new io_type_override(src, io_entry, default_data)) + io_list.Add(new io_type_override(src, io_entry, default_data, pin_type)) else - io_list.Add(new io_type(src, io_entry, default_data)) + io_list.Add(new io_type(src, io_entry, default_data, pin_type)) -/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, datum/new_data) +/obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data) if (istype(new_data) && !isweakref(new_data)) new_data = WEAKREF(new_data) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) return pin.write_data_to_pin(new_data) -/obj/item/integrated_circuit/proc/get_pin_data(var/pin_type, var/pin_number) +/obj/item/integrated_circuit/proc/get_pin_data(pin_type, pin_number) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) return pin.get_data() -/obj/item/integrated_circuit/proc/get_pin_data_as_type(var/pin_type, var/pin_number, var/as_type) +/obj/item/integrated_circuit/proc/get_pin_data_as_type(pin_type, pin_number, as_type) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) return pin.data_as_type(as_type) -/obj/item/integrated_circuit/proc/activate_pin(var/pin_number) +/obj/item/integrated_circuit/proc/activate_pin(pin_number) var/datum/integrated_io/activate/A = activators[pin_number] A.push_data() -/datum/integrated_io/proc/get_data() - if(isweakref(data)) - return data.resolve() - return data - -/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number) +/obj/item/integrated_circuit/proc/get_pin_ref(pin_type, pin_number) switch(pin_type) if(IC_INPUT) if(pin_number > inputs.len) @@ -72,60 +69,75 @@ return FALSE -/obj/item/integrated_circuit/proc/asc2b64(var/S) - var/static/list/b64 = list( - "A"=0,"B"=1,"C"=2,"D"=3, - "E"=4,"F"=5,"G"=6,"H"=7, - "I"=8,"J"=9,"K"=10,"L"=11, - "M"=12,"N"=13,"O"=14,"P"=15, - "Q"=16,"R"=17,"S"=18,"T"=19, - "U"=20,"V"=21,"W"=22,"X"=23, - "Y"=24,"Z"=25,"a"=26,"b"=27, - "c"=28,"d"=29,"e"=30,"f"=31, - "g"=32,"h"=33,"i"=34,"j"=35, - "k"=36,"l"=37,"m"=38,"n"=39, - "o"=40,"p"=41,"q"=42,"r"=43, - "s"=44,"t"=45,"u"=46,"v"=47, - "w"=48,"x"=49,"y"=50,"z"=51, - "0"=52,"1"=53,"2"=54,"3"=55, - "4"=56,"5"=57,"6"=58,"7"=59, - "8"=60,"9"=61,","=62,"."=63 - ) - var/ls = lentext(S) - var/c - var/i=1 - while(i <= ls) - var/sb1=text2ascii(S,i) - var/sb2=text2ascii(S,i+1) - var/sb3=text2ascii(S,i+2) - var/cb1 = (sb1 & 252)>>2 - var/cb2 = ((sb1 & 3)<<6 | (sb2 & 240)>>2)>>2 - var/cb3 = (sb2 & 15)<<2 | (sb3 & 192)>>6 - var/cb4 = (sb3 & 63) - c=c+b64[cb1+1]+b64[cb2+1]+b64[cb3+1]+b64[cb4+1] - i=i+3 - return c +/datum/integrated_io/proc/get_data() + if(isweakref(data)) + return data.resolve() + return data -/obj/item/integrated_circuit/proc/b642asc(var/S) - var/static/list/b64 = list("A"=1,"B"=2,"C"=3,"D"=4,"E"=5,"F"=6,"G"=7,"H"=8,"I"=9,"J"=10,"K"=11,"L"=12,"M"=13,"N"=14,"O"=15,"P"=16,"Q"=17,"R"=18, - "S"=19,"T"=20,"U"=21,"V"=22,"W"=23,"X"=24,"Y"=25,"Z"=26,"a"=27,"b"=28,"c"=29,"d"=30,"e"=31,"f"=32,"g"=33,"h"=34,"i"=35,"j"=36,"k"=37,"l"=38,"m"=39,"n"=40,"o"=41, - "p"=42,"q"=43,"r"=44,"s"=45,"t"=46,"u"=47,"v"=48,"w"=49,"x"=50,"y"=51,"z"=52,"0"=53,"1"=54,"2"=55,"3"=56,"4"=57,"5"=58,"6"=59,"7"=60,"8"=61,"9"=62,","=63,"."=64) - var/ls = lentext(S) - var/c - var/i=1 - while(i<=ls) - var/cb1=b64[copytext(S,i,i+1)]-1 - var/cb2=b64[copytext(S,i+1,i+2)]-1 - var/cb3=b64[copytext(S,i+2,i+3)]-1 - var/cb4=b64[copytext(S,i+3,i+4)]-1 - var/sb1=cb1<<2 | (cb2 & 48)>>4 - var/sb2=(cb2 & 15) <<4 | (cb3 & 60)>>2 - var/sb3=(cb3 & 3)<<6 | cb4 - c=c+ascii2text(sb1)+ascii2text(sb2)+ascii2text(sb3) - i=i+4 - return c -/proc/XorEncrypt(string,key) +// Returns a list of parameters necessary to locate a pin in the assembly: component number, pin type and pin number +// Components list can be supplied from the outside, for use in savefiles or for extra performance if you are calling this multiple times +/datum/integrated_io/proc/get_pin_parameters(list/components) + if(!holder) + return + + if(!components) + if(!holder.assembly) + return + components = holder.assembly.return_all_components() + + var/component_number = components.Find(holder) + + var/list/pin_holder_list + switch(pin_type) + if(IC_INPUT) + pin_holder_list = holder.inputs + if(IC_OUTPUT) + pin_holder_list = holder.outputs + if(IC_ACTIVATOR) + pin_holder_list = holder.activators + else + return + + var/pin_number = pin_holder_list.Find(src) + + return list(component_number, pin_type, pin_number) + + +// Locates a pin in the assembly when given component number, pin type and pin number +// Components list can be supplied from the outside, for use in savefiles or for extra performance if you are calling this multiple times +/obj/item/device/electronic_assembly/proc/get_pin_ref(component_number, pin_type, pin_number, list/components) + if(!components) + components = return_all_components() + + if(component_number > components.len) + return + + var/obj/item/integrated_circuit/component = components[component_number] + return component.get_pin_ref(pin_type, pin_number) + + +// Same as get_pin_ref, but takes in a list of 3 parameters (same format as get_pin_parameters) +// and performs extra sanity checks on parameters list and index numbers +/obj/item/device/electronic_assembly/proc/get_pin_ref_list(list/parameters, list/components) + if(!islist(parameters) || parameters.len != 3) + return + + // Those are supposed to be list indexes, check them for sanity + if(!isnum(parameters[1]) || parameters[1] % 1 || parameters[1] < 1) + return + + if(!isnum(parameters[3]) || parameters[3] % 1 || parameters[3] < 1) + return + + return get_pin_ref(parameters[1], parameters[2], parameters[3], components) + + + + +// Used to obfuscate object refs imported/exported as strings. +// Not very secure, but if someone still finds a way to abuse refs, they deserve it. +/proc/XorEncrypt(string, key) if(!string || !key ||!istext(string)||!istext(key)) return var/r diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 908a9bcfbe0a..042e93a2aa63 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "template" w_class = WEIGHT_CLASS_TINY + materials = list() // To be filled later var/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any. var/extended_desc var/list/inputs = list() @@ -13,7 +14,7 @@ var/list/activators = list() var/next_use = 0 // Uses world.time var/complexity = 1 // This acts as a limitation on building machines, more resource-intensive components cost more 'space'. - var/size = 1 // This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0 + var/size = 1 // This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0 var/cooldown_per_use = 9 // Circuits are limited in how many times they can be work()'d by this variable. var/power_draw_per_use = 0 // How much power is drawn when work()'d. var/power_draw_idle = 0 // How much power is drawn when doing nothing. @@ -67,10 +68,11 @@ a creative player the means to solve many problems. Circuits are held inside an /obj/item/integrated_circuit/Initialize() displayed_name = name - setup_io(inputs, /datum/integrated_io, inputs_default) - setup_io(outputs, /datum/integrated_io, outputs_default) - setup_io(activators, /datum/integrated_io/activate) - ..() + setup_io(inputs, /datum/integrated_io, inputs_default, IC_INPUT) + setup_io(outputs, /datum/integrated_io, outputs_default, IC_OUTPUT) + setup_io(activators, /datum/integrated_io/activate, null, IC_ACTIVATOR) + materials[MAT_METAL] = w_class * SScircuit.cost_multiplier + . = ..() /obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit. return @@ -117,7 +119,7 @@ a creative player the means to solve many problems. Circuits are held inside an var/table_edge_width = "30%" var/table_middle_width = "40%" - var/HTML = list() + var/HTML = "" HTML += "[src.displayed_name]" HTML += "
" HTML += "" @@ -127,7 +129,7 @@ a creative player the means to solve many problems. Circuits are held inside an HTML += "
\[Refresh\] | " HTML += "\[Rename\] | " HTML += "\[Scan with Device\] | " - if(src.removable) + if(removable) HTML += "\[Remove\]
" HTML += "" @@ -205,10 +207,10 @@ a creative player the means to solve many problems. Circuits are held inside an HTML += "
[extended_desc]" HTML += "" - if(src.assembly) - user << browse(jointext(HTML, null), "window=assembly-[REF(src.assembly)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + 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(jointext(HTML, null), "window=circuit-[REF(src)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + user << browse(HTML, "window=circuit-[REF(src)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") onclose(user, "assembly-[REF(src.assembly)]") @@ -300,7 +302,7 @@ a creative player the means to solve many problems. Circuits are held inside an if(D.accepting_refs) D.afterattack(src, usr, TRUE) else - to_chat(usr, "The Debugger's 'ref scanner' needs to be on.") + to_chat(usr, "The debugger's 'ref scanner' needs to be on.") else to_chat(usr, "You need a multitool/debugger set to 'ref' mode to do that.") @@ -378,16 +380,22 @@ a creative player the means to solve many problems. Circuits are held inside an return /obj/item/integrated_circuit/proc/disconnect_all() + var/datum/integrated_io/I - for(var/k in 1 to inputs.len) - var/datum/integrated_io/I = inputs[k] + for(var/i in inputs) + I = i + I.disconnect() + + for(var/i in outputs) + I = i + I.disconnect() + + for(var/i in activators) + I = i I.disconnect() - for(var/k in 1 to outputs.len) - var/datum/integrated_io/O = outputs[k] - O.disconnect() - for(var/k in 1 to activators.len) - var/datum/integrated_io/activate/A = activators[k] - A.disconnect() /obj/item/integrated_circuit/proc/ext_moved(oldLoc, dir) return + + + diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index a472ae894999..25ef3b80b8d1 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -24,12 +24,18 @@ D [1]/ || var/datum/weakref/data // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this. var/list/linked = list() var/io_type = DATA_CHANNEL + var/pin_type // IC_INPUT, IC_OUTPUT, IC_ACTIVATOR - used in saving assembly wiring + + +/datum/integrated_io/New(loc, _name, _data, _pin_type) + name = _name + if(_data) + data = _data + if(_pin_type) + pin_type = _pin_type + + holder = loc -/datum/integrated_io/New(newloc, name1, new_data) - name = name1 - if(new_data) - data = new_data - holder = newloc if(!istype(holder)) message_admins("ERROR: An integrated_io ([name]) spawned without a valid holder! This is a bug.") diff --git a/code/modules/integrated_electronics/core/prefab.dm b/code/modules/integrated_electronics/core/prefab.dm deleted file mode 100644 index 3dc3f2d6efaf..000000000000 --- a/code/modules/integrated_electronics/core/prefab.dm +++ /dev/null @@ -1,156 +0,0 @@ -/obj/item/device/integrated_electronics/prefab - var/debug = FALSE - name = "prefab" - desc = "new machine in package" - icon = 'icons/obj/electronic_assemblies.dmi' - icon_state = "box_template" - w_class = WEIGHT_CLASS_BULKY - var/program="blank" - var/list/as_names = list() - -/obj/item/device/integrated_electronics/prefab/attack_self(var/mob/user) - if(program && program != "blank") - assemble(program) - else - return ..() - -/obj/item/device/integrated_electronics/prefab/Initialize() - . = ..() - var/list/assembly_list = list( - /obj/item/device/electronic_assembly, - /obj/item/device/electronic_assembly/medium, - /obj/item/device/electronic_assembly/large, - /obj/item/device/electronic_assembly/drone, - ) - for(var/k in 1 to assembly_list.len) - var/obj/item/I = assembly_list[k] - as_names[initial(I.name)] = I - addtimer(CALLBACK(src, .proc/attack_self), 2) //IDK, why it's need dely,but otherwise it doesn't work. - -/obj/item/device/integrated_electronics/prefab/proc/assemble(var/program) - var/list/all_circuits = SScircuit.all_circuits //cached lists = free performance - var/list/chap = splittext( program ,"{{*}}") - var/list/elements = list() - var/list/elements_input = list() - var/list/element = list() - var/obj/item/AS - var/PA - var/i = 0 - - var/list/ioa = list() - var/datum/integrated_io/IO - var/datum/integrated_io/IO2 - if(debug) - visible_message( "started successful") - if(chap[2] != "") - if(debug) - visible_message( "assembly") - element = splittext( chap[2] ,"=-=") - PA = as_names[element[1]] - AS = new PA(null) - AS.loc = src - AS.name = element[2] - else - return //what's the point if there is no assembly? - if(chap[3] != "components") //if there is only one word,there is no components. - elements_input = splittext( chap[3] ,"^%^") - if(debug) - visible_message( "components[elements_input.len]") - i = 0 - elements = list() - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) //I don't know,why Cut or copy don't works. If somebody can fix it, it should be fixed. - if(debug) - visible_message( "components[elements.len]") - if(!length(elements_input)) - return - if(debug) - visible_message( "inserting components[elements.len]") - var/obj/item/integrated_circuit/comp - i=0 - for(var/E in elements) - i=i+1 - element = splittext( E ,"=-=") - if(debug) - visible_message( "[E]") - var/path_to_use = all_circuits[element[1]] - comp = new path_to_use(null) - comp.loc = AS - comp.displayed_name = element[2] - comp.assembly = AS - if(comp.inputs && comp.inputs.len) - for(var/j in 1 to comp.inputs.len) - var/datum/integrated_io/IN = comp.inputs[j] - ioa["[i]i[j]"] = IN - if(debug) - visible_message( "[i]i[j]") - if(comp.outputs && comp.outputs.len) - for(var/j in 1 to comp.outputs.len) //Also this block uses for setting all i/o id's - var/datum/integrated_io/OUT = comp.outputs[j] - ioa["[i]o[j]"] = OUT - if(debug) - visible_message( "[i]o[j]") - if(comp.activators && comp.activators.len) - for(var/j in 1 to comp.activators.len) - var/datum/integrated_io/ACT = comp.activators[j] - ioa["[i]a[j]"] = ACT - if(debug) - visible_message( "[i]a[j]") - - else - return - if(!AS.contents.len) - return - if(chap[4] != "values") //if there is only one word,there is no values - elements_input = splittext( chap[4] ,"^%^") - if(debug) - visible_message( "values[elements_input.len]") - i=0 - elements = list() - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) - if(debug) - visible_message( "values[elements.len]") - if(elements.len>0) - if(debug) - visible_message( "setting values[elements.len]") - for(var/E in elements) - element = splittext( E ,":+:") - if(debug) - visible_message( "[E]") - IO = ioa[element[1]] - if(element[2]=="text") - IO.write_data_to_pin(element[3]) - else if(element[2]=="num") - IO.write_data_to_pin(text2num(element[3])) - else if(element[2]=="list") - IO.write_data_to_pin(params2list(element[3])) - if(chap[5] != "wires") //if there is only one word,there is no wires - elements_input = splittext( chap[5] ,"^%^") - i=0 - elements = list() - if(debug) - visible_message( "wires[elements_input.len]") - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) - if(debug) - visible_message( "wires[elements.len]") - if(elements.len>0) - if(debug) - visible_message( "setting wires[elements.len]") - for(var/E in elements) - element = splittext( E ,"=-=") - if(debug) - visible_message( "[E]") - IO = ioa[element[1]] - IO2 = ioa[element[2]] - IO.linked |= IO2 - - AS.forceMove(loc) - qdel(src) diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm index 5bffdc780471..e2d979603fd6 100644 --- a/code/modules/integrated_electronics/core/printer.dm +++ b/code/modules/integrated_electronics/core/printer.dm @@ -4,22 +4,13 @@ icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "circuit_printer" w_class = WEIGHT_CLASS_BULKY - var/metal = 0 - var/init_max_metal = 100 - var/max_metal = 100 - var/metal_per_sheet = 10 // One sheet equals this much metal. - var/debug = FALSE - var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits. + var/upgraded = TRUE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits. var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly. - var/static/list/recipe_list //category = list(paths in category) var/current_category = null - var/as_printing = FALSE - var/as_needs = 0 - var/program ="blank" - var/obj/item/device/integrated_electronics/prefab/PR = null + var/list/program // Currently loaded save, in form of list /obj/item/device/integrated_circuit_printer/proc/check_interactivity(mob/user) - return user.canUseTopic(src,be_close = TRUE) + return user.canUseTopic(src, be_close = TRUE) /obj/item/device/integrated_circuit_printer/upgraded upgraded = TRUE @@ -27,56 +18,24 @@ /obj/item/device/integrated_circuit_printer/Initialize() . = ..() - if(!recipe_list) - recipe_list = SScircuit.circuit_fabricator_recipe_list + AddComponent(/datum/component/material_container, list(MAT_METAL), MINERAL_MATERIAL_AMOUNT * 25, TRUE, list(/obj/item/stack, /obj/item/integrated_circuit)) /obj/item/device/integrated_circuit_printer/attackby(var/obj/item/O, var/mob/user) - if(istype(O,/obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/stack = O - var/num = min((max_metal - metal) / metal_per_sheet, stack.amount) - if(num < 1) - to_chat(user, "\The [src] is too full to add more metal.") - return - if(stack.use(num)) - to_chat(user, "You add [num] sheet\s to \the [src].") - metal += num * metal_per_sheet - if(as_printing) - if(as_needs <= metal) - PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc)) - PR.program = program - metal = metal - as_needs - to_chat(user, "Assembly has been printed.") - as_printing = FALSE - as_needs = 0 - max_metal = init_max_metal - else - to_chat(user, "Please insert [(as_needs-metal)/10] more metal!") - interact(user) - return TRUE - - if(istype(O,/obj/item/integrated_circuit)) - to_chat(user, "You insert the circuit into \the [src]. ") - user.temporarilyRemoveItemFromInventory(O) - metal = min(metal + O.w_class, max_metal) - qdel(O) - interact(user) - return TRUE - - if(istype(O,/obj/item/disk/integrated_circuit/upgrade/advanced)) + if(istype(O, /obj/item/disk/integrated_circuit/upgrade/advanced)) if(upgraded) to_chat(user, "\The [src] already has this upgrade. ") return TRUE - to_chat(user, "You install \the [O] into \the [src]. ") + to_chat(user, "You install \the [O] into \the [src]. ") upgraded = TRUE qdel(O) interact(user) return TRUE - if(istype(O,/obj/item/disk/integrated_circuit/upgrade/clone)) + if(istype(O, /obj/item/disk/integrated_circuit/upgrade/clone)) if(can_clone) to_chat(user, "\The [src] already has this upgrade. ") return TRUE - to_chat(user, "You install \the [O] into \the [src]. ") + to_chat(user, "You install \the [O] into \the [src]. ") can_clone = TRUE qdel(O) interact(user) @@ -88,37 +47,33 @@ interact(user) /obj/item/device/integrated_circuit_printer/interact(mob/user) - var/window_height = 600 - var/window_width = 500 - if(isnull(current_category)) - current_category = recipe_list[1] + current_category = SScircuit.circuit_fabricator_recipe_list[1] + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/HTML = "

Integrated Circuit Printer


" - HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.
" + HTML += "Metal: [materials.total_amount]/[materials.max_amount].

" + + if(CONFIG_GET(flag/ic_printing)) + HTML += "Assembly cloning: [can_clone ? "Available": "Unavailable"].
" + HTML += "Circuits available: [upgraded ? "Advanced":"Regular"]." - HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"]." - HTML += "Crossed out circuits mean that the printer is not sufficiently upgraded to create that circuit.
" + if(!upgraded) + HTML += "
Crossed out circuits mean that the printer is not sufficiently upgraded to create that circuit." + HTML += "
" - if(can_clone) + if(can_clone && CONFIG_GET(flag/ic_printing)) HTML += "Here you can load script for your assembly.
" - if(as_printing) - HTML += " {Load Program} " + HTML += " {Load Program} " + if(!program) + HTML += " {Print Assembly}" else - HTML += " {Load Program} " - if(program == "blank") - HTML += " {Check Program} " - else - HTML += " {Check Program} " - if((program == "blank")|as_printing) - HTML += " {Print assembly} " - else - HTML += " {Print assembly} " - if(as_printing) - HTML += "
printing in process. Please insert more metal. " + HTML += " {Print Assembly}" + HTML += "

" HTML += "Categories:" - for(var/category in recipe_list) + for(var/category in SScircuit.circuit_fabricator_recipe_list) if(category != current_category) HTML += " \[[category]\] " else // Bold the button if it's already selected. @@ -126,28 +81,26 @@ HTML += "
" HTML += "

[current_category]

" - var/list/current_list = recipe_list[current_category] - for(var/k in 1 to current_list.len) - var/obj/O = current_list[k] + var/list/current_list = SScircuit.circuit_fabricator_recipe_list[current_category] + for(var/path in current_list) + var/obj/O = path var/can_build = TRUE - if(istype(O, /obj/item/integrated_circuit)) - var/obj/item/integrated_circuit/IC = current_list[k] + if(ispath(path, /obj/item/integrated_circuit)) + var/obj/item/integrated_circuit/IC = path if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded) can_build = FALSE if(can_build) - HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
" + HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
" else - HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
" + HTML += "\[[initial(O.name)]\]: [initial(O.desc)]
" - user << browse(jointext(HTML, null), "window=integrated_printer;size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + user << browse(HTML, "window=integrated_printer;size=600x500;border=1;can_resize=1;can_close=1;can_minimize=1") /obj/item/device/integrated_circuit_printer/Topic(href, href_list) if(!check_interactivity(usr)) return if(..()) return TRUE - var/sc = 0 - add_fingerprint(usr) if(href_list["category"]) current_category = href_list["category"] @@ -165,10 +118,15 @@ var/obj/item/integrated_circuit/IC = build_type cost = initial(IC.w_class) - if(metal - cost < 0) - to_chat(usr, "You need [cost] metal to build that!.") + + cost *= SScircuit.cost_multiplier + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + + if(!materials.use_amount_type(cost, MAT_METAL)) + to_chat(usr, "You need [cost] metal to build that!") return TRUE - metal -= cost + new build_type(get_turf(loc)) if(href_list["print"]) @@ -177,39 +135,48 @@ return switch(href_list["print"]) if("load") - program = input("Put your code there:", "loading", null, null) - if("check") - sc = sanity_check(program,usr) - if(sc == 0) - to_chat(usr, "Invalid program.") - else if(sc == -1) - to_chat(usr, "Unknown circuits found. Upgrades required to process this design.") - else if(sc == null) - to_chat(usr, "Invalid program.") - else - to_chat(usr, "Program is correct.You'll need [sc/10] sheets of metal") + var/input = input("Put your code there:", "loading", null, null) as message | null + if(!check_interactivity(usr)) + return + if(!input) + program = null + return + + var/validation = SScircuit.validate_electronic_assembly(input) + + // Validation error codes are returned as text. + if(istext(validation)) + to_chat(usr, "Error: [validation]") + return + else if(islist(validation)) + program = validation + to_chat(usr, "This is a valid program for [program["assembly"]["type"]].") + if(program["requires_upgrades"]) + if(upgraded) + to_chat(usr, "It uses advanced component designs.") + else + to_chat(usr, "It uses unknown component designs. Printer upgrade is required to proceed.") + to_chat(usr, "Used space: [program["used_space"]]/[program["max_space"]].") + to_chat(usr, "Complexity: [program["complexity"]]/[program["max_complexity"]].") + to_chat(usr, "Metal cost: [program["metal_cost"]].") + if("print") - sc = sanity_check(program,usr) - if(sc == 0 || sc == null) - to_chat(usr, "Invalid program.") - else if(sc == -1) - to_chat(usr, "Unknown circuits found. Upgrades required to process this design.") + if(!program) + return + + if(program["requires_upgrades"] && !upgraded) + to_chat(usr, "This program uses unknown component designs. Printer upgrade is required to proceed.") else - as_printing = TRUE - if(sc <= metal) - PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc)) - PR.program = program - metal = metal - sc + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if(materials.use_amount_type(program["metal_cost"], MAT_METAL)) + SScircuit.load_electronic_assembly(get_turf(src), program) to_chat(usr, "Assembly has been printed.") - as_printing = FALSE - as_needs = 0 - max_metal=init_max_metal else - max_metal = sc + metal_per_sheet - as_needs = sc - to_chat(usr, "Please insert [(as_needs-metal)/10] more metal!") + to_chat(usr, "You need [program["metal_cost"]] metal to build that!") + interact(usr) + // FUKKEN UPGRADE DISKS /obj/item/disk/integrated_circuit/upgrade name = "integrated circuit printer upgrade disk" @@ -228,180 +195,3 @@ name = "integrated circuit printer upgrade disk - circuit cloner" desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies." icon_state = "upgrade_disk_clone" - -/obj/item/device/integrated_circuit_printer/proc/sanity_check(var/program,var/mob/user) - var/list/chap = splittext( program ,"{{*}}") - if(chap.len != 6) - return 0 //splitting incorrect - var/list/elements = list() - var/list/elements_input = list() - var/list/element = list() - var/obj/item/PA - var/obj/item/device/electronic_assembly/PF - var/datum/integrated_io/IO - var/datum/integrated_io/IO2 - var/i = 0 - var/obj/item/integrated_circuit/comp - var/list/ioa = list() - var/list/as_samp = list() - var/list/all_circuits = SScircuit.all_circuits // It's free. Performance. We're giving you cpu time. It's free. We're giving you time. It's performance, free. It's free cpu time for you jim! - var/list/assembly_list = list( - /obj/item/device/electronic_assembly, - /obj/item/device/electronic_assembly/medium, - /obj/item/device/electronic_assembly/large, - /obj/item/device/electronic_assembly/drone, - ) - var/compl = 0 - var/maxcomp = 0 - var/cap = 0 - var/maxcap = 0 - var/metalcost = 0 - for(var/k in 1 to assembly_list.len) - var/obj/item/I = assembly_list[k] - as_samp[initial(I.name)] = I - if(debug) - visible_message( "started successful") - if(chap[2] != "") - if(debug) - visible_message( "assembly") - element = splittext( chap[2] ,"=-=") - PA = as_samp[element[1]] - if(ispath(PA,/obj/item/device/electronic_assembly)) - PF = PA - maxcap = initial(PF.max_components) - maxcomp = initial(PF.max_complexity) - metalcost = metalcost + round( (initial(PF.max_complexity) + initial(PF.max_components) ) / 4) - if(debug) - visible_message( "maxcap[maxcap]maxcomp[maxcomp]") - else - return 0 - to_chat(usr, "This is program for [element[2]]") - - else - return 0 //what's the point if there is no assembly? - if(chap[3] != "components") //if there is only one word,there is no components. - elements_input = splittext( chap[3] ,"^%^") - if(debug) - visible_message( "components[elements_input.len]") - i = 0 - elements = list() - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) - if(debug) - visible_message( "components[elements.len]") - if(elements_input.len<1) - return 0 - if(debug) - visible_message( "inserting components[elements.len]") - i=0 - for(var/E in elements) - i=i+1 - element = splittext( E ,"=-=") - if(debug) - visible_message( "[E]") - comp = all_circuits[element[1]] - if(!comp) - break - if(!upgraded) - var/obj/item/integrated_circuit/IC = comp - if(!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) - return -1 - compl = compl + initial(comp.complexity) - cap = cap + initial(comp.size) - metalcost = metalcost + initial(initial(comp.w_class)) - var/obj/item/integrated_circuit/circuit = new comp - var/list/ini = circuit.inputs - if(length(ini)) - for(var/j in 1 to ini.len) - var/datum/integrated_io/IN = ini[j] - ioa["[i]i[j]"] = IN - if(debug) - visible_message( "[i]i[j]") - ini = circuit.outputs - if(length(ini)) - for(var/j in 1 to ini.len) //Also this block uses for setting all i/o id's - var/datum/integrated_io/OUT = ini[j] - ioa["[i]o[j]"] = OUT - if(debug) - visible_message( "[i]o[j]") - ini = circuit.activators - if(length(ini)) - for(var/j in 1 to ini.len) - var/datum/integrated_io/ACT = ini.[j] - ioa["[i]a[j]"] = ACT - if(debug) - visible_message( "[i]a[j]") - if(icap[cap]compl[compl]maxcompl[maxcomp]maxcap[maxcap]") - if(cap == 0) - return 0 - if(cap>maxcap) - return 0 - if(compl>maxcomp) - return 0 - if(chap[4] != "values") //if there is only one word,there is no values - elements_input = splittext( chap[4] ,"^%^") - if(debug) - visible_message( "values[elements_input.len]") - i=0 - elements = list() - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) - if(debug) - visible_message( "values[elements.len]") - if(elements.len>0) - if(debug) - visible_message( "setting values[elements.len]") - for(var/E in elements) - element = splittext( E ,":+:") - if(debug) - visible_message( "[E]") - if(!ioa[element[1]]) - return 0 - if(element[2]=="text") - continue - else if(element[2]=="num") - continue - else if(element[2]=="list") - continue - else - return 0 - - if(chap[5] != "wires") //if there is only one word,there is no wires - elements_input = splittext( chap[5] ,"^%^") - i=0 - elements = list() - if(debug) - visible_message( "wires[elements_input.len]") - for(var/elem in elements_input) - i=i+1 - if(i>1) - elements.Add(elem) - if(debug) - visible_message( "wires[elements.len]") - if(elements.len>0) - if(debug) - visible_message( "setting wires[elements.len]") - for(var/E in elements) - element = splittext( E ,"=-=") - if(debug) - visible_message( "[E]") - IO = ioa[element[1]] - IO2 = ioa[element[2]] - if(!((element[2]+"=-="+element[1]) in elements)) - return 0 - if(!IO) - return 0 - if(!IO2) - return 0 - if(initial(IO.io_type) != initial(IO2.io_type)) - return 0 - return metalcost \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/saved_circuits.dm b/code/modules/integrated_electronics/core/saved_circuits.dm new file mode 100644 index 000000000000..cbbe58f16d53 --- /dev/null +++ b/code/modules/integrated_electronics/core/saved_circuits.dm @@ -0,0 +1,341 @@ +// Helpers for saving/loading integrated circuits. + + +// Saves type, modified name and modified inputs (if any) to a list +// The list is converted to JSON down the line. +/obj/item/integrated_circuit/proc/save() + var/list/component_params = list() + + // Save initial name used for differentiating assemblies + component_params["type"] = name + + // Save the modified name. + if(name != displayed_name) + component_params["name"] = displayed_name + + // Saving input values + if(length(inputs)) + var/list/saved_inputs = list() + + for(var/index in 1 to inputs.len) + var/datum/integrated_io/input = inputs[index] + + // Don't waste space saving the default values + if(input.data == inputs_default["[index]"]) + continue + + var/list/input_value = list(index, FALSE, input.data) + // Index, Type, Value + // FALSE is default type used for num/text/list/null + // TODO: support for special input types, such as internal refs and maybe typepaths + + if(islist(input.data) || isnum(input.data) || istext(input.data) || isnull(input.data)) + saved_inputs.Add(list(input_value)) + + if(saved_inputs.len) + component_params["inputs"] = saved_inputs + + return component_params + + +// Verifies a list of component parameters +// Returns null on success, error name on failure +/obj/item/integrated_circuit/proc/verify_save(list/component_params) + // Validate name + if(component_params["name"] && !reject_bad_name(component_params["name"], TRUE)) + return "Bad component name at [name]." + + // Validate input values + if(component_params["inputs"]) + var/list/loaded_inputs = component_params["inputs"] + if(!islist(loaded_inputs)) + return "Malformed input values list at [name]." + + var/inputs_amt = length(inputs) + + // Too many inputs? Inputs for input-less component? This is not good. + if(!inputs_amt || inputs_amt < length(loaded_inputs)) + return "Input values list out of bounds at [name]." + + for(var/list/input in loaded_inputs) + if(input.len != 3) + return "Malformed input data at [name]." + + var/input_id = input[1] + var/input_type = input[2] + //var/input_value = input[3] + + // No special type support yet. + if(input_type) + return "Unidentified input type at [name]!" + // TODO: support for special input types, such as typepaths and internal refs + + // Input ID is a list index, make sure it's sane. + if(!isnum(input_id) || input_id % 1 || input_id > inputs_amt || input_id < 1) + return "Invalid input index at [name]." + + +// Loads component parameters from a list +// Doesn't verify any of the parameters it loads, this is the job of verify_save() +/obj/item/integrated_circuit/proc/load(list/component_params) + // Load name + if(component_params["name"]) + displayed_name = component_params["name"] + + // Load input values + if(component_params["inputs"]) + var/list/loaded_inputs = component_params["inputs"] + + for(var/list/input in loaded_inputs) + var/index = input[1] + //var/input_type = input[2] + var/input_value = input[3] + + var/datum/integrated_io/IO = inputs[index] + IO.write_data_to_pin(input_value) + // write_data_to_pin includes all the value sanity checks you'll ever need + // TODO: support for special input types, such as internal refs and maybe typepaths + + + + + +// Saves type and modified name (if any) to a list +// The list is converted to JSON down the line. +/obj/item/device/electronic_assembly/proc/save() + var/list/assembly_params = list() + + // Save initial name used for differentiating assemblies + assembly_params["type"] = initial(name) + + // Save modified name + if(initial(name) != name) + assembly_params["name"] = name + + // Save panel status + if(opened) + assembly_params["opened"] = TRUE + + return assembly_params + + +// Verifies a list of assembly parameters +// Returns null on success, error name on failure +/obj/item/device/electronic_assembly/proc/verify_save(list/assembly_params) + // Validate name + if(assembly_params["name"] && !reject_bad_name(assembly_params["name"], TRUE)) + return "Bad assembly name." + + +// Loads assembly parameters from a list +// Doesn't verify any of the parameters it loads, this is the job of verify_save() +/obj/item/device/electronic_assembly/proc/load(list/assembly_params) + // Load modified name, if any. + if(assembly_params["name"]) + name = assembly_params["name"] + + // Load panel status + if(assembly_params["opened"]) + opened = TRUE + update_icon() + + + +// Attempts to save an assembly into a save file format. +// Returns null if assembly is not complete enough to be saved. +/datum/controller/subsystem/processing/circuit/proc/save_electronic_assembly(obj/item/device/electronic_assembly/assembly) + var/list/assembly_components = assembly.return_all_components() + + // No components? Don't even try to save it. + if(!length(assembly_components)) + return + + + var/list/blocks = list() + + // Block 1. Assembly. + blocks["assembly"] = assembly.save() + // (implant assemblies are not yet supported) + + + // Block 2. Components. + var/list/components = list() + for(var/c in assembly_components) + var/obj/item/integrated_circuit/component = c + components.Add(list(component.save())) + blocks["components"] = components + + + // Block 3. Wires. + var/list/wires = list() + var/list/saved_wires = list() + + for(var/c in assembly_components) + var/obj/item/integrated_circuit/component = c + var/list/all_pins = component.inputs + component.outputs + component.activators + + for(var/p in all_pins) + var/datum/integrated_io/pin = p + var/list/params = pin.get_pin_parameters(assembly_components) + var/text_params = params.Join() + + for(var/p2 in pin.linked) + var/datum/integrated_io/pin2 = p2 + var/list/params2 = pin2.get_pin_parameters(assembly_components) + var/text_params2 = params2.Join() + + // Check if we already saved an opposite version of this wire + // (do not save the same wire twice) + if((text_params2 + "=" + text_params) in saved_wires) + continue + + // If not, add a wire "hash" for future checks and save it + saved_wires.Add(text_params + "=" + text_params2) + wires.Add(list(list(params, params2))) + + if(wires.len) + blocks["wires"] = wires + + return json_encode(blocks) + + + +// Checks assembly save and calculates some of the parameters. +// Returns assembly (type: list) if the save is valid. +// Returns error code (type: text) if loading has failed. +// The following parameters area calculated during validation and added to the returned save list: +// "requires_upgrades", "metal_cost", "complexity", "max_complexity", "used_space", "max_space" +/datum/controller/subsystem/processing/circuit/proc/validate_electronic_assembly(program) + var/list/blocks = json_decode(program) + if(!blocks) + return + + var/error + + + // Block 1. Assembly. + var/list/assembly_params = blocks["assembly"] + + if(!islist(assembly_params) || !length(assembly_params)) + return "Invalid assembly data." // No assembly, damaged assembly or empty assembly + + // Validate type, get a temporary component + var/assembly_path = all_assemblies[assembly_params["type"]] + var/obj/item/device/electronic_assembly/assembly = cached_assemblies[assembly_path] + if(!assembly) + return "Invalid assembly type." + + // Check assembly save data for errors + error = assembly.verify_save(assembly_params) + if(error) + return error + + + // Read space & complexity limits and start keeping track of them + blocks["complexity"] = 0 + blocks["max_complexity"] = assembly.max_complexity + blocks["used_space"] = 0 + blocks["max_space"] = assembly.max_components + + // Start keeping track of total metal cost + blocks["metal_cost"] = assembly.materials[MAT_METAL] + + + // Block 2. Components. + if(!islist(blocks["components"]) || !length(blocks["components"])) + return "Invalid components list." // No components or damaged components list + + var/list/assembly_components = list() + for(var/C in blocks["components"]) + var/list/component_params = C + + if(!islist(component_params) || !length(component_params)) + return "Invalid component data." + + // Validate type, get a temporary component + var/component_path = all_components[component_params["type"]] + var/obj/item/integrated_circuit/component = cached_components[component_path] + if(!component) + return "Invalid component type." + + // Add temporary component to assembly_components list, to be used later when verifying the wires + assembly_components.Add(component) + + // Check component save data for errors + error = component.verify_save(component_params) + if(error) + return error + + // Update estimated assembly complexity, taken space and material cost + blocks["complexity"] += component.complexity + blocks["used_space"] += component.size + blocks["metal_cost"] += component.materials[MAT_METAL] + + // Check if the assembly requires printer upgrades + if(!(component.spawn_flags & IC_SPAWN_DEFAULT)) + blocks["requires_upgrades"] = TRUE + + + // Check complexity and space limitations + if(blocks["used_space"] > blocks["max_space"]) + return "Used space overflow." + if(blocks["complexity"] > blocks["max_complexity"]) + return "Complexity overflow." + + + // Block 3. Wires. + if(blocks["wires"]) + if(!islist(blocks["wires"])) + return "Invalid wiring list." // Damaged wires list + + for(var/w in blocks["wires"]) + var/list/wire = w + + if(!islist(wire) || wire.len != 2) + return "Invalid wire data." + + var/datum/integrated_io/IO = assembly.get_pin_ref_list(wire[1], assembly_components) + var/datum/integrated_io/IO2 = assembly.get_pin_ref_list(wire[2], assembly_components) + if(!IO || !IO2) + return "Invalid wire data." + + if(initial(IO.io_type) != initial(IO2.io_type)) + return "Wire type mismatch." + + return blocks + + +// Loads assembly (in form of list) into an object and returns it. +// No sanity checks are performed, save file is expected to be validated by validate_electronic_assembly +/datum/controller/subsystem/processing/circuit/proc/load_electronic_assembly(loc, list/blocks) + + // Block 1. Assembly. + var/list/assembly_params = blocks["assembly"] + var/obj/item/device/electronic_assembly/assembly_path = all_assemblies[assembly_params["type"]] + var/obj/item/device/electronic_assembly/assembly = new assembly_path(null) + assembly.load(assembly_params) + + + + // Block 2. Components. + var/list/assembly_components = list() + for(var/component_params in blocks["components"]) + var/obj/item/integrated_circuit/component_path = all_components[component_params["type"]] + var/obj/item/integrated_circuit/component = new component_path(assembly) + component.assembly = assembly + component.load(component_params) + assembly_components.Add(component) + + + // Block 3. Wires. + if(blocks["wires"]) + for(var/w in blocks["wires"]) + var/list/wire = w + var/datum/integrated_io/IO = assembly.get_pin_ref_list(wire[1], assembly_components) + var/datum/integrated_io/IO2 = assembly.get_pin_ref_list(wire[2], assembly_components) + IO.linked |= IO2 + IO2.linked |= IO + + assembly.forceMove(loc) + return assembly + diff --git a/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm b/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm index 46b1f4c759f9..da59434b6534 100644 --- a/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm @@ -5,7 +5,7 @@ /datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle. var/new_data = !data - to_chat(user, "You switch the data bit to [data? "true" : "false"].") + to_chat(user, "You switch the data bit to [new_data ? "TRUE" : "FALSE"].") write_data_to_pin(new_data) /datum/integrated_io/boolean/write_data_to_pin(var/new_data) @@ -21,6 +21,6 @@ return IC_FORMAT_BOOLEAN /datum/integrated_io/boolean/display_data(var/input) - if(data == TRUE) - return "(True)" - return "(False)" \ No newline at end of file + if(data) + return "(TRUE)" + return "(FALSE)" diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index 87ed709fcf19..4b67f08a0308 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -53,28 +53,51 @@ name = "tesla power relay" desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them." w_class = WEIGHT_CLASS_SMALL - extended_desc = "The siphon generates 50 W of power, so long as an APC is in the same room, with a cell that has energy. It will always drain \ + extended_desc = "The siphon generates 50 W of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \ from the 'equipment' power channel." icon_state = "power_relay" complexity = 7 spawn_flags = IC_SPAWN_RESEARCH var/power_amount = 50 -//fuel cell + +/obj/item/integrated_circuit/passive/power/relay/make_energy() + if(!assembly) + return + var/area/A = get_area(src) + if(A && A.powered(EQUIP) && assembly.give_power(power_amount)) + A.use_power(power_amount, EQUIP) + // give_power() handles CELLRATE on its own. + + +// For really fat machines. +/obj/item/integrated_circuit/passive/power/relay/large + name = "large tesla power relay" + desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them, now in industiral size!" + w_class = WEIGHT_CLASS_BULKY + extended_desc = "The siphon generates 2 kW of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \ + from the 'equipment' power channel." + icon_state = "power_relay" + complexity = 15 + spawn_flags = IC_SPAWN_RESEARCH + power_amount = 1000 + + +//fuel cell /obj/item/integrated_circuit/passive/power/chemical_cell name = "fuel cell" desc = "Produces electricity from chemicals." icon_state = "chemical_cell" - extended_desc = "This is effectively an internal beaker.It will consume and produce power from phoron, slime jelly, welding fuel, carbon,\ + extended_desc = "This is effectively an internal beaker. It will consume and produce power from plasma, slime jelly, welding fuel, carbon,\ ethanol, nutriments and blood , in order of decreasing efficiency. It will consume fuel only if the battery can take more energy." container_type = OPENCONTAINER_1 complexity = 4 inputs = list() - outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + outputs = list("volume used" = IC_PINTYPE_NUMBER, "self reference" = IC_PINTYPE_REF) activators = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH var/volume = 60 - var/list/fuel = list("plasma" = 10000, "welding_fuel" = 3000, "carbon" = 2000, "ethanol"= 2000, "nutriment" =1600, "blood" = 1000) + var/list/fuel = list("plasma" = 10000, "welding_fuel" = 3000, "carbon" = 2000, "ethanol" = 2000, "nutriment" = 1600, "blood" = 1000) /obj/item/integrated_circuit/passive/power/chemical_cell/New() ..() @@ -96,25 +119,3 @@ if((assembly.battery.maxcharge-assembly.battery.charge) / GLOB.CELLRATE > fuel[I]) if(reagents.remove_reagent(I, 1)) assembly.give_power(fuel[I]) - - -// For really fat machines. -/obj/item/integrated_circuit/passive/power/relay/large - name = "large tesla power relay" - desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them, now in industiral size!" - w_class = WEIGHT_CLASS_BULKY - extended_desc = "The siphon generates 1 kW of power, so long as an APC is in the same room, with a cell that has energy. It will always drain \ - from the 'equipment' power channel." - icon_state = "power_relay" - complexity = 15 - spawn_flags = IC_SPAWN_RESEARCH - power_amount = 1000 - -/obj/item/integrated_circuit/passive/power/relay/make_energy() - if(!assembly) - return - var/area/A = get_area(src) - if(A) - if(A.powered(EQUIP) && assembly.give_power(power_amount)) - A.use_power(power_amount, EQUIP) - // give_power() handles CELLRATE on its own. diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 56626afac2ed..0680f62e7724 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -675,7 +675,7 @@ return TRUE /obj/item/integrated_circuit/input/sensor/ranged - name = "Ranged sensor" + name = "ranged sensor" desc = "Scans and obtains a reference for any objects or persons in range. All you need to do is point the machine towards target." extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks." icon_state = "recorder" diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index b48b6feaff0c..62de766f5ac5 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -306,16 +306,14 @@ set_pin_data(IC_INPUT, 1, FALSE) /obj/item/integrated_circuit/output/led/external_examine(mob/user) - var/text_output = list() + var/text_output = "There is " - // Doing all this work just to have a color-blind friendly output. - text_output += "There is " - if(name == displayed_name ) + if(name == displayed_name) text_output += "\an [name]" else - text_output += "\an ["\improper[name]"] labeled '[displayed_name ]'" - text_output += " which is currently [(get_pin_data(IC_INPUT, 1)==1) ? "lit *" : "unlit."]" - to_chat(user,jointext(text_output,null)) + text_output += "\an ["\improper[name]"] labeled '[displayed_name]'" + text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit *" : "unlit"]." + to_chat(user, text_output) /obj/item/integrated_circuit/output/led/red name = "red LED" diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index a781716e353f..de9055acfae9 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -58,6 +58,10 @@ return FALSE if(transfer_amount && assembly.draw_power(amount_to_move)) // CELLRATE is already handled in draw_power() cell.give(transfer_amount * GLOB.CELLRATE) + if(istype(AM, /obj/item)) + var/obj/item/I = AM + I.update_icon() + return TRUE else set_pin_data(IC_OUTPUT, 1, null) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 06fa4f6f8ab6..aa5b137a5b2c 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -102,6 +102,16 @@ chambered = null //either way, released the prepared shot recharge_newshot() //try to charge a new shot +/obj/item/gun/energy/process_fire() + if(!chambered && can_shoot()) + process_chamber() // If the gun was drained and then recharged, load a new shot. + return ..() + +/obj/item/gun/energy/process_burst() + if(!chambered && can_shoot()) + process_chamber() // Ditto. + return ..() + /obj/item/gun/energy/proc/select_fire(mob/living/user) select++ if (select > ammo_type.len) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 0ca71451be89..3b93a960ca62 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -125,7 +125,6 @@ /obj/item/gun/energy/kinetic_accelerator/proc/reload() cell.give(cell.maxcharge) - recharge_newshot(1) if(!suppressed) playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) else diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 127637d3292d..06bda36c664c 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -139,12 +139,10 @@ var/obj/item/stack/sheet/S = A S.use(1) cell.give(1000) - recharge_newshot(1) to_chat(user, "You insert [A] in [src], recharging it.") else if(istype(A, /obj/item/ore/plasma)) qdel(A) cell.give(500) - recharge_newshot(1) to_chat(user, "You insert [A] in [src], recharging it.") else ..() diff --git a/tgstation.dme b/tgstation.dme index 662798a171bd..5f8118e83f6f 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1481,8 +1481,8 @@ #include "code\modules\integrated_electronics\core\helpers.dm" #include "code\modules\integrated_electronics\core\integrated_circuit.dm" #include "code\modules\integrated_electronics\core\pins.dm" -#include "code\modules\integrated_electronics\core\prefab.dm" #include "code\modules\integrated_electronics\core\printer.dm" +#include "code\modules\integrated_electronics\core\saved_circuits.dm" #include "code\modules\integrated_electronics\core\wirer.dm" #include "code\modules\integrated_electronics\core\special_pins\boolean_pin.dm" #include "code\modules\integrated_electronics\core\special_pins\char_pin.dm"