From cfa8a7479150aae09f573281ff0c3bacbfc9df2e Mon Sep 17 00:00:00 2001 From: Builder13 Date: Wed, 4 Sep 2024 16:40:05 +0300 Subject: [PATCH] Integrated circuits --- mods/global_modpacks.dm | 1 + mods/integrated_circuits/README.md | 77 ++++++++++ .../_integrated_circuits.dm | 3 + .../_integrated_circuits.dme | 11 ++ mods/integrated_circuits/code/assemblies.dm | 41 ++++++ mods/integrated_circuits/code/input.dm | 133 ++++++++++++++++++ .../code/integrated_circuit.dm | 128 +++++++++++++++++ mods/integrated_circuits/code/manipulation.dm | 115 +++++++++++++++ mods/integrated_circuits/code/pai.dm | 6 + 9 files changed, 515 insertions(+) create mode 100644 mods/integrated_circuits/README.md create mode 100644 mods/integrated_circuits/_integrated_circuits.dm create mode 100644 mods/integrated_circuits/_integrated_circuits.dme create mode 100644 mods/integrated_circuits/code/assemblies.dm create mode 100644 mods/integrated_circuits/code/input.dm create mode 100644 mods/integrated_circuits/code/integrated_circuit.dm create mode 100644 mods/integrated_circuits/code/manipulation.dm create mode 100644 mods/integrated_circuits/code/pai.dm diff --git a/mods/global_modpacks.dm b/mods/global_modpacks.dm index 2b1608de7a817..bd22c57b6ad8e 100644 --- a/mods/global_modpacks.dm +++ b/mods/global_modpacks.dm @@ -34,5 +34,6 @@ #include "newUI/_newUI.dme" #include "ai-update/_ai-update.dme" #include "anomaly/_anomaly.dme" +#include "integrated_circuits/_integrated_circuits.dme" #include "../packs/sierra-tweaks/_pack.dm" diff --git a/mods/integrated_circuits/README.md b/mods/integrated_circuits/README.md new file mode 100644 index 0000000000000..aec6a4697a0cf --- /dev/null +++ b/mods/integrated_circuits/README.md @@ -0,0 +1,77 @@ + +#### Список PRов: + +- https://github.com/SierraBay/SierraBay12/pull/2655 + + + +## Integrated circuits + +ID мода: INTEGRATED_CIRCUITS + + +### Описание мода + +Добавляет несколько новых плат, вносит дополнительный функционал в плату контроля ИИ, упрощает вставку и доставание предметов из интегральных плат для расширения функционала и удобства. + + +### Изменения *кор кода* + +- Отсутствуют + + +### Оверрайды + +- Отсутствуют + + +### Дефайны + +- Отсутствуют + + +### Используемые файлы, не содержащиеся в модпаке + +- Отсутствуют + + +### Авторы: + +Builder13 + diff --git a/mods/integrated_circuits/_integrated_circuits.dm b/mods/integrated_circuits/_integrated_circuits.dm new file mode 100644 index 0000000000000..10b73651431dd --- /dev/null +++ b/mods/integrated_circuits/_integrated_circuits.dm @@ -0,0 +1,3 @@ +/singleton/modpack/integrated_circuits + name = "Integrated circuits" + desc = "Изменения, связанные с интегральными платами." \ No newline at end of file diff --git a/mods/integrated_circuits/_integrated_circuits.dme b/mods/integrated_circuits/_integrated_circuits.dme new file mode 100644 index 0000000000000..d65f117a4db75 --- /dev/null +++ b/mods/integrated_circuits/_integrated_circuits.dme @@ -0,0 +1,11 @@ +#ifndef MODPACK_INTCIRCUITS +#define MODPACK_INTCIRCUITS + +#include "_integrated_circuits.dm" +#include "code/assemblies.dm" +#include "code/integrated_circuit.dm" +#include "code/pai.dm" +#include "code/input.dm" +#include "code/manipulation.dm" + +#endif diff --git a/mods/integrated_circuits/code/assemblies.dm b/mods/integrated_circuits/code/assemblies.dm new file mode 100644 index 0000000000000..e0891d3086820 --- /dev/null +++ b/mods/integrated_circuits/code/assemblies.dm @@ -0,0 +1,41 @@ +/obj/item/device/electronic_assembly + var/magnetized = 0 + +/obj/item/device/electronic_assembly/attack_hand(mob/user) + if(magnetized && istype(src.loc, /turf/simulated/floor)) + attack_self(user) + return + ..() + +/obj/item/device/electronic_assembly/proc/loading(obj/item/I, mob/living/user) + var/list/icomponents = list() + var/list/ircomponents = list() + if(istype(I, /obj/item/gun/energy)) + for (var/obj/item/integrated_circuit/manipulation/weapon_firing/P in assembly_components) + if(!P.installed_gun) + icomponents+=P.displayed_name + ircomponents+=P + else if(istype(I, /obj/item/grenade)) + for (var/obj/item/integrated_circuit/manipulation/grenade/P in assembly_components) + if(!P.attached_grenade) + icomponents+=P.displayed_name + ircomponents+=P + else + var/obj/item/card = I + var/mob/living/L = locate(/mob/living) in card.contents + if(L && L.key) + for (var/obj/item/integrated_circuit/manipulation/ai/P in assembly_components) + if(!P.controlling) + icomponents+=P.displayed_name + ircomponents+=P + var/component_choice = input("Please choose a component to insert the [I].","[src]") as null|anything in icomponents + if(component_choice) + var/obj/item/integrated_circuit/circuit = ircomponents[icomponents.Find(component_choice)] + if(in_range(user, circuit) && get_dist(I, user) < 1) + circuit.use_tool(I, user) + +/obj/item/device/electronic_assembly/use_tool(obj/item/I, mob/user, list/click_params) + if(is_type_in_list(I, list(/obj/item/gun/energy, /obj/item/grenade, /obj/item/aicard, /obj/item/device/paicard, /obj/item/device/mmi, /obj/item/organ/internal/posibrain)) && opened) + loading(I,user) + return TRUE + ..() \ No newline at end of file diff --git a/mods/integrated_circuits/code/input.dm b/mods/integrated_circuits/code/input.dm new file mode 100644 index 0000000000000..8b41eae1532d4 --- /dev/null +++ b/mods/integrated_circuits/code/input.dm @@ -0,0 +1,133 @@ +/obj/item/integrated_circuit/input/examiner + outputs = list( + "name" = IC_PINTYPE_STRING, + "description" = IC_PINTYPE_STRING, + "X" = IC_PINTYPE_NUMBER, + "Y" = IC_PINTYPE_NUMBER, + "distance" = IC_PINTYPE_NUMBER, + "max reagents" = IC_PINTYPE_NUMBER, + "amount of reagents" = IC_PINTYPE_NUMBER, + "density" = IC_PINTYPE_BOOLEAN, + "opacity" = IC_PINTYPE_BOOLEAN, + "occupied turf" = IC_PINTYPE_REF, + "object direction" = IC_PINTYPE_DIR + ) + +/obj/item/integrated_circuit/input/examiner/do_work() + var/atom/H = get_pin_data_as_type(IC_INPUT, 1, /atom) + var/turf/T = get_turf(src) + + if(!istype(H) || !(H in view(T))) + activate_pin(3) + else + set_pin_data(IC_OUTPUT, 1, H.name) + set_pin_data(IC_OUTPUT, 2, H.desc) + set_pin_data(IC_OUTPUT, 3, H.x-T.x) + set_pin_data(IC_OUTPUT, 4, H.y-T.y) + set_pin_data(IC_OUTPUT, 5, sqrt((H.x-T.x)*(H.x-T.x)+ (H.y-T.y)*(H.y-T.y))) + var/mr = 0 + var/tr = 0 + if(H.reagents) + mr = H.reagents.maximum_volume + tr = H.reagents.total_volume + set_pin_data(IC_OUTPUT, 6, mr) + set_pin_data(IC_OUTPUT, 7, tr) + set_pin_data(IC_OUTPUT, 8, H.density) + set_pin_data(IC_OUTPUT, 9, H.opacity) + set_pin_data(IC_OUTPUT, 10, get_turf(H)) + set_pin_data(IC_OUTPUT, 11, H.dir) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/list_pick + name = "list pick" + desc = "A touch screen with all the data you need to pick." + icon_state = "screen" + complexity = 3 + inputs = list("List" = IC_PINTYPE_LIST) + outputs = list("Picked element" = IC_PINTYPE_ANY) + activators = list("on pressed" = IC_PINTYPE_PULSE_OUT, "on picked" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 5 + +/obj/item/integrated_circuit/input/list_pick/get_topic_data(mob/user) + return list("Press" = "list_pick=1") + +/obj/item/integrated_circuit/input/list_pick/OnICTopic(href_list, user) + if(href_list["list_pick"]) + activate_pin(1) + var/list/input_list = get_pin_data(IC_INPUT, 1) + if(length(input_list)) + var/pick_element = input("Choose an element.") as null|anything in input_list + if(pick_element) + if(get_dist(src, user) <= 1) + set_pin_data(IC_OUTPUT, 1, pick_element) + push_data() + activate_pin(2) + else + to_chat(user, "You are not close enough for that!") + else + to_chat(user, "There is no list to pick from!") + return IC_TOPIC_REFRESH + +/obj/item/integrated_circuit/input/image_comparse + name = "image comparsion scanner" + desc = "A circuit with miniature camera attached to it." + extended_desc = "On pulsing 'store' activator, circuit would remember the selected target, \ + on 'check' it will compare stored object with the selected target, trying to include into comparsion every detail on them.\ + When both objects are almost completely identical, both outputs will be ones. \ + (matching form - type check, match of details - icon_state check)." + icon_state = "video_camera" + complexity = 5 + inputs = list( + "target" = IC_PINTYPE_REF + ) + outputs = list( + "stored object" = IC_PINTYPE_STRING, + "matching form" = IC_PINTYPE_BOOLEAN, + "match of details" = IC_PINTYPE_BOOLEAN + ) + activators = list( + "store" = IC_PINTYPE_PULSE_IN, + "check" = IC_PINTYPE_PULSE_IN, + "on checked" = IC_PINTYPE_PULSE_OUT, + "on failure" = IC_PINTYPE_PULSE_OUT + ) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 80 + var/obj_type + var/state + +/obj/item/integrated_circuit/input/image_comparse/do_work(ord) + switch(ord) + if(1) + var/atom/object = get_pin_data_as_type(IC_INPUT, 1, /atom) + if(object) + obj_type = object.type + state = object.icon_state + set_pin_data(IC_OUTPUT, 1, object.name) + push_data() + else + var/atom/H = get_pin_data_as_type(IC_INPUT, 1, /atom) + var/turf/T = get_turf(src) + + if(!istype(H) || !(H in view(T))) + activate_pin(4) + else + if(!H || !obj_type) + return + + if(H.type == obj_type) + set_pin_data(IC_OUTPUT, 2, 1) + + if(H.icon_state == state) + set_pin_data(IC_OUTPUT, 3, 1) + else + set_pin_data(IC_OUTPUT, 3, 0) + + else + set_pin_data(IC_OUTPUT, 2, 0) + set_pin_data(IC_OUTPUT, 3, 0) + + push_data() + activate_pin(3) \ No newline at end of file diff --git a/mods/integrated_circuits/code/integrated_circuit.dm b/mods/integrated_circuits/code/integrated_circuit.dm new file mode 100644 index 0000000000000..70079df9b50e4 --- /dev/null +++ b/mods/integrated_circuits/code/integrated_circuit.dm @@ -0,0 +1,128 @@ +/obj/item/integrated_circuit/interact(mob/user) + . = ..() + if(!check_interactivity(user)) + return + + var/window_height = 350 + var/window_width = 655 + + var/table_edge_width = "30%" + var/table_middle_width = "40%" + var/list/HTML = list() + HTML += "[src.displayed_name]" + HTML += "
" + HTML += "" + + if((istype(src, /obj/item/integrated_circuit/manipulation/weapon_firing) && src.vars["installed_gun"] != null) || (istype(src, /obj/item/integrated_circuit/manipulation/ai) && src.vars["controlling"] != null) || (istype(src, /obj/item/integrated_circuit/manipulation/grenade) && src.vars["attached_grenade"] != null)) + HTML += "\[Remove item\] | " + if(assembly) + HTML += "\[Return to Assembly\]
" + HTML += "\[Refresh\] | " + HTML += "\[Rename\] | " + HTML += "\[Copy Ref\]" + if(assembly && removable) + HTML += " | \[Remove\]" + HTML += "
" + + HTML += "" + HTML += "" + HTML += "" + HTML += "" + HTML += "" + + var/column_width = 3 + var/row_height = max(LAZYLEN(inputs), LAZYLEN(outputs), 1) + + for(var/i = 1 to row_height) + HTML += "" + for(var/j = 1 to column_width) + var/datum/integrated_io/io = null + var/words = list() + var/height = 1 + switch(j) + if(1) + io = get_pin_ref(IC_INPUT, i) + if(io) + words += "[io.display_pin_type()] [io.name] \ + [io.display_data(io.data)]
" + if(length(io.linked)) + for(var/k in 1 to length(io.linked)) + var/datum/integrated_io/linked = io.linked[k] + words += "[linked] \ + @ [linked.holder.displayed_name]
" + + if(LAZYLEN(outputs) > LAZYLEN(inputs)) + height = 1 + if(2) + if(i == 1) + 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.display_pin_type()] [io.name] \ + [io.display_data(io.data)]
" + if(length(io.linked)) + for(var/k in 1 to length(io.linked)) + var/datum/integrated_io/linked = io.linked[k] + words += "[linked] \ + @ [linked.holder.displayed_name]
" + + if(LAZYLEN(inputs) > LAZYLEN(outputs)) + height = 1 + HTML += "" + HTML += "" + + for(var/i in 1 to LAZYLEN(activators)) + var/datum/integrated_io/io = activators[i] + var/words = list() + + words += "[SPAN_COLOR("#ff0000", io)] " + words += "[SPAN_COLOR("#ff0000", io.data ? "\" : "\")]
" + if(length(io.linked)) + for(var/k in 1 to length(io.linked)) + var/datum/integrated_io/linked = io.linked[k] + words += "[SPAN_COLOR("#ff0000", linked)] \ + @ [SPAN_COLOR("#ff0000", linked.holder.displayed_name)]
" + + HTML += "" + HTML += "" + HTML += "" + + HTML += "
[jointext(words, null)]
[jointext(words, null)]
" + HTML += "
" + + HTML += "
[SPAN_COLOR("#0000aa", "Complexity: [complexity]")]" + HTML += "
[SPAN_COLOR("#0000aa", "Cooldown per use: [cooldown_per_use/10] sec")]" + if(ext_cooldown) + HTML += "
[SPAN_COLOR("#0000aa", "External manipulation cooldown: [ext_cooldown/10] sec")]" + if(power_draw_idle) + HTML += "
[SPAN_COLOR("#0000aa", "Power Draw: [power_draw_idle] W (Idle)")]" + if(power_draw_per_use) + HTML += "
[SPAN_COLOR("#0000aa", "Power Draw: [power_draw_per_use] W (Active)")]" // Borgcode says that powercells' checked_use() takes joules as input. + HTML += "
[SPAN_COLOR("#0000aa", extended_desc)]" + + HTML += "" + var/HTML_merged = jointext(HTML, null) + if(assembly) + show_browser(user, HTML_merged, "window=assembly-\ref[assembly];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + else + show_browser(user, HTML_merged, "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") + + onclose(user, "assembly-\ref[src.assembly]") + +/obj/item/integrated_circuit/Topic(href, href_list, state = GLOB.physical_state) + if(href_list["iremove"]) + if(istype(src,/obj/item/integrated_circuit/manipulation/weapon_firing)) + var/obj/item/integrated_circuit/manipulation/weapon_firing/B = src + B.eject_gun(usr) + else if(istype(src,/obj/item/integrated_circuit/manipulation/ai)) + var/obj/item/integrated_circuit/manipulation/ai/B = src + B.unload_ai() + else if(istype(src,/obj/item/integrated_circuit/manipulation/grenade)) + var/obj/item/integrated_circuit/manipulation/grenade/B = src + B.detach_grenade() + internal_examine(usr) + ..() \ No newline at end of file diff --git a/mods/integrated_circuits/code/manipulation.dm b/mods/integrated_circuits/code/manipulation.dm new file mode 100644 index 0000000000000..1c97f1149c13d --- /dev/null +++ b/mods/integrated_circuits/code/manipulation.dm @@ -0,0 +1,115 @@ +/datum/click_handler/default/aimodule/OnClick(atom/A, params) + aiclick(A,params,user,0) + +/datum/click_handler/default/aimodule/OnDblClick(atom/A, params) + aiclick(A,params,user,1) + +/datum/click_handler/default/aimodule/proc/aiclick(atom/A, params, mob/user, clicktype) + var/obj/item/integrated_circuit/manipulation/ai/C = user.loc + if(get_dist(A, user) <= 9) + C.set_pin_data(IC_OUTPUT, 2, weakref(A)) + C.push_data() + if(clicktype != 1) + var/list/modifiers = params2list(params) + if(modifiers["middle"]) + C.activate_pin(7) + else if(modifiers["shift"]) + C.activate_pin(9) + else if(modifiers["ctrl"]) + C.activate_pin(10) + else if(modifiers["alt"]) + C.activate_pin(11) + else + C.activate_pin(6) + else + C.activate_pin(8) + +/obj/item/integrated_circuit/manipulation/ai + var/eol = "<br>" + var/instruction = null + inputs = list("Instructions" = IC_PINTYPE_STRING) + outputs = list("AI's signature" = IC_PINTYPE_STRING, "Clicked Ref" = IC_PINTYPE_REF) + activators = list("Upwards" = IC_PINTYPE_PULSE_OUT, "Downwards" = IC_PINTYPE_PULSE_OUT, "Left" = IC_PINTYPE_PULSE_OUT, "Right" = IC_PINTYPE_PULSE_OUT, "Push AI Name" = IC_PINTYPE_PULSE_IN, "On click" = IC_PINTYPE_PULSE_OUT, "On middle click" = IC_PINTYPE_PULSE_OUT, "On double click" = IC_PINTYPE_PULSE_OUT, "On shift click" = IC_PINTYPE_PULSE_OUT, "On ctrl click" = IC_PINTYPE_PULSE_OUT, "On alt click" = IC_PINTYPE_PULSE_OUT) + +/obj/item/integrated_circuit/manipulation/ai/load_ai(mob/user, obj/item/card) + ..() + if(controlling) + card.forceMove(src) + controlling.PushClickHandler(/datum/click_handler/default/aimodule) + + var/datum/integrated_io/P = inputs[1] + if(isweakref(P.data)) + var/datum/d = P.data_as_type(/datum) + if(d) + instruction = "[d]" + else + instruction = replacetext("[P.data]", eol , "
") + + if(instruction) + to_chat(controlling, instruction) + set_pin_data(IC_OUTPUT, 1, controlling.name) + +/obj/item/integrated_circuit/manipulation/ai/unload_ai() + if(controlling) + controlling.RemoveClickHandler(/datum/click_handler/default/aimodule) + ..() + +/obj/item/integrated_circuit/manipulation/weapon_firing/proc/eject_gun(mob/user) + if(installed_gun) + installed_gun.dropInto(loc) + to_chat(user, "You slide \the [installed_gun] out of the firing mechanism.") + size = initial(size) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) + installed_gun = null + set_pin_data(IC_OUTPUT, 1, weakref(null)) + push_data() + else + to_chat(user, "There's no weapon to remove from the mechanism.") + +/obj/item/integrated_circuit/manipulation/magnetizer + name = "floor magnet" + desc = "Magnetize your assembly to the floor so no one can pick it up while it is active. Assembly can still be moved." + + outputs = list( + "enabled" = IC_PINTYPE_BOOLEAN + ) + activators = list( + "toggle" = IC_PINTYPE_PULSE_IN, + "on toggle" = IC_PINTYPE_PULSE_OUT + ) + + complexity = 16 + cooldown_per_use = 5 SECOND + power_draw_per_use = 50 + power_draw_idle = 0 + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 4, TECH_MAGNETS = 4) + +/obj/item/integrated_circuit/manipulation/magnetizer/do_work(ord) + if(!isturf(assembly.loc)) + return + + if(ord == 1 && src.loc == assembly) + assembly.magnetized = !assembly.magnetized + power_draw_idle = assembly.magnetized ? 50 : 0 + + visible_message( + assembly.magnetized ? \ + "\The [get_object()] sticks to the floor!" \ + : \ + "\The [get_object()] deactivates its magnets" + ) + + set_pin_data(IC_OUTPUT, 1, assembly.magnetized) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/manipulation/magnetizer/power_fail() + assembly.magnetized = 0 + power_draw_idle = 0 + set_pin_data(IC_OUTPUT, 1, assembly.magnetized) + +/obj/item/integrated_circuit/manipulation/magnetizer/disconnect_all() + assembly.magnetized = 0 + power_draw_idle = 0 + set_pin_data(IC_OUTPUT, 1, assembly.magnetized) \ No newline at end of file diff --git a/mods/integrated_circuits/code/pai.dm b/mods/integrated_circuits/code/pai.dm new file mode 100644 index 0000000000000..1ed32eda0f359 --- /dev/null +++ b/mods/integrated_circuits/code/pai.dm @@ -0,0 +1,6 @@ +/mob/living/silicon/pai/fold_up() + var/obj/item/integrated_circuit/manipulation/ai/A = src.loc + if(istype(A)) + A.unload_ai() + src.visible_message("[src] ejects from [A].") + ..() \ No newline at end of file