From 36b0f5fa99c7751060b0a96eb144d8f37ca7352b Mon Sep 17 00:00:00 2001 From: Neerti Date: Mon, 31 Jul 2017 10:58:03 -0400 Subject: [PATCH] Even More Circuit Changes See PR for changes. --- code/_helpers/type2type.dm | 4 +- code/datums/supplypacks/science.dm | 14 + .../items/weapons/implants/implantcircuits.dm | 1 + .../integrated_electronics/_defines.dm | 36 +- .../integrated_electronics/core/assemblies.dm | 10 +- .../integrated_electronics/core/helpers.dm | 18 +- .../core/integrated_circuit.dm | 41 +- .../integrated_electronics/core/pins.dm | 94 +++- .../core/special_pins/boolean_pin.dm | 25 ++ .../core/special_pins/char_pin.dm | 27 ++ .../core/special_pins/color_pin.dm | 51 +++ .../core/special_pins/dir_pin.dm | 33 ++ .../core/special_pins/list_pin.dm | 150 +++++++ .../core/special_pins/number_pin.dm | 18 + .../core/special_pins/ref_pin.dm | 14 + .../core/special_pins/string_pin.dm | 29 ++ .../subtypes/arithmetic.dm | 53 ++- .../subtypes/built_in.dm | 4 +- .../subtypes/converters.dm | 115 +++-- .../subtypes/data_transfer.dm | 117 +---- .../subtypes/{input_output.dm => input.dm} | 406 +++--------------- .../integrated_electronics/subtypes/lists.dm | 89 ++++ .../integrated_electronics/subtypes/logic.dm | 17 +- .../subtypes/manipulation.dm | 25 +- .../integrated_electronics/subtypes/memory.dm | 87 +--- .../integrated_electronics/subtypes/output.dm | 316 ++++++++++++++ .../integrated_electronics/subtypes/power.dm | 11 +- .../subtypes/reagents.dm | 29 +- .../integrated_electronics/subtypes/smart.dm | 6 +- .../integrated_electronics/subtypes/time.dm | 17 +- .../integrated_electronics/subtypes/trig.dm | 49 +-- .../~defines/~defines.dm | 24 +- code/modules/research/designs.dm | 18 + code/modules/research/research.dm | 5 +- .../integrated_circuits/data_transfer.dm | 17 - icons/obj/electronic_assemblies.dmi | Bin 33944 -> 35959 bytes icons/obj/machines/research.dmi | Bin 13585 -> 13580 bytes polaris.dme | 14 +- 38 files changed, 1210 insertions(+), 774 deletions(-) create mode 100644 code/modules/integrated_electronics/core/special_pins/boolean_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/char_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/color_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/dir_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/list_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/number_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/ref_pin.dm create mode 100644 code/modules/integrated_electronics/core/special_pins/string_pin.dm rename code/modules/integrated_electronics/subtypes/{input_output.dm => input.dm} (51%) create mode 100644 code/modules/integrated_electronics/subtypes/lists.dm create mode 100644 code/modules/integrated_electronics/subtypes/output.dm delete mode 100644 code/unit_tests/integrated_circuits/data_transfer.dm diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm index 8dc9cb020b..975e65e3ec 100644 --- a/code/_helpers/type2type.dm +++ b/code/_helpers/type2type.dm @@ -80,7 +80,9 @@ if (NORTHEAST) return "northeast" if (SOUTHEAST) return "southeast" if (NORTHWEST) return "northwest" - if (SOUTHWEST) return "southwest" + if (SOUTHWEST) return "southwest" + if (UP) return "up" + if (DOWN) return "down" // Turns text into proper directions /proc/text2dir(direction) diff --git a/code/datums/supplypacks/science.dm b/code/datums/supplypacks/science.dm index 5aca674229..c2f3a24159 100644 --- a/code/datums/supplypacks/science.dm +++ b/code/datums/supplypacks/science.dm @@ -42,3 +42,17 @@ containertype = /obj/structure/closet/crate/hydroponics containername = "Exotic Seeds crate" access = access_hydroponics + +/datum/supply_packs/sci/integrated_circuit_printer + name = "Integrated circuit printer" + contains = list(/obj/item/device/integrated_circuit_printer = 2) + cost = 15 + containertype = /obj/structure/closet/crate + containername = "Integrated circuit crate" + +/datum/supply_packs/sci/integrated_circuit_printer_upgrade + name = "Integrated circuit printer upgrade - advanced designs" + contains = list(/obj/item/weapon/disk/integrated_circuit/upgrade/advanced) + cost = 30 + containertype = /obj/structure/closet/crate + containername = "Integrated circuit crate" diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm index db24be3c0a..856e7a5d8b 100644 --- a/code/game/objects/items/weapons/implants/implantcircuits.dm +++ b/code/game/objects/items/weapons/implants/implantcircuits.dm @@ -1,5 +1,6 @@ /obj/item/weapon/implant/integrated_circuit name = "electronic implant" + desc = "It's a case, for building very tiny electronics with." icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "setup_implant" var/obj/item/device/electronic_assembly/implant/IC = null diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index 47a5e40b22..104b867532 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -2,19 +2,44 @@ #define IC_OUTPUT "output" #define IC_ACTIVATOR "activator" +// Pin functionality. #define DATA_CHANNEL "data channel" #define PULSE_CHANNEL "pulse channel" -#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box. -#define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD. +// Methods of obtaining a circuit. +#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer. +#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it. +// Displayed along with the pin name to show what type of pin it is. +#define IC_FORMAT_ANY "\" #define IC_FORMAT_STRING "\" +#define IC_FORMAT_CHAR "\" +#define IC_FORMAT_COLOR "\" #define IC_FORMAT_NUMBER "\" +#define IC_FORMAT_DIR "\" +#define IC_FORMAT_BOOLEAN "\" #define IC_FORMAT_REF "\" #define IC_FORMAT_LIST "\" -#define IC_FORMAT_ANY "\" + #define IC_FORMAT_PULSE "\" +// Used inside input/output list to tell the constructor what pin to make. +#define IC_PINTYPE_ANY /datum/integrated_io +#define IC_PINTYPE_STRING /datum/integrated_io/string +#define IC_PINTYPE_CHAR /datum/integrated_io/char +#define IC_PINTYPE_COLOR /datum/integrated_io/color +#define IC_PINTYPE_NUMBER /datum/integrated_io/number +#define IC_PINTYPE_DIR /datum/integrated_io/dir +#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean +#define IC_PINTYPE_REF /datum/integrated_io/ref +#define IC_PINTYPE_LIST /datum/integrated_io/list + +#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate +#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out + +// Data limits. +#define IC_MAX_LIST_LENGTH 200 + var/list/all_integrated_circuits = list() /proc/initialize_integrated_circuits_list() @@ -30,8 +55,10 @@ var/list/all_integrated_circuits = list() var/obj/item/device/electronic_assembly/assembly = null // Reference to the assembly holding this circuit, if any. var/extended_desc = null var/list/inputs = list() + var/list/inputs_default = list() // Assoc list which will fill a pin with data upon creation. e.g. "2" = 0 will set input pin 2 to equal 0 instead of null. var/list/outputs = list() - var/list/activators = list() //associated_list, = 1 for inbound, = 0 for outbound + var/list/outputs_default = list() // Ditto, for output. + 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 = null //This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0 @@ -40,7 +67,6 @@ var/list/all_integrated_circuits = list() var/power_draw_idle = 0 // How much power is drawn when doing nothing. var/spawn_flags = null // Used for world initializing, see the #defines above. var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places. - var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off. var/removable = TRUE // Determines if a circuit is removable from the assembly. var/displayed_name = "" var/allow_multitool = 1 // Allows additional multitool functionality diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index a4d292488d..b66c6b8b2d 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -3,7 +3,7 @@ /obj/item/device/electronic_assembly name = "electronic assembly" - desc = "It's a case, for building electronics with." + desc = "It's a case, for building small electronics with." w_class = ITEMSIZE_SMALL icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "setup_small" @@ -17,6 +17,7 @@ /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 = ITEMSIZE_NORMAL max_components = IC_COMPONENTS_BASE * 2 max_complexity = IC_COMPLEXITY_BASE * 2 @@ -24,6 +25,7 @@ /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 = ITEMSIZE_LARGE max_components = IC_COMPONENTS_BASE * 4 max_complexity = IC_COMPLEXITY_BASE * 4 @@ -31,6 +33,7 @@ /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 = ITEMSIZE_NORMAL max_components = IC_COMPONENTS_BASE * 1.5 max_complexity = IC_COMPLEXITY_BASE * 1.5 @@ -38,9 +41,10 @@ /obj/item/device/electronic_assembly/implant name = "electronic implant" icon_state = "setup_implant" + desc = "It's a case, for building very tiny electronics with." w_class = ITEMSIZE_TINY - max_components = IC_COMPONENTS_BASE / 4 - max_complexity = IC_COMPLEXITY_BASE / 4 + max_components = IC_COMPONENTS_BASE / 2 + max_complexity = IC_COMPLEXITY_BASE / 2 var/obj/item/weapon/implant/integrated_circuit/implant = null /obj/item/device/electronic_assembly/New() diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index 49779a4993..edfa6b1a86 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -1,8 +1,22 @@ -/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type) +/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type, var/list/io_default_list) var/list/io_list_copy = io_list.Copy() io_list.Cut() + var/i = 0 for(var/io_entry in io_list_copy) - io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry])) + 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. + 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) + // world << "io_type_override is now [io_type_override] on [src]." + io_list.Add(new io_type_override(src, io_entry, default_data)) + else + io_list.Add(new io_type(src, io_entry, default_data)) /obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, var/new_data) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 7c2a8100ea..08a3152908 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -11,10 +11,10 @@ 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/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) if(I.linked.len) to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].") - for(var/datum/integrated_io/output/O in outputs) + for(var/datum/integrated_io/O in outputs) if(O.linked.len) to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].") for(var/datum/integrated_io/activate/A in activators) @@ -34,8 +34,8 @@ a creative player the means to solve many problems. Circuits are held inside an displayed_name = name if(!size) size = w_class if(size == -1) size = 0 - setup_io(inputs, /datum/integrated_io/input) - setup_io(outputs, /datum/integrated_io/output) + setup_io(inputs, /datum/integrated_io, inputs_default) + setup_io(outputs, /datum/integrated_io, outputs_default) setup_io(activators, /datum/integrated_io/activate) ..() @@ -85,8 +85,8 @@ a creative player the means to solve many problems. Circuits are held inside an /obj/item/integrated_circuit/interact(mob/user) if(!check_interactivity(user)) return - if(!assembly) - return +// if(!assembly) +// return var/window_height = 350 var/window_width = 600 @@ -128,7 +128,7 @@ a creative player the means to solve many problems. Circuits are held inside an if(1) io = get_pin_ref(IC_INPUT, i) if(io) - words += "[io.name] [io.display_data()]
" + words += "[io.display_pin_type()] [io.name] [io.display_data(io.data)]
" if(io.linked.len) for(var/datum/integrated_io/linked in io.linked) // words += "\[[linked.name]\] @@ -139,14 +139,14 @@ a creative player the means to solve many problems. Circuits are held inside an height = 1 if(2) if(i == 1) - words += "[src.displayed_name]
([src.name])
[src.desc]" + words += "[src.displayed_name]
[src.name != src.displayed_name ? "([src.name])":""]
[src.desc]" height = row_height else continue if(3) io = get_pin_ref(IC_OUTPUT, i) if(io) - words += "[io.name] [io.display_data()]
" + words += "[io.display_pin_type()] [io.name] [io.display_data(io.data)]
" if(io.linked.len) for(var/datum/integrated_io/linked in io.linked) // words += "\[[linked.name]\] @@ -162,7 +162,7 @@ a creative player the means to solve many problems. Circuits are held inside an var/datum/integrated_io/io = activator var/words = list() - words += "[io.name] [io.data?"\":"\"]
" + words += "[io.name] [io.data?"\":"\"]
" if(io.linked.len) for(var/datum/integrated_io/linked in io.linked) // words += "\[[linked.name]\] @@ -176,10 +176,8 @@ a creative player the means to solve many problems. Circuits are held inside an HTML += "" HTML += "" - if(autopulse != -1) - HTML += "
Meta Variables;" - HTML += "
\[Autopulse\] = [autopulse ? "ON" : "OFF"]" - HTML += "
" +// HTML += "
Meta Variables;" // If more meta vars get introduced, uncomment this. +// HTML += "
" HTML += "
Complexity: [complexity]" if(power_draw_idle) @@ -235,6 +233,8 @@ a creative player the means to solve many problems. Circuits are held inside an else var/datum/integrated_io/io = pin + io.ask_for_pin_data(usr) // The pins themselves will determine how to ask for data, and will validate the data. + /* if(io.io_type == DATA_CHANNEL) var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number", "null") @@ -260,6 +260,7 @@ a creative player the means to solve many problems. Circuits are held inside an else if(io.io_type == PULSE_CHANNEL) io.holder.check_then_do_work(ignore_power = TRUE) to_chat(usr, "You pulse \the [io.holder]'s [io] pin.") + */ if(href_list["pin_unwire"]) @@ -313,10 +314,6 @@ a creative player the means to solve many problems. Circuits are held inside an else to_chat(usr, "You need a multitool/debugger set to 'ref' mode to do that.") - if(href_list["autopulse"]) - if(autopulse != -1) - autopulse = !autopulse - if(href_list["return"]) if(A) update_to_assembly = 1 @@ -354,11 +351,11 @@ a creative player the means to solve many problems. Circuits are held inside an /obj/item/integrated_circuit/proc/push_data() - for(var/datum/integrated_io/output/O in outputs) + for(var/datum/integrated_io/O in outputs) O.push_data() /obj/item/integrated_circuit/proc/pull_data() - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.push_data() /obj/item/integrated_circuit/proc/draw_idle_power() @@ -391,9 +388,9 @@ a creative player the means to solve many problems. Circuits are held inside an return /obj/item/integrated_circuit/proc/disconnect_all() - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.disconnect() - for(var/datum/integrated_io/output/O in outputs) + for(var/datum/integrated_io/O in outputs) O.disconnect() for(var/datum/integrated_io/activate/A in activators) A.disconnect() diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index dc6d48e303..c22d65e421 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -25,10 +25,11 @@ D [1]/ || var/list/linked = list() var/io_type = DATA_CHANNEL -/datum/integrated_io/New(var/newloc, var/name, var/data) +/datum/integrated_io/New(var/newloc, var/name, var/new_data) ..() src.name = name - src.data = data + if(new_data) + src.data = new_data holder = newloc if(!istype(holder)) message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.") @@ -50,17 +51,43 @@ D [1]/ || var/output = w.resolve() return istype(output, as_type) ? output : null -/datum/integrated_io/proc/display_data() - if(isnull(data)) +/datum/integrated_io/proc/display_data(var/input) + if(isnull(input)) return "(null)" // Empty data means nothing to show. - if(istext(data)) - return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'. - if(isweakref(data)) - var/weakref/w = data + + if(istext(input)) + return "(\"[input]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'. + +/* +list[]( + "A", + "B", + "C" +) +*/ + + if(islist(input)) + var/list/my_list = input + var/result = "list\[[my_list.len]\](" + if(my_list.len) + result += "
" + var/pos = 0 + for(var/line in my_list) + result += "[display_data(line)]" + pos++ + if(pos != my_list.len) + result += ",
" + result += "
" + result += ")" + return result + + if(isweakref(input)) + var/weakref/w = input var/atom/A = w.resolve() //return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed. return A ? "(\ref[A] \[Ref\])" : "(null)" - return "([data])" // Nothing special needed for numbers or other stuff. + + return "([input])" // Nothing special needed for numbers or other stuff. /datum/integrated_io/activate/display_data() return "(\[pulse\])" @@ -117,23 +144,44 @@ D [1]/ || //Now that we're removed from them, we gotta remove them from us. src.linked.Remove(their_io) -/datum/integrated_io/input - name = "input pin" +/datum/integrated_io/proc/ask_for_data_type(mob/user, var/default, var/list/allowed_data_types = list("string","number","null")) + var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in allowed_data_types + if(!holder.check_interactivity(user)) + return -/datum/integrated_io/output - name = "output pin" + var/new_data = null + switch(type_to_use) + if("string") + new_data = input("Now type in a string.","[src] string writing", istext(default) ? default : null) as null|text + if(istext(new_data) && holder.check_interactivity(user) ) + to_chat(user, "You input [new_data] into the pin.") + return new_data + if("number") + new_data = input("Now type in a number.","[src] number writing", isnum(default) ? default : null) as null|num + if(isnum(new_data) && holder.check_interactivity(user) ) + to_chat(user, "You input [new_data] into the pin.") + return new_data + if("null") + if(holder.check_interactivity(user)) + to_chat(user, "You clear the pin's memory.") + return new_data + +// Basically a null check +/datum/integrated_io/proc/is_valid() + return !isnull(data) + +// This proc asks for the data to write, then writes it. +/datum/integrated_io/proc/ask_for_pin_data(mob/user) + var/new_data = ask_for_data_type(user) + write_data_to_pin(new_data) + +/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin. + holder.check_then_do_work(ignore_power = TRUE) + to_chat(user, "You pulse \the [holder]'s [src] pin.") /datum/integrated_io/activate name = "activation pin" io_type = PULSE_CHANNEL -/datum/integrated_io/list - name = "list pin" - -/datum/integrated_io/list/write_data_to_pin(var/new_data) - if(islist(new_data)) - data = new_data - holder.on_data_written() - -/datum/integrated_io/list/display_pin_type() - return IC_FORMAT_LIST \ No newline at end of file +/datum/integrated_io/activate/out // All this does is just make the UI say 'out' instead of 'in' + data = 1 diff --git a/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm b/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm new file mode 100644 index 0000000000..baf3d029da --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/boolean_pin.dm @@ -0,0 +1,25 @@ +// These pins only contain 0 or 1. Null is not allowed. +/datum/integrated_io/boolean + name = "boolean pin" + data = FALSE + +/datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle. + var/new_data = !data + write_data_to_pin(new_data) + +/datum/integrated_io/boolean/write_data_to_pin(var/new_data) + if(new_data == FALSE || new_data == TRUE) + data = new_data + holder.on_data_written() + +/datum/integrated_io/boolean/scramble() + write_data_to_pin(rand(FALSE,TRUE)) + push_data() + +/datum/integrated_io/boolean/display_pin_type() + 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 diff --git a/code/modules/integrated_electronics/core/special_pins/char_pin.dm b/code/modules/integrated_electronics/core/special_pins/char_pin.dm new file mode 100644 index 0000000000..bd36d18495 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/char_pin.dm @@ -0,0 +1,27 @@ +// These pins can only contain a 1 character string or null. +/datum/integrated_io/char + name = "char pin" + +/datum/integrated_io/char/ask_for_pin_data(mob/user) + var/new_data = input("Please type in one character.","[src] char writing") as null|text + if(holder.check_interactivity(user) ) + to_chat(user, "You input [new_data ? "new_data" : "NULL"] into the pin.") + write_data_to_pin(new_data) + +/datum/integrated_io/char/write_data_to_pin(var/new_data) + if(isnull(new_data) || istext(new_data)) + if(length(new_data) > 1) + return + data = new_data + holder.on_data_written() + +// This makes the text go from "A" to "%". +/datum/integrated_io/char/scramble() + if(!is_valid()) + return + var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase + data = pick(options) + push_data() + +/datum/integrated_io/char/display_pin_type() + return IC_FORMAT_CHAR \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/special_pins/color_pin.dm b/code/modules/integrated_electronics/core/special_pins/color_pin.dm new file mode 100644 index 0000000000..0fa82b4506 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/color_pin.dm @@ -0,0 +1,51 @@ +// These pins can only contain a color (in the form of #FFFFFF) or null. +/datum/integrated_io/color + name = "color pin" + +/datum/integrated_io/color/ask_for_pin_data(mob/user) + var/new_data = input("Please select a color.","[src] color writing") as null|color + if(holder.check_interactivity(user) ) + to_chat(user, "You input a new color into the pin.") + world << "new_data equals [new_data]." + write_data_to_pin(new_data) + +/datum/integrated_io/color/write_data_to_pin(var/new_data) + // Since this is storing the color as a string hex color code, we need to make sure it's actually one. + if(isnull(new_data) || istext(new_data)) + if(istext(new_data)) + new_data = uppertext(new_data) + if(length(new_data) != 7) // We can hex if we want to, we can leave your strings behind + world << "Wrong length." + return // Cause your strings don't hex and if they don't hex + var/friends = copytext(new_data, 2, 8) // Well they're are no strings of mine + world << "friends equal [friends]." + // I say, we can go where we want to, a place where they will never find + var/safety_dance = 1 + while(safety_dance >= 7) // And we can act like we come from out of this world.log + var/hex = copytext(friends, safety_dance, safety_dance+1) + world << "Checking [hex]." + if(!(hex in list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"))) + world << "Hex [hex] failed" + return // Leave the fake one far behind, + safety_dance++ + + data = new_data // And we can hex + holder.on_data_written() + world << "Done." + world << "Rip." + +// This randomizes the color. +/datum/integrated_io/color/scramble() + if(!is_valid()) + return + var/new_data = get_random_colour(simple = FALSE, lower = 0, upper = 255) + data = new_data + push_data() + +/datum/integrated_io/color/display_pin_type() + return IC_FORMAT_COLOR + +/datum/integrated_io/color/display_data(var/input) + if(!isnull(data)) + return "([data])" + return ..() \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/special_pins/dir_pin.dm b/code/modules/integrated_electronics/core/special_pins/dir_pin.dm new file mode 100644 index 0000000000..bbb00faa27 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/dir_pin.dm @@ -0,0 +1,33 @@ +// These pins can only contain directions (1,2,4,8...) or null. +/datum/integrated_io/dir + name = "dir pin" + +/datum/integrated_io/dir/ask_for_pin_data(mob/user) + var/new_data = input("Please type in a valid dir number. \ + Valid dirs are;\n\ + North/Fore = [NORTH],\n\ + South/Aft = [SOUTH],\n\ + East/Starboard = [EAST],\n\ + West/Port = [WEST],\n\ + Northeast = [NORTHEAST],\n\ + Northwest = [NORTHWEST],\n\ + Southeast = [SOUTHEAST],\n\ + Southwest = [SOUTHWEST],\n\ + Up = [UP],\n\ + Down = [DOWN]","[src] dir writing") as null|num + if(isnum(new_data) && holder.check_interactivity(user) ) + to_chat(user, "You input [new_data] into the pin.") + write_data_to_pin(new_data) + +/datum/integrated_io/dir/write_data_to_pin(var/new_data) + if(isnull(new_data) || new_data in alldirs + list(UP, DOWN)) + data = new_data + holder.on_data_written() + +/datum/integrated_io/dir/display_pin_type() + return IC_FORMAT_DIR + +/datum/integrated_io/dir/display_data(var/input) + if(!isnull(data)) + return "([dir2text(data)])" + return ..() \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/special_pins/list_pin.dm b/code/modules/integrated_electronics/core/special_pins/list_pin.dm new file mode 100644 index 0000000000..535a535514 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/list_pin.dm @@ -0,0 +1,150 @@ +// These pins contain a list. Null is not allowed. +/datum/integrated_io/list + name = "list pin" + data = list() + + +/datum/integrated_io/list/ask_for_pin_data(mob/user) + interact(user) + +/datum/integrated_io/list/proc/interact(mob/user) + var/list/my_list = data + var/t = "

[src]


" + t += "List length: [my_list.len]
" + t += "\[Refresh\] | " + t += "\[Add\] | " + t += "\[Swap\] | " + t += "\[Clear\]
" + t += "
" + var/i = 0 + for(var/line in my_list) + i++ + t += "#[i] | [display_data(line)] | " + t += "\[Edit\] | " + t += "\[Remove\]
" + user << browse(t, "window=list_pin_\ref[src];size=500x400") + +/datum/integrated_io/list/proc/add_to_list(mob/user, var/new_entry) + if(!new_entry && user) + new_entry = ask_for_data_type(user) + if(is_valid(new_entry)) + Add(new_entry) + +/datum/integrated_io/list/proc/Add(var/new_entry) + var/list/my_list = data + if(my_list.len > IC_MAX_LIST_LENGTH) + my_list.Cut(Start=1,End=2) + my_list.Add(new_entry) + +/datum/integrated_io/list/proc/remove_from_list_by_position(mob/user, var/position) + var/list/my_list = data + if(!my_list.len) + to_chat(user, "The list is empty, there's nothing to remove.") + return + if(!position) + return + var/target_entry = my_list.Find(position) + if(target_entry) + my_list.Remove(target_entry) + +/datum/integrated_io/list/proc/remove_from_list(mob/user, var/target_entry) + var/list/my_list = data + if(!my_list.len) + to_chat(user, "The list is empty, there's nothing to remove.") + return + if(!target_entry) + target_entry = input("Which piece of data do you want to remove?", "Remove") as null|anything in my_list + if(target_entry) + my_list.Remove(target_entry) + +/datum/integrated_io/list/proc/edit_in_list(mob/user, var/target_entry) + var/list/my_list = data + if(!my_list.len) + to_chat(user, "The list is empty, there's nothing to modify.") + return + if(!target_entry) + target_entry = input("Which piece of data do you want to edit?", "Edit") as null|anything in my_list + if(target_entry) + var/edited_entry = ask_for_data_type(user, target_entry) + if(edited_entry) + target_entry = edited_entry + +/datum/integrated_io/list/proc/edit_in_list_by_position(mob/user, var/position) + var/list/my_list = data + if(!my_list.len) + to_chat(user, "The list is empty, there's nothing to modify.") + return + if(!position) + return + var/target_entry = my_list.Find(position) + if(target_entry) + var/edited_entry = ask_for_data_type(user, target_entry) + if(edited_entry) + target_entry = edited_entry + +/datum/integrated_io/list/proc/swap_inside_list(mob/user, var/first_target, var/second_target) + var/list/my_list = data + if(my_list.len <= 1) + to_chat(user, "The list is empty, or too small to do any meaningful swapping.") + return + if(!first_target) + first_target = input("Which piece of data do you want to swap? (1)", "Swap") as null|anything in my_list + + if(first_target) + if(!second_target) + second_target = input("Which piece of data do you want to swap? (2)", "Swap") as null|anything in my_list - first_target + + if(second_target) + var/first_pos = my_list.Find(first_target) + var/second_pos = my_list.Find(second_target) + my_list.Swap(first_pos, second_pos) + +/datum/integrated_io/list/proc/clear_list(mob/user) + var/list/my_list = data + my_list.Cut() + +/datum/integrated_io/list/scramble() + var/list/my_list = data + my_list = shuffle(my_list) + push_data() + +/datum/integrated_io/list/write_data_to_pin(var/new_data) + if(islist(new_data)) + var/list/new_list = new_data + data = new_list.Copy() + holder.on_data_written() + +/datum/integrated_io/list/display_pin_type() + return IC_FORMAT_LIST + +/datum/integrated_io/list/Topic(href, href_list, state = interactive_state) + if(!holder.check_interactivity(usr)) + return + if(..()) + return 1 + + if(href_list["add"]) + add_to_list(usr) + + if(href_list["swap"]) + swap_inside_list(usr) + + if(href_list["clear"]) + clear_list(usr) + + if(href_list["remove"]) + world << "Removing [href_list["pos"]]" + if(href_list["pos"]) + remove_from_list_by_position(usr, text2num(href_list["pos"])) + else + remove_from_list(usr) + + if(href_list["edit"]) + if(href_list["pos"]) + edit_in_list_by_position(usr, text2num(href_list["pos"])) + else + edit_in_list(usr) + + holder.interact(usr) // Refresh the main UI, + interact(usr) // and the list UI. + diff --git a/code/modules/integrated_electronics/core/special_pins/number_pin.dm b/code/modules/integrated_electronics/core/special_pins/number_pin.dm new file mode 100644 index 0000000000..319ac2de06 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/number_pin.dm @@ -0,0 +1,18 @@ +// These pins can only contain numbers (int and floating point) or null. +/datum/integrated_io/number + name = "number pin" +// data = 0 + +/datum/integrated_io/number/ask_for_pin_data(mob/user) + var/new_data = input("Please type in a number.","[src] number writing") as null|num + if(isnum(new_data) && holder.check_interactivity(user) ) + to_chat(user, "You input [new_data] into the pin.") + write_data_to_pin(new_data) + +/datum/integrated_io/number/write_data_to_pin(var/new_data) + if(isnull(new_data) || isnum(new_data)) + data = new_data + holder.on_data_written() + +/datum/integrated_io/number/display_pin_type() + return IC_FORMAT_NUMBER \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/special_pins/ref_pin.dm b/code/modules/integrated_electronics/core/special_pins/ref_pin.dm new file mode 100644 index 0000000000..461965f254 --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/ref_pin.dm @@ -0,0 +1,14 @@ +// These pins only contain weakrefs or null. +/datum/integrated_io/ref + name = "ref pin" + +/datum/integrated_io/ref/ask_for_pin_data(mob/user) // This clears the pin. + write_data_to_pin(null) + +/datum/integrated_io/ref/write_data_to_pin(var/new_data) + if(isnull(new_data) || isweakref(new_data)) + data = new_data + holder.on_data_written() + +/datum/integrated_io/ref/display_pin_type() + return IC_FORMAT_REF \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/special_pins/string_pin.dm b/code/modules/integrated_electronics/core/special_pins/string_pin.dm new file mode 100644 index 0000000000..6128418c1f --- /dev/null +++ b/code/modules/integrated_electronics/core/special_pins/string_pin.dm @@ -0,0 +1,29 @@ +// These pins can only contain text and null. +/datum/integrated_io/string + name = "string pin" + +/datum/integrated_io/string/ask_for_pin_data(mob/user) + var/new_data = input("Please type in a string.","[src] string writing") as null|text + if(holder.check_interactivity(user) ) + to_chat(user, "You input [new_data ? "new_data" : "NULL"] into the pin.") + write_data_to_pin(new_data) + +/datum/integrated_io/string/write_data_to_pin(var/new_data) + if(isnull(new_data) || istext(new_data)) + data = new_data + holder.on_data_written() + +// This makes the text go "from this" to "#G&*!HD$%L" +/datum/integrated_io/string/scramble() + if(!is_valid()) + return + var/string_length = length(data) + var/list/options = list("!","@","#","$","%","^","&","*") + alphabet_uppercase + var/new_data = "" + while(string_length) + new_data += pick(options) + string_length-- + push_data() + +/datum/integrated_io/string/display_pin_type() + return IC_FORMAT_STRING diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm index 48ad90928a..192d317baf 100644 --- a/code/modules/integrated_electronics/subtypes/arithmetic.dm +++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm @@ -2,25 +2,20 @@ /obj/item/integrated_circuit/arithmetic complexity = 1 inputs = list( - "\ A", - "\ B", - "\ C", - "\ D", - "\ E", - "\ F", - "\ G", - "\ H" + "A" = IC_PINTYPE_NUMBER, + "B" = IC_PINTYPE_NUMBER, + "C" = IC_PINTYPE_NUMBER, + "D" = IC_PINTYPE_NUMBER, + "E" = IC_PINTYPE_NUMBER, + "F" = IC_PINTYPE_NUMBER, + "G" = IC_PINTYPE_NUMBER, + "H" = IC_PINTYPE_NUMBER ) - outputs = list("\ result") - activators = list("compute" = 1, "on computed" = 0) + outputs = list("result" = IC_PINTYPE_NUMBER) + activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT) category_text = "Arithmetic" - autopulse = 1 power_draw_per_use = 5 // Math is pretty cheap. -/obj/item/integrated_circuit/arithmetic/on_data_written() - if(autopulse == 1) - check_then_do_work() - // +Adding+ // /obj/item/integrated_circuit/arithmetic/addition @@ -34,7 +29,7 @@ /obj/item/integrated_circuit/arithmetic/addition/do_work() var/result = 0 - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.pull_data() if(isnum(I.data)) result = result + I.data @@ -60,7 +55,7 @@ return var/result = A.data - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) if(I == A) continue I.pull_data() @@ -88,7 +83,7 @@ if(!isnum(A.data)) return var/result = A.data - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) if(I == A) continue I.pull_data() @@ -116,7 +111,7 @@ return var/result = A.data - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) if(I == A) continue I.pull_data() @@ -133,7 +128,7 @@ name = "exponent circuit" desc = "Outputs A to the power of B." icon_state = "exponent" - inputs = list("A", "B") + inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/exponent/do_work() @@ -154,7 +149,7 @@ desc = "This will say if a number is positive, negative, or zero." extended_desc = "Will output 1, -1, or 0, depending on if A is a postive number, a negative number, or zero, respectively." icon_state = "sign" - inputs = list("A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/sign/do_work() @@ -179,7 +174,7 @@ desc = "Rounds A to the nearest B multiple of A." extended_desc = "If B is not given a number, it will output the floor of A instead." icon_state = "round" - inputs = list("A", "B") + inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/round/do_work() @@ -203,12 +198,12 @@ name = "absolute circuit" desc = "This outputs a non-negative version of the number you put in. This may also be thought of as its distance from zero." icon_state = "absolute" - inputs = list("A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/absolute/do_work() var/result = 0 - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.pull_data() if(isnum(I.data)) result = abs(I.data) @@ -229,7 +224,7 @@ /obj/item/integrated_circuit/arithmetic/average/do_work() var/result = 0 var/inputs_used = 0 - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.pull_data() if(isnum(I.data)) inputs_used++ @@ -262,7 +257,7 @@ extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \ for outputs of 1, 2, or 3. H being the higher number is not strictly required." icon_state = "random" - inputs = list("\ L","\ H") + inputs = list("L" = IC_PINTYPE_NUMBER,"H" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/random/do_work() @@ -283,12 +278,12 @@ name = "square root circuit" desc = "This outputs the square root of a number you put in." icon_state = "square_root" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/square_root/do_work() var/result = 0 - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.pull_data() if(isnum(I.data)) result = sqrt(I.data) @@ -303,7 +298,7 @@ name = "modulo circuit" desc = "Gets the remainder of A / B." icon_state = "modulo" - inputs = list("\ A", "\ B") + inputs = list("A" = IC_PINTYPE_NUMBER, "B" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/arithmetic/modulo/do_work() diff --git a/code/modules/integrated_electronics/subtypes/built_in.dm b/code/modules/integrated_electronics/subtypes/built_in.dm index e4a6d8e1b4..24eac86802 100644 --- a/code/modules/integrated_electronics/subtypes/built_in.dm +++ b/code/modules/integrated_electronics/subtypes/built_in.dm @@ -11,7 +11,7 @@ name = "assembly input" desc = "A built in chip for handling pulses from attached assembly items." complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. - activators = list("on pulsed" = 0) + activators = list("on pulsed" = IC_PINTYPE_PULSE_OUT) /obj/item/integrated_circuit/built_in/device_input/do_work() activate_pin(1) @@ -20,7 +20,7 @@ name = "assembly out" desc = "A built in chip for pulsing attached assembly items." complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. - activators = list("pulse attached" = 1) + activators = list("pulse attached" = IC_PINTYPE_PULSE_IN) /obj/item/integrated_circuit/built_in/device_output/do_work() if(istype(assembly, /obj/item/device/electronic_assembly/device)) diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm index 498b20a7a0..343890af56 100644 --- a/code/modules/integrated_electronics/subtypes/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -3,29 +3,24 @@ complexity = 2 inputs = list("input") outputs = list("output") - activators = list("convert" = 1, "on convert" = 0) + activators = list("convert" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT) category_text = "Converter" - autopulse = 1 power_draw_per_use = 10 -/obj/item/integrated_circuit/converter/on_data_written() - if(autopulse == 1) - check_then_do_work() - /obj/item/integrated_circuit/converter/num2text name = "number to string" desc = "This circuit can convert a number variable into a string." extended_desc = "Because of game limitations null/false variables will output a '0' string." icon_state = "num-string" - inputs = list("\ input") - outputs = list("\ output") + inputs = list("input" = IC_PINTYPE_NUMBER) + outputs = list("output" = IC_PINTYPE_STRING) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/num2text/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && isnum(incoming)) + if(!isnull(incoming)) result = num2text(incoming) else if(!incoming) result = "0" @@ -38,15 +33,15 @@ name = "string to number" desc = "This circuit can convert a string variable into a number." icon_state = "string-num" - inputs = list("\ input") - outputs = list("\ output") + inputs = list("input" = IC_PINTYPE_STRING) + outputs = list("output" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/text2num/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && istext(incoming)) + if(!isnull(incoming)) result = text2num(incoming) set_pin_data(IC_OUTPUT, 1, result) @@ -57,8 +52,8 @@ name = "reference to string" desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference." icon_state = "ref-string" - inputs = list("\ input") - outputs = list("\ output") + inputs = list("input" = IC_PINTYPE_REF) + outputs = list("output" = IC_PINTYPE_STRING) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/ref2text/do_work() @@ -76,15 +71,15 @@ name = "lowercase string converter" desc = "this will cause a string to come out in all lowercase." icon_state = "lowercase" - inputs = list("\ input") - outputs = list("\ output") + inputs = list("input" = IC_PINTYPE_STRING) + outputs = list("output" = IC_PINTYPE_STRING) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/lowercase/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && istext(incoming)) + if(!isnull(incoming)) result = lowertext(incoming) set_pin_data(IC_OUTPUT, 1, result) @@ -95,15 +90,15 @@ name = "uppercase string converter" desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE." icon_state = "uppercase" - inputs = list("\ input") - outputs = list("\ output") + inputs = list("input" = IC_PINTYPE_STRING) + outputs = list("output" = IC_PINTYPE_STRING) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/uppercase/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && istext(incoming)) + if(!isnull(incoming)) result = uppertext(incoming) set_pin_data(IC_OUTPUT, 1, result) @@ -112,34 +107,31 @@ /obj/item/integrated_circuit/converter/concatenator name = "concatenator" - desc = "This joins many strings or numbers together to get one big string." + desc = "This joins many strings together to get one big string." complexity = 4 inputs = list( - "\ A", - "\ B", - "\ C", - "\ D", - "\ E", - "\ F", - "\ G", - "\ H" + "A" = IC_PINTYPE_STRING, + "B" = IC_PINTYPE_STRING, + "C" = IC_PINTYPE_STRING, + "D" = IC_PINTYPE_STRING, + "E" = IC_PINTYPE_STRING, + "F" = IC_PINTYPE_STRING, + "G" = IC_PINTYPE_STRING, + "H" = IC_PINTYPE_STRING ) - outputs = list("\ result") - activators = list("concatenate" = 1, "on concatenated" = 0) + outputs = list("result" = IC_PINTYPE_STRING) + activators = list("concatenate" = IC_PINTYPE_PULSE_IN, "on concatenated" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/concatenator/do_work() var/result = null - for(var/datum/integrated_io/input/I in inputs) + for(var/datum/integrated_io/I in inputs) I.pull_data() - if(istext(I.data)) + if(!isnull(I.data)) result = result + I.data - else if(!isnull(I.data) && num2text(I.data)) - result = result + num2text(I.data) - var/datum/integrated_io/outgoing = outputs[1] - outgoing.data = result - outgoing.push_data() + set_pin_data(IC_OUTPUT, 1, result) + push_data() activate_pin(2) /obj/item/integrated_circuit/converter/separator @@ -150,14 +142,14 @@ will split into 'a p' and 'erson'." complexity = 4 inputs = list( - "\ string", - "\ index", + "string to split" = IC_PINTYPE_STRING, + "index" = IC_PINTYPE_NUMBER, ) outputs = list( - "\ before split", - "\ after split" + "before split" = IC_PINTYPE_STRING, + "after split" = IC_PINTYPE_STRING ) - activators = list("separate" = 1, "on separated" = 0) + activators = list("separate" = IC_PINTYPE_PULSE_IN, "on separated" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH @@ -170,12 +162,9 @@ var/before_text = copytext(text, 1, split) var/after_text = copytext(text, split, 0) - var/datum/integrated_io/outgoing1 = outputs[1] - var/datum/integrated_io/outgoing2 = outputs[2] - outgoing1.data = before_text - outgoing2.data = after_text - outgoing1.push_data() - outgoing2.push_data() + set_pin_data(IC_OUTPUT, 1, before_text) + set_pin_data(IC_OUTPUT, 2, after_text) + push_data() activate_pin(2) @@ -183,15 +172,15 @@ /obj/item/integrated_circuit/converter/radians2degrees name = "radians to degrees converter" desc = "Converts radians to degrees." - inputs = list("\ radian") - outputs = list("\ degrees") + inputs = list("radian" = IC_PINTYPE_NUMBER) + outputs = list("degrees" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/radians2degrees/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && isnum(incoming)) + if(!isnull(incoming)) result = ToDegrees(incoming) set_pin_data(IC_OUTPUT, 1, result) @@ -201,15 +190,15 @@ /obj/item/integrated_circuit/converter/degrees2radians name = "degrees to radians converter" desc = "Converts degrees to radians." - inputs = list("\ degrees") - outputs = list("\ radians") + inputs = list("degrees" = IC_PINTYPE_NUMBER) + outputs = list("radians" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/degrees2radians/do_work() var/result = null pull_data() var/incoming = get_pin_data(IC_INPUT, 1) - if(incoming && isnum(incoming)) + if(!isnull(incoming)) result = ToRadians(incoming) set_pin_data(IC_OUTPUT, 1, result) @@ -221,9 +210,17 @@ name = "abs to rel coordinate converter" desc = "Easily convert absolute coordinates to relative coordinates with this." complexity = 4 - inputs = list("\ X1", "\ Y1", "\ X2", "\ Y2") - outputs = list("\ X", "\ Y") - activators = list("compute rel coordinates" = 1, "on convert" = 0) + inputs = list( + "X1" = IC_PINTYPE_NUMBER, + "Y1" = IC_PINTYPE_NUMBER, + "X2" = IC_PINTYPE_NUMBER, + "Y2" = IC_PINTYPE_NUMBER + ) + outputs = list( + "X" = IC_PINTYPE_NUMBER, + "Y" = IC_PINTYPE_NUMBER + ) + activators = list("compute rel coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() @@ -233,7 +230,7 @@ var/x2 = get_pin_data(IC_INPUT, 3) var/y2 = get_pin_data(IC_INPUT, 4) - if(x1 && y1 && x2 && y2) + if(!isnull(x1) && !isnull(y1) && !isnull(x2) && !isnull(y2)) set_pin_data(IC_OUTPUT, 1, x1 - x2) set_pin_data(IC_OUTPUT, 2, y1 - y2) diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm index 92a807906f..7b5846eb8d 100644 --- a/code/modules/integrated_electronics/subtypes/data_transfer.dm +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -1,114 +1,25 @@ /obj/item/integrated_circuit/transfer category_text = "Data Transfer" - autopulse = 1 power_draw_per_use = 2 -/obj/item/integrated_circuit/transfer/on_data_written() - if(autopulse == 1) - check_then_do_work() - -/obj/item/integrated_circuit/transfer/splitter - name = "splitter" - desc = "Splits incoming data into all of the output pins." - icon_state = "splitter" - complexity = 3 - inputs = list("data to split") - outputs = list("A","B") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/transfer/splitter/medium - name = "four splitter" - icon_state = "splitter4" - complexity = 5 - outputs = list("A","B","C","D") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_per_use = 4 - -/obj/item/integrated_circuit/transfer/splitter/large - name = "eight splitter" - icon_state = "splitter8" - w_class = ITEMSIZE_SMALL - complexity = 9 - outputs = list("A","B","C","D","E","F","G","H") - spawn_flags = IC_SPAWN_RESEARCH - power_draw_per_use = 8 - -/obj/item/integrated_circuit/transfer/splitter/do_work() - var/datum/integrated_io/I = inputs[1] - for(var/datum/integrated_io/output/O in outputs) - O.data = I.data - -/obj/item/integrated_circuit/transfer/activator_splitter - name = "activator splitter" - desc = "Splits incoming activation pulses into all of the output pins." - icon_state = "splitter" - complexity = 3 - activators = list( - "pulse" = 1, - "pulse A" = 0, - "pulse B" = 0 - ) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_per_use = 2 - -/obj/item/integrated_circuit/transfer/activator_splitter/do_work() - for(var/datum/integrated_io/activate/A in outputs) - if(A == activators[1]) - continue - if(A.linked.len) - for(var/datum/integrated_io/activate/target in A.linked) - target.holder.check_then_do_work() - -/obj/item/integrated_circuit/transfer/activator_splitter/medium - name = "four activator splitter" - icon_state = "splitter4" - complexity = 5 - activators = list( - "pulse" = 1, - "pulse A" = 0, - "pulse B" = 0, - "pulse C" = 0, - "pulse D" = 0 - ) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_per_use = 4 - -/obj/item/integrated_circuit/transfer/activator_splitter/large - name = "eight activator splitter" - icon_state = "splitter4" - w_class = ITEMSIZE_SMALL - complexity = 9 - activators = list( - "incoming pulse" = 1, - "outgoing pulse A" = 0, - "outgoing pulse B" = 0, - "outgoing pulse C" = 0, - "outgoing pulse D" = 0, - "outgoing pulse E" = 0, - "outgoing pulse F" = 0, - "outgoing pulse G" = 0, - "outgoing pulse H" = 0 - ) - spawn_flags = IC_SPAWN_RESEARCH - power_draw_per_use = 8 - - /obj/item/integrated_circuit/transfer/multiplexer name = "two multiplexer" desc = "This is what those in the business tend to refer to as a 'mux' or data selector. It moves data from one of the selected inputs to the output." - extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. If the input selection is outside the valid range then no output is given." + extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. \ + If the input selection is outside the valid range then no output is given." complexity = 2 icon_state = "mux2" - inputs = list("input selection") - outputs = list("output") - activators = list("select" = 1, "on select" = 0) + inputs = list("input selection" = IC_PINTYPE_NUMBER) + outputs = list("output" = IC_PINTYPE_ANY) + activators = list("select" = IC_PINTYPE_PULSE_IN, "on select" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 var/number_of_inputs = 2 /obj/item/integrated_circuit/transfer/multiplexer/New() for(var/i = 1 to number_of_inputs) - inputs += "input [i]" + inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called. +// inputs += "input [i]" complexity = number_of_inputs ..() desc += " It has [number_of_inputs] input pins." @@ -118,7 +29,7 @@ var/input_index = get_pin_data(IC_INPUT, 1) var/output = null - if(isnum(input_index) && (input_index >= 1 && input_index < inputs.len)) + if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len)) output = get_pin_data(IC_INPUT, input_index + 1) set_pin_data(IC_OUTPUT, 1, output) @@ -145,19 +56,21 @@ /obj/item/integrated_circuit/transfer/demultiplexer name = "two demultiplexer" desc = "This is what those in the business tend to refer to as a 'demux'. It moves data from the input to one of the selected outputs." - extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. If the output selection is outside the valid range then no output is given." + extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. \ + If the output selection is outside the valid range then no output is given." complexity = 2 icon_state = "dmux2" - inputs = list("output selection","input") + inputs = list("output selection" = IC_PINTYPE_NUMBER, "input" = IC_PINTYPE_ANY) outputs = list() - activators = list("select" = 1) + activators = list("select" = IC_PINTYPE_PULSE_IN, "on select" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 var/number_of_outputs = 2 /obj/item/integrated_circuit/transfer/demultiplexer/New() for(var/i = 1 to number_of_outputs) - outputs += "output [i]" + // outputs += "output [i]" + outputs["output [i]"] = IC_PINTYPE_ANY complexity = number_of_outputs ..() @@ -171,6 +84,8 @@ for(var/i = 1 to outputs.len) set_pin_data(IC_OUTPUT, i, i == output_index ? output : null) + activate_pin(2) + /obj/item/integrated_circuit/transfer/demultiplexer/medium name = "four demultiplexer" icon_state = "dmux4" diff --git a/code/modules/integrated_electronics/subtypes/input_output.dm b/code/modules/integrated_electronics/subtypes/input.dm similarity index 51% rename from code/modules/integrated_electronics/subtypes/input_output.dm rename to code/modules/integrated_electronics/subtypes/input.dm index 9b666267a4..95ed94b813 100644 --- a/code/modules/integrated_electronics/subtypes/input_output.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -14,7 +14,7 @@ can_be_asked_input = 1 inputs = list() outputs = list() - activators = list("on pressed" = 0) + activators = list("on pressed" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use. @@ -28,8 +28,8 @@ complexity = 1 can_be_asked_input = 1 inputs = list() - outputs = list("\ on" = 0) - activators = list("on toggle" = 0) + outputs = list("on" = IC_PINTYPE_BOOLEAN) + activators = list("on toggle" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto. @@ -45,8 +45,8 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("\ number entered") - activators = list("on entered" = 0) + outputs = list("number entered" = IC_PINTYPE_NUMBER) + activators = list("on entered" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -64,8 +64,8 @@ complexity = 2 can_be_asked_input = 1 inputs = list() - outputs = list("\ string entered") - activators = list("on entered" = 0) + outputs = list("string entered" = IC_PINTYPE_STRING) + activators = list("on entered" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -82,8 +82,11 @@ icon_state = "medscan" complexity = 4 inputs = list("\ target") - outputs = list("\ total health %", "\ total missing health") - activators = list("scan" = 1, "on scanned" = 0) + outputs = list( + "total health %" = IC_PINTYPE_NUMBER, + "total missing health" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) power_draw_per_use = 40 @@ -93,7 +96,7 @@ if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. - var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 + var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100 var/missing_health = H.getMaxHealth() - H.health set_pin_data(IC_OUTPUT, 1, total_health) @@ -110,15 +113,15 @@ complexity = 12 inputs = list("\ target") outputs = list( - "\ total health %", - "\ total missing health", - "\ brute damage", - "\ burn damage", - "\ tox damage", - "\ oxy damage", - "\ clone damage" + "total health %" = IC_PINTYPE_NUMBER, + "total missing health" = IC_PINTYPE_NUMBER, + "brute damage" = IC_PINTYPE_NUMBER, + "burn damage" = IC_PINTYPE_NUMBER, + "tox damage" = IC_PINTYPE_NUMBER, + "oxy damage" = IC_PINTYPE_NUMBER, + "clone damage" = IC_PINTYPE_NUMBER ) - activators = list("scan" = 1, "on scanned" = 0) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4) power_draw_per_use = 80 @@ -128,7 +131,7 @@ if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. - var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100 + var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100 var/missing_health = H.getMaxHealth() - H.health set_pin_data(IC_OUTPUT, 1, total_health) @@ -148,7 +151,7 @@ that is holding the machine containing it." inputs = list() outputs = list("located ref") - activators = list("locate" = 1) + activators = list("locate" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 20 @@ -170,7 +173,7 @@ random." inputs = list("desired type ref") outputs = list("located ref") - activators = list("locate" = 1) + activators = list("locate" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 @@ -204,9 +207,12 @@ Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin." icon_state = "signal" complexity = 4 - inputs = list("\ frequency","\ code") + inputs = list("frequency" = IC_PINTYPE_NUMBER,"code" = IC_PINTYPE_NUMBER) outputs = list() - activators = list("send signal" = 1,"on signal sent" = 0, "on signal received" = 0) + activators = list( + "send signal" = IC_PINTYPE_PULSE_IN, + "on signal sent" = IC_PINTYPE_PULSE_OUT, + "on signal received" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2) power_draw_idle = 5 @@ -286,9 +292,17 @@ will pulse whatever's connected to it. Pulsing the first activation pin will send a message." icon_state = "signal" complexity = 4 - inputs = list("\ target EPv2 address", "\ data to send", "\ secondary text") - outputs = list("\ address received", "\ data received", "\ secondary text received") - activators = list("send data" = 1, "on data received" = 0) + inputs = list( + "target EPv2 address" = IC_PINTYPE_STRING, + "data to send" = IC_PINTYPE_STRING, + "secondary text" = IC_PINTYPE_STRING + ) + outputs = list( + "address received" = IC_PINTYPE_STRING, + "data received" = IC_PINTYPE_STRING, + "secondary text received" = IC_PINTYPE_STRING + ) + activators = list("send data" = IC_PINTYPE_PULSE_IN, "on data received" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2) power_draw_per_use = 50 @@ -331,8 +345,8 @@ icon_state = "gps" complexity = 4 inputs = list() - outputs = list("\ X", "\ Y") - activators = list("get coordinates" = 1, "on get coordinates" = 0) + outputs = list("X"= IC_PINTYPE_NUMBER, "Y" = IC_PINTYPE_NUMBER) + activators = list("get coordinates" = IC_PINTYPE_PULSE_IN, "on get coordinates" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 @@ -360,8 +374,11 @@ icon_state = "recorder" complexity = 8 inputs = list() - outputs = list("\ speaker", "\ message") - activators = list("on message received" = 1, "on translation" = 0) + outputs = list( + "speaker" = IC_PINTYPE_STRING, + "message" = IC_PINTYPE_STRING + ) + activators = list("on message received" = IC_PINTYPE_PULSE_IN, "on translation" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -394,12 +411,12 @@ /obj/item/integrated_circuit/input/sensor name = "sensor" desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face." - extended_desc = "If 'ignore storage' pin is set to 1, the sensor will disregard scanning various storage containers such as backpacks." + extended_desc = "If 'ignore storage' pin is set to true, the sensor will disregard scanning various storage containers such as backpacks." icon_state = "recorder" complexity = 12 - inputs = list("\ ignore storage" = 1) - outputs = list("\ scanned") - activators = list("on scanned" = 0) + inputs = list("ignore storage" = IC_PINTYPE_BOOLEAN) + outputs = list("scanned" = IC_PINTYPE_REF) + activators = list("on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 120 @@ -414,324 +431,3 @@ activate_pin(1) return TRUE -/obj/item/integrated_circuit/output - category_text = "Output" - -/obj/item/integrated_circuit/output/screen - name = "small screen" - desc = "This small screen can display a single piece of data, when the machine is examined closely." - icon_state = "screen" - inputs = list("\ displayed data") - outputs = list() - activators = list("load data" = 1) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_per_use = 10 - autopulse = 1 - var/stuff_to_display = null - - -/obj/item/integrated_circuit/output/screen/disconnect_all() - ..() - stuff_to_display = null - -/obj/item/integrated_circuit/output/screen/any_examine(mob/user) - to_chat(user, "There is a little screen labeled '[name]', which displays [stuff_to_display ? "'[stuff_to_display]'" : "nothing"].") - -/obj/item/integrated_circuit/output/screen/do_work() - var/datum/integrated_io/I = inputs[1] - if(isweakref(I.data)) - var/datum/d = I.data_as_type(/datum) - if(d) - stuff_to_display = "[d]" - else - stuff_to_display = I.data - -/obj/item/integrated_circuit/output/screen/medium - name = "screen" - desc = "This screen allows for people holding the device to see a piece of data." - icon_state = "screen_medium" - power_draw_per_use = 20 - -/obj/item/integrated_circuit/output/screen/medium/do_work() - ..() - var/list/nearby_things = range(0, get_turf(src)) - for(var/mob/M in nearby_things) - var/obj/O = assembly ? assembly : src - to_chat(M, "\icon[O] [stuff_to_display]") - -/obj/item/integrated_circuit/output/screen/large - name = "large screen" - desc = "This screen allows for people able to see the device to see a piece of data." - icon_state = "screen_large" - power_draw_per_use = 40 - -/obj/item/integrated_circuit/output/screen/large/do_work() - ..() - var/obj/O = assembly ? loc : assembly - O.visible_message("\icon[O] [stuff_to_display]") - -/obj/item/integrated_circuit/output/light - name = "light" - desc = "This light can turn on and off on command." - icon_state = "light" - complexity = 4 - inputs = list() - outputs = list() - activators = list("toggle light" = 1) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - var/light_toggled = 0 - var/light_brightness = 3 - var/light_rgb = "#FFFFFF" - power_draw_idle = 0 // Adjusted based on brightness. - -/obj/item/integrated_circuit/output/light/do_work() - light_toggled = !light_toggled - update_lighting() - -/obj/item/integrated_circuit/output/light/proc/update_lighting() - if(light_toggled) - set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb) - else - set_light(0) - power_draw_idle = light_toggled ? light_brightness * 2 : 0 - -/obj/item/integrated_circuit/output/light/advanced/update_lighting() - var/R = get_pin_data(IC_INPUT, 1) - var/G = get_pin_data(IC_INPUT, 2) - var/B = get_pin_data(IC_INPUT, 3) - var/brightness = get_pin_data(IC_INPUT, 4) - - if(isnum(R) && isnum(G) && isnum(B) && isnum(brightness)) - R = Clamp(R, 0, 255) - G = Clamp(G, 0, 255) - B = Clamp(B, 0, 255) - brightness = Clamp(brightness, 0, 6) - light_rgb = rgb(R, G, B) - light_brightness = brightness - - ..() - -/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left. - light_toggled = FALSE - update_lighting() - -/obj/item/integrated_circuit/output/light/advanced - name = "advanced light" - desc = "This light can turn on and off on command, in any color, and in various brightness levels." - icon_state = "light_adv" - complexity = 8 - inputs = list( - "\ R", - "\ G", - "\ B", - "\ Brightness" - ) - outputs = list() - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) - -/obj/item/integrated_circuit/output/light/advanced/on_data_written() - update_lighting() - -/obj/item/integrated_circuit/output/sound - name = "speaker circuit" - desc = "A miniature speaker is attached to this component." - icon_state = "speaker" - complexity = 8 - cooldown_per_use = 4 SECONDS - inputs = list( - "\ sound ID", - "\ volume", - "\ frequency" - ) - outputs = list() - activators = list("play sound" = 1) - power_draw_per_use = 20 - var/list/sounds = list() - -/obj/item/integrated_circuit/output/text_to_speech - name = "text-to-speech circuit" - desc = "A miniature speaker is attached to this component." - extended_desc = "This unit is more advanced than the plain speaker circuit, able to transpose any valid text to speech." - icon_state = "speaker" - complexity = 12 - cooldown_per_use = 4 SECONDS - inputs = list("text") - outputs = list() - activators = list("to speech" = 1) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_per_use = 60 - -/obj/item/integrated_circuit/output/text_to_speech/do_work() - var/datum/integrated_io/text = inputs[1] - if(istext(text.data)) - var/obj/O = assembly ? loc : assembly - audible_message("\icon[O] \The [O.name] states, \"[text.data]\"") - -/obj/item/integrated_circuit/output/sound/New() - ..() - extended_desc = list() - extended_desc += "The first input pin determines which sound is used. The choices are; " - extended_desc += jointext(sounds, ", ") - extended_desc += ". The second pin determines the volume of sound that is played" - extended_desc += ", and the third determines if the frequency of the sound will vary with each activation." - extended_desc = jointext(extended_desc, null) - -/obj/item/integrated_circuit/output/sound/do_work() - var/datum/integrated_io/ID = inputs[1] - var/datum/integrated_io/vol = inputs[2] - var/datum/integrated_io/frequency = inputs[3] - if(istext(ID.data) && isnum(vol.data) && isnum(frequency.data)) - var/selected_sound = sounds[ID.data] - if(!selected_sound) - return - vol.data = Clamp(vol.data, 0, 100) - frequency.data = round(Clamp(frequency.data, 0, 1)) - playsound(get_turf(src), selected_sound, vol.data, frequency.data, -1) - -/obj/item/integrated_circuit/output/sound/beeper - name = "beeper circuit" - desc = "A miniature speaker is attached to this component. This is often used in the construction of motherboards, which use \ - the speaker to tell the user if something goes very wrong when booting up. It can also do other similar synthetic sounds such \ - as buzzing, pinging, chiming, and more." - sounds = list( - "beep" = 'sound/machines/twobeep.ogg', - "chime" = 'sound/machines/chime.ogg', - "buzz sigh" = 'sound/machines/buzz-sigh.ogg', - "buzz twice" = 'sound/machines/buzz-two.ogg', - "ping" = 'sound/machines/ping.ogg', - "synth yes" = 'sound/machines/synth_yes.ogg', - "synth no" = 'sound/machines/synth_no.ogg', - "warning buzz" = 'sound/machines/warning-buzzer.ogg' - ) - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - -/obj/item/integrated_circuit/output/sound/beepsky - name = "securitron sound circuit" - desc = "A miniature speaker is attached to this component. Considered by some to be the essential component for a securitron." - sounds = list( - "creep" = 'sound/voice/bcreep.ogg', - "criminal" = 'sound/voice/bcriminal.ogg', - "freeze" = 'sound/voice/bfreeze.ogg', - "god" = 'sound/voice/bgod.ogg', - "i am the law" = 'sound/voice/biamthelaw.ogg', - "insult" = 'sound/voice/binsult.ogg', - "radio" = 'sound/voice/bradio.ogg', - "secure day" = 'sound/voice/bsecureday.ogg', - ) - spawn_flags = IC_SPAWN_RESEARCH - origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1) - -/obj/item/integrated_circuit/output/video_camera - name = "video camera circuit" - desc = "This small camera allows a remote viewer to see what it sees." - extended_desc = "The camera is linked to the Research camera network." - icon_state = "video_camera" - w_class = ITEMSIZE_SMALL - complexity = 10 - inputs = list("camera name" = "video camera circuit", "camera active" = 0) - outputs = list() - activators = list() - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - power_draw_idle = 5 // Raises to 80 when on. - var/obj/machinery/camera/network/research/camera - -/obj/item/integrated_circuit/output/video_camera/New() - ..() - camera = new(src) - on_data_written() - -/obj/item/integrated_circuit/output/video_camera/Destroy() - qdel_null(camera) - return ..() - -/obj/item/integrated_circuit/output/video_camera/proc/set_camera_status(var/status) - if(camera) - camera.set_status(status) - power_draw_idle = camera.status ? 80 : 5 - if(camera.status) // Ensure that there's actually power. - if(!draw_idle_power()) - power_fail() - -/obj/item/integrated_circuit/output/video_camera/on_data_written() - if(camera) - var/datum/integrated_io/cam_name = inputs[1] - var/datum/integrated_io/cam_active = inputs[2] - if(istext(cam_name.data)) - camera.c_tag = cam_name.data - if(isnum(cam_active.data)) - set_camera_status(cam_active.data) - -/obj/item/integrated_circuit/output/video_camera/power_fail() - if(camera) - set_camera_status(0) - var/datum/integrated_io/cam_active = inputs[2] - cam_active.data = FALSE - -/obj/item/integrated_circuit/output/led - name = "light-emitting diode" - desc = "This a LED that is lit whenever there is TRUE-equivalent data on its input." - extended_desc = "TRUE-equivalent values are: Non-empty strings, non-zero numbers, and valid refs." - complexity = 0.1 - icon_state = "led" - inputs = list("lit") - outputs = list() - activators = list() - power_draw_idle = 0 // Raises to 1 when lit. - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - var/led_color - -/obj/item/integrated_circuit/output/led/on_data_written() - power_draw_idle = get_pin_data(IC_INPUT, 1) ? 1 : 0 - -/obj/item/integrated_circuit/output/led/power_fail() - set_pin_data(IC_INPUT, 1, FALSE) - -/obj/item/integrated_circuit/output/led/any_examine(mob/user) - var/text_output = list() - var/initial_name = initial(name) - - // Doing all this work just to have a color-blind friendly output. - text_output += "There is " - if(name == initial_name) - text_output += "\an [name]" - else - text_output += "\an ["\improper[initial_name]"] labeled '[name]'" - text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit ¤" : "unlit."]" - to_chat(user,jointext(text_output,null)) - -/obj/item/integrated_circuit/output/led/red - name = "red LED" - led_color = COLOR_RED - -/obj/item/integrated_circuit/output/led/orange - name = "orange LED" - led_color = COLOR_ORANGE - -/obj/item/integrated_circuit/output/led/yellow - name = "yellow LED" - led_color = COLOR_YELLOW - -/obj/item/integrated_circuit/output/led/green - name = "green LED" - led_color = COLOR_GREEN - -/obj/item/integrated_circuit/output/led/blue - name = "blue LED" - led_color = COLOR_BLUE - -/obj/item/integrated_circuit/output/led/purple - name = "purple LED" - led_color = COLOR_PURPLE - -/obj/item/integrated_circuit/output/led/cyan - name = "cyan LED" - led_color = COLOR_CYAN - -/obj/item/integrated_circuit/output/led/white - name = "white LED" - led_color = COLOR_WHITE - -/obj/item/integrated_circuit/output/led/pink - name = "pink LED" - led_color = COLOR_PINK diff --git a/code/modules/integrated_electronics/subtypes/lists.dm b/code/modules/integrated_electronics/subtypes/lists.dm new file mode 100644 index 0000000000..84e0724bb9 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/lists.dm @@ -0,0 +1,89 @@ +//These circuits do things with lists, and use special list pins for stability. +/obj/item/integrated_circuit/list + complexity = 1 + inputs = list( + "input" = IC_PINTYPE_LIST + ) + outputs = list("result" = IC_PINTYPE_STRING) + activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT) + category_text = "Lists" + power_draw_per_use = 20 + +/obj/item/integrated_circuit/list/pick + name = "pick circuit" + desc = "This circuit will randomly 'pick' an element from a list that is inputted." + extended_desc = "Will output null if the list is empty. Input list is unmodified." + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/pick/do_work() + var/result = null + var/list/input_list = get_pin_data(IC_INPUT, 1) // List pins guarantee that there is a list inside, even if just an empty one. + if(input_list.len) + result = pick(input_list) + + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) + + +/obj/item/integrated_circuit/list/append + name = "append circuit" + desc = "This circuit will add an element to a list." + extended_desc = "The new element will always be at the bottom of the list." + inputs = list( + "list to append" = IC_PINTYPE_LIST, + "input" = IC_PINTYPE_ANY + ) + outputs = list( + "appended list" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/append/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/list/output_list = list() + var/new_entry = get_pin_data(IC_INPUT, 2) + output_list = input_list.Copy() + output_list.Add(new_entry) + + set_pin_data(IC_OUTPUT, 1, output_list) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/jointext + name = "join text circuit" + desc = "This circuit will add all elements of a list into one string, seperated by a character." + extended_desc = "Default settings will encode the entire list into a string." + inputs = list( + "list to join" = IC_PINTYPE_LIST, + "delimiter" = IC_PINTYPE_CHAR, + "start" = IC_PINTYPE_NUMBER, + "end" = IC_PINTYPE_NUMBER + ) + inputs_default = list( + "2" = ",", + "3" = 1, + "4" = 0 + ) + outputs = list( + "joined text" = IC_PINTYPE_STRING + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/jointext/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/delimiter = get_pin_data(IC_INPUT, 2) + var/start = get_pin_data(IC_INPUT, 3) + var/end = get_pin_data(IC_INPUT, 4) + + var/result = null + + if(input_list.len && delimiter && !isnull(start) && !isnull(end)) + result = jointext(input_list, delimiter, start, end) + + set_pin_data(IC_OUTPUT, 1, result) + push_data() + activate_pin(2) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm index 849c4e37a7..4bbffede35 100644 --- a/code/modules/integrated_electronics/subtypes/logic.dm +++ b/code/modules/integrated_electronics/subtypes/logic.dm @@ -4,21 +4,16 @@ extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE." complexity = 3 outputs = list("result") - activators = list("compare" = 1) + activators = list("compare" = IC_PINTYPE_PULSE_IN) category_text = "Logic" - autopulse = 1 power_draw_per_use = 1 -/obj/item/integrated_circuit/logic/on_data_written() - if(autopulse == 1) - check_then_do_work() - /obj/item/integrated_circuit/logic/do_work() push_data() /obj/item/integrated_circuit/logic/binary - inputs = list("\ A","\ B") - activators = list("compare" = 1, "on true result" = 0, "on false result" = 0) + inputs = list("A","B") + activators = list("compare" = IC_PINTYPE_PULSE_IN, "on true result" = IC_PINTYPE_PULSE_OUT, "on false result" = IC_PINTYPE_PULSE_OUT) /obj/item/integrated_circuit/logic/binary/do_work() pull_data() @@ -37,8 +32,8 @@ return FALSE /obj/item/integrated_circuit/logic/unary - inputs = list("\ A") - activators = list("compare" = 1, "on compare" = 0) + inputs = list("A") + activators = list("compare" = IC_PINTYPE_PULSE_IN, "on compare" = IC_PINTYPE_PULSE_OUT) /obj/item/integrated_circuit/logic/unary/do_work() pull_data() @@ -128,7 +123,7 @@ desc = "This gate inverts what's fed into it." icon_state = "not" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - activators = list("invert" = 1, "on inverted" = 0) + activators = list("invert" = IC_PINTYPE_PULSE_IN, "on inverted" = IC_PINTYPE_PULSE_OUT) /obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A) return !A.data diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index 9b779ee39b..7d22bc49a4 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -12,12 +12,12 @@ w_class = ITEMSIZE_NORMAL size = 3 inputs = list( - "\ target X rel", - "\ target Y rel" + "target X rel" = IC_PINTYPE_NUMBER, + "target Y rel" = IC_PINTYPE_NUMBER ) outputs = list() activators = list( - "fire" = 1 + "fire" = IC_PINTYPE_PULSE_IN ) var/obj/item/weapon/gun/installed_gun = null spawn_flags = IC_SPAWN_RESEARCH @@ -104,24 +104,15 @@ name = "locomotion circuit" desc = "This allows a machine to move in a given direction." icon_state = "locomotion" - extended_desc = "The circuit accepts a number as a direction to move towards.
\ - North/Fore = 1,
\ - South/Aft = 2,
\ - East/Starboard = 4,
\ - West/Port = 8,
\ - Northeast = 5,
\ - Northwest = 9,
\ - Southeast = 6,
\ - Southwest = 10
\ -
\ + extended_desc = "The circuit accepts a 'dir' number as a direction to move towards.
\ Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \ being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits." w_class = ITEMSIZE_NORMAL complexity = 20 // size = 5 - inputs = list("dir num") + inputs = list("direction" = IC_PINTYPE_DIR) outputs = list() - activators = list("step towards dir" = 1) + activators = list("step towards dir" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 100 @@ -146,9 +137,9 @@ icon_state = "grenade" complexity = 30 size = 2 - inputs = list("\ detonation time") + inputs = list("detonation time" = IC_PINTYPE_NUMBER) outputs = list() - activators = list("prime grenade" = 1) + activators = list("prime grenade" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4) var/obj/item/weapon/grenade/attached_grenade diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index 91fe45e04b..fa4fd9ded6 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -3,12 +3,20 @@ desc = "This tiny chip can store one piece of data." icon_state = "memory" complexity = 1 - inputs = list("input pin 1") - outputs = list("output pin 1") - activators = list("set" = 1, "on set") + inputs = list() + outputs = list() + activators = list("set" = IC_PINTYPE_PULSE_IN, "on set" = IC_PINTYPE_PULSE_OUT) category_text = "Memory" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 1 + var/number_of_pins = 1 + +/obj/item/integrated_circuit/memory/New() + for(var/i = 1 to number_of_pins) + inputs["input [i]"] = IC_PINTYPE_ANY // This is just a string since pins don't get built until ..() is called. + outputs["output [i]"] = IC_PINTYPE_ANY + complexity = number_of_pins + ..() /obj/item/integrated_circuit/memory/examine(mob/user) ..() @@ -36,83 +44,26 @@ name = "memory circuit" desc = "This circuit can store four pieces of data." icon_state = "memory4" - complexity = 4 - inputs = list("input pin 1","input pin 2","input pin 3","input pin 4") - outputs = list("output pin 1","output pin 2","output pin 3","output pin 4") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 + number_of_pins = 4 /obj/item/integrated_circuit/memory/large name = "large memory circuit" desc = "This big circuit can hold eight pieces of data." icon_state = "memory8" - complexity = 8 - inputs = list( - "input pin 1", - "input pin 2", - "input pin 3", - "input pin 4", - "input pin 5", - "input pin 6", - "input pin 7", - "input pin 8") - outputs = list( - "output pin 1", - "output pin 2", - "output pin 3", - "output pin 4", - "output pin 5", - "output pin 6", - "output pin 7", - "output pin 8") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) power_draw_per_use = 4 + number_of_pins = 8 /obj/item/integrated_circuit/memory/huge name = "large memory stick" desc = "This stick of memory can hold up up to sixteen pieces of data." icon_state = "memory16" w_class = ITEMSIZE_NORMAL - complexity = 16 - inputs = list( - "input pin 1", - "input pin 2", - "input pin 3", - "input pin 4", - "input pin 5", - "input pin 6", - "input pin 7", - "input pin 8", - "input pin 9", - "input pin 10", - "input pin 11", - "input pin 12", - "input pin 13", - "input pin 14", - "input pin 15", - "input pin 16" - ) - outputs = list( - "output pin 1", - "output pin 2", - "output pin 3", - "output pin 4", - "output pin 5", - "output pin 6", - "output pin 7", - "output pin 8", - "output pin 9", - "output pin 10", - "output pin 11", - "output pin 12", - "output pin 13", - "output pin 14", - "output pin 15", - "output pin 16") spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4) power_draw_per_use = 8 + number_of_pins = 16 /obj/item/integrated_circuit/memory/constant name = "constant chip" @@ -120,8 +71,8 @@ icon_state = "memory" complexity = 1 inputs = list() - outputs = list("output pin") - activators = list("push data" = 0) + outputs = list("output pin" = IC_PINTYPE_ANY) + activators = list("push data" = IC_PINTYPE_PULSE_IN) var/accepting_refs = 0 spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH @@ -142,13 +93,13 @@ new_data = input("Now type in a string.","[src] string writing") as null|text if(istext(new_data) && CanInteract(user, physical_state)) O.data = new_data - to_chat(user, "You set \the [src]'s memory to [O.display_data()].") + to_chat(user, "You set \the [src]'s memory to [O.display_data(O.data)].") if("number") accepting_refs = 0 new_data = input("Now type in a number.","[src] number writing") as null|num if(isnum(new_data) && CanInteract(user, physical_state)) O.data = new_data - to_chat(user, "You set \the [src]'s memory to [O.display_data()].") + to_chat(user, "You set \the [src]'s memory to [O.display_data(O.data)].") if("ref") accepting_refs = 1 to_chat(user, "You turn \the [src]'s ref scanner on. Slide it across \ @@ -162,6 +113,6 @@ var/datum/integrated_io/O = outputs[1] O.data = weakref(target) visible_message("[user] slides \a [src]'s over \the [target].") - to_chat(user, "You set \the [src]'s memory to a reference to [O.display_data()]. The ref scanner is \ + to_chat(user, "You set \the [src]'s memory to a reference to [O.display_data(O.data)]. The ref scanner is \ now off.") accepting_refs = 0 \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm new file mode 100644 index 0000000000..50c54a0462 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -0,0 +1,316 @@ +/obj/item/integrated_circuit/output + category_text = "Output" + +/obj/item/integrated_circuit/output/screen + name = "small screen" + desc = "This small screen can display a single piece of data, when the machine is examined closely." + icon_state = "screen" + inputs = list("displayed data" = IC_PINTYPE_ANY) + outputs = list() + activators = list("load data" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 10 + var/stuff_to_display = null + + +/obj/item/integrated_circuit/output/screen/disconnect_all() + ..() + stuff_to_display = null + +/obj/item/integrated_circuit/output/screen/any_examine(mob/user) + to_chat(user, "There is a little screen labeled '[name]', which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].") + +/obj/item/integrated_circuit/output/screen/do_work() + var/datum/integrated_io/I = inputs[1] + if(isweakref(I.data)) + var/datum/d = I.data_as_type(/datum) + if(d) + stuff_to_display = "[d]" + else + stuff_to_display = I.data + +/obj/item/integrated_circuit/output/screen/medium + name = "screen" + desc = "This screen allows for people holding the device to see a piece of data." + icon_state = "screen_medium" + power_draw_per_use = 20 + +/obj/item/integrated_circuit/output/screen/medium/do_work() + ..() + var/list/nearby_things = range(0, get_turf(src)) + for(var/mob/M in nearby_things) + var/obj/O = assembly ? assembly : src + to_chat(M, "\icon[O] [stuff_to_display]") + +/obj/item/integrated_circuit/output/screen/large + name = "large screen" + desc = "This screen allows for people able to see the device to see a piece of data." + icon_state = "screen_large" + power_draw_per_use = 40 + +/obj/item/integrated_circuit/output/screen/large/do_work() + ..() + var/obj/O = assembly ? loc : assembly + O.visible_message("\icon[O] [stuff_to_display]") + +/obj/item/integrated_circuit/output/light + name = "light" + desc = "This light can turn on and off on command." + icon_state = "light" + complexity = 4 + inputs = list() + outputs = list() + activators = list("toggle light" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + var/light_toggled = 0 + var/light_brightness = 3 + var/light_rgb = "#FFFFFF" + power_draw_idle = 0 // Adjusted based on brightness. + +/obj/item/integrated_circuit/output/light/do_work() + light_toggled = !light_toggled + update_lighting() + +/obj/item/integrated_circuit/output/light/proc/update_lighting() + if(light_toggled) + if(assembly) + assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb) + else + if(assembly) + assembly.set_light(0) + power_draw_idle = light_toggled ? light_brightness * 2 : 0 + +/obj/item/integrated_circuit/output/light/advanced/update_lighting() + var/new_color = get_pin_data(IC_INPUT, 1) + var/brightness = get_pin_data(IC_INPUT, 2) + + if(new_color && isnum(brightness)) + brightness = Clamp(brightness, 0, 6) + light_rgb = new_color + light_brightness = brightness + + ..() + +/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left. + light_toggled = FALSE + update_lighting() + +/obj/item/integrated_circuit/output/light/advanced + name = "advanced light" + desc = "This light can turn on and off on command, in any color, and in various brightness levels." + icon_state = "light_adv" + complexity = 8 + inputs = list( + "color" = IC_PINTYPE_COLOR, + "brightness" = IC_PINTYPE_NUMBER + ) + outputs = list() + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + +/obj/item/integrated_circuit/output/light/advanced/on_data_written() + update_lighting() + +/obj/item/integrated_circuit/output/sound + name = "speaker circuit" + desc = "A miniature speaker is attached to this component." + icon_state = "speaker" + complexity = 8 + cooldown_per_use = 4 SECONDS + inputs = list( + "sound ID" = IC_PINTYPE_STRING, + "volume" = IC_PINTYPE_NUMBER, + "frequency" = IC_PINTYPE_BOOLEAN + ) + outputs = list() + activators = list("play sound" = IC_PINTYPE_PULSE_IN) + power_draw_per_use = 20 + var/list/sounds = list() + +/obj/item/integrated_circuit/output/text_to_speech + name = "text-to-speech circuit" + desc = "A miniature speaker is attached to this component." + extended_desc = "This unit is more advanced than the plain speaker circuit, able to transpose any valid text to speech." + icon_state = "speaker" + complexity = 12 + cooldown_per_use = 4 SECONDS + inputs = list("text" = IC_PINTYPE_STRING) + outputs = list() + activators = list("to speech" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 60 + +/obj/item/integrated_circuit/output/text_to_speech/do_work() + text = get_pin_data(IC_INPUT, 1) + if(!isnull(text)) + var/obj/O = assembly ? loc : assembly + audible_message("\icon[O] \The [O.name] states, \"[text]\"") + +/obj/item/integrated_circuit/output/sound/New() + ..() + extended_desc = list() + extended_desc += "The first input pin determines which sound is used. The choices are; " + extended_desc += jointext(sounds, ", ") + extended_desc += ". The second pin determines the volume of sound that is played" + extended_desc += ", and the third determines if the frequency of the sound will vary with each activation." + extended_desc = jointext(extended_desc, null) + +/obj/item/integrated_circuit/output/sound/do_work() + var/ID = get_pin_data(IC_INPUT, 1) + var/vol = get_pin_data(IC_INPUT, 2) + var/freq = get_pin_data(IC_INPUT, 3) + if(!isnull(ID) && !isnull(vol)) + var/selected_sound = sounds[ID] + if(!selected_sound) + return + vol = between(0, vol, 100) + playsound(get_turf(src), selected_sound, vol, freq, -1) + +/obj/item/integrated_circuit/output/sound/beeper + name = "beeper circuit" + desc = "A miniature speaker is attached to this component. This is often used in the construction of motherboards, which use \ + the speaker to tell the user if something goes very wrong when booting up. It can also do other similar synthetic sounds such \ + as buzzing, pinging, chiming, and more." + sounds = list( + "beep" = 'sound/machines/twobeep.ogg', + "chime" = 'sound/machines/chime.ogg', + "buzz sigh" = 'sound/machines/buzz-sigh.ogg', + "buzz twice" = 'sound/machines/buzz-two.ogg', + "ping" = 'sound/machines/ping.ogg', + "synth yes" = 'sound/machines/synth_yes.ogg', + "synth no" = 'sound/machines/synth_no.ogg', + "warning buzz" = 'sound/machines/warning-buzzer.ogg' + ) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/output/sound/beepsky + name = "securitron sound circuit" + desc = "A miniature speaker is attached to this component. Considered by some to be the essential component for a securitron." + sounds = list( + "creep" = 'sound/voice/bcreep.ogg', + "criminal" = 'sound/voice/bcriminal.ogg', + "freeze" = 'sound/voice/bfreeze.ogg', + "god" = 'sound/voice/bgod.ogg', + "i am the law" = 'sound/voice/biamthelaw.ogg', + "insult" = 'sound/voice/binsult.ogg', + "radio" = 'sound/voice/bradio.ogg', + "secure day" = 'sound/voice/bsecureday.ogg', + ) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1) + +/obj/item/integrated_circuit/output/video_camera + name = "video camera circuit" + desc = "This small camera allows a remote viewer to see what it sees." + extended_desc = "The camera is linked to the Research camera network." + icon_state = "video_camera" + w_class = ITEMSIZE_SMALL + complexity = 10 + inputs = list( + "camera name" = IC_PINTYPE_STRING, + "camera active" = IC_PINTYPE_BOOLEAN + ) + inputs_default = list("1" = "video camera circuit") + outputs = list() + activators = list() + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_idle = 5 // Raises to 80 when on. + var/obj/machinery/camera/network/research/camera + +/obj/item/integrated_circuit/output/video_camera/New() + ..() + camera = new(src) + on_data_written() + +/obj/item/integrated_circuit/output/video_camera/Destroy() + qdel_null(camera) + return ..() + +/obj/item/integrated_circuit/output/video_camera/proc/set_camera_status(var/status) + if(camera) + camera.set_status(status) + power_draw_idle = camera.status ? 80 : 5 + if(camera.status) // Ensure that there's actually power. + if(!draw_idle_power()) + power_fail() + +/obj/item/integrated_circuit/output/video_camera/on_data_written() + if(camera) + var/cam_name = get_pin_data(IC_INPUT, 1) + var/cam_active = get_pin_data(IC_INPUT, 2) + if(!isnull(cam_name)) + camera.c_tag = cam_name + set_camera_status(cam_active) + +/obj/item/integrated_circuit/output/video_camera/power_fail() + if(camera) + set_camera_status(0) + set_pin_data(IC_INPUT, 2, FALSE) + +/obj/item/integrated_circuit/output/led + name = "light-emitting diode" + desc = "This a LED that is lit whenever there is TRUE-equivalent data on its input." + extended_desc = "TRUE-equivalent values are: Non-empty strings, non-zero numbers, and valid refs." + complexity = 0.1 + icon_state = "led" + inputs = list("lit" = IC_PINTYPE_BOOLEAN) + outputs = list() + activators = list() + power_draw_idle = 0 // Raises to 1 when lit. + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + var/led_color + +/obj/item/integrated_circuit/output/led/on_data_written() + power_draw_idle = get_pin_data(IC_INPUT, 1) ? 1 : 0 + +/obj/item/integrated_circuit/output/led/power_fail() + set_pin_data(IC_INPUT, 1, FALSE) + +/obj/item/integrated_circuit/output/led/any_examine(mob/user) + var/text_output = list() + var/initial_name = initial(name) + + // Doing all this work just to have a color-blind friendly output. + text_output += "There is " + if(name == initial_name) + text_output += "\an [name]" + else + text_output += "\an ["\improper[initial_name]"] labeled '[name]'" + text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit ¤" : "unlit."]" + to_chat(user,jointext(text_output,null)) + +/obj/item/integrated_circuit/output/led/red + name = "red LED" + led_color = COLOR_RED + +/obj/item/integrated_circuit/output/led/orange + name = "orange LED" + led_color = COLOR_ORANGE + +/obj/item/integrated_circuit/output/led/yellow + name = "yellow LED" + led_color = COLOR_YELLOW + +/obj/item/integrated_circuit/output/led/green + name = "green LED" + led_color = COLOR_GREEN + +/obj/item/integrated_circuit/output/led/blue + name = "blue LED" + led_color = COLOR_BLUE + +/obj/item/integrated_circuit/output/led/purple + name = "purple LED" + led_color = COLOR_PURPLE + +/obj/item/integrated_circuit/output/led/cyan + name = "cyan LED" + led_color = COLOR_CYAN + +/obj/item/integrated_circuit/output/led/white + name = "white LED" + led_color = COLOR_WHITE + +/obj/item/integrated_circuit/output/led/pink + name = "pink LED" + led_color = COLOR_PINK diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index 215c1ff856..f528434129 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -11,9 +11,13 @@ some power is lost due to ineffiency." w_class = ITEMSIZE_SMALL complexity = 16 - inputs = list("\ target") - outputs = list("\ target cell charge", "\ target cell max charge", "\ target cell percentage") - activators = list("transmit" = 1) + inputs = list("target" = IC_PINTYPE_REF) + outputs = list( + "target cell charge" = IC_PINTYPE_NUMBER, + "target cell max charge" = IC_PINTYPE_NUMBER, + "target cell percentage" = IC_PINTYPE_NUMBER + ) + activators = list("transmit" = IC_PINTYPE_PULSE_IN, "on transmit" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3) power_draw_per_use = 500 // Inefficency has to come from somewhere. @@ -67,6 +71,7 @@ set_pin_data(IC_OUTPUT, 1, cell.charge) set_pin_data(IC_OUTPUT, 2, cell.maxcharge) set_pin_data(IC_OUTPUT, 3, cell.percent()) + activate_pin(2) return TRUE return FALSE diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index d67feb1c08..47629abda1 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -13,13 +13,13 @@ desc = "Unlike most electronics, creating smoke is completely intentional." icon_state = "smoke" extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \ - into the smoke clouds when activated." + into the smoke clouds when activated. The reagents are consumed when smoke is made." flags = OPENCONTAINER complexity = 20 cooldown_per_use = 30 SECONDS inputs = list() outputs = list() - activators = list("create smoke" = 1) + activators = list("create smoke" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3) volume = 100 @@ -43,9 +43,10 @@ flags = OPENCONTAINER complexity = 20 cooldown_per_use = 6 SECONDS - inputs = list("\ target", "\ injection amount" = 5) + inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER) + inputs_default = list("2" = 5) outputs = list() - activators = list("inject" = 1) + activators = list("inject" = IC_PINTYPE_PULSE_IN) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 @@ -88,19 +89,20 @@ outside the machine if it is next to the machine. Note that this cannot be used on entities." flags = OPENCONTAINER complexity = 8 - inputs = list("\ source", "\ target", "\ injection amount" = 10) + inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER) + inputs_default = list("3" = 5) outputs = list() - activators = list("transfer reagents" = 1, "on transfer" = 0) + activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 power_draw_per_use = 10 /obj/item/integrated_circuit/reagent/pump/on_data_written() - var/datum/integrated_io/amount = inputs[3] - if(isnum(amount.data)) - amount.data = Clamp(amount.data, 0, 50) - transfer_amount = amount.data + var/new_amount = get_pin_data(IC_INPUT, 3) + if(!isnull(new_amount)) + new_amount = Clamp(new_amount, 0, 50) + transfer_amount = new_amount /obj/item/integrated_circuit/reagent/pump/do_work() var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) @@ -130,16 +132,15 @@ flags = OPENCONTAINER complexity = 4 inputs = list() - outputs = list("volume used") + outputs = list("volume used" = IC_PINTYPE_NUMBER) activators = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) volume = 60 /obj/item/integrated_circuit/reagent/storage/on_reagent_change() - var/datum/integrated_io/A = outputs[1] - A.data = reagents.total_volume - A.push_data() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() /obj/item/integrated_circuit/reagent/storage/cryo name = "cryo reagent storage" diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index 7570734197..14aa9b6eab 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -8,9 +8,9 @@ cannot see the target, it will not be able to calculate the correct direction." icon_state = "numberpad" complexity = 25 - inputs = list("\ target") - outputs = list("\ dir") - activators = list("calculate dir" = 1, "on calculated" = 0) + inputs = list("target" = IC_PINTYPE_REF) + outputs = list("dir" = IC_PINTYPE_DIR) + activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5) power_draw_per_use = 40 diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm index 64855d2a56..b03a5a2ada 100644 --- a/code/modules/integrated_electronics/subtypes/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -12,7 +12,7 @@ This circuit is set to send a pulse after a delay of two seconds." icon_state = "delay-20" var/delay = 2 SECONDS - activators = list("incoming"= 1,"outgoing" = 0) + activators = list("incoming"= IC_PINTYPE_PULSE_IN,"outgoing" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 @@ -59,7 +59,7 @@ desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \ This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse." icon_state = "delay" - inputs = list("\ delay time") + inputs = list("delay time" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_RESEARCH /obj/item/integrated_circuit/time/delay/custom/do_work() @@ -78,8 +78,8 @@ var/ticks_to_pulse = 4 var/ticks_completed = 0 var/is_running = FALSE - inputs = list("\ enable ticking" = 0) - activators = list("outgoing pulse" = 0) + inputs = list("enable ticking" = IC_PINTYPE_BOOLEAN) + activators = list("outgoing pulse" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -131,8 +131,13 @@ desc = "Tells you what the local time is, specific to your station or planet." icon_state = "clock" inputs = list() - outputs = list("\ time", "\ hours", "\ minutes", "\ seconds") - activators = list("get time" = 1,"on time got" = 0) + outputs = list( + "time" = IC_PINTYPE_STRING, + "hours" = IC_PINTYPE_NUMBER, + "minutes" = IC_PINTYPE_NUMBER, + "seconds" = IC_PINTYPE_NUMBER + ) + activators = list("get time" = IC_PINTYPE_PULSE_IN, "on time got" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 diff --git a/code/modules/integrated_electronics/subtypes/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm index ec773a160b..daadf52d42 100644 --- a/code/modules/integrated_electronics/subtypes/trig.dm +++ b/code/modules/integrated_electronics/subtypes/trig.dm @@ -2,40 +2,35 @@ /obj/item/integrated_circuit/trig complexity = 1 inputs = list( - "\ A", - "\ B", - "\ C", - "\ D", - "\ E", - "\ F", - "\ G", - "\ H" + "A" = IC_PINTYPE_NUMBER, + "B" = IC_PINTYPE_NUMBER, + "C" = IC_PINTYPE_NUMBER, + "D" = IC_PINTYPE_NUMBER, + "E" = IC_PINTYPE_NUMBER, + "F" = IC_PINTYPE_NUMBER, + "G" = IC_PINTYPE_NUMBER, + "H" = IC_PINTYPE_NUMBER ) - outputs = list("\ result") - activators = list("compute" = 1, "on computed" = 0) + outputs = list("result" = IC_PINTYPE_NUMBER) + activators = list("compute" = IC_PINTYPE_PULSE_IN, "on computed" = IC_PINTYPE_PULSE_OUT) category_text = "Trig" extended_desc = "Input and output are in degrees." - autopulse = 1 power_draw_per_use = 1 // Still cheap math. -/obj/item/integrated_circuit/trig/on_data_written() - if(autopulse == 1) - check_then_do_work() - // Sine // /obj/item/integrated_circuit/trig/sine name = "sin circuit" desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A." icon_state = "sine" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/sine/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = sin(A) set_pin_data(IC_OUTPUT, 1, result) @@ -48,14 +43,14 @@ name = "cos circuit" desc = "Outputs the cosine of A." icon_state = "cosine" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosine/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = cos(A) set_pin_data(IC_OUTPUT, 1, result) @@ -68,14 +63,14 @@ name = "tan circuit" desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance." icon_state = "tangent" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/tangent/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = Tan(A) set_pin_data(IC_OUTPUT, 1, result) @@ -88,14 +83,14 @@ name = "csc circuit" desc = "Outputs the cosecant of A." icon_state = "cosecant" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cosecant/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = Csc(A) set_pin_data(IC_OUTPUT, 1, result) @@ -109,14 +104,14 @@ name = "sec circuit" desc = "Outputs the secant of A. Has nothing to do with the security department." icon_state = "secant" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/secant/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = Sec(A) set_pin_data(IC_OUTPUT, 1, result) @@ -130,14 +125,14 @@ name = "cot circuit" desc = "Outputs the cotangent of A." icon_state = "cotangent" - inputs = list("\ A") + inputs = list("A" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/trig/cotangent/do_work() pull_data() var/result = null var/A = get_pin_data(IC_INPUT, 1) - if(isnum(A)) + if(!isnull(A)) result = Cot(A) set_pin_data(IC_OUTPUT, 1, result) diff --git a/code/modules/integrated_electronics/~defines/~defines.dm b/code/modules/integrated_electronics/~defines/~defines.dm index 78ce72f365..90aa05acf1 100644 --- a/code/modules/integrated_electronics/~defines/~defines.dm +++ b/code/modules/integrated_electronics/~defines/~defines.dm @@ -8,9 +8,29 @@ #undef IC_SPAWN_DEFAULT //#undef IC_SPAWN_RESEARCH // Research designs depend on this unfortunately. +#undef IC_FORMAT_ANY #undef IC_FORMAT_STRING +#undef IC_FORMAT_CHAR +#undef IC_FORMAT_COLOR #undef IC_FORMAT_NUMBER +#undef IC_FORMAT_DIR +#undef IC_FORMAT_BOOLEAN #undef IC_FORMAT_REF #undef IC_FORMAT_LIST -#undef IC_FORMAT_ANY -#undef IC_FORMAT_PULSE \ No newline at end of file + +#undef IC_FORMAT_PULSE + +#undef IC_PINTYPE_ANY +#undef IC_PINTYPE_STRING +#undef IC_PINTYPE_CHAR +#undef IC_PINTYPE_COLOR +#undef IC_PINTYPE_NUMBER +#undef IC_PINTYPE_DIR +#undef IC_PINTYPE_BOOLEAN +#undef IC_PINTYPE_REF +#undef IC_PINTYPE_LIST + +#undef IC_PINTYPE_PULSE_IN +#undef IC_PINTYPE_PULSE_OUT + +#undef IC_MAX_LIST_LENGTH \ No newline at end of file diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index a7da54dabf..fd75b22eaf 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1595,6 +1595,24 @@ CIRCUITS BELOW build_path = /obj/item/device/assembly/electronic_assembly sort_string = "VCAAF" +/datum/design/item/custom_circuit_printer + name = "Portable integrated circuit printer" + desc = "A portable(ish) printer for modular machines." + id = "ic_printer" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5) + materials = list(DEFAULT_WALL_MATERIAL = 10000) + build_path = /obj/item/device/integrated_circuit_printer + sort_string = "VCAAG" + +/datum/design/item/custom_circuit_printer + name = "Integrated circuit printer upgrade - advanced designs" + desc = "Allows the integrated circuit printer to create advanced circuits" + id = "ic_printer_upgrade_adv" + req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4) + materials = list(DEFAULT_WALL_MATERIAL = 2000) + build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced + sort_string = "VCAAH" + /datum/design/item/translator name = "handheld translator" id = "translator" diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm index 1730eb639b..22a8bc1a3f 100644 --- a/code/modules/research/research.dm +++ b/code/modules/research/research.dm @@ -54,7 +54,7 @@ research holder datum. known_tech += new T(src) for(var/D in typesof(/datum/design) - /datum/design) possible_designs += new D(src) - generate_integrated_circuit_designs() +// generate_integrated_circuit_designs() RefreshResearch() /datum/research/techonly @@ -129,7 +129,7 @@ research holder datum. var/datum/tech/check_tech = T if(initial(check_tech.id) == ID) return initial(check_tech.name) - +/* /datum/research/proc/generate_integrated_circuit_designs() spawn(2 SECONDS) // So the list has time to initialize. for(var/obj/item/integrated_circuit/IC in all_integrated_circuits) @@ -143,6 +143,7 @@ research holder datum. D.req_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2) D.build_path = IC.type possible_designs += D +*/ /*************************************************************** ** Technology Datums ** diff --git a/code/unit_tests/integrated_circuits/data_transfer.dm b/code/unit_tests/integrated_circuits/data_transfer.dm deleted file mode 100644 index 1d02e8f837..0000000000 --- a/code/unit_tests/integrated_circuits/data_transfer.dm +++ /dev/null @@ -1,17 +0,0 @@ -/datum/unit_test/integrated_circuits/splitter - name = "Data Transfer Circuits: Splitter" - circuit_type = /obj/item/integrated_circuit/transfer/splitter - inputs_to_give = list("Test") - expected_outputs = list("Test", "Test") - -/datum/unit_test/integrated_circuits/splitter4 - name = "Data Transfer Circuits: Splitter 4" - circuit_type = /obj/item/integrated_circuit/transfer/splitter/medium - inputs_to_give = list("Test") - expected_outputs = list("Test", "Test", "Test", "Test") - -/datum/unit_test/integrated_circuits/splitter8 - name = "Data Transfer Circuits: Splitter 8" - circuit_type = /obj/item/integrated_circuit/transfer/splitter/large - inputs_to_give = list("Test") - expected_outputs = list("Test", "Test", "Test", "Test", "Test", "Test", "Test", "Test") \ No newline at end of file diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi index e81053bc3642547884e36f3ed5b3c436f0083567..6ad2b65b2f92eb46c37a5abc9da34d2c515f70dd 100644 GIT binary patch literal 35959 zcmbTdcUY56`z;y_O^Sdhh)5AsP{1mcrXXw(^VS%J~C#jyOHqr|LS zTAjJO)Fa8a^Q?j|MkGC5>oV-vQ_#I3zWd7TtTjxMXI2JX6W46_DzHZrN4Z%;bFsNQ zoYktkL$$`!TJ71;@#@0iAqyo=N3wKBMf~#T7~R5r5vK7Ok1&zB_`93mJ*C)VKNwZH zUP`DNmSC zcs12kCog!+5&T{qPlx_v@tn{ieb@ZXnm*BGYC$M^;FiUw8-a+L1lF97EMeDN z`rfXyt{#|dO02+%xw4&aaIE`n+qRLW6>-!le$XCgrC$3%YmLkkrI|G*XJ^YGbS!Hb zYPGxMU)gnOs$Y06uNR9js5(1U{3j68u!WjtBzrZwXxvnB-K02^NwUWc{=L(zMO<1)^4;?XXGMhqAy{gIBMP0V%I(PGEVoXS?00#v$`J%1W zT|1+AGlQ=w&}KnptvThhCJlWK7ejj}eX`iPopu9Es_#nH-TNwQ8urKhQS?i%_YXIV zgiA%*Ev}@R%7q&qOw=v0yT}hjZ&D3!nK(DEB>%QEPC!(f3_^S52I{-Y|8rH)C0SR8 zqWVC)_C{@>F5+$`u3Gn@vP>Pyor}xkCb@Zb-7e$GGPfFbP`mcma=M#yOjKj4PjhSM zwxE^gs6*%bq84lRy^Wj*H6m9Ezbv)bGG)Nys}&1uSo+Dk=Q$R7w>!2UEZ$jsF8a5J zlG!aSk*qo8$}*&Y#~xEr>OOrhWbgW4{X=KHfqBh6`u!j}MLF(ds{T7e3S!rZN7d(2 zVh3RTYa+#t%imgMGTG&CbziCyQj@G=@MM?&{>$fWf0k8AH@}hH4e-_eRjXZez2ui; zSPp9HUE&wd#Y%09@@)0_yt29O-}>X;y)_q}nQCTrq7A-w9Y1=*tcqaB5E3{)VX`51 z&3l2eq5dfN+-HtUUX%Vs{J+~&TV^UQ=6rhahr+RgujVauZ0$AEVaoePMYA8A-4zli zO^JHu`$i+b)kiK|9%e~s6PEBNyx*|#e5JvrF@~o9YPh^Qc5HvJvGn5Lc+U2eolQ8f z*Ttks90K8n+*4C|?31zH5SVgdA$5!B7%JZ{5hTvEO$QZVzSJgFD#%;i{$+Gd`+NeU zfgGC=tHSS~pv$Hnd~yxvV$8ATeDAm)F^SrCbAEH29!Ld3uC-PeYN#= z&t5I$pUVYGs3`a(j4}B+M4j|LD^Ax$dcX7R71<@ydt|35gqL)$D;uTxKmQ~A;wFSP z{LW`niceVx>`E@_MT8Q~aa=&xDlc|3()6NOR$$xz@|^>k!?HUl{LWQZ3q3{~1Ddq> z#T2`Z18W1C+14Cx<7nM(>_!N}8DI19-}VR=*HLsSjGWbwk#Ez>L#b5U!xnH$yI(M6 z2QvKiIZOcuq+bVy-yhIH^AQB+*Lnq@H;N>0uo`~t5B0KYiu$)TFjmdHcTx~q%FxE5 zHz~bUKStF91%kk($R#@CH+TNiDY&g8`Sm@O3#`yt3)F*II@Qt!Hk$C(U%OtB0{SY6 zYSqFS*jy(UGs(+$amQYeJi5_7=8#KI2dD*9QjE~1f3^zY3?lealLha5x`kDSk?_9B zNjk`Axh->Adip|M>sPJxdAI7nhJJ}#a(`hpSj#j9NSdJx0|CXaqp$yd1JQstBr^E; zp9c3&5$RUNZG1PXa0(yuc^2y&Lb+e9{h-bd6h6M5fI}&cTubnDZiNrBi55bi^O@NM zm7aVF^xnNRUq;l%F5LLj7KdZ0T@bcJkFR;ix&8eL$A0dV>ZJ#NTFT`(3P6P$AcObz z4>5)EzZSe}ub6Eh-QC^IvLyImZ#x|AeKTA-G01a{82^NPUPG*rzZ&h zjBSB3h}kij>}E2wi5}}@ct)24?Y8Xc`&$k(G_4Lio!Vyq?IZu!5IJ0$*nSf|o;!45ZEy)@7<7FD{Q`sbwP?UQ2lSRa5Y{&(F?URFmjxF9?CF1Ig z{+7a@k}ZrNe{47ta#;Jg+5FE)IJdA#ywW-KB5g$D#XQ%hkmhID^^}7N3j8#7Asxb! ziy@z>;L;>E$qkWzTQWrM`1H}Os54h5>EqERfyn(+Kh)H2o$nQz3SzR!!nPaHeW=O= zSG45bA!60ki28dldxgB*#JmfuHAQjrXm^B-x_hOL+x_GpKXZdrt1u>VR&7=e?m;&L zW)4oxo}E^>46GUa(E@J88UwGTE#1-myN<>_eJUsYRouMBMIO4yvhTkpqSkTn_K!Wf z@1p|sTeuR*1#Qu$bcba25vgB&>RjxI(N;~8PHiJUO6Z<`K-7K2m>{pt4zV)f!{Xdj zJA!;o&*h4Gv06s|%%Y5$qDalf2rnNE>wt)paLb76r;wHM&&N;&+#a%eq3gbiqTiWf z0jTw$Gb`wt4|wYR#DagL5_L&dfmYl<;iwgHDTs*_!>Z~2f5fsDNYpYkHFc zq6X@%G8l~Pj~)bm=H~`?*XvSIh=9e<$No#!htVL|uvQh3>ACP)W$Y)pXWRB~mL6M_ zq->`DuvVcP371%uk&)>nI**s%oWsAAd~>+75h?UXgj-CV|H66R&WVMOomFJYB0-mx zpJk+Z?~^k=9f&j+T|RcrO1aQlL^CV`CX&|-4oy&rn~5GBm3LH}6`?@(BtqEpQ>DWuaD(wX5Z&ZMU% zhAhulC7b1b|&k^$dhr}rL>|@Vw zQ}NuInZD3|{5z8$h00xPa5%6OMxAKSdcv;B;7QK&glTW(i=OvkdjKib zO!0l3$Lkd{Y3MAAfEn5TV$PevAIf5Oh|C6$(K!L9w%Q&?g;$GTyyO??D9rL|-dLHY zaZoGTuRG3((mZ})WBJY>sjOs#)s0&*T?k+8FNo_~DAloKcKzsJ!Dn^LYLtR=tWQOP z(z@VQUN)vu$P=p_g-4X#Zq?;PGhBlb!3^iw**v$ku`_Zr)IJL)gmk_IajR2^Jdb(v zm{M?g#%kvkyOWF4oUnpBrTKZirY{#AtnAY~-iZw<8=@72J@qGh2q`+d59UH;eP^jc zRp6{4%d1qM`?}z)3b+?ak0D-J$M0kqyByv;{ygc;2Mch^YOQVd)q7v{-cqt{#7cP1 zT25EyDT_?~eY8C9<|;xJtq}Hp;n%2h>>AqF(>j?!rvChWbl5;U+)Loy8K=!nZy zB0oJtM_L{<`oGSe4!}3k=UHXYG`gMWlYN}|73*@=6Th^|xsWqpXGF)KT4Fo!RWe>) z)IHQkQTXSa>kbZmmX|ZO?%n2NX|nrfw%9M`*)Oz$&VSO?%m9W6Z02}PS7E%pDmzfq z4ht?puK&!O2mg&*i$iQv&{;RF3y03LvZ`*r;Fj`K@a?hn9r7_cC)4P$f9hmeyEo>{ z7mHNFZK&h@?^f=?r*6$wqIEUvC=b6nsk@b(Xa&+!>RCk!I(vWdk4nN+or&>QeN^?M zX6N>|rE+7I7P1tq>XIi*mrw#(+%Qg?Liv0LM7I{F`=jcU2QKIy0z>(WL+J}c!~3O- zBttg=;?d_TP84uIMAHekU>4qM_jsuc<1~oo)K)k+gu5vOp0nQbkG|lMyMfeN^&gE^ zDo!JiP4cTsquB$Sa(c7;Rb(SUSY4 z(WS7YrBWp$f)~4j_T`bnc9bw-;+fv#GhWSEhLjzD=dvWAHf1oA8=~~AYcPAtuJApW zfbbQhl|bCU{DwFGgO`K7bSd;~#pQ4==yIlmADd_$nvUisq~8zI4cR6w$TL>;rOA2Z=u+wXUp87@% z5HEQ*5R~PIw;kQ=MV#J}N$%#Efjzs#mfv;7lha6m z4Y6E9cJc6&=c!)-Pv@TFCT_O1v~QAO_PEXDvT4F1WGgn0VtZzA=m*S>PX;+p2(v zv|~)_g*Akct9jRYrovMOw)#!u&O80&u&cT(VI?YgzESVEm!eg-qfZ%fMXFO`^zw0yiyL3>4tvoH$o`sP%ljvRB`qKQr#%bxeBbo;Ese*`<(` zv3lOP?;9HCVVGmWRxCm>(0kSzw3g#>GlA}DUc3aPv$C{W_BNw#3#7n9m(pTYUgto; zeC96o)rBbi*j9ljrIhA1+gRJ}R^M`Q^VLtv399bfEgE1v^FQ?U^?>>&odpy_ zR-!@mRY7k6XOWl3IJZ=PsRp-MM_V~vKnV*B45U~S>7YxwK)oKdBbT5J5~kXM>xY}v zJc#rY#b3|X*JDoxCwLamhTlnprvyk|a(#!H_FyK5pf6H=rE&@pWxupHkq#lNwl%kt zQ9l#rxi&mTVB@DEPI+U5RtwjL2+3~S6c{SS}q}gnG;sqhdk`LsL+*@&hc~SP_ucge4r}Sf2)y41)|_wO3JZn! zLHC%gPMg&W3ykEx8zKqZ4?kyT^P(1R=zPc!>wUPr@Dk-A_U9 z-P@c75>Z~{@NA7(>AKp*!%JaIdXt(eno6>4eJPvqYPED`blT5E*J`H3??8%_~%fer`OjcoSz? zA(HYQF>yvzCXM*H@7t!o%%qFz_?jMdZFz{cgrub8e4wBkMXmZD<6cc8$V?hjZZV;5 zF|_!4zQ$aIKJP;ms;$(jvy}5K-v^%`eeNRZ$gxtZ&jW~AVOmz<3-=4wiLIOU&GV;FE-BPw5*o4kykB?ewVO;?I22yk=pm5UdQ@@p+bTCd=XA zMY05@blw7wJ!riCASv>J0W^4JF{HR@|3&0FnVCXTM~IOX=+8n+D|*qtp`jtEDk~Ni zulcfZ=?KShB)}w3AtwF1uGcRQ_oYdL1_7CI(P3DWk(}9v9hwu+GBexG{-Q`DXk$P% z72lG~$0Zkr%ZoA}D=S%U-@aXqKb&Z@`QZEWFH67ZP}+U+Zn8*b6y`KKzgOPYWdx>@z7D8Jq4nqh^O29WN_2qB(+fubo%nW`xAS zUDh9Oe-VDrsHyUF;=_(nGV{5Zrd1T49b%4cUa{ShipD^%+^2YMkjCXs0S6&EhVpq$ zh)6EpE-Z`orE2=<@bKb2#>X89tM^&E5iO@CPWQBkf#$V>Qn%$`QVmw-w+h|oe=$8E z=qR0BE9513j+iEo41UjItSipuZPZ6-V1s=7{ssqP4t2W2vAm)EY-AqLm|iX_MSTSVc;v!MPZPO=WNIszv{N zgTf#BI=8L-Cfa6_BemX~jE|42LB8eZx3mSa&b5?reGN&HUg|BOBVwLKF+9&g7Zz$g z-ZYd(?@}`H9ij8{X`Kh_gWJ#@4ePJi$vno`$vr(i|37; zrc}bvChn-X0RA*U)c!uEjPhv#aYJoo9u5TNYO8;5$@E7v(qce>oqjq-XFtk?d{)(GA<}$GkLRS9vD0IvT_JU`U_3^&RHY* zuoBOaB72w4H6`Fb4SLty&3>fxR-1wXO)sNM}O`Y^D$x`q4RR~YHoRJvZ z^{k!*%l5~RMX8RDz0r_A58=WG@*T=uAM_Hb=GtT1_g4nuAKn-spirpxNG9Ix3RIww zqudIfEAXVVD7m7lYGg;Oss4~QGbCUHvxOx3`yxzC(tD$?UY*<)s7mif)hqP9#_Qam zN*|M%Ou@*nE(9p;-POZB%089|x`ic0r3@*h=;VPw^ySN!13+MsWDc{PB3n85wcGY{xi6dPZ5ucB8NdV; z(T$Bth0Nt1VhNn_kKpiF)rfOe4mym|Z%ancOvDDtk;9e0Gs}yPGOV^Rz&t95i35aZ z6Hjm&v78&n1f2|7rsWQl^T-gi^Fi}_4y_<&K5gsFE20u z5@;&HiK#gqYf+e+dH8s*o@)=-w&Q=T%x&JOT;QZom~b~TM?CC6bE>4;rkC^aP$aQW)JmGF5Sx%xu)=;Tt@JK9A-pJZouzs$#oWZ$l zO9f&`v-xk_!M58qtllAPuS=qF!WnH^P*^A>NtxVQ{Jg~l1i}=K@M+MsCL5pU;yu3& zNxLk0=EWqq2=k((woTK0jux_~dE|G(--s*QZ#QKLJazwk@;H*(LXdHRn~W#(bkuP>0N8XW=SObX=!h&Zl~%8q;4C7&T-e94QeAgU|tH{EEh z=URX_Ca~(MvrB=RjJP=m2ZyiF(&Mik_mGbc$pk0?sp267xE#L@c$ICADGr{Y9p+@q zxkIiy+@5ej#ED!id_7r|o%@e-tg7D@=ql!<0xV)v!g0Q@P#wCNz};mFgNjCsj&bc> zHSn7Yl5=HN0Yg5^q@o6i9INP4xj$RYJbV3)EV0q4gvF+Dt^5r6f(tE!#p=wD#=y!W zXy>9~9T^VyY2~D1(i*QGTI|rGH9AFpbLwyU*2h*S-!DhqlT^PUUC-}d-*&s4cUCXx zkTp=y{8X0ahqbRs$D+D4?EE{J+je3vTr12 zcJqbJt2E9b?`1D2L|z~#fi$B>Y`Bp^lUy9f${`_NLdT0z*}CJo&5ancOJd>T%cT-8 z>u*SpvcctgSH0LgnDpc=X&IMA0%37TNV)xp@ab+cy1cMn9g1>5fS$t)xFrDW^gd+0 zr@meV4a5jq7*YZ$NpnZscXz&C!o-+khJjP@<;`Qa@m@$l(9Ktiny-Oe#DF(T4q=?7 z?uc+%GLB(n7xTBtHcb`b!_zgHr7I#Q8# z;?}vPuLO_%2gBR{gW<*CUY3oM+YGTaYhDKtdg@~I@fdNFyfV|vVX`OknHnMl)%ALrEJ&=bqN?%*y-L;d1 zSGK@fMQ=MGui|G@PA9$W<5%&B#}B(UYgS+L_|DZ*Bk# z{uAUA0Kwa31CEPF?iSM@&{J$R;+*awtgj$haz;4%GI#SsiyjEqkY@!RroJFdIMr!o zh`o4~=V@bI*46nFnkkn+pq-aYLGy@ z<}b2T%$7*1c@)E358&;*aWs{a^OX}$%pg)a*|PWFjRdw_HCPV9I3`*G;)B$Cv`HuR%=z` zd2Tlq6BCo+IddPf=&9jRclscP^C#NOztEb9a!^UVh~Ayu`#~#m$@nPA#HpEh%teH9 zA&#$togC-55ptDhXUy?B2n)MFsrDESiGZtSrIxRsK6(@kK%U&&q=z@eELy4Mn%>KL zu3pg2luxW&&(qHplnU(MD&*3fnv`-Jm&}lLz2lv_x@re$>XyOKL3|E|Ca1i1ug7bC ztgD;YmiN+q@+91LpudjA)7$&SkFc}U{;bvwvv<6MW2UQ5i{i6`wwqt z;dgQPmv(mV%-#ecm~Tm#`);E~%-*8t=rmkGJ}f7IL@c-K(km8KC^r2tUPPpR`;48P zov7FPQ{QP|`}6Pv)qFk!A&5FJ(96^Fys?Q0PBsJ5oKaJvg4jpD+ucKUspMF^> zdC}gVG-9ltCgRwu$*7F3LP+VweQ5^{*zGhfIu@dmt4sORxqgSTs1a*7aprcm=0e;l z0u9@stY7-zf6k=Jsf{;QaW;^$;DRpYb7MRjSZi8f)4JvQXvwkVl+(jZn)L~)$I}KP zGKEnb3M_TrTS>`M<3@6DVpd}*JMNH7KlcomS^Or^^2q5SMKOc&7b*hm$uVrdiA(nw zxf};G!K3t#o!x(Nor~xj8VY~S%xBT}`EDt32}YDFB90v}a#03M1a)+Dl<&FzjAHwm z&P{)kl}3Yk6_|t%DK;W!fl>wgvvNJ`UZ-eHY#N7AA;RdDXTi(uU0&yg$O29 z?eRJ^HGrw%kYo*8F+JTgGPu(*no{#A2y83f-w*i!OhS!^sld2`CSH>~Sh?w)My!xY zJt@@N4VxyW3r$aogpO4_gjGqyMf+rdHn_XEslLHhlQj2#*Qn zLykCE6`uH}?@#jojE~>yb?0UN>SUa-*qsH#^x=n8-JHfsDI6UgHE+CM-rRfzOdi@C z0KG$LPAMzBBs%UFTp65yDi9qFwAJ<$yP4&)=9>r`yhhBG<_N=_#%1`=8KJ}T9mLFE zK^$^!@X4Uq(Hv5p>3c^WwRO*oK{|%E~v8V!NU5<%{_a&Dxbw z3DbvB!Xj3~32f30A9Vo}Ts1`5gx`J3@|s=7Npfht?qwejNd&UpOCW>u#K(n-6dnZ+ zDp^iAQ=0ph9=-JsHiJkt9p*JP=0X0%$PxMR46<3oJI3&&>1ngUk&(HX=0P0?fXK#x zTHRE70yZ+O_UhuvIv2fpp*K#x%xLTq?G{ijb0W^;p2vv3(jXu<-v{K89V^w?jK zWp4}yEGuT`Tcgj?D)ehr!=r3{0;PsK&$A|XQp(C>rvJ+HvzfP}mayGej5@;voE_42Nr9yw zHTLtT>hen7mHjPf0P@4MSWnNMm%M@{r!|tW&!Y&9{M~4&6Z(AZ5l9z50d)2}173JlT9eA<(Po5;M z2pa0^Gka}}TaDA_#LNxoz#Q$S0)9Gm3P2Y<%vF#C%Qf;%bxJ`n?*Fk_4&*JmW9r&GMd?0l`bBI-jXtw0_upPs!mV%)<*H1)+wC6%>p z9T4i)4Jnm7RCH~+Qi5IQe*WG5+p^2i*spkY!9QM8jl3UP8=xyJ;t18eJ@lofh7I`h zB{{d8(*)KPxB~|BR0RY@_#1=Hob{-$ZU$eBKMBP z!-&KCUN36o?CGy~-fsmuBIy$Z2GeaD1p>_D@3GAuX7LqTJkdnKXItcvzB{+juT-%Y zl(n^b_)Nm?j0(TAzM|W_<|FLEt8;OS`MJhVYmNut2t*;>B}f#z%(;pe_I;t8a=$Li zI9*8+feVYEt-CLu+`b95l7d=GQEL{xp^zfLk z5X%+6yReBVvtbC@hws}J#FVJP@IOzHc|Hx7nkb(k@vq7cShy4;-&akBR89Nk^W(jw zOi~+2BOq9c-;9;;?YqnR#j5EXmr@kxe$H(V9GJqVW!75b_OCUs@!WWSubzNi+dbUf z5lA+)Zi?bLNyNQiu~ODIG>j;->0Q;%R30yy+RPw(s-dCLb8h=Qj(wfs4ox$1+INWz za_;Dg>XQWuqhwDW>U5<*c_r*JFJRGhT!H&c;}a7S>axk|w+%%!VECS6o!M|!mRzCS z!|X`Bfx2K76x%s~+?oW-lxeLF@JL}dGowqUzHyXRY z<8ys5mgkJPMtc=>Mb5{V^~r(zPPuSn)ubEk;rbY_%)}oZbUL9;`4R5y&Kavktq$c> z-%HYzA5{4%7*DMC6FN0O2rgoa-+04w$q;|6W zZ{L(19Sifs2Zx8pCC;VD&-D3k?8`o_>G&)8B$0KQ5}y3b?R8-+&pTlyV+L*~2L}@C zpC18mE@Y9yw)eyB6fk?!errPehle~YZx;f2`gPDxh%vYQMeC|qMMg$gGqV^`x|GVm zO$X%!=#y#zUF>@a$$6&4NPS$OIIfu*EWsS<>E$&GNcd=-x5%q=9B*VW0n9eN9};u@ z_U3kEfhaV;__*w0n&dr1Yg|7W#Gi^&>zfR^tW07_pK+I_$&Es>e+^H6;?ONyQ}09` zWX$lFQm=U=m7wGD6_Xm_y0j;1RcHkO$%otif~ElgZoWabgP{j*a}TrTWieKj`2V64 zU=vj+F6FrS-pb1^v8P8HsOc}A6tYgZ0=89#H*ot-nIHZ`;z9$9zdi>bR~B*VGwzs2 z#lYDrf;@Sk3J(gOhi%pG{lmZ(&c7C}ClV;lZ;5WyYgL{&*KJ5Ys6rne9(KIAmRfV% zuY;5WOZSG9c!MggUMO(rwMP%vT9?!^Xyd?Ec+gHAB$4b_k!c+r71zJqGr`q^+n_Ea z*6rvYDq8;Qau5d$F}eS$Te7b2AFAo5Ty^%mrc_JnR53@h#(&6Vnk7AH2M<)M;WL&z z$^Nb(WhbdZL=-ztr`~PW3#Q7=l=W|FB-)pryMT}?+{2lJ)#ecdWeX~HnhLI(e zxs*7JiI;r;erw4McHGRcow*gDK^`Pw(=+p$??dsIk05+zNZ7=D@~m{m!~k(^3=Qrl zaSq!(kl0!QA5!CqFIdCk5uH|mgIVyzi&i*kXhaBkHeqe>Wdy3{c>5NtPQ*bkw)e>^ zkp6$a=X)_;ZY%3L8@4GvG&BSWN_TE#gKV$nqZZ3n>NT&O2WU{bK8EA*lPAx?jkbFL zOORM8`5ChEii+oi)05JHt)tFPtrXGbQY6TjwzvlFu{8wcbkl95vnsV3#XW8Qp9T-gJ^RBI{`tq_e&}$(d^YYFDaR}M70XVe!p}r{)g*EmrfY@lMS&rEcVajWE7C|Pbzl* zfjj_)nwNJ!r7hba8jK{0mNERhu;{;uk1xEyuW=yD4xIOo%Ls)ifk#nU$lK^Ktjub% zOExemQLErY-kKN^W?>kyn5=fy?J;Q#s5#9I&@moarc$n{PwaE};@NEw6y`St$FGJK z=ofkxe4I2;a>^$-9H5Hk+=_@C3SKW8hmG55IviKzroI!$OHNOh^r^IwgtAP31H4~5 zW_=0MK~c@PmX(FHff4Voe?#WWo}Bc)40(9tz0XpnHw40J>hWm&1%!lIK2Z6&9B)7O zJps7%MR%H%E$TWz=qV3x>|obWofDnme!f=Z4i|o-Cb`P^8I}u-oVC5D+c(Zpe$tW8h1Ko#a(CZ*aUydE=Oq7C7zz{?KvBA zSdyDB^<=gHO5D4NATsl#&8g7_fA8^Kz#z*=9(vbnm1^#4tu!i{|qqwJj_yJf2pl8n?;H)g4`AJ&HSKeb%iu}y~xw3Nj zF}71@`*n@u~eZ#m$S- zsSnefG!iKvkl@+N{dqu$sL2D!Xk(>y)tju9!T=hQ4a7JdoLPr>;e$S%;{cl z`x8Uc@V_k)odXVg8^;hYFR#y^K3#R3Ff{eN*aIV;X6*54rCE0TCUxx0F^u-D|As`x zqCqjn>YNA%{9tD!&G`_Z|Kye>j6M2%E{xdtR4_?Q|9<+ID?2Dk^xYUS9uYJ+YNkbx zw1YbU=pY6D!h&9`HwINvWJFqDhb{a6RL``^Nv3oEQ)CnA{(n@v|KAb8|CG#MzZhhS zI9W)d)cUtlKJ*>Uzi{LY*?;SEBwE+bFwT;LB8);g`ODEfm*~cK9mKG-7yxR*0s6?X z%=`ZR2Z)nEp?K;V3+ zx9050a74|w)4f{7w);Hs+mpzRiV?rrX@E0HDzMKiWsp6pVYqLO%V@d?Hyy*F(CUB! z((@=j=lEtGq#(iPXv#aV1Fgn$^*+)pxiDoLhyPFmd}=L^3qn{$5jx5sjG7$82LB`Z z(had8>{j=O+Y@}I`(Ep#S9`$a;i3+9<)}YPhqCA1a@FQhn?*?hEnw$;>!?w{#}#*4 znUi$ttvZulpGdwqCF#syD}n(c>%JHzL=`V1^=RqVdp;fQ^brtM z|2LS!ABJW9ac5Nx)d#;($(^*=hjmHW2vq}mXU&!L@O{TayX1RDNzQ?5CbJ~|+j#`R z@B6P9O8k2sL8DR&tw6}g++ONR4c**yI`LFueSyZre*Jo5W3c`*+4-< z3lJzhlJknR@mFe27SqWfs7CB}BU8%PYCId4=IdgZ8u1&>_UZ#qo;*pBb~GNZ2hBZ9 z5hVlVCO}t9fgu|grTHGFn17=)9(_WTnexyd7mvMt__Sy5>IItDpxTtt@J!=H&A`88 zc_OzLh_}Luxh*so{Z+`_lQIcEc1%>p=6Ug3YAhiLY{PDB9%U_dW0D8&gww)M+>|QR zWVJ+N7_7c7)+~K!87?&0`NbPM>eYWwC5aQ1AXPm`RH>X{_+?u8O!08^MWZtkH}To; zd(|nsbA50=s!?8u`~J1_MN+;CCPWZL--i^I2X?kI(NPAPQqPuNd_(sTWf2@q8!-1t zy{q6tYc`)A*PEX@?0rhthG3-XLedckA3WjmKI>QbJtZUA*IC5VrP;!&=~ZYD0B;@L zu#S`c0r*2gxtpfdGKFsTuZ{z|qL8O=1C4mF8wV5Obaz!%q3?cQo86IxEMcdXDO3P( z0Wj`qh22G-cxn*5H#VP<4U^y;L{o&<>Y`Qg+!3yCd_0Yb+BbOa09CskvGzlmW1iL@ z7w1JPAk&S<-tAYioKfwgRb#ljB4UA5XVKn;Do@S0b#QOxVU)si5xB?S>3AW38=FOb zn>aTlBCv0NIwzz@U}D;;@EnKhv2)FaAz)QBbf_)NwXy|TniM@ushvGMEOs1`5hAw{ zp?nC4Pj)u5i4JV8mN??AUSfk>l~3v2k+~Rjk98CX$sY>~=>f=`nwkR6wW%-M7$;mtiE(~te7fH9&@|(r!#!*02S}~sBz>tPn+^9<;yL{-Zeu3eE3T5 zuOAB*TtRtQXWFB)7VCYdNG4EWpNzPj!=<9^x9xo}f6r&;6P4?Lp)+|L&E*$DV(>qU z!^qn($i4^B?A)EnL!GStASzBjMh4h1W2F)yYK=fo+?N2~a#k?wIWO+oG|;+%l*7iC zDb5IB|8AS%S|9|BO)4N)+1@_?Tg5cV{)vmdS+UC8AK4O?9eX3uwYA2eawEfYprdhN zE;)^TNI(DO(5FPt=wX;S0t3o;WPzK_b_BCE)`b!V)GCgQ{td5m=?JbMOOuSgu z;OP@QLh5^OzWM=fF)d={Xc%SmO0i}&F<-RK+iN@ltVuUY&55$RxrIR~Oh#UwO!m)d zQs|2Q<@uQwTH-4tmdy#f8tn#It|YGhe(wS%pmlbF00f&aH#BdqS=!wAT2b+&ajpcs zKC7@xtcO}-jVk_y!~K&Vn2<_=O~MWP{ZT#G6Kn#5H8C}uX@PNZ9pCxW$p>4FEgI{#8vRdX8h7XeRs=>)7f{55iew~q zAnOe6vd9gzHCySYUxP!#!yPj7kS3C6vP`=T5f4V-?YRPmev3zbMA|l(WgCqmu}y?! zfdC!v{^+;4l!fHPA=zaXN?M3Vm<9%BzSGx*R-&^=T;a$zW=VTuQF;{#lyCYCWDmrF zq*<~8$+8_9w5d5k!qq?%+q)In`j0|tF84nQDT%p}iZ_*4dlVZ=?{9I*x$bhC&LJBko?geKm3nVOjw8kh(!hX2X@^pPexLicX2sRISuLYcBkj zY7hLQ6hsN~hxTM|oX`Y)8F2i!UJ31mgPGR!>%-#4iDOHd5g*=)9CiUcQAX)h)DLm2 zI)Yaq(9pmcA$Am=Etop z4OfW_hOk>Um|Z!7FTLsxIB>u&=tff(%N>7)1p;_tBLL#A!v#jwC#~I0O5AQd@BH-b zoG~)R+Y~{^qT7Gt2EFlMJ_Ch>gl7MIQr+`HZZ}gM&xA7cn?ak9geBzcJE7#9svQA5 zbng)1E~4E7dwo;?>&%yAv-=b3(&az3YL`F11?k(W7WM=X45!AE5s2{5P=**1{o$rg zZxcYB_D1d0farFEQ+69Bh9pE(?{*06{84R65<<5R7Y?ryKfe`rvwZmNajv?6NiijU z`b47fRPtLv0Xd{gX-hHSyU#`?dgpJ%fSLba;sxb}pV39Qh=Qk&7;#&P!~rzXU-Em$ z3koa7QKd#x_bcL_T%uPq@DcB(5Znz6DH90rcNKnB2?+c~&|<(nvEWDW;I8<jOE4*1{}>3M@M8AEg7y3T z4?+o@lo`qNr#BaeI19s%XC4FP*4V(<``@aeI0<`Wa&W2voM0ImsHZJbm3ddI7(XQtVC7OzP+lh^0NElSvV0`sA18GmHGPB! zxNvh%QXNaLxBNayv|UTv!SGSf{`#q2BiP}n`66gVD{%qY_=SR)|Ahkl<2xT9qh?Hl z%8K8ejmLjfshy_M7JJ(Z_w$e1v~sLP^Sj~utZ}gRHjUZB@nC{<|J~j%Z@KXM3ah=Y z8atsV@?b+s_ymI0{2Vcv6HNvwKDg+73NjUMUBfo)xFd+a7vEdQ+~}c_DV0ytWJDbj z1f*l@`pWy_sjUiI^-%61^5l3j_V-xkr7xwXkf1y$ic7PBPlz3`e6S%m0!Nxon>A{Z zMI_u^+uEX%hUg!WH3sIbDBWDUVKoOa=lX-{Xu1dV?9>4PVB5Xdv*uGBAUrBn&T0`bM1&BM=>0*buy%&8qLlS#2?s zt@$&d2&&T)I-5`H?>+{9xe5W2<^z~G*U5tP{={1EiQq31x*_qrylA-3-|$!I+^j;z z*GT0b5SP`#n>B16Bxj#TU4-!-3Q>M_(ljxod819h-6L5nX(z%N8!{%iGhRZQ0wdphOa*tbp8E3Ig<-u8GxEJ>Dtbbf;|NNO}i+eVNR=5d>)}juhqR(8KDN>~DSxynK#@$5JuNEQx z+z!}+B0#&qgo!92*;RBoG+5u|W+E%K}q;KKSj?*H|?F z8y~&kCBg! zjlCYo)p-FJZv6(AR+_Gp`9*GFC>IcPCgs4 zCO(`l?Rfcvvn?6q89DcMD|4f1ofjYtc&j}DD#Hd~BpRH)t$bREYru$hfKs?~PgM@k zi;()$qq8B^3~!m<3T;n;iOw!*mdwQ-KWH}$JRREmGDie@#9ZIgF7GVv$P^gYR>Kje zyu7@4$Hxplt1cE`HDI^kzq3*P0((89c7Qk!9&SNx80;DWh5js% zJ2U`}1w=K#*Kg>F;X(#xY%JA&FO6Tq{5*IVjR&37ipMjT%FCnTma=4B&j2x)fP)JO z9s9{fbuRU`2Zor-LccB~S7xi7vy+T$V*y71Dcrb|I#G0LIgQ5s_6Ix3F(~Y@eYYVO z5jg39H!vscpsFsUiCIVS@B3-Po~`wDHC0vB@k&(f>aCidvhFNN+jsRGplsm#k^WH- zss8J_c8`*|0jCv|+a@dDLEF|eZ?Ad~c5k(lTv@L53`BXVcST8s5r+N2N|$(d#n9TW zyi|JC7bN-wN`*v%;Z`iC-prRPfM?Lb9VP`NGTjwGo+%Hk5K$}Z-X5$C>F7&X z&aYH50rG^{{=QY*m+;|CgmwIx^Hz{-seh{5u5rELftXY}q<)j~^Oq(q6=#(yNz~V) zzHs;7bLx8c=j;DH&Js3C`@fz0%;E3z4`aU>c>mKTThPU`y^4ELxqRs(h&!5p{~p{G zEzO9P+M^k6@cie%r&#z1YqQwUht_!Q)Gi7N}gb@Xfto~@pfBUi6h%vl7 zWZ6XQ7+q|H>vL&ktN-S2Wh$^Xjej=^g%IQ$`4ojee-bbX13P>& zZ|=}UqUA<+!uFRujWT|2tgDJ%+V_0Y8lZq1;A&n}m+PODTG^7~v?KSMq9?Ea8h7Yw zgX|)msiX*1naENC#YdeNTpJ`H0z8C6_Nq5XT(rr6&YeQ$QZ>Atn^dsyvufSb@sY+? z;k2yd*iZXdRkKZk!)bSO44?LN30;4dzRJ^2SD;mOWG}6n6kY8Dw+3a|sVxPPO@yz9 z4^p)LhVYxr&^ML&RYAevn=ptugPjN7rc^5;^q`N{Q$L>}^3?-Ycnz-X5u2aoN+B)F zFJ$5;jU@TMHxpjW9NH+0Ko@IG*8JPEA4VE3-MQ*X_MEcoifTc@6>wHcgty0S7rp(M zF1z)Co=D?IpKR75auqY&bwIN_8bMVD6y53{JYHodkpyr!;<-N?IB#r(2!5jq$|8;s2fw8Wy+ZfL6V3pR>5~ zTvD=ni7xz(g{7|oXwtQMf>mQhT_i|;=nOQK@iCi^T)o4`Zaz5nB5UlK|s zNrbYMQ7T0YS}1F>m1U5nMIrk(g9;%_C9-GDI+g6p*k#YY87rNyY?Yx~<5y;z`HBvk^xG!qOwoXoNVrdEyG z#SfT-n4Cs9sS$p^I;&bJ{@SmlOb!yHomhXF)RIhM3*-_Er>Op_(m zu_b$VTiMmEj}t33dOYca65pS$BPSK!^ZC#fY}OKL+|SD5 zpLQoh!O|E28`t}u)VW%oL&!TWIXf&u0VXdkjR9JX7X}kNQeD)3+ZG4PHncPh?Vw-Z zBRO&pr5XU_VlR7sNh4wpnop3k8rrm1UkCZtFt1G={a*Kq+&Mrp<@Bww?MztcCCXNG z2l3Aj12XKmQG zu$Ty`g3`M6tv+;hYEbIJo<0Z#hVMOVK})JEpP$kJWSYw$m&0T3IdhN$lo<@rR4#;z zi_2tY{FAzc-YkK=kSbLuZrV+b6$&V8wl#jsu9N8)DF-DP2HWsFx>%Pwc(E$CzkfCF zBK%nE;CTk$a}cnqRLYG8K-d#@#5W$)S8r&jt7$npz{TD9Q7)6(eSa%jqlSy)m`RJ2 zFLzqEIOmiQWHLmmpaujfXKY#zxVXAnPBpxIm#_#WyM47wU;t$-o|Bq2k;kv-nwh-< zwXm+&y&nOtt&M_0Z03R_c}Xq>gx<72!k5vn!w7=Pcc|L8#Cc&*1|dJ+f3^CpiQuO* zF|Vl0^TeQ2n1)za2EA4z(`>J_>(e^^rTagL2xM=yrC|^wv9p|e7Sg8Pg}_??V=l1U z=v9sTC{@l!N(jz4&W@a549Jo_Y*>>huY5TY z+N;`u$wJNMBY8(p5^-WqQmO89iMFNdG?m5a#LtuxUmw6gRzUK9jX{WP>YA8@78FQp zzCX+4fF>6^zgQGVIJuwA#oc{6nYxqQJwCpo4M_*t8w5B+i_)m;Q0kO650HZov zQ#%lxD-CVcIyWmh8LP@!?MfAw8DBgL3sHb!0nB&xOI9p!??}sS=*Vm69_~Q&&d`eh*SxDWICm0TK^l zI!O%x29n6-r%&rDkR+dmQKn&zuXu|!{Po)7CEygvtjyLwz6*>Uhw#SYVAV(j7au*h-nIG zM-{LLMSI>3S26UK=^wlAE+}*2Gt&rfqOQ0oU^yNEzz8<&WTh2jNctSjB;tXYm;|wu z`&S;HVsbK=mOeZIp}y3Fo%FU`&QzPGo+@-enV4~8Wq_X7?|xp>uR z-ugaBy2P0Hvz`@`sPdf~3l4&qUnASPWobvLr;fau8vNi^x(~t@&veU|<*Ui2^sDWn zb#Ll+;Xx`M*;DSYGFH~BFJmvxkh$5Ib^hG5+k78Ac{|@=Dps?zdNOg8NG}Ke;<710 zuSNZlJ~s4g>UM8(+vvW!kYdLeX4TD++T3286_|biDkN za=pGg8*nB0Zrw>znCSNLERS?-Kzz8@swBeMxytVamL&C-Bof5;fCLG0ffUw z@hzW_VzF;!$JVS|1`>21z|qTqHJb>!#AoLz4W0!$QKyB_uc^syWpu4wOe=BgU|cfy z)M@i`{x`+rQ`2q5YpM#k8~C4h1Ppn6ywzFl+0B^!LPRU_CZJGYMv5La7CjoYvVVL! zd}G7H{@UqqQSa5&p}UtI(^+Wa<6dphPZmF_CwcR5){mHXQrFON`Z=zSix+l-xv81) zl$&V&X`$D3AAl*Dq$pZsKFhO@y_w;=wwQanmtU_}5nee`y?k;gDgGuFmdV?ONYJrt2hkc?&R<4X_q*8EC0^UY`QNB9{fDhrw z!)@cB4kX$LG*33Hbd9G@>s9f3lleJmRisE&KVRLpH+l=t>`feKq>TnG`bT4)2lypU zrF%iQ2zE5u2{>vKOZQ)Nn*MX;N}?5FpD7e9%d{=XtU(K`tyq`@{W|hAxxU)62b9Vl z!mWfg`f$|k#@t~Cd?3YzaM*V%z@z}}u}Yt0kg<^Y{`w2ttL^gx8mHVTNmu;mLQ(Mn z(zShlblF0h0zMK9U+lHsEZS;f znaepalCmpzwQ|+;{ljCpoQVD8UwDv4z9A+DKZH<||KU9>y>#+k&hANVy{I4urtcuI z_KX%t#|Th+GBgs$eD2^+Gg&-2CwE8~D87U>Pfu+ld1&G;GjC;RidM*%MCV)5d?`=2 zV^nD|N;k)qTfsh9Zw#&vv(9xoiBLwJ_=PMZ-l6^?zW5}R%F8Zv7 z9n{j&ddIE;@&&8=>ar=e-S_n=43X@NECDKFvNAyG$4HNzPh5ktdCaEfN%=zN*Fg}3 zC*<VIETlo9zJ`B35VURPf4oLHhb^ z4i2EF)c+Q|$=8@bvRpKs0)ligTo4uxv}Wi)vO%(9Rt-`LLg5CxBqwT{QHyNX<>?CW z_vHn5BUU0D)M7KL^JsEaH8f?TW#?&23txCHc{l}wK*xc~Ow-2__v7AtKEpF5 zE0$x=x$V{nsygg3YJ$Ff-9o1hnN0F92H$2e2lWDF_d8-|WggN7tF z1f7}549>^3!&%egE-sYN{{zyqQ=w&K{{K~c`ZuMFzY=(V1UM?#Rd?0qXg}c62>7W( zvQ_Iqxy}u&stxz3{OdDqga+TIGyR4G#hkRcy!!$23_;7L26!mY`wS2;|9~ovNO4V- zI;eU5*3Qd9$CBTjwE%SoL&K7=ISNu7N6tc5k}p#ipmwk>B;mA`1jKv2MeHCb-Z> zOyR#D%(tn*?|Dvnx`iWUp%Z@J3%z#^UBq!1>Hi(xiAVyM`SXpEA0+56B@5bR(KUbC z)HV#KpF=ur)1`ryl9;ps($kaD3-6@tzes&gmxifCGa~!}e)qxOhGNz)#Qw+QQns-F z?XJjfVojieV;JyN<#gdp!2<>xPjtCQJGl zJvW|57v*31SJ#9gH0X>iUb#ys|9$Jp6st{>hXFJ}FV^EtpWpuWp2q=t^Z&6B;(vCq z|KTE5ksz{uSD0+vtOuFhWK;grK6CCn6TdPhoME5Cp@%}>n|lJC#0p6(C1S|mCwPHP z2H64yV%wljo@_&F>#iHD2>ClMU(5h-gk-N_npYaH@+%?Rb_VW8pP@4ABZ5H55a@&5 zNik|g+~$+9ETjnvLj3+Ji#bB~@5(oVA7W&Xb_(02{nV7u%hT!3UUoX+xT`S6D#iN* zWSGqDj%W-!WOEs7XoQ;0$jnh$BFN@gFwRzJlr*}yPPZYX{{x-1#$L?wuQ-g}HtH35e5C>Y9MG%EN|H2B1wW|WyF zb@ceeRlWiW!wdLO-u;oj`-}Q^M|bI_wSAWj|O}AK^NmS%r0B)?5#I@hOc0f(S9A z-}=ac3jDcF0kWrc@tx=T4S8|Ka`bSnpSkO z$-zYSTb_Lic++l#jFsH12Yo`PS);;3H|(MlMsMSBk|?^_j(9OUkCMlufu6Woo6R`` z^MeCtEzGI(v>A7TvL^vSC?t4N6w1k_zMp!eSF0kS4S=?j9_n+16MrJeOS0mC_5(?# z48v!FHhgD`v!(}6qnOf#PKn^ZJfMQvxLTCZHP!aj` zpAmpgC-b=<=R7ByF;16t=1|N%ca`$xi0f&=*VERiapHh$up)$7S-`J|tHI&$UqY=@ z6q8-!7t(Yc=gw!Gu}s!@m+EA~_jgpHpHaZ*UsC0c$=40LiYi~q_jHx){ctp{rbPJs zeqR~mF^c__)A#o>9EYOLE89oy;5gF{9FqmEC}g+`KKaK2O56Y2pxeo{bzaZ> z(~1vAWG0ONd{c8}kIRvn3aN(0`M$FM zM*3+z`Ab1TA%3)_n`dJ#bO8budtPw}X;x}X>%R#cJ(S0oP?^Y(~NLamR_&{mXD@CK!gX;tL;!d$jG6A6ho}-FheM`bLbDJJ)39$_TC}3|hM(`(7 zQ+sQBkZnvHb-fMB3k4AUGlQ22&h?OXX4Mbe@uCK$u9}rfTQnOV^^r(;{(2h?WTvV? zfHYX*vYdKthtF?V+1hhQFlC8SgFoOROWG z?*&~1zZpdUaT_bn+jPbt)CX45?%;9}JQLXJCaO&h6=6;JrGV}8sQ;%SRk#Yjqt>&^ z?3V$`dS$fSHTQ9C1kgM>Ma#aE=3o&3#~gO#JUdMt36RV03>LIxOaVC3wRa_HdsJj| zM*;>BTI} zO1>DB4bjZqkpPJk1RC(^=(XXbs;%wKO`FbB-EjZAtjNmsgQpNjO(?-eZ*lkL1WTnK ztFT10V2@D*Ad_8$hpQD)RS-WAw0`5ebAg&n=0j{(V7fsENE600%gXK~-BgKe0IS@F zW&J}p-}}eiktprqYClZ{8TA<pG)?BEYF)w$(??Dlfp{5enULU}; z=jY5oftl0J^Pn+5C&`s`^T=jB+|0CC?1janl(T#!OQ zQSXK|CQ$1%a9o-I#=Sa-Pd%(a^>e3C(N%>Jucj)u$?gWGs5*@pjrI%+U4{o=^aEp0 zzG!$&qG!P={B=&w zk&rn5ttKK1|ApFza#1OYP3dFGHB4!FD3cEIy{-3&iN1;B@8|Ad5wM6&&^D*D;aT>m*GU|L3#+7;bdt#8|dY70Jy;$T9*VF*! z$xP)O05UNt-4S45VDRTUV_{o4a()_|*1nM|ihe^AwZc#FqJwF_)a)PKbC#fRDHFca zYD8lPL53|jAoN{vbnib4;@b>5JeGG@eA?J4CAv&ATaiG9%a}z_NREF8pn<0Wdg%PG zs%>)&r|JpvT=)+&#un!+T#I@<3Vi0TNimg=x5z0XyO&@pqd4@>HYAi2v48@tJM#e8#6-hrk zJ+oL{Xb-XNQnqBjxHI>r%;7%EA@e)2h4+8djqTjkU2*Rj83_R)5{63I_MBN|w@dV| z>&?nax`3>ekUh*`!DQ|C{!Cx;00V=PTMUux@{-rr{`Ki0j#K-<+=p|Tgri@aem_U8 z%`Tb~wJIzS=$cf65!7_hCHlvR?wx$jd$z?nq;GV{;a%-K z1AUj$V`6{bz^NJO-{0MyeLu{Xj)o=Y_^6Lzkz?g31l z@0&%@pE#>isYZf+dy|%0i6X^kD{qsWt9Rfk#azbGl*K34e%@!sDKNMh-IXmq)f1Lb zqwyMjz~8RJw)jfiw$|hN`ugjl`~5xg?i4ol*HeZ;%P^h77y_fmWHhqTyqY>*A| z_3Ky0YJg%oN-0V7P3^)2VbF zVN&|BHOyW<%E07P&;N#=JEoT3Eyoq1{rrk>hP7O z6ZnmoRgJ>|B3;P0ug=c-NV?xZWQ z>dG&jI~L*nChGRQ1JLUrnuT*jma^Z{W0q`&5-j#gt*hBbNXq&pZR}2&N>DUx0)XUC zjz3f}EUNip=ooUsdK}RnU==%ivF;b#4MQf@gNR=X;a)6D$If)gC!**AQRE+IFM|;N z@@ff-pOO2IK`P}@0=|xIetWUndjTa&o!W!nM8WJQ2y(I1w*@Q-9g(h1MqDYA2IJXV z2ON*!r#~MU*nW=7G~Y{ii;FTmdy9_~r8kfy~_+Sn_*iWC{Cm`X@*TYr|Nbm2^hrod<0lFN_HLl)EoXnBlF6xBPQyykFRbb^aJ zw^LSMFyZ>qKxYA>EOWU1&aZ^+(Cav(LAGS$U?}3jm z+Jn3~xCXGT-aDIGGj_~*%o|yoHSmImfxe6V?jU$!T25RW&%DU{S+2IAZTUjMB9@)Ubwd6`}o$65L2oV#K@ zglbx_?m8FqaB4KIn_IC3^L;nB0iDP7 z1ioD*bZPKmP8_|#j){rM9$P=_u=@UBieJIfM9glqzqcL)xM9EprvSARY!MizfKJ8$ z2Fd1WR{N_UP^YEV-d`+t&o1uQgENSkO=<4?=!Mrr)TmdvZK^#BHME) z^la2Bpk3vna}x}{F}Kmjv^Y&hPHxWIAwnTeJ2c3)@z+TwI9(|6)qkPu_&u@oR2N4Sn$8ORCPeuhT$ghyLlN|^(gwJ&$6f$sB0 z3rKszeCka2EQKmpkxYaU=9Va3uFRT|+FAK?UnFS@*WYPm3@c)gE;jPzEekq}Cr>)J zZ{7d5VcH0W>6eTQrdkW`1(%T!dS0lxX>{e0T^aw~)8;Bbe6Q(p*&7&2CqPMr)YLv> z$#4xWB+^X+{e+t&z$~Z-`KD+hodrm^-z4qUd`^IOF-CzrLFOQl{RqEN!4mXN1=*mV z<^y=kO)6TjAnjrt-Zie%O?&SF%QNvV zWH*!H@6^v&2DDcaCYQissR>B7IxY>IuHR8Yv8#i7a`)UXWv>CCIc{-Y(|ogvfl|jG z^zov*_X?Q==H=M)L@T=Em_w_@61DGnd5y%p^80(H0|&C7 zE|#?#VzD;W2$~Q81gC8nO<#I9h8(PZ%=kBZj=YD@eHiey&|}StW_5}XTG#ZC_%~Ud zsYeOrm6Y&;N2~{U0OxlR5fS%XTn;R_lw0rot1rzWo}=$IbAt8=Fw;U&<2IAKcZJ>& zTQ)Y%NyDp6Hvq~Qv{5p|aQy7Ka|aF!2sG~C=GK5Op9V3{z&)VBJioHixUund@a{id zTuUm56T0RHs5OD_-W`(asqosA1So-LTuOKds%k3^B{11~Ek*c>+s?X8*X_tDPRNxX zj>Fr8D1Vx3+I>;{^;mg^lL1gjsVDAafq7Mk^R|}7)2BTvMrGGs898F5VDD}ocSW*i z7tKzWK+_{{jz<_v&g91b+uH;7>(4sP`0M?BG>JUgHR=@v@ZjC~cKBt7`JG?!D85nX zFqEK8*MyjC?3i6Xw(*0BRW+4;YCwLoRyFIyT`QxsmlPUKW zNsWuz$T#>5E z;6+v6KVtp@;Z5Eis3jPEr8+ACcbRk6g1^~W*5c*!M-B!D6o?xN^aGnKbddS6J~qfa zW-#LZxrf>nKtQYJXi&QxwNqQj5*Kk}%VCjGIGliez0A_?H9APuzJyRYcch3E{Il99 z2bm}6NZL*x#HjT4!>6!NPDJ%?YSLhWtZ|r*g~vRP&t7vy?0@D-Cb(kU11R>+y$ktQAH|Y$ZU-WYaPhj zoonC*1fIo3D0nAeZwbE9WIgoh(T@!dX-GKIjbBrIHDY*C@YZsWDf(Nbg6t};8@`zz zye#~_Hs;|*iR;yh)bEzs)6-5aPZqBpd9cK?ihHu$N)CFAPz=FG&E~)$ZA(Y%GJcTv z#Z!ap2-wy>WQ-O1C&B&6;&X(dT6x>pcIyO1!QD+&usdoZ;~T1+qKzJ+uGsewq(-QV zUR#GP?34(=BM1+D*{%SaWVMx@j*=vW`@OMyGtgw4tdpcAT&c87j7UD}gjW+KhV~;x zUphvpqSFZ?mdt(uc#knJ=|;gb3>G#B>&0Z<ov6l;JJAszmOSbRb&tsl4PNg zQ<&kGc=a*%rVJwZD1=<>NtoGLp~CF=X45dPkdseTthrpki#~OFlT8TQetXiL@u<0A zF(+kfXVnYGu8BsH93$#6BE#@JiedoWK;WRJso~x9zrokZ6jrMH?g{4Q_O_RI+=2bwhrFi%; z#Up?$!fb12hdUUi`mgWn}h)tu%{b^NYB zOTX}Eza#a(X@2Yf!2wfDm;w+)8V~&TGFh(kUsf&|i!dq?4r#Okz!p`R!>0&IF7mGy z79PM2|5h+S$S#5hLttj2(5jIg^Iwk3sQ?WjtMPJI<7ywz&h@o5r?BvF;Y972Fz!b$ z{u<>hWHr&uwNCKJ5q9wD6p--5)A)@mBj=ZB@;X4Q$qM+u4x{pa++`LB7l1E$6K4yl z(Yv`-@=vK;oJ?=Eg_lvhtZVg52=%}ln_~q zIJe8Abou`$bH8<&KI0#Y?{ENlEpheyO6fk%;`+3;O?-`I!uU5nR?sydC$C*-tX(L;K?0t}UVgOFUf@7QC?r5XY zlqmUZs(C!jQYxl>6Ful7q-R2wT6~UL8g(9#1sLT>nJnRTo{Mu;DJg;-OIXaHgVutB zD%BW$K6+)a_#r4d3?P+}CNWEx+##A}pjtK}u5Aut20ozkMMe%9OvCc7!1BI>k8()f z0u(b`1;vIzX0B5Z!py}vt4U5zL3_*CNsgmRDQB}ykg1b;o)q=kjCIm$M?xZt=^W=b zceKc4&Xgo zuBxLscZlP)&z^P6VRG*@SJgggp(HXbLY;`Yp_|yx7+_Z+%7Yz!@tlfwW#WFx?jj|m za@v~(;XWF@A5AF^cQJAk<5>y0t8iR`QZL_AaR4yov4+b*@9AzYVngn-SPqXOeJ+RJ zj~U)8`pU(5XH)(oHR@t&MVt%S`=`5r-=*8%A$hsA>H6kHm~KY;n(`yBHXQ;8a%E`e z+hRT6j`=0p`Bf9$CAV@5(7niX&c)=&IroXh6H3Qo%E`UhRl%1U%%@Mr+4Iv6LmRMu+hK zZiWINgnj}o1fSYlAZyXv+j{~I|7^tsYK{-FkBbnl`UIgb8We8>fW)ziO6zvldc zg3a^u;#UJ_K`@+zVkPtw<1aC&|B2ARYKO@pm0OtA_>)k)GA&$H+WE-?Y?Ku(*k*)m zr%*OkEN{@x=5W58n#Rx5}7K6H1##^R*#De!zjNUP0c&w@*fEaN}naEPUN zV4Y=yo<#aDo#RCVKBTP|2lTRuz-o;l5+BVQ&HY~(#CI!c*Z+o*754-BzD^Hsm|#9# zN~8}X*M!D*3@gsp?>XG0dvV#5IS^5VsA;dEv*kAC{O9Hu51vkCy+?7o$xxUCOTo+rMe z2B59q+xh>gfnf!_KG0F!$^y6TTw});>Gr<$M^f`80+{KRI7&GRE( z2?#bylrUxA%T1Um%MyB20iDZXTn61HPU?VpuFNsP zFBkzl&$YQs?ewUA}b>QDkZ`+>m_Bjw0f8)pZ9k$7%fiEkX?!aR6CTP6$zp!eig0 zQ^;9KbqR#^Hf+H~9vd?pHozK%vS=nwvjnV9}(Xvq@T_!vqQ%%l@ z>Kr|0L!n0F4F)j_*azzb?@1K?kFjpxH+8S0K{Qy87uEhw?_T}8@2}_|bjN=-ND)PG#hX@9b5DU#yU} zGW+?_M_qkj-s}9V@dm(8bphx3&MPnArLyi@K(TiK#{<9k~$9#Bv=4J=+7yRcc^z{zb2=~5B!lrlKG9;Cg}$rK-mAQDEQ>wzk{>_OA8pzn)|`Zd zfU4Drw&=OQ(`{B#_25(|tJ;^ZXL>eo(`k)b<(b$q!^;sl%kpb|FlWh>(<4@S&-i>6 zWS^3|6x}6-0t&K{MyxJxCs9W zq*d5pA1G}*HvFdkKV4XN(?*MYMtrdnlaX%U9x@lY)0fCy z8j-b_i4#`Djm8~a;rsMdE6RLlMJs#@Ox8^GE>iJHHE-rHt*HLA2XQpIR?GI#Gnqj? znSMLJT~8xP0(@wH@PZnc{hL$EREF+#x8ZLbRo9NU`FN=0PUO?l1%{K~LDk;sa9C=G z>4~`Op-gw8FI*c~hVHl4A31O*7i}DA@Zh#}2Ss?(deuNc7+>zP@Or7M;BHZ?m-#%d zfZ-F6{{|&Q&bAn6*BvD#rSR_VTbM4$ZXj=f2kVLk2*->1A>5K~_qG{O=UcSZHM$eY z?%2zc$9<{8^kDe43`H9$Z*g~XWas!{128(}6t*UprW!+yf%;?PZG|bEwkeav6vrp9 zEfHxoV7VFWw-5+!3WA3L7v|jn10I2>;i$ICKCrb>Ti&ypHeS;jL|CN{Jad4PIBQt@ zL7}k2v~#u~VE8?wpZXfMH>rn1P6a}KNN%KQ`A*3e>*+!>BY+VTiJL5g!5gAn`tX>U0AmvpzGm`lYkkK+5c^11G2Vg@ZnT{UkPm+RjlGWcze)^6 z={sj0Y33%WK1Qh(?cDJ8QqtWbmDs|rm~ZzDc*Uvgpb0o(ct zoUx3{!+dk<%Roi27FNA|j8cq*K_+Q(JB*ckm0NcJZju>dyt-V7FY*3$YnG*N0K-M~ z#-bw}Y?IVLv(~&Xcx{azJRWDA*mkqZ{CMYN+eAd$-kAVsO`|#pkfNx-&LcZb>{2?Fx0Yt8p07@yTv22JkO%56FRr0MZ;*Qt+gM?ZmYfN08T z?$-R|h3G_WZS5%s;`VfdY!^gk?vcRwIEd@CFXK2slhJyxlw!bfg|Dqvb`&FdbH&^ zzy@>vlwZVCotwKlLPvt*7J$Gg1j0q?h0V0fr6FqzyR4$pZWnV<1MHIX%P7}&1Sdem zXunAfg8Dv3ZmT$v39hHi%Fj96WqT2T%FfOnX`*vBH+y?I{wi>dkXgKf@+`;dQ_96l z=8w33P_bU|l(yOIufN#G@SgW%gd9Fs7^+{Oq!Zza2ock;TQGuG&k*2J6mClK|Z!HaRnn)3+@2FW?sDNau|fK+KC8N{c)DOs+zR@!ZPu-A(thO(fcEcDEotR1*W&{zXm|x*Xz<`PW)f3 zy&5`<2?kqQ2>^W)Z?|tRC5&s0^6PcS&I~2Wl5bOuC%g?&=7~5*JxM&hA1D$ZJb3a@ zC?6;#fjsR99s5H2H+Ksaam+WPuy0kBlxbT|kJ2YrQ9cO^wrgALxv2wJi$baSR18hrPG_M!2p% zKes0?lg~1uAYD5{@5D1`3RvANvtTH`WLrU26DkY3OL?g&Sw>cfAl*W#FLzyi+_Z^$ z+|T{$`WcV!?Mfh1xzVphOZulgbURT&ZC@fL*%6x)y#j;3U)uD8WBj{953nAwt#c#U?_@A!G%G zd?_6RyuUqj!FTx-FtXmyQdLJ&k`d^o6Q3|)#6HaxmS?9!&(*JVl(HRv>Uhu(VDg?1 z2JJcKLq~Pj+ZgmmtND`Y4xC~jYXMr%T#Wx=mgRarhiYtJ*fC{pU|?iagOU1UY`dF0 zJ@>fMSR%YzIXXU3^ZzcE0|DUwO|G5A`kDfL3c#+uXK&9z(+SHTJg+578e;uhKcY0Pg0T4k zuzl|C6{nqRvDvmWAGc^a;Lkm-T?5rCgtS@t&%0ow56LCZ^T{X{q(oCw(`BmmKg-k4 zWRNQIUUgoZx(0SIET762So19TxTUZFc0C&#JIaj2*9V}qG&TE{L3jNA7XK*xEF|{? zzRY7y7?5)y=WAnlDOSOqZc(zcK30X7Hd9}I)kFT|;C^XMVk_kMLb^>|(rP=cF6yVi zJku`-A)HmD50c&6dUg=0h)?{kgOuG7vHL2~EdHxr_t>|$%mdV|>hGuu}rZ&h&;!tD1vXO~N9!r1XgC>Nu<&KwGO z2-77~g`kk$a~<=Gi|gt2UPZMrH<2e~AZINhePibyLDC6~?Y|5JAlcVlXU%4mB7f~* zp~Ec8gv})YzkV?Bbw4{34Cu)fH2u(9fd+o-H1odNK1g_l>qW5>mKu`TE?OshfX-!j zR#VhY5_sL_*lbZUQ~a)_caB6guxAI7SGi9aYKqj#qs#o|N2s34-AWdND7c!M8cP8j z9sZ(O?-I_9CaaATzYaQT^-|mMdU!A(8CroM6(emXDX*2GS0w(=fI7L#;$qfyM<@<* zZBq8k8A~nRV;VmUb%t71^TAF)K#O$_2g*GtY;^o&RwUe`u`+pgQ#5Y0#4zJd7UfKe zm;#9+@N7I*`PW6>&b8u%zWpRt^N=ClZ<-OURC$oqch(w0SwhW_pjZ>p7kTEBCFud^>f`1$#9sYh`Gzu(Eb5TYL& zkof=*mY`Ze%BRUkz;!1b$TKJZUW87`Lm0j!jwgb_F{mHAGqt-m&1TyA&B=<=?4UFL z8OGZfi+n<}29Xc5bJ)Igo%wd9F7&m&ifC%57A^6pcN$;;29LF@JUUUa6g|J>y0UNQ z_xX2eHF`i42z&L47F1o!0v(3>BDuTAz;h23dV%-#bE2=i!BOtmhyQ$OUyZl}8W=sS@~b zQB#65&Msq45C}Pi{}V$m6>HBI9`3j?-d_Hm z?{F&09z$ohSndD)%Kon1`M*w!>si7m>e0uCLZPmi(L2ua<-g1hpY(O+8jNx1z~Q7- zRafKgUHto1`=zsrVU}t8*ylgowH*pRm$+(bM9Qkxnd~ zj-|fhZO2p1ifXaDsHbt0=cPt#@(riqIL&yyX|j#H4~{>IQt6TdWk_2X5j0ks*SGcG zr5E??66EX+R4CqSgnJEo-*WMmk!Gc253!!pHGXh=kH+!jMe^G z;3II;_D+@9$Q$DbGls{7gEhh?e5;Fb6!}OnH&Vr(<;T~?{kFPq4z>*zwvoK<^VBW~i{)>8CWCr+*{g&@L`0%s)h|5YHsYd7Vd)Kn!*cVHeSe=G zxBR*gHrwMD3$i@^<31_F@5d$6>5wVbsF>?LAG{RO$H-8#vCU?ds_c1%GDUiNr&qIGF+QHbo({8dw=hhZp0D-(LN&#rycpPZ)A_jLol#~TBt3Q` zWkSGF8BKnnFYdbTX={+X)k(?{hfu88B$;Dtv|EOzQs@ssb_#I=*>jY_fLCd}V+~?LD)<2tksncd=))vtn zcf}e!&XuBKke^&z*0rRK=`)Zuv!TPT38R$)_>-~%D#aA7eX-#MD}DMv;Zz&zyot7Y zjuTTO1D-TRd12J_c+zvy`ic7fprAirt0|=F1?l6W>F&K$gAG0C983)Gd`a8KL(OL% zZg8`(&Bo-D7rWHdM^}CYo^W`JN-KAJHXF5m)$bJBHF`H@^~!FGxup4;-q*d0mOssC z`IaOE$wKeceI+YbqLQ!JUSETYrK5>C484>z+mjEWDb1FYiAL`>dUc6XDdp zNuXahDSc^epXpbeaCNKTq95vclZ>Cn+il5|&_cm=&C}!VL>8!q`*VTKkP7Pu&l|=` zrj}e9vs2K`Uth0LhO-~13To`_42qIFQ`oOv@+y{E*4}ow9)P@R6(h60ad_#-&Sh(< zV)q!;Rl15gUF|uspczqgV-8*|gFv_->MF`lUS(`H!M!dYHW7)}&R?C_xvxgicwH~z z`ui$94JCBdhvSVXp)li;y^G%rhNV=L>WtU4u@kH+W!O>YuU}8d$ehQ=L{J7oS?0Ho z(;D*WW+RmnpO132=P-Cs#Br&S{_&T~f=Y>}W@gT0W@a_W4Rpx_`1tzRaG+Cnj6*X9d$qa?T@e|qqexUGUHzeXuGnr-G z_S=4mHi%kO|ATOuQ*7*&K?@0jb|=Zzf4|b?Fufb{yRf(SJEz}MZiVG1lmZ5b$Ajq7 zEYNxP$PXlXcduQU)Z|e%jGNL5V^Ru;;Ca(#Wul+`^gnm0xqU-1S=W)ovQ4KFgSDWl z+!tl4izxQKtLWu26o24Td~!q|*|liLf+XdNBa!tmP23n8`KiP3auj{}0K1|4HVZad zydUs1JR6gnq(3q~P6m;3nSO`C_#c{CEp|pZ$TaRaHccX@cd}}UD)ICX6uJ~mEV?;> zJKbkL&NqSKZCj9s^q0|l`Fg3czg!W+*x;i}>a}G?iJ(1|Lq#eaMJCCR%Ynp{4c=jwf+z$Qm>58#~HR}AgX^{cwDaJ|+HiE7k>jOHz z7q=Mvm?hg3ucM4Wz`#B2LRtzJKAl;hFCTyXC09K&Fpoa`$FNvJRKSVYmR88Svs*%5 z|G!$M|JHyZ-=&COu#_`v_k)y->v`(m@+*i)CD6WMC<()l-j8C$>0ZT)_tf0n7p`)t z#V;x8Pb*LJbpPqL>)tt2;r-4iw#TrTf9bz{2v4nX3*=&i$`WWta_wRoi5IB=)lztS z*^RD{ddVv4w{0b*$KTEMT|}(#m+q-CfL8VNSh7J&z%aZ3)&Ql+qB_lcjqdywZ+uy? z$t4)>tw0V?^Nx0G)x5FOM)Dh=`)-0K5h~ngrg7jlleK$-K+H`|@?Q&i?PZ|pBQe1x zU&{Buu+o=6IlJd-kOdUn<1dt3Uj`?(@Uu@MQ%O8HoPn^w)%v?T7Tp^e?A>|Ez6{8d z{DyTD&po};ji$W}tS6@_Trsg#6H%+Kb-@l}%oX2E7R%a~VjpbncO`>X@k1ylUX+)O zoQLkcIYWfXOOdpIy;e@Tw_!eS{>)y06yKa`t9DUWqG6zGSS&uDPkGO{G9+f$TJ*UV z3uY_~dgc^b4_EKA;Evd?my$+bW45l~Z_Oj+g6fm9^VaHzayakg;`@45%D_xkw!O}E z<~XTJ{rK$5QBRuDt!@{aVDon`Ib1kXcr&7X_uK?=;1}{6IoIqV#psP9wU@!YpU78(AYZb{Kikfi*YAho$pox8qqo_l2 z+%)0j(F9!n+V1O%CH{Swu$A_^E)>uST#0q?0b4LfDS>uUNiBg~?G$E*f}Y(aDY7=5C+s5dA?)OYs}31|e0Kttr)ZdoDy&oZrf#a}zm{+C%MD zTra-Pr=ITZT73ncoQtFjq+ ziSK~u-f9|2_vtOs;*kQGZs&v66r>SX>7Y4<^+Cgw!9Dv@QpU6dIAhxUx*1cVP4ZME zM)&PhzgJIb?aVBt_$gjBK(bQ9?>TgHC8?GLAM{E;Tnpy+G{>`gV$rgnB-X$-=xI|< z(X<6$0&>miSD)DOeaQ2JhLn`g8ygQ?++0tY(C6b0`Ye>-l)oZ-=98e7LsH|ZhV(Aj zs(!C!w*V6fT19zdSXd%^HWdu-f&D=^WZ|m8t78}Xmppjpt?(PzFjUWcm-C(JJ+@-_ zmXPIiXC-3T&0_%n^ZhibsKGYb%j1~X%R$F+CFR4`!5IYcmB;_|faGJ!G0C1BS>ihV z+6s$dJ(=zptx8?R)bl(K9z4I9EScmU+b6tVEkWGI@|y9#hAy2D@ubnb2;NaVqTKD? z+HvT5E@limh~PkNY?z%_(#B$8o*T7}lUXk)fBn!IoP_2NW~@cIR6*ZY;}6@Kt=7eK z*D>T1LihO^>wC>3Eiz-7Lj9ROmd}bfU9nCKFgS+!dER`>Y%R8jU4AOCvfQuQ>_l`) zY16`EpK^vzExhuL@v{NW!1~wP@xm?9AShS<)Qc)Mi%PM5T$OM5(RbHS&XnVIx$BPN z`VmF3a-jWJoY~~&W?P9O<_fTs8wDFkR|M%e0&!v%?L<)Fw>y@7ZhN@;_u}+OW_E{m zj%h%dRQ^3#cPJ@7Gn-`bLkvNBmS)oL6~7&@+AvF$O|Q!g4eJhcPXe`hEm5##k7Sk# zSadbT$6mgnNA+7NS6_e^DmFIL$NrI;JIc(ax&CHJy6%WXY=%79Q8~kbwCA8D(qz!5@u4}jBNy+M*# zr0xs;GoWhqXz*VSEp`~UDQYFBLD=M**G9>^WRRKAJDDWRsQ)aZ|z zT(uiTQZAu$+KGPGt=8>#x?_r7)bi25mW*4p0X<`%ENtc=TV`D2lDS9> zd46bnAsG18av$5$nTUX<`vdvquO2X@$XJLPBc^!Nm1-<_x!;hdqEM)!#oK1}Pke4r z-&BQ<@rf??j_yd`#Jjr0>RRu<=Mwh(@mV74jv+6Pv`gLc6^mn67`Ez(fx!!8b5LGq z5ATahFA?APM7KhuhIOVR^HKwEMH-O1r$$mVgbd_7h`crxS7d?sG(~Y!;MT2Md)>q) zbdav-{`M6OhFBrS9C8vJ+vo55Td2dUYH1*7%*3P3{yiT)=PNeu)5sT7it3O< zb05Z3%ht`~u99DT^!H=m8_2fAL#71is?K0>aWRU;-cjP*L6B>d>ctq9CAYh`*V1h^ zZFnmCD;Hlqxq=Wirs`Q7Ze$_#YJ9*k@7jmr#x2=;L~Kndezr4h+9x zAy=J=-I9KeIaoL9ny7MQ#O2?xstE7(Gp|r z!zLb5%HrVQpj8^_6k;QMRXat~2x7UnlVC_B+fW|N!9HB9N@x?(b#0I5)f6jh&0vL5BZb(Ft@6TNm5cWZ`Kt|_e2C&yDOYejD4<;oLc$V zNyM2t%Rt* zr@LSNk=f$-kkN>%;kHq^im-@?G_JU!V)zKxcM{<5PYXXEcCQ3m^$z>MC~XZ1Z~BYZ znEOo532`gPCEIs!a9exJ{_&Vo^6r5H)r!!!Rs%Zkx%Ng@uWKl!zDCw3Po8Aw=91OS z`WNC(7Gq3q<;D>~oF{p>{RVk^96?a+E?X5QHl}yy?1Ii8Oi+sKwAoYQNxai}XkZ6* z-%3jdZfYie>?w!qIM0x>U7`iSOp^DKWwUPPt0$z>ka z+|)bVHxd@$`aio1GY?Bm>mDUjYBCJG8>Euo4%x}u>2FK-%^nH5y=nA>Cr*o(fj;d zrKDr9Z_u5(^Yu#9kZP#{PI$PDC1=@eyLS7K`;>Fdd`k#fIHK6Ri8V&y=;N{c6s@wRo~1Q`hmcY)U40y5m8@Hh`WJ-)T_9&>s38Tze~5W(JOm3H8qQe zd*gq0u$zlg@C!-}70PM>0dnS9yRw5cN{qG^C%CYaDNUp%t1ou;Jc%gvt;@F+&KET| z&+g1<56R#KG!++o$0G0cfd0Q+-t^pCdZy))nenPgn&mNy|3#2@6(&u-j_J|w(u?Wx zEI)onAi*fKK25(zp;Fuo*hTAH&D#}KwH3{!?o<46$mxXGnT1b&VR+JZkuy2@ut&83nQ$=@Y&TZ{L<*O=WN zl5Lh;Y@wF6Ao9@T%32lSLkt^C{FVFHr+2WaB;|%z@IB{C>Q>S!O9QRbdA=RIdU?_#jgdQWba zDjT)Tn9}fDZ^XVCEvbX zJTp&%%CUc#EMZ8ay1}c!;PR-43cQcyQD-+dGs_&Ic`9@DX3e|Ol9JBW*Hn*J_}{0$ zR5zYGsi(iUL&hUZLKZ$HYPvHd7(HV^V; zYcjCl7{_<--C7=OvTb|Dne7Gii8J&Xw0mxh$=qgV`EIMIt4Cm9J9DjH(BR*buE&FP<2TgLlM5;jzKBr>pK@ss+H!TF;)G$N^n~$8 zlN;4YC#A)ez4M{LkMngt1Dgr-SjOV%=$}6!pYOjl?r%BSlGd#6jWJ-k`mbJLdK0!4 z*kq`bVAtL`Iyk&hqJ3nAYfR_b& z@X-cQ;PoQo-T&B{C!$?)kJrVO%}lwSnJO*wT7Oh$?8#Xgggr`yT`geLeIfD; znnj^%YGw0HU{MpFf=I8srigsaDe`f;21lp(!;F$)&0FIfbB(yb>9&C(05aM1q-!)<2eBSxR z&fCxTnXj+tzvdKAX*r$|{8h|FttLT5vf@Iz_Jr}t4-5+=t}!Pzlxw*nVL1pq{#*Dq zyx#I1Lp;l!Tir4<#QfnI2=y90Y44mDF_@lm~vn@uh7t%X&Uq7$^Q?l9bYhXpi;pXPPz*VXFr!7d0*Wombd zt^0ZvQ4h~iN`=HV{w!{me8ccODX{k3hr3{U0G0-1tfubkGcZei^X0kk^n>2xX11r* zO9<=?+9{uRoxU27ooc&!qS}_@X1iTQ|TES_eoMNiRwZ@y_3-s?9^U@JE zNuJyj71r3f-C9~$7zx7w(9Mwag|F5_JYsL$iVWTLJWF^qNaN?af-V(q&zjd4L5G%w@(h02i{%0u>la!q zZXVbI$9wT<&A}>Vi@egvzzX>nowO$VdUT|Kq({h%m0F10Hm+179MvE$K(2~%)wGT7 z%(s#7gcev3_ELZi_tF^_y!(g#x6W7u>=;LJC_r0yGIKE*W{ZoAzIHadE`N#qkM&-5 zmCl?(v6~e#+5v4Bq~}}-E3P~9Z#jnm^CPpDCeR%TDIzY52x*tDuKmfC;e5vokZVd} zV)mCWDt+9CM@P@WGB^Z(b=zA~&ye>Mv!4cLZPLL%7ik9PBISDY7dLgVe&S&9cq4+5 zKORGbM68tEXMcF7TK-s~&gfInkx^nw%8SjvKTu_DZ|Mtdt5gvRpf|Pi;cRR9NJe5& zzm9}74y>ny?lL{zrcgMC9iBvy=`E{PwTjR4sg)Nzdv5Qm31k}e9(u168GpfXD?`F zo(p`XUQSG4mlI`bae;hQJb{+(!q;9SbQX!2?4KGhSu@=Vri7+r#l zgS^8By<;xo6sL=vg|P|RvfvEqw5G)S=BRA->0poZNk!Hp^~|^HE!@$wnV2c;^77xw z{LM@4wCzQ;`v>b{7p$|h3I!%0}eOo3{ZGrYdA+CL!RhaFN; zOZaB1V^fo%g;}P%DdYs2L%o)!Rer~9PN{7ke%fPEhVH>;Kk+%#oWMUTQOZRIfiV;W zE~mnFY8& z5izAyocYUOvC}5d{H{-L^P|9iwMzRFbOXuz?PNqh)%xG1wi zj7a?D^KyTq)3cYDllZqFKg|%<_bM7gVks@UNXNK=aFrJ)G!8(t(o#>dpDuERyaK8fG^rSz;gBhf-h);|nOj zKC}&G0ZR+hi>~LtVy{DjCnsO8tqE)$qbc8r@cMr6@CcAtCOYg%Ji}pVV;K*QjwWRx z!xoK%&|i?cAj{k=SOsW%;{m0>V}8^BTDxNSKZh>IB;BTE?bh=^r72*ZqfcLbn*@pu zJ3XAZ)^hTmGj}(bK$bn4zPnz*vW`<-lvzNueL-5vKg7XA5Rqr&yBIG5nhyY`^-Ffw zc96l)>9F@tg}@V0jlzVUl`7(WdR*!lQCGo`n2M7Qm>1DrN(QK3th?u!kAmgwt&>xX zc(dk4SI){5dv?XZS}y#$aOSh{4P;cA=gwC|E#3iA=`tg0wLbJ!2D;fFNgKPTvgcHr zbTb?JmyjvvORA=rJNn|7L-1fYE1lSrhQ0tvb02-$r#>vXIrWxNdOG;bCvo9*B-0HQ zPKGRSgfFyud0c9zTO;2dM_=x~eYQHEROuiA4jEADAvA)R;n`0DxrVy?{`%L~V$mC_ z3=+Vh1s?o)cvaR*KoPTcqq4H{%k;cK-9{-)9<%P-1t%R)oQjqBG#f*DgvGb}U|!Gb z+LQK3Qr|+>-r4HSbRl&l7%w!J|FojR*<4!sGv!8Y$S~{2LrBQw$}EPOJDX%*$YpI{`#D)Lgy8h;1``rBsnWe5 z-6%O2A_eIrGi{@`o?Y2`=G(6YT@Ekbm-dIebaoaBr+ZSg$?~6C0QT=N_|b&z1$t@_ zXtaM|5#L!!cg?A&V2tNURV@6R1#2J_%lSTkX3KB>y+rsf^tyR$HRD0O_r{P*kp@F$ zA$mf~B^TP_&mR18zg}CabezPn-lL8sm_>n{NsSzu-vDi0ck$&2cUZAX29Apg0aj>o z@)Q68cH&qjKnh63A`w04b(iO-x5~6g;tf7tP^xxCMkDdtzR^k2<1Jk`5u?F9CD3$f z6UfTQ9-E}+;X&o%TAYpLEzv8TeLtSzHCA;6fk~PKpivjWNT8rV@wYqg5$tyWpcBiS z5Jf>6T#WA|H$idR=hBnd%LpBVq$Rzmz zS^5X9J~XFN>WXHskT0I;CBq+p{NhdXH(oXL15{_ovQ6+$@7#X?j{ zm4Pt_pXCnQ9sg(5f|~@Sek~{Rwy!a782twHZyDkB1@LqEIbNLX|B`lm==$a)bs$ic zkVQPr%BdwQZN5J)hi-g)xo4TLh-le{p_c+bkKY{*Kz{KkC@7#fxi6n%S{9oOJLGgS zB({cwpL0J5+6uJZfEwJ3y?(zu`ZysAM~);Cj;$eggD?^teoGf0K2yDYC1JHUHDOr7 zq}oXt#L><~KrOz+5C2*n$Pxh%it9?Gb%xaCa}&b%!L5MjyRAJnHnyV1UPdq?77<~F z#LhB8f)#!hj!!=q%%`39#(p?&{$zL2zU!u-AQ{9Ijz5G18<_ibJW=i&93Fm6Mn$(I zAH_(^B1S%(r>)8AGuJ|*^-+|>+uPf)&VzTQFFjxO{^wZP**7$dPS~@)Rc_iO3tm2F zMZleQ8?cn6{ItebfS2RT2#>A6QOM6i_+ygT(DK;zyFQzS!W9({^19v5Z&4C38>NeT zJtDrFG0B1&GMC{3mqU-VmcQkH`sq2K@Ro|>Rm+b=o{g--ESfQd@7Z`XQWMcd#OdER zAsYNbf`VYgZK%=0i;*3A1_rAt6OUf4q}q-|=|$8J?`}7s>mN~eaGnbr92rS0zm8GX z*1iBd@}J4ca}agg>pDL%ws^Ky@O9SLFhgSWSt{-g+rhzsXOJH~}AH!O=&y7}Xl$!Rx z!p<{ygP;mNB)Ua8Hawi`f>TA1MOc^BPoJ6-Qwgy}MDh+(B7{gRf{(%VHjoi`cy|;- zdRp4j_50zLzzf}EQ!+9#nl#7@W07>YtQy5??eMx=ia^0^3gOacNj0}g=4Y{-IN`WE;Q6l_&wqTpb}r0g`%kkk+8hwK zr;9Pr&Qx*R5kK4eP#6%qsmaN~KYvIdAE9u?=Hn)`b>_hOaQ;(-kDtf#!TRvu24C0y zVUjZW%w!>x>Mt|dT``^b<_8+dvi1Bl7K)n^ga1cy}U{nn!`owNtbT_8PggEJ! zz8hdf4A-{QAc16;l<2IXQ1PBkw9fq*GFN3hz6}2TD?ra7e>dO0YH@sYl*YB`Fj?N| zuc-IOBTqh%@_5tPscO_9UnlnR7emj*Lr`V&BM9r$&cQ5 zVH1Ms6r5xXK?;O>0KD2Htv2Rf5gdOu=DHHN$Odx9s=&5CL;w8eru2nc_eH%s)!g#FhO*S0p^+A~y!Zf%qzKJCufvC7%4T6a2+XZ;|c zU*Lg7LE8pOr*+az`lY&09ol|}2eDJt5o%m!98Ugqb5j5MQ@kh9wS;b(K(w7a+QbYO zg9;v^={O?gFe{z}wYAkTDvt`IZ~l1opL8555!Xh`tCqvD2B^qYq<<86sSG1G$0G zr3vo;q!2mZ_LdBy^GW_&H3?};G`rl$L2~FH(J;W~Sz(X1JOFzqi+0LT2)Hu2yMaQD zNPLN(975!?<(*XZBnZByyind~H3RsIlhXmXi@oudeBxo8;OeIUm;T{@%;uSKD1r-K zcEE3pBW5rI*7yK3Vt7z6umGb28ss+1Rxj5A=pxFMCQohd$(`wfZkA$Z0^1sz;!~tS zjEDLx0gu%;GmH9%9m~4w&V7VNx?&X>0MB1gP*CN8;t{(i)KvOfVGaZU*$67U7zzNx1jTc?FxoP&())oe6)V!+qGuAt8=wrb)uza#o4>=Cb(zsWkDw6#)Iu3L>gH;QgIuD&Jq0DuM$zaqWKs z1kpfNc|eJ6R908>Nxtn|bO+^v4?j7pzzJA&s}@>NBw5=6Tz46;iojjA8xUuk0)qAh zt#`<*CuWR^acVq{SqOCCs$9w8`7g+3s58Xt&jaS)lPO80luEb*&!8(C}X z>+8ES&>)PL#dL$u)=y5t4wc0;L=>Db7>7FUt)2VrKft1&;apgtCwj7~#{de!;gLiIh~@rDU-QZR&kR0Wlgr(WU5O-H zGo6UOG)YZ8x_Xlumn7T1wB-|cI1EcD3JOlXZN#mcCUMjLFEEzN@$r}1pa1wU9DeUQ zNY+gl?-<_ZGl^ON=6>hbjhMgYyPCT!h@43!~KxfFiq7GEf0?_g2w{1+Zwc@6{Ul)?#fIWnT9YkN;F3{)TWbAuu( z=Eq{^HH?5w;gvt0_Kar7t^3YqNkUk~UQ*|2rzcBng6!2tQ7ckl;LALgHG0#f>6N%= zzAG$(llQ78Y^{NJxa&3-jG5`}7yU0>qNb4B7p9)TXEj-Ae;1@sCf&QcyCINq3%CMg zF3G_B$9K)o`T6|z>>o2bX#hkkAi@c&a4D^etB;8Od*2AQ1D`S_`Ul{I{i3P+JeT5L z^caIY+Z!geO}CKt5JRld+pA30v}$;v4{l@S!&y+6oL#zU;(*Ib<+YmCfp3hJKCAlx z@Z{FijMqqQ>j@-!m0bwC2Q=jjn4ICV{7?Spz*@Bd9C_of%!xgKXPQ{j;1^xdGN12s z>@IeRH%|v2qAlYE$8*Cb zf63=Ru7U+I-Gu^-gu>|hjur3x3xkcpZ<&uEF1`GEBgMJxmIgaj389LGiihrdftEx? zgp5QB>*o{1q2g6fIyQbOWOS=1-PNHKFoet$a|Mdi9B;oR3Z$oze7RJo~FyPco zw7SbBjCRedThB{h8@Pe^22n#+ex^;AcKsxhxp{e2d_ewnlAysEp-V+~O-bPLBj0wH z%~)~vHwRSY(m>T(0ciX)GD6OUCz-eaoGlVFFow%RN@cVc5J+mT*jcyjW5z%Ep(+?M zmA3LDXxrl!BcfBQvc__(mCozYReDvw+-$f9hhf|1%Lb!Gg-zoo$J=9PAbEL2BU9n- zq1W;2A0+VG7;&i(kl~+b_Hv&88J4_iB~k42a2jB`ZQKVKRguvB$Bz@7B+T;o-udmX zd&UGIUp(1ZiV!Gg z1T|8(OHpitsjoT~cL_Sx%St^bDwH`*DwnFgHShHVx2M`o1Xv5m<TQS z+YNM$1kldHK>et+Y~db<`L7Sru6Wx*ba}a$_f*+}G>Un6WP}I4_nRLgHtv__Y`M4e zo24f+!f80|8_}vQycH#t<#9BTqHedYrSp3uj+OU}JLqXXEOworEY%_GohKemY9cVB zrNI;j%<;%F+SI|9-$6mi$a!waT;1xYw)9uSkBL!m45Ol1Rkt((+2h&?OoMC?rgB-% zPu87k@E?HL8qEn+%v}Z06QIPGI?XXq!qsk)MG*A>Vf7HW+zWHuomrP24b(xv+LG1B)Ow6rHUWrVv`+nC0R zO=@h;#vJV0bWmu4KeqwS+=p9XlEey97V~qjwO}E#p9vNw+s$lM$1}Dl;zlKL_-SF_ zAz8$7mUq9*+FfEG5|^5c9I@VcHn0bxz?iM68k4kVR$vq-9U?F*d*i|yB?G#v5D*mc zdwF~Rt}_ppx9z_Mu=XQ6C#OUzdJd-^B1qx=ZVSKg_^mzEHV4RFyv6wqs6NraB1p0X z3R5U!d&eHb3wtt|?t2_1PaTUUQ@j@Ycii|J5dbml2J=Xr$F_Bfb0j*OZ0XfDqeHr{bRi`pxlKzO#PeJvPU6dftu>7mv2TJ7D&I zxvp^B|N8YSB-m&*!y!?MEmweJDdXu2p5eMz z0ahOwA3w{n+;|wR0x&+LAgc=PgF9D5Bw*0n+lb|YX;G$oo)#myS6fMC1`3Rr(96ft`yWx$y!FcTJHPnCS91_JkO{(~6vl8X6i>!f>+7 zU73O6?Nt%qu#k1%IRr6i;e!W|#BgL(-jCNl=Ia^VzWlhe03?5W_P5V;t$V>$leo(} zAK0YnfJc99F^NpH2XaJPXmnN1cgTA|r$q@>FY%blWfYO>JWzrxAdHH?J5MrSJ%cx5 zc9vRETgVkF$;9Yxz(wM$e+EE0c_@D$YiTDgDk#~_I5wcUkCk#694`%t6NSg#i^-XlMlK%;z&8eh)Tdpl;>!9GJ{aG7Zal(R*z808*r zYWe3wiMTvDWk+8D0}BQ67M6E8@6N)Gz_YO9Y*Y=veJyO&ASq+*NC$0#>DXo8(0TDF z9P9xBFs!iA9`X$X80Q$=qzlI+$U?YZzy0C4*8)2=V+^30?JsC!aB72t)Ci&dSJnG0ZV8?hPvTWto zltzkW)BioV(a_MitsSskx4I(V2d4L|as<-yJAr>xkqc7xqKmG|PqWqT<2^t#m4R5p z=q6%9+_K5SKKxNy^#KScjCMDy@cbx5W#whNZBE_VVv>)OP$j!$BlP)pCw?pugVvQHAM)5(-g8Y`6W9UbF%b2Q_E*Uh-A zkB1E?yeQYnWnTqAtd&t$-l~Cc*t7IR{3^{A%xcuvj-R782iU~{f6i=>7|hAZAq7Iw z0pem0|I+W@%Y!%>jFN@04*}P)t|$uXVo(zvAQG!_nh2#~NbEZz-0cFY^f&0b7!gmNt5*Q$5Wl zNS!8=%vFt>zn&qUp}U0SZ(ptD!R=b36xYAh{!SxFyX&6gA9*T0`-%)w<~S})%OQUi z1P~e)g08|l(&980ok9+RCH3c zi9~Sb>tsIKc-BxdkRg-c^UBdt5QKLlE6n*ge~bG0_sCu*J^zCZM1KCmPg2gTtZc-h zXhtBKTGGyw5>?1QJNmzj1``ooP5-s&3@D`J}?Iq;EJ%RfZQR` zpqooQp6h+=VUIdB4Tq7OG8%Lk0IRboRJdVNjP}}H2JjaZkT*YhQ1kQv)+93QRtR&Z zY@ykF8I0R;Oa)}m_c}GR8;L9){Y1JE8j9*x5g0q{N|DcqG#QYuT;A5ru?)jBzVZ+;pz5EJQ9Z8 z`U#AR@R~>nRWK;}RMCTt)A^!^A^-{CJ@U*z`GgYKQIhCRE~kApxTz-_zbB~EU|k~% zMc`G3jlW(+S*$k}n)c&?dq}Z!6yBwT2q2pFx&>?TM^jKUC^Xsu&{BQoAZT1h(`ZMy5&{&Tpf5^Cl-H^!hB4u@UN0GlRuHjk zxiO6b=YHQHxLZu!=e6nc3nBz1}X@d|I5oTJ+fs}w9bN% z?nKg0l8(vQR-C@XY( zK*fG3q(fTBFuPgf2K{ZHwgi!lmTfp!zHP|YFaB~?wPdkZ4xpbgXM@E>THt=h&9%8A zKK--7Xcuii4fY?#fQ>?TujL`F{~5_J8MIZvj~p_$6^Ycrp_4W>{r2F^e{ugreOUP| zLMdaxs|xNdF9hMRlwA-BBE;FT%*MtzH5IzBdmu~-nVNbN2j7~k@&E|r-e-pG#(kXu zytxqk5#DjPj6kyJJtqlDvc(`HBO`{wU69rH2_LF|tDkPFUg^{&eiX}Yn))p>WT8el z+tzbK3qkcE{^13k3YgstS?_a><0VNm)c1x?L3q2+n<`!l6y=Nn8z=P??;(PO zLPIq!bti|w1ZonOpQ-3SUR-n1{`W>LPy}Fn@oCQsNoq0nvt6aSu-OO*Fl!M0}Z*YMmP>*{MJezD|LP|oD(zG zbsu4LmRJA|yypWp;PQ}5BI)M58NVFDDlNFbxcv&ebn_$!}vs>zvOf&c7RD6U;y7F~MU61SLRT9Y?+I3fy}4zMOKt=W3m)<=Bf$l2V<423k# zR&x$y`cHcj&)0PQ@YEHA{52;|Lh)dqm#9mqHV2iDIe|-eEqzm8Z;yNIhsvN< zYfO;a#Maz1!8Drn-w@JD6{83^+HB=bF?}8Yn{mp6^mPmWJ-Kd0jgZzs1J`t6bEbJ;I3TVs0lK1^B`9 zh9a!#>MeRwx6K=mF*NPTRde$b!DkiV#UHpiVr)OvQsaX8&PR`I!8wmeAi{M^m%vb{ z9_MK(2Lv>1(drF_l$s`1rP7B1w(cyEMn*{sGBl~VEDYiVJ%KMEGCC{;Bo8}Se1HF) z!&3N6((-uxBVv#pD4Y?a;Bd*<`EtXI%OGe_MQ%vqP7 zM$k?Als+29p6xO25O9DNYkNHGXr8BXjO;F5E`{R-RV}2hLG4a0BDCC)%D)Qd+H~Q< z*p}#MI!Ur8`f<&VixSqvIm~U9{QdpKV7_cMDM-|vL3I$v44QM(sIq6(05SsbQm^7@ z9*uSM4voBM1;(b|8<8Lhd343p9@hPiPpqV%pyhDfA_fgRZm8YWg_q-Oy?%mlV0>zl z<>Mp-I}K{dBsgYv7znGIH+vN22xx+(%-Qj#U)3lx(ZsbmT%oiYvjPXZ%zvzoK9jGX zzdmJ-ug<501X1}@;N7e!=Gy75=Q~^6|8Y{4A#_Up5GfylbtJ-n6=qXr3N4z%muI=m z=R;Hc0Wq%x>a6m#QbWOphn}W;-baYzgM&Fhe4K2#!XrV7^c7>U9qzLpH6WN;0PVdC zBH_|ma!bk{_`#aKK{66W98?EuXTIRYWrI;v%Ip6knfX{wRu%#g@Lg z3KB>JpJgv^H;}X>7m)<8{ihZHX-D>ZI4N zt?bo2d-G|2;5W)F8P|^@gsfR2S6<+^&bY&@J3FY6Mz7kW5SlcLp6rV2fj&bFxSsRl z_YLC|uX>+{;#Ci0%kjs%fC2anEY%N1rSP@#EHD-jF1CUCx-&C-OvaE2&>q#21v961~5*KU&0RluX02!nX zTx$_=7!6~tN<;eqx<}bQ+@1yb{1wGJu+t0hrTJ+gy(b|{ic03#!=T{CqYW%%Vs`_Z z#p~>=0spu+vi0X1Ojr5X@wA6OOIEsqbf4|;^@uBx344jfB_9j1SNAQ=1)DCifLFMo z`l039<9yTeN<*jPC1!#M++I&D>U*K-)|(9bQ-1BVFFvHc_4InehiHm!;!I3HtPChK zegyfF7btE@Iyo~Fb%9MPyP<&%Pz!4yd{Z^NZT;!A!a9DtVbxp$*awK)>a7A=!kJzX z9>Pxk>92*NJ-2X{#6|JEk-56JTV`Q-2+})dk01W8_TD@k%J+XCo-vjz8OjpM5=9AR zN!CFLB}-*V7|K@3l0D1}k}X@5B3mg%b`oJEqR1Y~GWLDnX3Y9rqu!s-=lgwrzu)ma zp6B`VIqK**nz`?Lu6wy&*Xwn@&hxyxSB++#swAP8S-e8Lpg|B} z2(dAF{?Yy9DKviAkDD#rdL!)}T5gpzoo{5z^mH&iD^@jo9tL2@^N!EHkuX2=i^;THU1nWo9-Hno%2y#LKb5IPAwi`rB$^`s355e9bG2hGft}ioYl6 zqISu1TR1#1Zg>uTPlm8sZyXxF?RwS{dSJb=!kD-=<8?SD4;{G@I!(L{q^p>T&AuM}eFJaFlj9_?7PF&UVeC zxgZ4xyq}=^_TqnYh_1)w3(CUU*-%_|CUQw(|}|rm8szcNQ)eH ztSrm>xv^Y7(;8nNwhYj&8yRn0O|B3~@OGv8mr1LMHer32tmy6CJALm>(SU0q0CYhS z0E#bjq1;bq86$3KS<~}N(z7~_j0DkF2YbOY7K3vedEt*fu}1xcJ33M^Q8mSa!G4<0 zlc2d%myds0i~d%W>vrjG_osdWJ%fz^8LY~Bc&nUo4Km3ew-er~;Uxlo68Vw5-bhl4 z!lxtkYgj%PWtEdiKDyC3lul$YP{iwVzPI^w`mP=sjHYKR%)S#0W1Q!oe%Bw#{Qp29 z&m;ml)&Udy9Oh#T$S}u0z(lcdof1bG)I4nO0ubQqXWvkRtdm3)-?Ui-XW0+4Bms?L z2hWwvNTWSs;f;__3J0z*m;0%iCJ%8bZ!KZepvm}^N3WTJPG(yWO!2pCVFo@O_x&P3 zR!~#$2|e7-qZ^QxOemxng54h$aG2b=lTV&NoJ&7`vHcv#jiRYLVeRoWE?w~XqTZEf zm+=)WJ0~wF|LT)roh#KC%-O^OEq+~+7la3B>_M8FaqTyD;?CW>TMm-XCYKjQgbN(F zCY6Y)nLr~BaB#`bTnmHOleHwTe~q|w^Fe~n;Tee3A8~!wr5Mu<{{)Rp07*iz9Yh%Pc@M*~x-9|HJF?Fqlj$b&h|c18KB{BSp*v%aTvjr))m@1%P^8- zYsE!Gw31{$c~K+_NH>4fokSG|VuCT{?}=Tsh3m|-pp5~6xc)9@HP+bTf!F~z1{7~I zztz{uO%3)qx={^Ia1rKEc5uyKeNGvhT2F2dVmbz6gv4u-pYaQx1v&dp&dSD22mYM| z@T>T^di-P>NYp>aXNe2PPo&-{G{usFB_~B4F?=|bkU4o3ojGB_=d!){%K(>ofBu-U zf)>aeAP~b0^=p*HBi*5mtn~$zBgYXVgpV_lH^5~>dlG%Jw!?`dfF_4w*EK~rxx^UWZixzfw>mgXph?Dl8l0Dz_3fMBG{1I9F5fk^(XBz_NZgQT^P%;#aE)YTlI@N3 z7qBeDL-xZ*7eb1AhGD1Xnp=;4d>`VDnIB$p+!%yIT2tgY(qNrndx;asI&0MGXBG`< z2fV$pC1accIzH)DN72RbAy*fe+Pf?SWK{|UbqBx=JJzc=J62d@^^=SHg)xp&u7sRvn44dui{X9KlV`!jju*6#G$FvEyq1{b+RMnvhA&A=ICjekj6 zSuO%ciD9TCZ?X(_EaA4*Pk^4sfsd~5mCU=8IRf&A7pCb1!AmO#$CS@x@$_Wu%R1^w*riAD{b?ocoxhAqx)BUe$aP!sS7 zm2cos6z4n;zfHSXZwr$9yIWygu>VEVXN8{5>=d4YZUmZ)Cs5G9TSgt0Q zmsnH4Xh1?R>vjA?KeT}D6!PM!7a;@d8yv}i(^^I8ao>LtnozE_FNf*z$-=uYh`)Rd z3_T{E$wZM_lktvOigGe;j=Q63#w&3B9Xy)IKIAS9+XR|xcE2Id2uTY;jr%>9)_e4( zp9%KIaxj7mw6}EOy2XCf*qi(w= zVCBzz0i8t|qJkZ8AxpSKO)a>_WP8-BporkqL|m}2LF_B|S)00`D)ML;yc*AOe7Ai; zC&pXW_@5FE-ZXU`sZptdN5^!$>?X<8Ze9kW9nv&N?r)YH*j^r9s6rZ>h%jH=br8b_ zV+$g(=RFk&P>6w*C}7}x*Sbf_v`8Bsl{wJQU}YYWtMo zUo^Zc^6w9&ErAi*|7~jPC;atQ18Y_s&YbyeNl91xwToB#8+ zyENoJ;L6|S$50uzi{J$Myhc=_!Lu(Hx`Z=_l>4vU7-Y)AJw%(kH`?xWz>ZS>SD%HaLvJt|p%eZ*bo2q8 zKDNlgCGN31?~MO^Q5jYH-#?P`!2T~jL)+t_F99w5UvngE(a(+~V&~HUkg(sst-v{C zqFSl`|8WxZ$MbbW_HlZ+zdJml!5I7RtHz2gI0{Ugmj3I-9$>@F_YqPUfJ)=1s_blSF6F4G{aHqksVH0y(`N!AhqMw{VMMmYH;s$f<#OHpj@foo z^D1Vcd|r*|s*A0)#-EkM+%q*2VAi_rz1%Tdi2x<*n8!dR>|!V7K3O&%hvNP5S#r(` zLO{aX20ckj%n1M81L}@f_A(xI+c(wMXTH;njyw!@ysbFRy~*-LH{zn+@tKUbz6bzL9}aDIFH`hGtT2fCzRG`ZNf zv7ct(fEcCL@X{ znh|{O!A#l&O@|vG^7uO0vlD~2i_ko2V;S^I0t&7KizA_IWi9y_@n+pBw@U>DVIi5+ zocF2PSJLWg)voi&_HTP)DRi$BvK2Q|Crv{*{*_~p+chppqND^~Z5BCFCDPUu%EaEg z)(3D7T)<3v9HZFx(`VioR_?t&sZ4Kg8y%YM4$Bn-VWdkJwYV92He$dT)mnm`g7|Zjdkm_-1S0~ zqsGEaN_$cA6{M{+V65!h+S;1GGue{(PTWT@xj%bK8T^9oQf>uh*(i%n*E>k@QEM-pqB%1-t zKwX)AJ%uCT9&pBG!j5-h^JQbN1XzUXeEJ;mf#cZ5#R=o6EXTA8Poz zoKTlTMehn&TT{zj>NgD@`ZbA-Ngj5CbUN#3*HsmBVIlq|bOEj|bPS4Byl}?srCromF{o_(Zs{F^fjt9kuyN(Gx=__n&J?G_BrtUL; zb&JFz5|q%hnMql6PMUU<-1EJW-3GHAeNwrf6#^RPCS1Cvr@xnI7C6#*ajrON9PZ`)`38JUHXI9?ZCn#bWF`kR_7JapLrj~ra+vY-% z`@FX_OhQR8e&P)do|=|+B{dFy@JvFFdO0*f-dIgLAvL{wn535pU1u-=ZW6b1={klV zMz+=r$bbE2y&P!Od=I__>BZr2{pSMfy@?|t$Eb$MYF-`Bt!J_i;i8w6+Z&V^oIs0-t_fK@^#rA<8gmU8ufpp!BJ$6;zUCW7l%~)wgoLtVo8l42wu4voqccwl+K} zC@9DXOyE8Vh~`t!Z4UbYIpV{s+H=+NYe63x?<%~om3$}_yw4|izs9RQWKi{mKAV37 zTC_$;ds7#b4*A^e=t=ZD<1Z@$oR1|)B*kI#cp7nW`H0+SIq}5QWdnbsV zqSz}xHd&fi&NYwgZ0~;zS3F@Y6>;HWwqn>Z5=42M$&E$UZERXqto<->-1HLw*%j9f zSdp3-e;5$dga7C-L=-sxCHWuzFFDkI_z(YQeSPCO=(Bmjqh8~9WvgcogWL_byWdmL z(N2uuJT!lui_06d`-T7GVB?|+7j=2h>H zVUWB*-%&F`c46G?bjuwqP9PzRxV2&2&+@GRl;-G?ox3dbbiX|WMPyIAJNy_tT75Z) zVLCklWUK1hBX_W-AHKwM78Tqf-)c7aH6VJJ_XkPZuGJx)tn=1^%vzF#mUDRbnznWD80q z-W?2gtl@wBEzGx->Nz&-P{sA=md(UZ*;{*V{jTVFjehW{#Gq%yRcPc&S>Ca1p@G08 zy=&X?h5fEat7@#!=SqG*D6rE1c*oG)ZHPJP<02s-B>?@%Nm20P)AOk+dVN6%(HwzR z;tK`U)QvQpih?+^v!utw*S&$Y6-EwR=Mj`U!#EF!gKrS8ZA>WDgT!RV5};Jf06Lhf z5s4R5WOw+2TDFV6*4JaYK(7W6Gl8xG_Zj@xlS&S-*S2^@=`*5AB6gzaU+?S$M7~#} zY*xl#*B~uXi|z5?h_LD2{kagx*|TR`9ONOGckhlFYTBmKCJ%;|+LCx9TekP>=&SAP zQY^?uTVqkRPzYU#v9-_-h2U3k{2#u&Mhv02Ed`!kF@Dj|*_lwQne;80N%U*63Y-N3 z_^!GWwfK=3$h5?y)AZOGiq;lHN(!465&~6gvBIJ>RMphDW6!Uxet}PHbRe47*Y9QN zh1%mkwRR5=?}Y$iTLa+nh6{%S=ueFx^d0gp@3v)n#ugd$L?@m*XPi=$Aq0qSUfh;L z_kWC2v8SFlu0Wv3AKe|lImkOgBa`k@JR!$m5LH#xgbS~ur((s^xAPf)a*tK2qVEjo z_4}NVmA&EV$qiZUy<$8DMu68lj~)i};4wfp<6C~6N%dU~i%&)a;HCuhx zKcXnrC4g>GuWC=cUXSEJog);CI@IFq$1kDaC#M z{5cP8{QB~F)pWON4s+)3haN<&!<=StU0wEmRApo}D+jCv>OTSx)1$?v)vG`ZqNoSk zn$Mik;0V+z^Uf>BU`HC@kd2LvXYEcUju$<gU znP^8Yi~@T_z=qSgSEi8q#l;gD_vhc0a)PNhR}?z~aRH4TUNy~yct1B=@4V#ouUY$w*jaXCLi_nC6M2}tfavWc#?Ri# zjI*z8+ydzsO_bb=tG^^e59ue4RB7@7^ibL+id&MaB0k zE#uW0w<8ebY}a1_vYK|BVT=Z|6vDYeq!xV$o=vG2dkNcTL(%*l-R@|r!@ll8^sBv{8(fxpdU})K ziGN3^e5FR@o@5+KrM}W@BCM5LV;70++ej4xtmCYm1t+y$nKn6*G(D01t$U%_Vgz=# zV)UkiL(Z7tQ&(&gnXK+>q&8h|xq)PK)G{X=Y12Nw!JYwgcw$eibQ17g{ZvoSOZ~fxtdwY1ngt1N`%w!tZ6<_HVWLLyLzCyS% zsajl0eM$cL0WCy~7eNTC1gz(*EecUSGStuiUI;kUB4FqBlU8ok=ct;tB`JQS3kQOd zG09qhYvIHRZGmUxBx|t z=r3pO^m60I0m8~op6AjeR>q&)AxMeTJpanl*7oc6q1PdJu-c5tp?6}C zc|>x@#ciy3AN-kKeFr6g508>?=hO$ch!bkQ9+Lqx`z9A{PNt@1zq@Y#>=r@t)XpnO zsCtw%4Nhw%4vx?sW}Y?!&7l;-VP!v!J>(gSyhNj1@#UF{MZbGMAFf|<$K$Hic3Lq> z=EXIsYkH%btv|G?D2HLi=0nsUokO+t(~!3G3VwXu{n1>=chv^1Y^)6BNvT#rJ5GZo zD7zqt`MB|-Z9cWV-3U@#^x1yQmNUATlzvUBb!RPZsX^XkvuIOJL#`i7IaEbGBvNF9 z{=%=rXma6OYqh{p%H4&^P|=y{+PvF~OYc`W=SoYy%Sk7&chef!+IDYG|g2G5XMKHK$EK^w}480JUTN1VOu@=(~n$E|x-B7M+cLqg#BSyh2`FT>Pu| z={s_2VbQm>A7+L`xMFn`1)G4_*<*P~C1@oOSC*;E?Tf7_^K*LfG$kc`@8>QM<#*DA z7{n#)tQ-%x1_h~)tH<2dwd)^oRBu|l75Vgl&-;a>9sdmVODx5xj)Kw?12M!F`ZIZ@C4jpP* z9{%*21hoU~;LBu4aUkC97}fU{8XTpxgPaW(wnWRbm$x`{E0VzD@$Lq*!!3ihfRpxk zm=h5V_Hk@I+|hE2i8e5BfU=KLibZ3|2N}e3pzp-zp~jvqFxg7qL}dTsk$xs3|GrkzofzDWPNNA8EQewiZhgb0vOlvzg$ z2R@>MdI)cnPHH%`Q*cJa**Vc-YFGrApv~nXpJpaFx!mXMtgPFTnQ%vw(#lVbo+PHL zy_m$()OKHF@nu}HQ7*NPYn(#DuK`NXV0>vOl4aQ-0%Quxf3_HvY&2Hi8&V}nMs561 z{z}|hSObn;2l8t>hSW@j!;_g4HhPd%6!-|NID;_oBy4!8pJM zU*;qm-PPeCDriP!x1r+x>kFZ7!?ZkD2hDK~u6zgnt-R+%OcNy%Av^JcB<3QhV0$@TdZh;`g zyYhHZ`JeN_78hga9*eQW|KgWR4(aD<_1A9lZ$ktU!VT5JZz%E>clBEeX& z6`L%x_+)6Qpg&l8LFTilf5+FCkKWSNq>;Uh?-l)Ndx;n!M3rHQ7G~m1q8g`4=1BmF z+23;VAcacOaK^m<3Wop_fqEc)3Kzm*qpoTDF}*>*rcGbGM_Cw2S)ft(5*>-i>SO&h zYPAQA`ei&NJp_XBR*$=yjcLeWV7vaKS)_xB8Z~A^LZxqjg5@9fc{TjbVihkxYw*PAB}z< zA}Y_7cmMO5PKo5tHleqdI`9vlqtq+JQlr+r4;XwV1s^!)%_0uyCJ(*_`;+li~ z^5&Vug|Svvo)wb=eeilK4k@S(+JpL4UJLsqh;jS+H$5#7sv*Ucu8!?~`9UOOsR9=; zM>}syc#m;WtRA;t%g*Z-$)Ul}lvqa$)m{M-rDrFLT@^o>0#4V$4XvYK;)>q%qDi`v zTHCbV&NGo*OUZ^KD0BR~PT4!#r18OVlb>>-Th7+h9>D~j+01V+6$^?N zwi1e$Rt@$P`m8`!de6Q1`XN-8o?XE-zkxLI7j=>dQV7%s#Hr;Adep=6T&cb%86Z(3 zj1W5qZ^r1C&pLvmYlTl1o#lCkmV!;j z@spLvP3~udnXS+P*$%mVMCnRIqQKh=OU5P}cfKu&_@dQTXfJ?i4^R?HkK9b(;XTLP zFdwwEzIX-Nm_mwF~vh9IhX<%*5_x<(CcI@SVO$1h= zpVsbMMUD3ZsULQ;#+tV6H%W8^PuH?Lo|5@#|5ctQ)W>*2Sc}$20TCg&zz+|dylvnq zG>ildYC%zmB?;B>KD;6^->kRWFGKs2mq+zZ|90GaA(LV6w3n}H%sF=kRqszQ&ULrh zZc6SU)Ftih#ovY48A!|R#dgnrV5MBz`jUn9Pd938v*>)MKqR;$%dY9IJI~d@{Rr`+ z?mTMEs&_uox1&SNa`CiYY}he!*w!les%3r zgwq>}<)Uindi9=nZ8*6BWC4}(m~yEX=LK=N6eRR#LGoPst@J21mNkuQb{j^gQ3A2A z9l#MTlT&1E8Y=GeL$tncg9hI|h(3+#NP>Pq(EpfHf4cc_JFM>ao-x86M4$D-yzG+t z`t|Ggr@9&3+GrkNZ2+%8Zi93Vxs8__lnW$9bRnf%B|aq`y#w!nCiw7SlKw7GJKz;2 zyYW&M5hk>cG4b}qyPpUCEK=AT6cF1%ZMjn~bnKsN1RO{+V50S8?vMRZuKy8-k%~Nj z?1tVusv}ub>9hccg1^4<*?-?zqVxA{N)P^do6@1b0EFsawt)9;CrC$s_Ai>zIkw~U z_TAOnO^%(zi~$p>f5R+b>Nrs{+`4cH|_1k5@NM>p9T6qD-qyI zUtQ2hJAIeURs7Fc(odB%2Fi=mAbbLl#C7Oni7RDuQ}O80qge~YJZ`J9e{ZO~fLCNy zO*hg5UwSO`$qdy7@`GDbCL(m&wSII|l#h?ECMZYp->-F|tOg1)wC3kQA#?sUg$?(Q z|9!IPiIXUHrf0Ng?abwH2DU&pDOV*CwE7jT>|&O8I-eJs10K>>-Q6}D_8NLvK-8?( zBo(6=)E<-pd$hk^&Mz%S@8lzeGZEhE%Ylsg|31eQY@tCX2$GS_MNiGGWnO1}*n$=F z!Pp>wj|L72UPL9xART0`r6^cHC?=Sg)ux0}E5>MAg}8gXn$iPs;t>MEC4`7Jk-8J# zK-st8{zSWPrQ>%;BB)6F?|cs$1sTOrgl(LQAFLH0-QDKD0Z6S z(D(rJnkOtjMa z(|h|M*CAVTB9F07QSYY6zS$1w?^{t@#(WECt;-ZK8i{`|MP|Ok%v!o#F7g6u0Y5`N z)GgPE9HOb>zvxgNFUUR4qGT9{Rd!>aoUSWe2swv2t?~_3Z$!Jeaeb?3bz=W?$G3cJ zQ_E~iw0xusP>001rtx6I61x&F3$+=nBE5UT$lxWY8Ey|33aIvPOb1WiI8%vM>U)XX zC^!k(c#BX=4=3^5&xdG_>^08=raL=4$$zN3+ht zM-a)Fr(Ibhk0(=X(3MC9G)q)=LLagir_-Y-70jmS;GuRFMj4X^IwyH)%3?dqd%JX<0NE68d%jnbjB;NfMq75ZoJ9i=? z?(+95&#=f+P>{`~Oc!kmm4DYl?;-ON?fS5u*xbNBXl6MqLsFammZS&oeg1b5;4fe3 z|9J@c?+0i;YfBRYDPYA&5-7`Jc_aQc^AP^%b3Ka2>;Hd9`5%N7RrWTOPpXI{y_d@N zatqa*5D-{G)ck5v913<60wf+z?m)eSEE_AEzRYw?hUAk7GD zW?wCU*~qZ)Q)CQtg62Mi)4+L3#S{co_-2eV3h_hT$iI4L)f4TVAESsRg?=j*>{ zh6e40fwgIcaf*4mOi{Hl??Q+Ec55Ma5N%kBw4)T@YO9SaM8LBT@5{WENEGoRc*Wg| z8lpD0u{<81hu2e=R776myRm&_pG%>ARA~RTGLM-f>*$`!U|zF&<$Oo5JX zUkBCjil8?EH)pZM4>QSM*}v@9PfKt>CvD+_j?Dh-^wCJzlR(`!ugU9iaPy2BQtWS9 zww-x5ggDbk*k8*Ee9WYxL)S_?AH~O}P&BSmVG{=sCpjOnZor}d{Xa|9^q)v1^IUx37Hh$fPELQuNOkMP@+c8UHjgV4rLueNc@ufM0KP6;sb+) z@s#6&-|Z}Vo4b&5aZ`vi88rq@8_E$`mhmc50KsG&ZlxXmI1QO0-%aXKmL7K=KLeV5_*|3NDA-{a8#I2ZD7SwQ4m zKK80FuzSusr)2!!2@1a660@Qhr*HnUV1o)L`B=NF|*+eE-^zo@X7^&h43N0bjZeSBHP{ zTNwuyPup~3g#!lcvMd5#Fm_^e%knG!_wP<+3crSXy7B7Zlv;h)3@ z2?nVO>*bkf*&9Q{3#KRHo!O*#wnfdP{3&NT{(WM~3q@+MoIL&u`x72^Jn!(rcrp;C z+`QKI{8OyO|7U))-mk=JWhQrEjqtNOI{!6K?*|m5?}ips^xvb(L>W7WfI0-^FT6B9 zoYT|svt~@oLuL)vJ^)lwRTJ<&R&8f zY>+yf*Y!CJHc2M5RH(_dc~(rdaX5${AWHS$N~stR#J;_5EqA8@ZB>eNpv1rHG`eFF zABDfJ_Tqw1JXoq%I(R7U)%;kJKNbR@-;3KRRX1Nd+Aq-)9j|hYRwP-2ZS9L0EoYSY ziPE$r_5;4Q72jl7GR)Fwm$@U+>%IjoC2RhqXNmNRFxeLa!W~GrqF)Xqri2Ing1e&M zMB@^V|j)k5aRbQ^mAF08Ck|^r$Xqm*k;3@M5zl z@fDdiWBlc`iek#QZfGPA+Q^nvmf>R~*Lse1L-G*y5hJ=ili1$|shWD3ok@MVE(x{v zmWkP%v3B>6V_D*V)RQ@TX+UoT6Cj#(OVHaUf|KS~v-yd9R;&m_b5F+KVxFj&wUV{c znRD(s8Q3!ikN2YOYBtsTtSP~@LN&Wd*lz6wDz);~)LNKtVJ;GbxYCr#ZAt5qDWXl|5PvTi{0qsN>h{bjVUm=*23L!X3T4 z6w1Zz>&_WwLhISMPq-@(hxGYM9qSW@ow3H%Si~f_Nkvaaa1wQ`&rg@rVJ7j?`m-quk`jCTkGSZxu=QSPg1EFEcTdfqSb>yVD0QT~ zwUGPBP;4d3@>_dFlX$&VgwLPvnYBMKr*kkf((ue%7s-%9zDP|iMH*`glM|xKtgl?T z!kaEvM|imgUe3VOE!HE~4**b)J&(A$FTc&b`sKT@5?Ns0_GZOYJtbWhooh*Jl}jNF zwT6&vwtVFFce8=BZ4o^DN+H_hdCC1{gdFRHx8QX~;s`JK?E+927J+BYii6{8Z zf*Ot}Y|~G#e9wnv0W$-=x_VDnRBfD!R(=Un{fl3Tw~KBkPBaU7^b>++60RRnT)HsX z#BXY`x<3-Vc41OCt8i3u4=v3-b*o5{z}kp>j|da#&hzKQglaO--;J7IR$N>>j{~k2 z4=hjgUFDL9xgZev^I1?(>HMViotD<`5U7)uL>saVwRy(2pX~v8Q!S$AeSZam7?Khv zCbysj6YIY1&xSd7FoX`o{xoRhOAxLqD|MYnOF%|y_ivfC_J8;PuGI$3?Y**n@{!lR zLa&zA=g>SQp6N8)smZA}$WKAGjn-U^6xA%tcO#5*Js3>S1WD_rVIKz>!C~g8k z<9r0D%P+r6P84Lxu=pO9HSixPo)%rVaq|o#% z)*2zEJ$?*Q8mGm=!tw)+db_#u7d8NBLaOTSwYE5Rb{9bv|5DshPFz1(yi;ZW;sGU zT`7R34a-^Bssy*!Wb6ye>ifFE_3Y1$Nkjf?B|g%;yAVUEJ+nR-#?dyTk45Lm12^Nx zGBtM?(Hfo%5RbX;BSR0cP%RnIU?D*v@LH-WYGbpfn~WJEvW(FtdyLm6#_xckBnIEl zb&!IAaMvXqb4AprV4Y z<7IF*(B_jC<`X#`;4Ze{^!97ic=Y)q*ww}}P=cpIFYncP>*)&}Wo2aq@Meu?+};zpNVI7#F_W$VoX@(FEjr8(fMDGf_oP9Z1<91*)TdTUQxuSuMC zQs3|nzrh`k@D37WD2^~Y-llYI=|W>nObp>?5h}c?Nf%g_)2R`J6|pS@@huOHhT1ee zL2bn0ZGE@RS*DDM;gu>A6aPw1Vm)@=0Orcr*8`)jAC1Hcbo? zJ6@RkhL5q&f)lK0Tm&Tm@ko3RZoVoNy^`9Ob6&FS_n{egP4gG-H+-sNz3Vnxw~89t zbNv|N3_2T1LO%z2?m4mM7?98cxpm2;|DY(|$nw~72uMW=7q$~maOTzwDydOjSL{wv*oGEt9i>zQm6kQsJ}yvkABC;9T0 zm5sY0h`!*>BPaOE)FAA4_Sk`Zy3^+nJ3D(_CiBp7lyfofZS2H-dhypT{OyK-i68^V zm+j1NlU;sqlNnMq({$ZSs9i2R)rF*S-;6%eB3gZ6hqiPj=W`q;;r8208Rc53ua?W| zPn7qh4zE3W1m>>v(j&?lhJraiMua>WTxNQedJkYn2GpC!&&$RQ+%-|*$yh>wXYO-c z;ezk#L>puWMG=3q&MI~{x{_V2ee&WVV}OHO{lXO-@-k5lEsv)j*^&9${B=pbQ$&Xr z;wfq&92B+cz7YQ0r3Iz<@Jp42O^PanuZ%-+9t#{J=a$C91w{Mz)qu`Q>!54a997(){Z z7b4wbEI2eVqki4hh2kS}zpy{le-~b5CY~K#Ntxjf@i~+w$4A+zk&dxqG|lQ-03foy zNw3Bq1eyBTp!43EI;+tUJ01uGB5ZI@`|AG&T5hJXq^lpZJS5ov7HkPI&^0<&sACuU Fe*xYB$36f6 diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi index 00bb9d9e137c1ce7d86146cf9f0bab24dda04497..7b7238c3ab799e529ce21b767d0e1d94a782a746 100644 GIT binary patch delta 359 zcmV-t0hs=gYK&@-B!5tPR9JLGWpiV4X>fFDZ*Bkpc$}@2!EVAZ3_#DxS6Fam6Lf61 zUMA4Q0e+$Knm{e3apj~S_Vqik4K_8Spvsq4dVX;t+hcfLzO6Q}Sg-WnN+9--!~Aio z)qzZ`Acv<+tIE=@il?6tF5ptMKdWBYE59H17GaKQ^4r67nmUl*b+~orH-SA824YYF1P14m4=-N39 zq1*R-_GOc=xMHhqL^qgi$Ic8U3*`2xmc2t~2y6DkmDdV-YU{y#O~t~Arn^J;j(*ts z&|r-|l243WUt48}(w4CmbWos2cl_wFm&^}ZI84z0@0M=Y4F}&+>O^tLm zzjeAk49m>|7VDM%1VIr7ZV?I4`?G=p Fk2B>9wekP} delta 364 zcmV-y0h9iWYLRM?B!5+UR9JLGWpiV4X>fFDZ*Bkpc$}@2!EVAZ42I9iQ&@0i6Ybb; zy-c8~2Y7|bYXY^DCY6(d*wgR8HW+H4MU^j!^!v;2$o3T8S0DKXmg`*ZHG6UvGFUv% zr8tlZ6=d*|N>ORrRpE5;0fUANCM9v%QYffym~7BIkwOuB$bTS_V#`?T(>b0|ga>la zQg>E5mqKZSN5~+V^$ICiAIPfzZ#L|LGZ-p;*WOv$qm~P??H0dvRv?9Ou8FeRA*}2A zZ<2Qgz3-;Kp6TiAC+^T{9ng$M+c~2~gLyLhSOY(RQ-rm%v8B|Xv@jS^-`+IctN{-X@pymjT!aMvr|}Ymatss@*6d=2>Cig KS3t9U0gp5K+qAF% diff --git a/polaris.dme b/polaris.dme index 74efedd213..098fdd7491 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1451,17 +1451,28 @@ #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\printer.dm" #include "code\modules\integrated_electronics\core\tools.dm" +#include "code\modules\integrated_electronics\core\special_pins\boolean_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\char_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\color_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\dir_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\list_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\number_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\ref_pin.dm" +#include "code\modules\integrated_electronics\core\special_pins\string_pin.dm" #include "code\modules\integrated_electronics\passive\passive.dm" #include "code\modules\integrated_electronics\passive\power.dm" #include "code\modules\integrated_electronics\subtypes\arithmetic.dm" #include "code\modules\integrated_electronics\subtypes\built_in.dm" #include "code\modules\integrated_electronics\subtypes\converters.dm" #include "code\modules\integrated_electronics\subtypes\data_transfer.dm" -#include "code\modules\integrated_electronics\subtypes\input_output.dm" +#include "code\modules\integrated_electronics\subtypes\input.dm" +#include "code\modules\integrated_electronics\subtypes\lists.dm" #include "code\modules\integrated_electronics\subtypes\logic.dm" #include "code\modules\integrated_electronics\subtypes\manipulation.dm" #include "code\modules\integrated_electronics\subtypes\memory.dm" +#include "code\modules\integrated_electronics\subtypes\output.dm" #include "code\modules\integrated_electronics\subtypes\power.dm" #include "code\modules\integrated_electronics\subtypes\reagents.dm" #include "code\modules\integrated_electronics\subtypes\smart.dm" @@ -2217,7 +2228,6 @@ #include "code\unit_tests\integrated_circuits\arithmetic.dm" #include "code\unit_tests\integrated_circuits\circuits.dm" #include "code\unit_tests\integrated_circuits\converter.dm" -#include "code\unit_tests\integrated_circuits\data_transfer.dm" #include "code\unit_tests\integrated_circuits\logic.dm" #include "code\unit_tests\integrated_circuits\trig.dm" #include "code\ZAS\_docs.dm"