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