/* 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 = "Centrifugal analysis report #[report_num]