From 8bcc1da9bbede4c2f76b4b80be3f454caa85f11c Mon Sep 17 00:00:00 2001 From: Dimasw99 Date: Wed, 12 Feb 2025 21:48:01 +0100 Subject: [PATCH] IC filter fix plus additions (#6979) --- .../subtypes/filters.dm | 14 ++ .../integrated_electronics/subtypes/input.dm | 132 +++++++++++++++++- .../subtypes/reagents.dm | 81 ++++++++--- 3 files changed, 202 insertions(+), 25 deletions(-) diff --git a/code/modules/integrated_electronics/subtypes/filters.dm b/code/modules/integrated_electronics/subtypes/filters.dm index c18002dac33..4bc7475ddd5 100644 --- a/code/modules/integrated_electronics/subtypes/filters.dm +++ b/code/modules/integrated_electronics/subtypes/filters.dm @@ -89,6 +89,20 @@ filter_type = /obj/structure spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH +/obj/item/integrated_circuit/filter/ref/object/ore + name = "ore filter" + desc = "Only allow refs of ores through." + icon_state = "filter_structure" + filter_type = /obj/item/stack/ore + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/filter/ref/object/produce + name = "produce filter" + desc = "Only allow refs of grown produce through, such as apples and wheat." + icon_state = "filter_structure" + filter_type = /obj/item/reagent_containers/food/snacks/grown + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + /obj/item/integrated_circuit/filter/ref/custom name = "custom filter" desc = "Allows custom filtering. It will match type against a stored reference; it will also take a type string." diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 2dd9e32b12b..8429e5016cb 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -369,7 +369,8 @@ desc = "This circuit will filter every object in assembly view." extended_desc = "The first pin is ref to filter, to see avaliable filters go to Filter category. The output will contents everything with filtering type" inputs = list( - "filter" = IC_PINTYPE_REF + "filter" = IC_PINTYPE_REF, + "radius" = IC_PINTYPE_NUMBER ) outputs = list( "objects" = IC_PINTYPE_LIST @@ -377,12 +378,19 @@ activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 30 + var/radius = 1 + +/obj/item/integrated_circuit/input/view_filter/on_data_written() + var/rad = get_pin_data(IC_INPUT, 2) + if(isnum(rad)) + rad = clamp(rad, 0, 8) + radius = rad /obj/item/integrated_circuit/input/view_filter/do_work(ord) var/list/objects = list() var/obj/item/integrated_circuit/filter/ref/filter = get_pin_data(IC_INPUT, 1) if(istype(filter) && assembly && (filter in assembly.assembly_components)) - for(var/atom/A in view(get_turf(assembly))) + for(var/atom/A in view(radius,get_turf(assembly))) if(istype(A, filter.filter_type)) objects.Add(WEAKREF(A)) set_pin_data(IC_OUTPUT, 1, objects) @@ -405,6 +413,9 @@ "genetic destability" = IC_PINTYPE_NUMBER, "slime core amount" = IC_PINTYPE_NUMBER, "Growth progress" = IC_PINTYPE_NUMBER, + "rabid" = IC_PINTYPE_BOOLEAN, + "disciplined" = IC_PINTYPE_BOOLEAN, + "obedience" = IC_PINTYPE_NUMBER ) activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH @@ -426,6 +437,10 @@ set_pin_data(IC_OUTPUT, 7, T.mutation_chance) set_pin_data(IC_OUTPUT, 8, T.cores) set_pin_data(IC_OUTPUT, 9, T.amount_grown/1000) + var/datum/ai_holder/polaris/simple_mob/xenobio_slime/AI = T.ai_holder + set_pin_data(IC_OUTPUT, 10, AI.rabid) + set_pin_data(IC_OUTPUT, 11, AI.obedience) + set_pin_data(IC_OUTPUT, 12, AI.discipline) push_data() @@ -1793,3 +1808,116 @@ GLOBAL_DATUM_INIT(circuit_translation_context, /datum/translation_context/simple set_pin_data(IC_OUTPUT, 1, 0) push_data() activate_pin(2) + +/obj/item/integrated_circuit/input/plant_scanner + name = "integrated plant analyzer" + desc = "A very small version of the plant analyser. This allows the machine to know all valuable parameters of plants in trays. \ + It can only scan plants, not seeds or fruits." + icon_state = "medscan_adv" + complexity = 12 + inputs = list("target" = IC_PINTYPE_REF) + outputs = list( + "plant type" = IC_PINTYPE_STRING, + "age" = IC_PINTYPE_NUMBER, + "potency" = IC_PINTYPE_NUMBER, + "yield" = IC_PINTYPE_NUMBER, + "Maturation speed" = IC_PINTYPE_NUMBER, + "Production speed" = IC_PINTYPE_NUMBER, + "Endurance" = IC_PINTYPE_NUMBER, + "Lifespan" = IC_PINTYPE_NUMBER, + "Weed Resistance" = IC_PINTYPE_NUMBER, + "Weed level" = IC_PINTYPE_NUMBER, + "Pest level" = IC_PINTYPE_NUMBER, + "Water level" = IC_PINTYPE_NUMBER, + "Nutrition level" = IC_PINTYPE_NUMBER, + "harvest" = IC_PINTYPE_NUMBER, + "dead" = IC_PINTYPE_NUMBER, + "plant health" = IC_PINTYPE_NUMBER, + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 10 + +/obj/item/integrated_circuit/input/plant_scanner/do_work() + var/obj/machinery/portable_atmospherics/hydroponics/H = get_pin_data_as_type(IC_INPUT, 1, /obj/machinery/portable_atmospherics/hydroponics) + if(!istype(H)) //Invalid input + return + for(var/i=1, i<=outputs.len, i++) + set_pin_data(IC_OUTPUT, i, null) + if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range.. + if(H.seed) + set_pin_data(IC_OUTPUT, 1, H.seed.seed_name) + set_pin_data(IC_OUTPUT, 2, H.age) + set_pin_data(IC_OUTPUT, 3, H.seed.get_trait(TRAIT_POTENCY)) + set_pin_data(IC_OUTPUT, 4, H.seed.get_trait(TRAIT_YIELD)) + set_pin_data(IC_OUTPUT, 5, H.seed.get_trait(TRAIT_MATURATION)) + set_pin_data(IC_OUTPUT, 6, H.seed.get_trait(TRAIT_PRODUCTION)) + set_pin_data(IC_OUTPUT, 7, H.seed.get_trait(TRAIT_ENDURANCE)) + set_pin_data(IC_OUTPUT, 8, !!H.seed.get_trait(TRAIT_HARVEST_REPEAT)) + set_pin_data(IC_OUTPUT, 9, H.seed.get_trait(TRAIT_WEED_TOLERANCE)) + set_pin_data(IC_OUTPUT, 10, H.weedlevel) + set_pin_data(IC_OUTPUT, 11, H.pestlevel) + set_pin_data(IC_OUTPUT, 12, H.waterlevel) + set_pin_data(IC_OUTPUT, 13, H.nutrilevel) + set_pin_data(IC_OUTPUT, 14, H.harvest) + set_pin_data(IC_OUTPUT, 15, H.dead) + set_pin_data(IC_OUTPUT, 16, H.health) + push_data() + activate_pin(2) + + +/obj/item/integrated_circuit/input/projectile_simulator + name = "projectile simulator" + desc = "An IR laser pointer with a camera. Aim at a target or location and get the output the final result. Aiming at coordinates will output a hit refrence. Aiming at a refrence will output a hit or not hit pulse." + icon_state = "medscan_adv" + complexity = 8 + inputs = list( + "x" = IC_PINTYPE_NUMBER, + "y" = IC_PINTYPE_NUMBER, + "target ref" = IC_PINTYPE_REF + ) + outputs = list( + "target hit" = IC_PINTYPE_REF + ) + activators = list( + "shoot cords" = IC_PINTYPE_PULSE_IN, + "shoot ref" = IC_PINTYPE_PULSE_IN, + "cords out" = IC_PINTYPE_PULSE_OUT, + "target hit" = IC_PINTYPE_PULSE_OUT, + "target missed" = IC_PINTYPE_PULSE_OUT + ) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/projectile_simulator/do_work(ord) + switch(ord) + if(1) + var/list/hit_things + var/turf/T = get_turf(assembly) + var/target_x = get_pin_data(IC_INPUT, 1) + var/target_y = get_pin_data(IC_INPUT, 2) + var/turf/A = locate(clamp(target_x + T.x,0,world.maxx), clamp(target_y + T.y,0,world.maxy), T.z) + var/obj/projectile/trace/trace_projectile = new(assembly.loc) + trace_projectile.pass_flags = ATOM_PASS_TABLE | ATOM_PASS_GLASS | ATOM_PASS_GRILLE + trace_projectile.prepare_trace(A, TRUE) + trace_projectile.fire() + hit_things = trace_projectile.scanned_atoms + if(hit_things.len) + set_pin_data(IC_OUTPUT, 1, WEAKREF(hit_things[1])) + activate_pin(3) + if(2) + var/atom/target = get_pin_data(IC_INPUT, 3) + var/obj/projectile/trace/trace_projectile = new(assembly.loc) + trace_projectile.pass_flags = ATOM_PASS_TABLE | ATOM_PASS_GLASS | ATOM_PASS_GRILLE + trace_projectile.prepare_trace(target, TRUE) + trace_projectile.fire() + if(trace_projectile.could_hit_target) + activate_pin(4) + return + activate_pin(5) + + + + + diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index fc491f64e63..a71007107ad 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -611,10 +611,20 @@ how much reagent is moved per pulse, between 0 and 50. Amount is given for each separate reagent." atom_flags = OPENCONTAINER complexity = 8 - inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER, "list of reagents" = IC_PINTYPE_LIST) - inputs_default = list("3" = 5) + inputs = list( + "source" = IC_PINTYPE_REF, + "target" = IC_PINTYPE_REF, + "injection amount" = IC_PINTYPE_NUMBER, + "list of reagents" = IC_PINTYPE_LIST + ) + inputs_default = list( + "3" = 5 + ) outputs = list() - activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT) + 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 @@ -636,27 +646,25 @@ var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable) var/list/demand = get_pin_data(IC_INPUT, 4) - if(!istype(source) || !istype(target)) //Invalid input + // Check for invalid input. + if(!check_target(source) || !check_target(target)) return - var/turf/T = get_turf(src) - if(source.Adjacent(T) && target.Adjacent(T)) - if(!source.reagents || !target.reagents) - return - if(ismob(source) || ismob(target)) - return - if(!source.is_open_container() || !target.is_open_container()) - return - if(!target.reagents.available_volume()) - return - for(var/datum/reagent/G in source.reagents.reagent_list) - if (!direc) - if(G.id in demand) - source.reagents.trans_id_to(target, G.id, transfer_amount) - else - if(!(G.id in demand)) - source.reagents.trans_id_to(target, G.id, transfer_amount) - activate_pin(2) - push_data() + if(!source.reagents || !target.reagents) + return + // FALSE in those procs makes mobs invalid targets. + if(!source.is_open_container(FALSE) || istype(source, /mob)) + return + if(target.reagents.maximum_volume - target.reagents.total_volume <= 0) + return + for(var/datum/reagent/G in source.reagents?.reagent_list) + if (!direc) + if(G.id in demand) + source.reagents.trans_id_to(target, G.id, transfer_amount) + else + if(!(G.id in demand)) + source.reagents.trans_id_to(target, G.id, transfer_amount) + activate_pin(2) + push_data() /obj/item/integrated_circuit/reagent/extinguisher name = "integrated extinguisher" @@ -712,3 +720,30 @@ activate_pin(2) +/obj/item/integrated_circuit/reagent/purger + name = "reagent purger" + desc = "A safe way to dispose of unwanted fluids." + icon_state = "smoke" + extended_desc = "The purger clears its storage when pulsed." + atom_flags = OPENCONTAINER + volume = 60 + complexity = 4 + cooldown_per_use = 1 + inputs = list() + outputs = list( + "volume used" = IC_PINTYPE_NUMBER, + "self reference" = IC_PINTYPE_SELFREF + ) + activators = list( + "purge" = IC_PINTYPE_PULSE_IN, + "on purged" = IC_PINTYPE_PULSE_OUT + ) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 2 + +/obj/item/integrated_circuit/reagent/purger/on_reagent_change() + push_vol() + +/obj/item/integrated_circuit/reagent/purger/do_work() + reagents.clear_reagents() + activate_pin(2)