[READY] A few additions, tweaks, and fixes for integrated circuits (#36270)

* A few additions, tweaks, and fixes for integrated circuits, and some very minor tweaks to hydroponics and carbon/silicon examine() to support those changes.

🆑 SailorDave
rscadd: A new manipulation circuit, the Seed Extractor. Extracts seeds from produce, and outputs a list of the extracted seeds.
rscadd: A new list circuit, the List Filter. Searches through a list for anything matching the desired element and outputs two lists: one containing just the matches, and the other with matches filtered out.
rscadd: A new list circuit, the Set circuit. Removes duplicate entries from a list.
tweak: The Plant Manipulation circuit can now plant seeds, and outputs a list of harvested plants.
tweak: Reagent circuits can now irrigate connected hydroponic trays and inject blood samples into Replica pods.
tweak: The Examiner circuit outputs worn items and other examined details of carbon and silicon mobs into the description pin.
tweak: List Advanced Locator circuit now accepts refs as well as strings.
bugfix: Fixed the Power Transmitter circuit not properly displaying a message when activated.
bugfix: Medical Analyzer circuit can now properly scan non-human mobs.
/🆑

Additional details:
- Plant Manipulation: obj/item/seeds harvest() proc and obj/machinery/hydroponics attack_hand() procs were adjusted slightly to allow this, returning a list when harvested.

- Seed Extractor Module: obj/machinery/seed_extractor /proc/seedify() was adjusted to return a list of seeds.

- Hydroponics replica pod was adjusted to be injectable|drawable, and use reagents and on_reagent_change() rather than a hardcoded attackby(), so other injection methods can use it to allow blood sampling/future reagent reactions regardless of type.

- IC Examiner Module returns a list of examine() messages from mob/living/carbon, mob/living/carbon/human, mob/living/carbon/silicon, and mob/living/carbon/silicon/ai in the description data pin, rather than outputting null since they had an empty desc var. The relevant examine procs were adjusted to return their messages.

 - IC get_data() and set_pin_data() adjusted to return text/num properly and to WEAKREF/un-WEAKREF the contents of passed lists.

* fixes errors from screwy merge conflicts and replaces illegal proc name

* re-added a traits tag that accidentally got removed

* review changes

* plant analyzer outputs irrigation status and connected trays, search circuit uses 2 Cx down from 6

* examiner outputs the occupied turf of the examined object and can also scan turfs

* string inputs on circuit pins now use multiline input; fixed edit/remove not working on list pins; fixed large screens not outputting visible messages when held

* locomotion now has a cooldown of 0.1sec and their complexity + pathfinder complexity reduced

* assemblies can open doors they have access to from a card reader through collision

* Merge master branch; fixes pathfinder AStar runtime; fixes tile pointer; fixes material manager self-ref; various grammar touchups

* review changes

* fixes improper weakref type checking

* fixes seed extractor merge confict, removes unnecessary weakref change

* dang ol merge undoing my changes HECK

* updated to robbym's tile pointer PR with clearer var names

* added missing "not scanned" results to tile analyzer, removes duplicate circuit entries(???? how)
This commit is contained in:
SailorDave
2018-04-21 09:00:25 -04:00
committed by yogstation13-bot
parent 46f0506ccd
commit fade44bd7c
22 changed files with 375 additions and 156 deletions

View File

@@ -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

View File

@@ -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, "<span class='notice'>You inject the contents of the syringe into the seeds.</span>")
contains_sample = 1
else
to_chat(user, "<span class='warning'>The seeds reject the sample!</span>")
else
to_chat(user, "<span class='warning'>The seeds already contain a genetic sample!</span>")
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("<span class='notice'>The [src] is injected with a fresh blood sample.</span>")
else
visible_message("<span class='warning'>The [src] rejects the sample!</span>")
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,i<seed_count,i++)
var/obj/item/seeds/replicapod/harvestseeds = src.Copy()
result.Add(harvestseeds)
harvestseeds.forceMove(output_loc)
parent.update_tray()
return result

View File

@@ -850,7 +850,8 @@
if(issilicon(user)) //How does AI know what plant is?
return
if(harvest)
myseed.harvest(user)
return myseed.harvest(user)
else if(dead)
dead = 0
to_chat(user, "<span class='notice'>You remove the dead plant from [src].</span>")
@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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, "<span class='notice'>You input "+new_data+" into the pin.</span>")
return new_data

View File

@@ -13,6 +13,8 @@
t += "List length: [my_list.len]<br>"
t += "<a href='?src=[REF(src)]'>\[Refresh\]</a> | "
t += "<a href='?src=[REF(src)];add=1'>\[Add\]</a> | "
t += "<a href='?src=[REF(src)];remove=1'>\[Remove\]</a> | "
t += "<a href='?src=[REF(src)];edit=1'>\[Edit\]</a> | "
t += "<a href='?src=[REF(src)];swap=1'>\[Swap\]</a> | "
t += "<a href='?src=[REF(src)];clear=1'>\[Clear\]</a><br>"
t += "<hr>"
@@ -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

View File

@@ -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, "<span class='notice'>You input [new_data ? "[new_data]" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)

View File

@@ -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)

View File

@@ -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(

View File

@@ -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

View File

@@ -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("<span class='notice'>[acting_object] plants [O].</span>")
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)

View File

@@ -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("<span class='notice'>[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]</span>")
/obj/item/integrated_circuit/output/light

View File

@@ -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("<span class='warning'>\The [assembly] makes some sparks!</span>")
acting_object.visible_message("<span class='warning'>\The [acting_object] makes some sparks!</span>")
return TRUE

View File

@@ -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("<span class='notice'>[visi_msg].</span>")
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("<span class='danger'>[acting_object] takes a blood sample from [L]!</span>", \
"<span class='userdanger'>[acting_object] takes a blood sample from you!</span>")
else
L.visible_message("<span class='warning'>[acting_object] fails to take a blood sample from [L].</span>", \
"<span class='userdanger'>[acting_object] fails to take a blood sample from you!</span>")
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("<span class='notice'>[acting_object] tries to draw from [AM], but it is empty!</span>")
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)

View File

@@ -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)

View File

@@ -108,3 +108,4 @@
msg += "*---------*</span>"
to_chat(user, msg)
return msg

View File

@@ -318,6 +318,7 @@
msg += "*---------*</span>"
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()

View File

@@ -22,5 +22,5 @@
msg += "*---------*</span>"
to_chat(user, msg)
..()
..()
return msg

View File

@@ -51,5 +51,5 @@
msg += "*---------*</span>"
to_chat(user, msg)
..()
return msg