mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-18 05:12:55 +00:00
Refactored the attack proc signature. Added signals and components for the attack proc. Added signals and components for the attackby proc. Adjusted some leftover attackby procs signatures. Added grep test to ensure people don't keep adding attack/attackby procs with the wrong signature.
370 lines
12 KiB
Plaintext
370 lines
12 KiB
Plaintext
/*
|
|
Sampling
|
|
*/
|
|
/obj/item/sampler
|
|
name = "science sampler"
|
|
desc = "A multi-purpose sampling device designed by Zeng-Hu Pharmaceuticals for gathering samples during their research expeditions."
|
|
desc_extended = "The \"Chimera\" model field sampling device was developed by Zeng-Hu Pharmaceuticals in the 2450s to make allow their \
|
|
researchers to take a variety of samples, ranging from plant and animal tissue to soil or water samples, compacted into \
|
|
a single handheld device. It became widely popular even among rival corporations and independant research groups, with \
|
|
its versatility and compact nature making it the tool-of-choice for almost every modern scientific expedition."
|
|
desc_info = "It has attachments allowing for sampling of biological tissue, surface soil and water sources. Must be loaded with a vial. Alt-click to cycle between attachments."
|
|
icon = 'icons/obj/item/sampling.dmi'
|
|
icon_state = "sampler"
|
|
item_state = "sampler"
|
|
contained_sprite = TRUE
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
/**
|
|
* Which attachment we are using
|
|
*/
|
|
var/attachment = SAMPLE_BIO
|
|
/**
|
|
* The vial we load our sample into
|
|
*/
|
|
var/obj/item/reagent_containers/glass/beaker/vial/vial
|
|
|
|
/obj/item/sampler/Initialize(mapload, ...)
|
|
. = ..()
|
|
update_icon()
|
|
|
|
/obj/item/sampler/attackby(obj/item/attacking_item, mob/user, params)
|
|
if(istype(attacking_item, /obj/item/reagent_containers/glass/beaker/vial))
|
|
if(!vial)
|
|
to_chat(user, SPAN_NOTICE("You insert \the [attacking_item] into \the [src]."))
|
|
vial = attacking_item
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
H.drop_from_inventory(vial)
|
|
vial.forceMove(src)
|
|
update_icon()
|
|
return TRUE
|
|
to_chat(user, SPAN_NOTICE("\The [src] already has a vial inserted."))
|
|
return ..()
|
|
|
|
/obj/item/sampler/attack_hand(mob/user)
|
|
if(vial)
|
|
to_chat(user, SPAN_NOTICE("You remove \the [vial] from \the [src]."))
|
|
user.put_in_active_hand(vial)
|
|
vial = null
|
|
update_icon()
|
|
return TRUE
|
|
return ..()
|
|
|
|
/obj/item/sampler/AltClick(mob/user)
|
|
attachment = next_in_list(attachment, ALL_SAMPLE_ATTACHMENTS)
|
|
to_chat(user, SPAN_NOTICE("You switch \the [src] to its [attachment] attachment."))
|
|
update_icon()
|
|
|
|
/obj/item/sampler/update_icon()
|
|
. = ..()
|
|
ClearOverlays()
|
|
if(vial)
|
|
icon_state = "[initial(icon_state)]_loaded"
|
|
if(vial.reagents.total_volume)
|
|
AddOverlays(overlay_image(icon, "sampler_full"))
|
|
else
|
|
icon_state = initial(icon_state)
|
|
var/image/I
|
|
switch(attachment)
|
|
if(SAMPLE_BIO)
|
|
I = overlay_image(icon, "bio_attachment")
|
|
if(SAMPLE_SOIL)
|
|
I = overlay_image(icon, "soil_attachment")
|
|
if(SAMPLE_WATER)
|
|
I = overlay_image(icon, "water_attachment")
|
|
if(I)
|
|
AddOverlays(I)
|
|
|
|
/obj/item/sampler/attack(mob/living/target_mob, mob/living/user, target_zone)
|
|
if(!vial || vial.reagents.total_volume)
|
|
return ..()
|
|
else
|
|
return FALSE
|
|
|
|
/obj/item/sampler/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
|
if(!vial || vial.reagents.total_volume)
|
|
return ..()
|
|
if(try_sample(target, user))
|
|
to_chat(user, SPAN_NOTICE("\The [src]'s attachment whirrs as it samples \the [target]."))
|
|
else
|
|
to_chat(user, SPAN_NOTICE("\The [src]'s attachment buzzes as it fails to sample \the [target]. Maybe try another attachment?"))
|
|
|
|
/**
|
|
* Tries to sample the target using our current attachment, loading a sample into our vial if successful.
|
|
*/
|
|
/obj/item/sampler/proc/try_sample(atom/target, mob/user)
|
|
switch(attachment)
|
|
if(SAMPLE_BIO)
|
|
if(istype(target, /mob/living/simple_animal))
|
|
var/mob/living/simple_animal/fauna = target
|
|
if(!fauna.sample_data)
|
|
return FALSE
|
|
vial.reagents.add_reagent(/singleton/reagent/biological_tissue, 10, fauna.sample_data)
|
|
return TRUE
|
|
if(istype(target, /obj/structure/flora))
|
|
var/obj/structure/flora/flora = target
|
|
if(flora.is_rock)
|
|
return FALSE
|
|
vial.reagents.add_reagent(/singleton/reagent/biological_tissue, 10, flora.sample_data)
|
|
return TRUE
|
|
if(SAMPLE_SOIL)
|
|
if(istype(target, /obj/structure/flora))
|
|
var/obj/structure/flora/rock = target
|
|
if(!rock.is_rock)
|
|
return FALSE
|
|
vial.reagents.add_reagent(/singleton/reagent/soil, 10, rock.sample_data)
|
|
return TRUE
|
|
if(istype(target, /turf/simulated/floor/exoplanet))
|
|
var/turf/simulated/floor/exoplanet/ground = target
|
|
var/obj/effect/overmap/visitable/sector/planet = GLOB.map_sectors["[target.z]"]
|
|
if(istype(ground, /turf/simulated/floor/exoplanet/water) || !ground.has_resources || !istype(planet))
|
|
return FALSE
|
|
var/list/possible_data = planet.soil_data.Copy()
|
|
var/list/data = list()
|
|
for(var/_ in 1 to rand(2,4))
|
|
var/d = pick(possible_data)
|
|
possible_data -= d
|
|
data += d
|
|
vial.reagents.add_reagent(/singleton/reagent/soil, 10, data)
|
|
return TRUE
|
|
if(SAMPLE_WATER)
|
|
if(istype(target, /turf/simulated/floor/exoplanet/water))
|
|
var/obj/effect/overmap/visitable/sector/planet = GLOB.map_sectors["[target.z]"]
|
|
if(!istype(planet))
|
|
return FALSE
|
|
var/list/possible_data = planet.water_data.Copy()
|
|
var/list/data = list()
|
|
for(var/_ in 1 to rand(2,4))
|
|
var/d = pick(possible_data)
|
|
possible_data -= d
|
|
data += d
|
|
vial.reagents.add_reagent(/singleton/reagent/water, 10, data)
|
|
return TRUE
|
|
|
|
/obj/machinery/microscope/science
|
|
name = "compound microscope"
|
|
desc = "A less-than-state-of-the-art means of examining tiny samples. At least it has a printer for recording its results."
|
|
icon = 'icons/obj/item/sampling.dmi'
|
|
density = FALSE
|
|
allowed_analysis = MICROSCOPE_CELLS
|
|
|
|
/obj/machinery/centrifuge
|
|
name = "centrifuge"
|
|
desc = "A device capable of spinning samples at 1000 RPM, to separate their components for analysis. It has a printer attached to record its results."
|
|
icon = 'icons/obj/item/sampling.dmi'
|
|
icon_state = "centrifuge_0"
|
|
anchored = TRUE
|
|
density = FALSE
|
|
|
|
/**
|
|
* The sample vials loaded in this centrifuge
|
|
*/
|
|
var/list/obj/item/reagent_containers/glass/beaker/vial/samples = list()
|
|
/**
|
|
* The report number of our last report
|
|
*/
|
|
var/report_num = 0
|
|
|
|
/obj/machinery/centrifuge/Initialize(mapload, d, populate_components, is_internal)
|
|
. = ..()
|
|
update_icon()
|
|
|
|
/obj/machinery/centrifuge/attackby(obj/item/attacking_item, mob/user)
|
|
|
|
if(LAZYLEN(samples) >= 4)
|
|
to_chat(user, SPAN_WARNING("\The [src] is already full with samples."))
|
|
return
|
|
|
|
if(istype(attacking_item, /obj/item/reagent_containers/glass/beaker/vial))
|
|
to_chat(user, SPAN_NOTICE("You insert \the [attacking_item] into \the [src]."))
|
|
user.unEquip(attacking_item)
|
|
attacking_item.forceMove(src)
|
|
samples += attacking_item
|
|
update_icon()
|
|
return
|
|
|
|
/obj/machinery/centrifuge/attack_hand(mob/user)
|
|
|
|
if(!LAZYLEN(samples))
|
|
to_chat(user, SPAN_WARNING("\The [src] has no samples to examine."))
|
|
return
|
|
|
|
if(LAZYLEN(samples) == 1 || LAZYLEN(samples) == 3) //Odd number, unbalanced
|
|
to_chat(user, SPAN_WARNING("\The [src] is unbalanced. Try adding blank samples as counter-weights."))
|
|
return
|
|
|
|
to_chat(user, SPAN_NOTICE("\The [src] begins to spin, separating the contents of the samples."))
|
|
|
|
icon_state = "centrifuge_working"
|
|
addtimer(CALLBACK(src, PROC_REF(process_samples)), 30 SECONDS)
|
|
|
|
/obj/machinery/centrifuge/proc/process_samples()
|
|
update_icon()
|
|
visible_message(SPAN_NOTICE("\The [src] prints out a report of its findings."))
|
|
var/obj/item/paper/report = new()
|
|
|
|
report_num++
|
|
var/pname = "Centrifuge report #[report_num]"
|
|
var/info = "<b><font size=\"4\">Centrifugal analysis report #[report_num]</font></b><HR>"
|
|
var/sample = 1
|
|
for(var/obj/item/reagent_containers/glass/beaker/vial/V in samples)
|
|
var/list/soil = REAGENT_DATA(V.reagents, /singleton/reagent/soil)
|
|
if(soil)
|
|
info += "Separation of sample [sample] has revealed the following characteristics<ul>"
|
|
for(var/characteristic in soil)
|
|
info += "<li>[characteristic]</li>"
|
|
info += "</ul>"
|
|
else
|
|
info += "<li>No soil or dust found in sample [sample].</li>"
|
|
sample++
|
|
|
|
report.set_content_unsafe(pname, info)
|
|
|
|
if(report)
|
|
report.update_icon()
|
|
print(report)
|
|
|
|
/**
|
|
* Removes the last sample from the centrifuge
|
|
*/
|
|
/obj/machinery/centrifuge/proc/remove_sample(mob/living/remover)
|
|
if(!istype(remover) || remover.incapacitated() || !Adjacent(remover))
|
|
return
|
|
if(!LAZYLEN(samples))
|
|
to_chat(remover, SPAN_WARNING("\The [src] does not have a sample in it."))
|
|
return
|
|
var/obj/item/reagent_containers/glass/beaker/vial/sample = samples[LAZYLEN(samples)]
|
|
to_chat(remover, SPAN_NOTICE("You remove \the [sample] from \the [src]."))
|
|
sample.forceMove(get_turf(src))
|
|
remover.put_in_hands(sample)
|
|
samples -= sample
|
|
update_icon()
|
|
|
|
/obj/machinery/centrifuge/AltClick()
|
|
remove_sample(usr)
|
|
|
|
/obj/machinery/centrifuge/MouseDrop(var/atom/other)
|
|
if(usr == other)
|
|
remove_sample(usr)
|
|
else
|
|
return ..()
|
|
|
|
/obj/machinery/centrifuge/update_icon()
|
|
. = ..()
|
|
icon_state = "centrifuge_[LAZYLEN(samples)]"
|
|
|
|
/obj/machinery/spectrophotometer
|
|
name = "spectrophotometer"
|
|
desc = "A device to analyse liquid samples by shining various frequencies of light through and measuring absorption. It has a printer attached to record its results."
|
|
icon = 'icons/obj/item/sampling.dmi'
|
|
icon_state = "spectrophotometer_closed_empty"
|
|
anchored = TRUE
|
|
density = TRUE
|
|
|
|
/**
|
|
* The sample vial to analyse
|
|
*/
|
|
var/obj/item/reagent_containers/glass/beaker/vial/sample
|
|
/**
|
|
* The report number of our last report
|
|
*/
|
|
var/report_num = 0
|
|
/**
|
|
* Whether this spectrophotometer has been calibrated already.
|
|
* Must be done with pure water
|
|
*/
|
|
var/zeroed = FALSE
|
|
/**
|
|
* Whether the hatch is open, allowing samples to be added/removed
|
|
*/
|
|
var/open = FALSE
|
|
|
|
/obj/machinery/spectrophotometer/Initialize(mapload, d, populate_components, is_internal)
|
|
. = ..()
|
|
update_icon()
|
|
|
|
/obj/machinery/spectrophotometer/attackby(obj/item/attacking_item, mob/user)
|
|
if(!open)
|
|
to_chat(user, SPAN_WARNING("\The [src] is closed."))
|
|
return
|
|
|
|
if(sample)
|
|
to_chat(user, SPAN_WARNING("\The [src] already has a sample."))
|
|
return
|
|
|
|
if(istype(attacking_item, /obj/item/reagent_containers/glass/beaker/vial))
|
|
to_chat(user, SPAN_NOTICE("You insert \the [attacking_item] into \the [src]."))
|
|
user.unEquip(attacking_item)
|
|
attacking_item.forceMove(src)
|
|
sample = attacking_item
|
|
update_icon()
|
|
return
|
|
|
|
/obj/machinery/spectrophotometer/attack_hand(mob/user)
|
|
if(open)
|
|
if(!sample)
|
|
to_chat(user, SPAN_WARNING("\The [src] has no samples to remove."))
|
|
return
|
|
to_chat(user, SPAN_NOTICE("You remove \the [sample] from \the [src]."))
|
|
sample.forceMove(get_turf(src))
|
|
user.put_in_hands(sample)
|
|
sample = null
|
|
update_icon()
|
|
return
|
|
|
|
if(!sample)
|
|
to_chat(user, SPAN_WARNING("\The [src] has no sample to examine."))
|
|
return
|
|
|
|
if(!REAGENT_VOLUME(sample.reagents, /singleton/reagent/water))
|
|
to_chat(user, SPAN_WARNING("\The [src] can only examine water samples."))
|
|
return
|
|
|
|
if(!zeroed && REAGENT_DATA(sample.reagents, /singleton/reagent/water))
|
|
to_chat(user, SPAN_WARNING("\The [src] has not yet been calibrated. Try zeroing it with a blank sample."))
|
|
return
|
|
|
|
to_chat(user, SPAN_NOTICE("\The [src] begins to glow, shining light through its sample."))
|
|
|
|
icon_state = "spectrophotometer_working"
|
|
addtimer(CALLBACK(src, PROC_REF(process_sample)), 15 SECONDS)
|
|
|
|
/**
|
|
* Prints a report of the analysis after finishing, or zeroes successfully
|
|
*/
|
|
/obj/machinery/spectrophotometer/proc/process_sample()
|
|
update_icon()
|
|
if(!zeroed)
|
|
zeroed = TRUE
|
|
visible_message(SPAN_NOTICE("\The [src] beeps, \"Calibration complete!\""))
|
|
return
|
|
|
|
visible_message(SPAN_NOTICE("\The [src] prints out a report of its findings."))
|
|
var/obj/item/paper/report = new()
|
|
|
|
report_num++
|
|
var/pname = "Spectrophotometer report #[report_num]"
|
|
var/info = "<b><font size=\"4\">Spectrophotometry anaylsis report #[report_num]</font></b><HR>"
|
|
var/list/water = REAGENT_DATA(sample.reagents, /singleton/reagent/water)
|
|
if(water)
|
|
info += "Absorption spectra of [src] have revealed the following electrolytes present<ul>"
|
|
for(var/characteristic in water)
|
|
info += "<li>[characteristic]</li>"
|
|
info += "</ul>"
|
|
else
|
|
info += "Absorption spectra of [src] match those of pure water."
|
|
|
|
report.set_content_unsafe(pname, info)
|
|
|
|
if(report)
|
|
report.update_icon()
|
|
print(report)
|
|
|
|
/obj/machinery/spectrophotometer/AltClick()
|
|
open = !open
|
|
update_icon()
|
|
|
|
/obj/machinery/spectrophotometer/update_icon()
|
|
. = ..()
|
|
icon_state = "spectrophotometer_[open ? "open" : "closed"]_[sample ? "full" : "empty"]"
|