diff --git a/code/datums/weakrefs.dm b/code/datums/weakrefs.dm index 3c64d5f60d28..fbe9036ea79c 100644 --- a/code/datums/weakrefs.dm +++ b/code/datums/weakrefs.dm @@ -2,6 +2,7 @@ if(istype(input) && !QDELETED(input)) if(istype(input, /datum/weakref)) return input + if(!input.weak_reference) input.weak_reference = new /datum/weakref(input) return input.weak_reference diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 7f6ffe766b95..9eaa8747b910 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -7,12 +7,14 @@ species = "replicapod" plantname = "Replica Pod" product = /mob/living/carbon/human //verrry special -- Urist + container_type = INJECTABLE|DRAWABLE lifespan = 50 endurance = 8 maturation = 10 production = 1 yield = 1 //seeds if there isn't a dna inside potency = 30 + var/volume = 5 var/ckey = null var/realName = null var/datum/mind/mind = null @@ -23,28 +25,38 @@ var/list/traits = null var/contains_sample = 0 -/obj/item/seeds/replicapod/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/reagent_containers/syringe)) - if(!contains_sample) - for(var/datum/reagent/blood/bloodSample in W.reagents.reagent_list) - if(bloodSample.data["mind"] && bloodSample.data["cloneable"] == 1) - mind = bloodSample.data["mind"] - ckey = bloodSample.data["ckey"] - realName = bloodSample.data["real_name"] - blood_gender = bloodSample.data["gender"] - blood_type = bloodSample.data["blood_type"] - features = bloodSample.data["features"] - factions = bloodSample.data["factions"] - traits = bloodSample.data["traits"] - W.reagents.clear_reagents() - to_chat(user, "You inject the contents of the syringe into the seeds.") - contains_sample = 1 - else - to_chat(user, "The seeds reject the sample!") - else - to_chat(user, "The seeds already contain a genetic sample!") - else - return ..() +/obj/item/seeds/replicapod/Initialize() + . = ..() + + create_reagents(volume) + +/obj/item/seeds/replicapod/on_reagent_change(changetype) + if(changetype == ADD_REAGENT) + var/datum/reagent/blood/B = reagents.has_reagent("blood") + if(B) + if(B.data["mind"] && B.data["cloneable"]) + mind = B.data["mind"] + ckey = B.data["ckey"] + realName = B.data["real_name"] + blood_gender = B.data["gender"] + blood_type = B.data["blood_type"] + features = B.data["features"] + factions = B.data["factions"] + factions = B.data["traits"] + contains_sample = TRUE + visible_message("The [src] is injected with a fresh blood sample.") + else + visible_message("The [src] rejects the sample!") + + if(!reagents.has_reagent("blood")) + mind = null + ckey = null + realName = null + blood_gender = null + blood_type = null + features = null + factions = null + contains_sample = FALSE /obj/item/seeds/replicapod/get_analyzer_text() var/text = ..() @@ -53,10 +65,11 @@ return text -/obj/item/seeds/replicapod/harvest(mob/user = usr) //now that one is fun -- Urist +/obj/item/seeds/replicapod/harvest(mob/user) //now that one is fun -- Urist var/obj/machinery/hydroponics/parent = loc var/make_podman = 0 var/ckey_holder = null + var/list/result = list() if(CONFIG_GET(flag/revival_pod_plants)) if(ckey) for(var/mob/M in GLOB.player_list) @@ -113,6 +126,8 @@ var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK for(var/i=0,iYou remove the dead plant from [src].") @@ -858,9 +859,10 @@ myseed = null update_icon() else - examine(user) + if(user) + examine(user) -/obj/machinery/hydroponics/proc/update_tray(mob/user = usr) +/obj/machinery/hydroponics/proc/update_tray(mob/user) harvest = 0 lastproduce = age if(istype(myseed, /obj/item/seeds/replicapod)) diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index bc467cc9cdf8..f188466434ee 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -1,5 +1,6 @@ /proc/seedify(obj/item/O, t_max, obj/machinery/seed_extractor/extractor, mob/living/user) var/t_amount = 0 + var/list/seeds = list() if(t_max == -1) if(extractor) t_max = rand(1,4) * extractor.seed_multiplier @@ -17,10 +18,11 @@ return while(t_amount < t_max) var/obj/item/seeds/t_prod = F.seed.Copy() + seeds.Add(t_prod) t_prod.forceMove(seedloc) t_amount++ qdel(O) - return 1 + return seeds else if(istype(O, /obj/item/grown)) var/obj/item/grown/F = O diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index f948aa0479ef..f0c3e18cd9af 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -136,7 +136,7 @@ return return_yield -/obj/item/seeds/proc/harvest(mob/user = usr) +/obj/item/seeds/proc/harvest(mob/user) var/obj/machinery/hydroponics/parent = loc //for ease of access var/t_amount = 0 var/list/result = list() @@ -151,7 +151,7 @@ product_name = t_prod.name if(getYield() >= 1) SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name) - parent.update_tray() + parent.update_tray(user) return result diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index ffe0d7193cb2..df1ea857ac9e 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -23,6 +23,7 @@ var/use_cyborg_cell = TRUE var/ext_next_use = 0 var/atom/collw + var/obj/item/card/id/access_card var/allowed_circuit_action_flags = IC_ACTION_COMBAT | IC_ACTION_LONG_RANGE //which circuit flags are allowed var/combat_circuits = 0 //number of combat cicuits in the assembly, used for diagnostic hud var/long_range_circuits = 0 //number of long range cicuits in the assembly, used for diagnostic hud @@ -66,6 +67,10 @@ /obj/item/device/electronic_assembly/Collide(atom/AM) collw = AM .=..() + if((istype(collw, /obj/machinery/door/airlock) || istype(collw, /obj/machinery/door/window)) && (!isnull(access_card))) + var/obj/machinery/door/D = collw + if(D.check_access(access_card)) + D.open() /obj/item/device/electronic_assembly/Initialize() .=..() @@ -81,10 +86,13 @@ diag_hud_set_circuitstat() diag_hud_set_circuittracking() + access_card = new /obj/item/card/id(src) + /obj/item/device/electronic_assembly/Destroy() STOP_PROCESSING(SScircuit, src) for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.remove_from_hud(src) + QDEL_NULL(access_card) return ..() /obj/item/device/electronic_assembly/process() diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index 773c4f06844b..4393170c0180 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -21,6 +21,10 @@ /obj/item/integrated_circuit/proc/set_pin_data(pin_type, pin_number, datum/new_data) + if(islist(new_data)) + for(var/i in 1 to length(new_data)) + if (istype(new_data) && !isweakref(new_data)) + new_data[i] = WEAKREF(new_data[i]) if (istype(new_data) && !isweakref(new_data)) new_data = WEAKREF(new_data) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) @@ -55,6 +59,10 @@ return /datum/integrated_io/proc/get_data() + if(islist(data)) + for(var/i in 1 to length(data)) + if(isweakref(data[i])) + data[i] = data[i].resolve() if(isweakref(data)) return data.resolve() return data diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index 528281c3b740..ca04cc2f3ac5 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -185,7 +185,7 @@ D [1]/ || var/new_data = null switch(type_to_use) if("string") - new_data = stripped_input(user, "Now type in a string.","[src] string writing", istext(default) ? default : null, no_trim = TRUE) + new_data = stripped_multiline_input(user, "Now type in a string.","[src] string writing", istext(default) ? default : null, no_trim = TRUE) if(istext(new_data) && holder.check_interactivity(user) ) to_chat(user, "You input "+new_data+" into the pin.") return new_data diff --git a/code/modules/integrated_electronics/core/special_pins/list_pin.dm b/code/modules/integrated_electronics/core/special_pins/list_pin.dm index e70927fbddb7..9e4731ac3650 100644 --- a/code/modules/integrated_electronics/core/special_pins/list_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/list_pin.dm @@ -13,6 +13,8 @@ t += "List length: [my_list.len]
" t += "\[Refresh\] | " t += "\[Add\] | " + t += "\[Remove\] | " + t += "\[Edit\] | " t += "\[Swap\] | " t += "\[Clear\]
" t += "
" @@ -43,7 +45,7 @@ return if(!position) return - var/target_entry = my_list.Find(position) + var/target_entry = my_list[position] if(target_entry) my_list.Remove(target_entry) @@ -67,7 +69,7 @@ if(holder.check_interactivity(user) && target_entry) var/edited_entry = ask_for_data_type(user, target_entry) if(edited_entry) - target_entry = edited_entry + my_list[my_list.Find(target_entry)] = edited_entry /datum/integrated_io/lists/proc/edit_in_list_by_position(mob/user, var/position) var/list/my_list = data @@ -76,11 +78,11 @@ return if(!position) return - var/target_entry = my_list.Find(position) + var/target_entry = my_list[position] if(target_entry) var/edited_entry = ask_for_data_type(user, target_entry) if(edited_entry) - target_entry = edited_entry + my_list[position] = edited_entry /datum/integrated_io/lists/proc/swap_inside_list(mob/user, var/first_target, var/second_target) var/list/my_list = data diff --git a/code/modules/integrated_electronics/core/special_pins/string_pin.dm b/code/modules/integrated_electronics/core/special_pins/string_pin.dm index 49d6aa9554a2..5aa0794d6eb9 100644 --- a/code/modules/integrated_electronics/core/special_pins/string_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/string_pin.dm @@ -3,7 +3,7 @@ name = "string pin" /datum/integrated_io/string/ask_for_pin_data(mob/user) - var/new_data = stripped_input(user, "Please type in a string.","[src] string writing", no_trim = TRUE) + var/new_data = stripped_multiline_input(user, "Please type in a string.","[src] string writing", no_trim = TRUE) if(holder.check_interactivity(user) ) to_chat(user, "You input [new_data ? "[new_data]" : "NULL"] into the pin.") write_data_to_pin(new_data) diff --git a/code/modules/integrated_electronics/subtypes/access.dm b/code/modules/integrated_electronics/subtypes/access.dm index 0f0626057a45..63b258d782bb 100644 --- a/code/modules/integrated_electronics/subtypes/access.dm +++ b/code/modules/integrated_electronics/subtypes/access.dm @@ -19,6 +19,9 @@ var/list/access = I.GetAccess() var/passkey = strtohex(XorEncrypt(json_encode(access), SScircuit.cipherkey)) + if(assembly) + assembly.access_card.access = access + if(card) // An ID card. set_pin_data(IC_OUTPUT, 1, card.registered_name) set_pin_data(IC_OUTPUT, 2, card.assignment) diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 321a5ac09fd1..a61dc18d347c 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -70,7 +70,7 @@ power_draw_per_use = 4 /obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user) - var/new_input = stripped_input(user, "Enter some words, please.",displayed_name) + var/new_input = stripped_multiline_input(user, "Enter some words, please.",displayed_name) if(istext(new_input) && user.IsAdvancedToolUser()) set_pin_data(IC_OUTPUT, 1, new_input) push_data() @@ -91,7 +91,7 @@ power_draw_per_use = 40 /obj/item/integrated_circuit/input/med_scanner/do_work() - var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) + var/mob/living/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living) if(!istype(H)) //Invalid input return if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range. @@ -125,7 +125,7 @@ power_draw_per_use = 80 /obj/item/integrated_circuit/input/adv_med_scanner/do_work() - var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) + var/mob/living/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living) if(!istype(H)) //Invalid input return if(H in view(get_turf(src))) // Like medbot's analyzer it can be used in range.. @@ -216,7 +216,10 @@ "Nutrition level" = IC_PINTYPE_NUMBER, "harvest" = IC_PINTYPE_NUMBER, "dead" = IC_PINTYPE_NUMBER, - "plant health" = IC_PINTYPE_NUMBER + "plant health" = IC_PINTYPE_NUMBER, + "self sustaining" = IC_PINTYPE_NUMBER, + "using irrigation" = IC_PINTYPE_NUMBER, + "connected trays" = IC_PINTYPE_LIST ) activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH @@ -248,7 +251,9 @@ set_pin_data(IC_OUTPUT, 16, H.harvest) set_pin_data(IC_OUTPUT, 17, H.dead) set_pin_data(IC_OUTPUT, 18, H.plant_health) - + set_pin_data(IC_OUTPUT, 19, H.self_sustaining) + set_pin_data(IC_OUTPUT, 20, H.using_irrigation) + set_pin_data(IC_OUTPUT, 21, H.FindConnected()) push_data() activate_pin(2) @@ -309,6 +314,7 @@ "amount of reagents" = IC_PINTYPE_NUMBER, "density" = IC_PINTYPE_BOOLEAN, "opacity" = IC_PINTYPE_BOOLEAN, + "occupied turf" = IC_PINTYPE_REF ) activators = list( "scan" = IC_PINTYPE_PULSE_IN, @@ -319,7 +325,7 @@ power_draw_per_use = 80 /obj/item/integrated_circuit/input/examiner/do_work() - var/atom/movable/H = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + 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))) @@ -327,6 +333,13 @@ else set_pin_data(IC_OUTPUT, 1, H.name) set_pin_data(IC_OUTPUT, 2, H.desc) + + if(istype(H, /mob/living)) + var/mob/living/M = H + var/msg = M.examine() + if(msg) + set_pin_data(IC_OUTPUT, 2, msg) + 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))) @@ -339,19 +352,20 @@ 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)) push_data() activate_pin(2) /obj/item/integrated_circuit/input/turfpoint - name = "tile pointer" - desc = "This circuit will get tile ref with given absolute coorinates." - extended_desc = "If the machine cannot see the target, it will not be able to scan it.\ - This circuit will only work in an assembly." + name = "Tile pointer" + desc = "This circuit will get tile ref with given absolute coordinates." + extended_desc = "If the machine cannot see the target, it will not be able to calculate the correct direction.\ + This circuit works only inside an assembly." icon_state = "numberpad" complexity = 5 inputs = list("X" = IC_PINTYPE_NUMBER,"Y" = IC_PINTYPE_NUMBER) outputs = list("tile" = IC_PINTYPE_REF) - activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT,"not scanned" = IC_PINTYPE_PULSE_OUT) + activators = list("calculate dir" = IC_PINTYPE_PULSE_IN, "on calculated" = IC_PINTYPE_PULSE_OUT,"not calculated" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 40 @@ -374,7 +388,7 @@ /obj/item/integrated_circuit/input/turfscan name = "tile analyzer" - desc = "This machine vision system can analyze contents of desired tile.And can read letters on floor." + desc = "This circuit can analyze the contents of the scanned turf, and can read letters on the turf." icon_state = "video_camera" complexity = 5 inputs = list( @@ -382,7 +396,8 @@ ) outputs = list( "located ref" = IC_PINTYPE_LIST, - "Written letters" = IC_PINTYPE_STRING + "Written letters" = IC_PINTYPE_STRING, + "area" = IC_PINTYPE_STRING ) activators = list( "scan" = IC_PINTYPE_PULSE_IN, @@ -394,20 +409,23 @@ cooldown_per_use = 10 /obj/item/integrated_circuit/input/turfscan/do_work() - var/turf/H = get_pin_data_as_type(IC_INPUT, 1, /turf) - var/turf/T = get_turf(src) - if(!istype(H)) //Invalid input + var/turf/scanned_turf = get_pin_data_as_type(IC_INPUT, 1, /turf) + var/turf/circuit_turf = get_turf(src) + var/area_name = get_area_name(scanned_turf) + if(!istype(scanned_turf)) //Invalid input + activate_pin(3) return - if(H in view(T)) // This is a camera. It can't examine thngs,that it can't see. - var/list/cont = new() - for(var/obj/U in H) - cont += WEAKREF(U) - for(var/mob/U in H) - cont += WEAKREF(U) - set_pin_data(IC_OUTPUT, 1, cont) + if(scanned_turf in view(circuit_turf)) // This is a camera. It can't examine things that it can't see. + var/list/turf_contents = new() + for(var/obj/U in scanned_turf) + turf_contents += WEAKREF(U) + for(var/mob/U in scanned_turf) + turf_contents += WEAKREF(U) + set_pin_data(IC_OUTPUT, 1, turf_contents) + set_pin_data(IC_OUTPUT, 3, area_name) var/list/St = new() - for(var/obj/effect/decal/cleanable/crayon/I in H) + for(var/obj/effect/decal/cleanable/crayon/I in scanned_turf) St.Add(I.icon_state) if(St.len) set_pin_data(IC_OUTPUT, 2, jointext(St, ",", 1, 0)) @@ -509,21 +527,20 @@ var/turf/T = get_turf(src) var/list/nearby_things = view(radius,T) var/list/valid_things = list() - var/list/GI = list() - GI = I.data - for(var/G in GI) - if(isweakref(G)) //It should search by refs. But don't want.will fix it later. - var/datum/integrated_io/G1 - G1.data = G - var/atom/A = G1.data.resolve() - var/desired_type = A.type - for(var/atom/thing in nearby_things) - if(thing.type != desired_type) - continue - valid_things.Add(WEAKREF(thing)) - else if(istext(G)) - for(var/atom/thing in nearby_things) - if(findtext(addtext(thing.name," ",thing.desc), G, 1, 0) ) + var/list/input_list = list() + input_list = I.data + for(var/item in input_list) + if(!isnull(item) && !isnum(item)) + if(istext(item)) + for(var/atom/thing in nearby_things) + if(findtext(addtext(thing.name," ",thing.desc), item, 1, 0) ) + valid_things.Add(WEAKREF(thing)) + else + var/atom/A = item + var/desired_type = A.type + for(var/atom/thing in nearby_things) + if(thing.type != desired_type) + continue valid_things.Add(WEAKREF(thing)) if(valid_things.len) O.data = valid_things @@ -974,9 +991,9 @@ activate_pin(3) /obj/item/integrated_circuit/input/matscan - name = "material scaner" - desc = "It's special module, designed to get information about material containers of different machinery.\ - Like ORM, lathes, etc." + name = "material scanner" + desc = "This special module is designed to get information about material containers of different machinery, \ + like ORM, lathes, etc." icon_state = "video_camera" complexity = 6 inputs = list( diff --git a/code/modules/integrated_electronics/subtypes/lists.dm b/code/modules/integrated_electronics/subtypes/lists.dm index 9f7dbe078b4e..c9744cc41c73 100644 --- a/code/modules/integrated_electronics/subtypes/lists.dm +++ b/code/modules/integrated_electronics/subtypes/lists.dm @@ -84,6 +84,7 @@ "on failure" = IC_PINTYPE_PULSE_OUT, ) icon_state = "addition" + complexity = 2 spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH cooldown_per_use = 1 @@ -100,6 +101,91 @@ activate_pin(3) +/obj/item/integrated_circuit/lists/filter + name = "filter circuit" + desc = "This circuit will search through a list for anything matching the desired element(s) and outputs two lists: \ + one containing just matching elements, and one with matching elements filtered out." + extended_desc = "Sample accepts lists. If no match is found, original list is sent to output 1." + inputs = list( + "input list" = IC_PINTYPE_LIST, + "sample" = IC_PINTYPE_ANY + ) + outputs = list( + "list filtered" = IC_PINTYPE_LIST, + "list matched" = IC_PINTYPE_LIST + ) + activators = list( + "compute" = IC_PINTYPE_PULSE_IN, + "on match" = IC_PINTYPE_PULSE_OUT, + "on no match" = IC_PINTYPE_PULSE_OUT + ) + complexity = 6 + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/lists/filter/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/sample = get_pin_data(IC_INPUT, 2) + var/list/sample_list = islist(sample) ? uniqueList(sample) : null + var/list/output_list1 = input_list.Copy() + var/list/output_list2 = list() + var/list/output = list() + + for(var/input_item in input_list) + if(sample_list) + for(var/sample_item in sample_list) + if(!isnull(sample_item)) + if(istext(input_item) && istext(sample_item) && findtext(input_item, sample_item)) + output += input_item + if(istype(input_item, /atom) && istext(sample_item)) + var/atom/input_item_atom = input_item + if(istext(sample_item) && findtext(input_item_atom.name, sample_item)) + output += input_item + if(!istext(input_item)) + if(input_item == sample_item) + output += input_item + else + if(!isnull(sample)) + if(istext(input_item) && istext(sample) && findtext(input_item, sample)) + output += input_item + continue + if(istype(input_item, /atom) && istext(sample)) + var/atom/input_itema = input_item + if(findtext(input_itema.name, sample)) + output += input_item + if(!istext(input_item)) + if(input_item == sample) + output += input_item + + output_list1.Remove(output) + output_list2.Add(output) + set_pin_data(IC_OUTPUT, 1, output_list1) + set_pin_data(IC_OUTPUT, 2, output_list2) + push_data() + + output_list1 ~! input_list ? activate_pin(2) : activate_pin(3) + +/obj/item/integrated_circuit/lists/listset + name = "list set circuit" + desc = "This circuit will remove any duplicate entries from a list." + extended_desc = "If there are no duplicate entries, result list will be unchanged." + inputs = list( + "list" = IC_PINTYPE_LIST + ) + outputs = list( + "list filtered" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/lists/listset/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + input_list = uniqueList(input_list) + + set_pin_data(IC_OUTPUT, 1, input_list) + push_data() + activate_pin(2) + /obj/item/integrated_circuit/lists/at name = "at circuit" desc = "This circuit will pick an element from a list by the input index." @@ -114,7 +200,7 @@ activators = list( "compute" = IC_PINTYPE_PULSE_IN, "on success" = IC_PINTYPE_PULSE_OUT, - "on failure" = IC_PINTYPE_PULSE_OUT, + "on failure" = IC_PINTYPE_PULSE_OUT ) icon_state = "addition" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index b6b83b846919..7e45902fe1c7 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -137,7 +137,7 @@ 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 = WEIGHT_CLASS_SMALL complexity = 10 - cooldown_per_use = 8 + cooldown_per_use = 1 ext_cooldown = 1 inputs = list("direction" = IC_PINTYPE_DIR) outputs = list("obstacle" = IC_PINTYPE_REF) @@ -240,61 +240,106 @@ /obj/item/integrated_circuit/manipulation/plant_module name = "plant manipulation module" - desc = "Used to uproot weeds or harvest plants in trays." + desc = "Used to uproot weeds and harvest/plant trays." icon_state = "plant_m" - extended_desc = "The circuit accepts a reference to a hydroponic tray in an adjacent tile. \ - Mode(0- harvest, 1-uproot weeds, 2-uproot plant) determinies action." - cooldown_per_use = 10 + extended_desc = "The circuit accepts a reference to a hydroponic tray or an item in an adjacent tile. \ + Mode input(0-harvest, 1-uproot weeds, 2-uproot plant, 3-plant seed) determines action. \ + Harvesting returns a list of the harvested plants." w_class = WEIGHT_CLASS_TINY complexity = 10 - inputs = list("target" = IC_PINTYPE_REF,"mode" = IC_PINTYPE_NUMBER) - outputs = list() - activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out"=IC_PINTYPE_PULSE_OUT) + inputs = list("tray" = IC_PINTYPE_REF,"mode" = IC_PINTYPE_NUMBER,"item" = IC_PINTYPE_REF) + outputs = list("result" = IC_PINTYPE_LIST) + activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 50 /obj/item/integrated_circuit/manipulation/plant_module/do_work() ..() - var/turf/T = get_turf(src) + var/obj/acting_object = get_object() var/obj/OM = get_pin_data_as_type(IC_INPUT, 1, /obj) - if(istype(OM,/obj/structure/spacevine) && get_pin_data(IC_INPUT, 2) == 2) - qdel(OM) + var/obj/O = get_pin_data_as_type(IC_INPUT, 3, /obj/item) + + if(!check_target(OM)) + push_data() activate_pin(2) return - var/obj/machinery/hydroponics/AM = OM - if(!istype(AM)) //Invalid input - return FALSE - var/mob/living/M = get_turf(AM) - if(!M.Adjacent(T)) - return //Can't reach - switch(get_pin_data(IC_INPUT, 2)) - if(0) - if(AM.myseed) - if(AM.harvest) - AM.myseed.harvest() - AM.harvest = 0 - AM.lastproduce = AM.age - if(!AM.myseed.get_gene(/datum/plant_gene/trait/repeated_harvest)) - qdel(AM.myseed) - AM.myseed = null - AM.dead = 0 - AM.update_icon() - if(1) - AM.weedlevel = 0 - if(2) - if(AM.myseed) //Could be that they're just using it as a de-weeder - AM.age = 0 - AM.plant_health = 0 - if(AM.harvest) - AM.harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it - qdel(AM.myseed) - AM.myseed = null - AM.weedlevel = 0 //Has a side effect of cleaning up those nasty weeds - AM.dead = 0 - AM.update_icon() - else - activate_pin(2) - return FALSE + + if(istype(OM,/obj/structure/spacevine) && check_target(OM) && get_pin_data(IC_INPUT, 2) == 2) + qdel(OM) + push_data() + activate_pin(2) + return + + var/obj/machinery/hydroponics/TR = OM + if(istype(TR)) + switch(get_pin_data(IC_INPUT, 2)) + if(0) + var/list/harvest_output = TR.attack_hand() + for(var/i in 1 to length(harvest_output)) + harvest_output[i] = WEAKREF(harvest_output[i]) + + if(harvest_output.len) + set_pin_data(IC_OUTPUT, 1, harvest_output) + push_data() + if(1) + TR.weedlevel = 0 + if(2) + if(TR.myseed) //Could be that they're just using it as a de-weeder + TR.age = 0 + TR.plant_health = 0 + if(TR.harvest) + TR.harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it + qdel(TR.myseed) + TR.myseed = null + TR.weedlevel = 0 //Has a side effect of cleaning up those nasty weeds + TR.dead = 0 + TR.update_icon() + if(3) + if(!check_target(O)) + activate_pin(2) + return FALSE + + else if(istype(O, /obj/item/seeds) && !istype(O, /obj/item/seeds/sample)) + if(!TR.myseed) + if(istype(O, /obj/item/seeds/kudzu)) + investigate_log("had Kudzu planted in it by [acting_object] at ([x],[y],[z])","kudzu") + acting_object.visible_message("[acting_object] plants [O].") + TR.dead = 0 + TR.myseed = O + TR.age = 1 + TR.plant_health = TR.myseed.endurance + TR.lastcycle = world.time + O.forceMove(TR) + TR.update_icon() + activate_pin(2) + +/obj/item/integrated_circuit/manipulation/seed_extractor + name = "seed extractor module" + desc = "Used to extract seeds from grown produce." + icon_state = "plant_m" + extended_desc = "The circuit accepts a reference to a plant item and extracts seeds from it, outputting the results to a list." + complexity = 8 + inputs = list("target" = IC_PINTYPE_REF) + outputs = list("result" = IC_PINTYPE_LIST) + activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 50 + +/obj/item/integrated_circuit/manipulation/seed_extractor/do_work() + ..() + var/obj/O = get_pin_data_as_type(IC_INPUT, 1, /obj/item) + if(!check_target(O)) + push_data() + activate_pin(2) + return + + var/list/seed_output = seedify(O, -1) + for(var/i in 1 to length(seed_output)) + seed_output[i] = WEAKREF(seed_output[i]) + + if(seed_output.len) + set_pin_data(IC_OUTPUT, 1, seed_output) + push_data() activate_pin(2) /obj/item/integrated_circuit/manipulation/grabber @@ -474,11 +519,12 @@ /obj/item/integrated_circuit/manipulation/matman name = "material manager" - desc = "It's module, designed to automatic storage and distribution of materials" - extended_desc = "The first input is ref to object of interaction.Second input used for interaction with stacks of materials.\ - It accepts amount of sheets to insert.Inputs 3-13 used to direct mat transer between containers of machines.\ - It accepts amount of material to transfer.Positive values means, that circuit will drain another machine.\ - Negative ones means, that machine needs to be filled.Outputs shows current stored amounts of mats." + desc = "This circuit is designed for automatic storage and distribution of materials." + extended_desc = "The first input takes a ref of a machine with a material container. \ + Second input is used for inserting material stacks into the internal material storage. \ + Inputs 3-13 are used to transfer materials between target machine and circuit storage. \ + Positive values will take that number of materials from another machine. \ + Negative values will fill another machine from internal storage. Outputs show current stored amounts of mats." icon_state = "grabber" complexity = 16 inputs = list( @@ -582,10 +628,10 @@ activate_pin(3) else activate_pin(4) - if(4) - AfterMaterialInsert() + if(5) set_pin_data(IC_OUTPUT, 1, WEAKREF(src)) - activate_pin(5) + AfterMaterialInsert() + activate_pin(6) /obj/item/integrated_circuit/manipulation/matman/Destroy() GET_COMPONENT(materials, /datum/component/material_container) diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index c1b173d8c253..6f7fd6eef58f 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -56,7 +56,7 @@ /obj/item/integrated_circuit/output/screen/large/do_work() ..() - var/obj/O = assembly ? loc : assembly + var/obj/O = assembly ? get_turf(assembly) : loc O.visible_message("[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]") /obj/item/integrated_circuit/output/light diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index 7db6ecfcc8d3..b3131663aa61 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -75,9 +75,10 @@ /obj/item/integrated_circuit/power/transmitter/large/do_work() if(..()) // If the above code succeeds, do this below. + var/atom/movable/acting_object = get_object() if(prob(20)) var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread s.set_up(12, 1, src) s.start() - visible_message("\The [assembly] makes some sparks!") + acting_object.visible_message("\The [acting_object] makes some sparks!") return TRUE diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 2cd3ccb8cf93..9f57dd6f435a 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -69,6 +69,34 @@ set_pin_data(IC_OUTPUT, 2, WEAKREF(src)) push_data() +// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way. +// This is a dirty hack to make injecting reagents into them work. +// TODO: refactor that. +/obj/item/integrated_circuit/reagent/proc/inject_tray(obj/machinery/hydroponics/tray, atom/movable/source, amount) + var/atom/movable/acting_object = get_object() + var/list/trays = list(tray) + var/visi_msg = "[acting_object] transfers fluid into [tray]" + + if(amount > 30 && source.reagents.total_volume >= 30 && tray.using_irrigation) + trays = tray.FindConnected() + if (trays.len > 1) + visi_msg += ", setting off the irrigation system" + + acting_object.visible_message("[visi_msg].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + + var/split = round(amount/trays.len) + + for(var/obj/machinery/hydroponics/H in trays) + var/datum/reagents/temp_reagents = new /datum/reagents() + temp_reagents.my_atom = H + + source.reagents.trans_to(temp_reagents, split) + H.applyChemicals(temp_reagents) + + temp_reagents.clear_reagents() + qdel(temp_reagents) + /obj/item/integrated_circuit/reagent/injector name = "integrated hypo-injector" desc = "This scary looking thing is able to pump liquids into whatever it's pointed at." @@ -119,18 +147,6 @@ new_amount = CLAMP(new_amount, 0, volume) transfer_amount = new_amount -// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way. -// This is a dirty hack to make injecting reagents into them work. -// TODO: refactor that. -/obj/item/integrated_circuit/reagent/proc/inject_tray(obj/machinery/hydroponics/tray, atom/movable/source, amount) - var/datum/reagents/temp_reagents = new /datum/reagents() - temp_reagents.my_atom = tray - - source.reagents.trans_to(temp_reagents, amount) - tray.applyChemicals(temp_reagents) - - temp_reagents.clear_reagents() - qdel(temp_reagents) /obj/item/integrated_circuit/reagent/injector/do_work(ord) switch(ord) @@ -150,7 +166,7 @@ return if(!AM.reagents) - if(istype(AM, /obj/machinery/hydroponics) && direction_mode == SYRINGE_INJECT && reagents.total_volume)//injection into tray. + if(istype(AM, /obj/machinery/hydroponics) && direction_mode == SYRINGE_INJECT && reagents.total_volume && transfer_amount)//injection into tray. inject_tray(AM, src, transfer_amount) activate_pin(2) return @@ -186,11 +202,13 @@ activate_pin(3) return busy = FALSE + else reagents.trans_to(AM, transfer_amount) - else - if(!AM.is_drawable() || reagents.total_volume >= reagents.maximum_volume) + if(direction_mode == SYRINGE_DRAW) + if(reagents.total_volume >= reagents.maximum_volume) + acting_object.visible_message("[acting_object] tries to draw from [AM], but the injector is full.") activate_pin(3) return @@ -206,16 +224,23 @@ L.visible_message("[acting_object] takes a blood sample from [L]!", \ "[acting_object] takes a blood sample from you!") else + L.visible_message("[acting_object] fails to take a blood sample from [L].", \ + "[acting_object] fails to take a blood sample from you!") busy = FALSE activate_pin(3) return busy = FALSE + else - tramount = min(tramount, AM.reagents.total_volume) if(!AM.reagents.total_volume) + acting_object.visible_message("[acting_object] tries to draw from [AM], but it is empty!") activate_pin(3) return + if(!AM.is_drawable()) + activate_pin(3) + return + tramount = min(tramount, AM.reagents.total_volume) AM.reagents.trans_to(src, tramount) activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index 6a5a8547c725..e0775f1a230f 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -73,9 +73,9 @@ /obj/item/integrated_circuit/smart/advanced_pathfinder name = "advanced pathfinder" - desc = "This complex circuit using complex processor for path planning." - extended_desc = "This circuit uses global coordinates for target. It will count as obstacle turf with given ref.Passkey\ - is the same as used in door remotes." + desc = "This circuit uses a complex processor for long-range pathfinding." + extended_desc = "This circuit uses absolute coordinates for target. A path will be generated taking obstacle input into account, \ + pathing around any instances of said input. The passkey provided from a card reader is used to create a valid path through doorways." icon_state = "numberpad" complexity = 40 cooldown_per_use = 50 @@ -100,7 +100,8 @@ var/list/Pl = json_decode(XorEncrypt(hextostr(Ps, TRUE), SScircuit.cipherkey)) if(Pl&&islist(Pl)) idc.access = Pl - var/list/P = cir_get_path_to(assembly, locate(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2),assembly.z), /turf/proc/Distance_cardinal, 0, 200, id=idc, exclude=get_turf(get_pin_data_as_type(IC_INPUT,3, /atom)), simulated_only = 0) + var/turf/a_loc = get_turf(assembly) + var/list/P = cir_get_path_to(assembly, locate(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2),a_loc.z), /turf/proc/Distance_cardinal, 0, 200, id=idc, exclude=get_turf(get_pin_data_as_type(IC_INPUT,3, /atom)), simulated_only = 0) if(!P) activate_pin(3) diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 9e0838210eab..c748658c4e8f 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -108,3 +108,4 @@ msg += "*---------*" to_chat(user, msg) + return msg \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 020a8bc59546..efb23cb4536f 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -318,6 +318,7 @@ msg += "*---------*" to_chat(user, msg) + return msg /mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects! var/list/dat = list() diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm index 025d3d8e6d8a..fb345e10ba2c 100644 --- a/code/modules/mob/living/silicon/ai/examine.dm +++ b/code/modules/mob/living/silicon/ai/examine.dm @@ -22,5 +22,5 @@ msg += "*---------*" to_chat(user, msg) - - ..() \ No newline at end of file + ..() + return msg \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm index 3f5b12ae2009..4c4bdb9a3fa6 100644 --- a/code/modules/mob/living/silicon/robot/examine.dm +++ b/code/modules/mob/living/silicon/robot/examine.dm @@ -51,5 +51,5 @@ msg += "*---------*" to_chat(user, msg) - ..() + return msg