/obj/item/measuring_tape name = "measuring tape" desc = "A coiled metallic tape used to check dimensions and lengths." icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "measuring" origin_tech = list(TECH_MATERIAL = 1) matter = list(MAT_STEEL = 100) w_class = ITEMSIZE_SMALL /obj/item/storage/bag/fossils name = "Fossil Satchel" desc = "Transports delicate fossils in suspension so they don't break during transit." icon = 'icons/obj/mining.dmi' icon_state = "satchel" slot_flags = SLOT_BELT | SLOT_POCKET w_class = ITEMSIZE_NORMAL storage_slots = 50 max_storage_space = ITEMSIZE_COST_NORMAL * 50 max_w_class = ITEMSIZE_NORMAL can_hold = list(/obj/item/fossil) /obj/item/storage/box/samplebags name = "sample bag box" desc = "A box claiming to contain sample bags." /obj/item/storage/box/samplebags/Initialize(mapload) . = ..() for(var/i = 1 to 7) var/obj/item/evidencebag/S = new(src) S.name = "sample bag" S.desc = "a bag for holding research samples." /obj/item/ano_scanner name = "Alden-Saraspova counter" desc = "Aids in triangulation of exotic particles." icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "xenoarch_scanner" item_state = "analyzer" origin_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 3) matter = list(MAT_STEEL = 10000,MAT_GLASS = 5000) w_class = ITEMSIZE_SMALL slot_flags = SLOT_BELT var/last_scan_time = 0 var/scan_delay = 25 var/last_repopulation_time = 0 var/repopulation_delay = 600 //Anti spam. /obj/item/ano_scanner/attack_self(mob/user) . = ..(user) if(.) return TRUE interact(user) /obj/item/ano_scanner/interact(mob/user) if(world.time - last_scan_time >= scan_delay) last_scan_time = world.time var/nearestTargetDist = -1 var/nearestTargetId var/nearestSimpleTargetDist = -1 var/turf/cur_turf = get_turf(src) if(SSxenoarch) //Sanity check due to runtimes ~Z for(var/turf/simulated/mineral/T as anything in SSxenoarch.artifact_spawning_turfs) if(T.density && T.artifact_find) if(T.z == cur_turf.z) var/cur_dist = get_dist(cur_turf, T) * 2 if(nearestTargetDist < 0 || cur_dist < nearestTargetDist) nearestTargetDist = cur_dist + rand() * 2 - 1 nearestTargetId = T.artifact_find.artifact_id else SSxenoarch.artifact_spawning_turfs.Remove(T) for(var/turf/simulated/mineral/T as anything in SSxenoarch.digsite_spawning_turfs) if(T.density && T.finds && T.finds.len) if(T.z == cur_turf.z) var/cur_dist = get_dist(cur_turf, T) * 2 if(nearestSimpleTargetDist < 0 || cur_dist < nearestSimpleTargetDist) nearestSimpleTargetDist = cur_dist + rand() * 2 - 1 else SSxenoarch.digsite_spawning_turfs.Remove(T) if(SSxenoarch && ((nearestTargetDist == -1) || (nearestSimpleTargetDist == -1)) && user.z && (world.time - last_repopulation_time >= repopulation_delay)) if(!(user.z in using_map.xenoarch_exempt_levels)) //We found no artifacts and our Z level is not spawn exempt. Time for random generation. last_repopulation_time = world.time to_chat(user, "The [src] beeps and buzzes, a warning popping up on screen stating 'No artifacts detected on current wavelength. Swapping to different wavelength. Please try scanning momentarily.'") SSxenoarch.continual_generation(user) if(nearestTargetDist >= 0) to_chat(user, "Large artifact energy signature detected on wavelength '[nearestTargetId]' in a radius of [nearestTargetDist]m[nearestSimpleTargetDist > 0 ? "; small anomaly detected in a radius of [nearestSimpleTargetDist]m" : ""]") else if(nearestSimpleTargetDist >= 0) to_chat(user, "Small anomaly detected in a radius of [nearestSimpleTargetDist]m.") else to_chat(user, "Background radiation levels detected.") else to_chat(user, "Scanning array is recharging.") /obj/item/depth_scanner name = "depth analysis scanner" desc = "Used to check spatial depth and density of rock outcroppings." icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "depth_scanner" item_state = "analyzer" origin_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2) matter = list(MAT_STEEL = 1000,MAT_GLASS = 1000) w_class = ITEMSIZE_SMALL slot_flags = SLOT_BELT var/list/positive_locations = list() var/datum/depth_scan/current /datum/depth_scan var/time = "" var/coords = "" var/depth = "" var/record_index = 1 var/material = "unknown" /obj/item/depth_scanner/proc/scan_atom(var/mob/user, var/atom/A) user.visible_message(span_bold("\The [user]") + " scans \the [A], the air around them humming gently.") if(istype(A, /turf/simulated/mineral)) var/turf/simulated/mineral/M = A if((M.finds && M.finds.len) || M.artifact_find) //create a new scanlog entry var/datum/depth_scan/D = new() D.coords = "[M.x]:[M.y]:[M.z]" D.time = stationtime2text() D.record_index = positive_locations.len + 1 D.material = M.mineral ? M.mineral.display_name : "Rock" //find the first artifact and store it if(M.finds.len) var/datum/find/F = M.finds[1] D.depth = "[F.excavation_required]" D.material = get_responsive_reagent(F.find_type) positive_locations.Add(D) to_chat(user, span_notice("[icon2html(src, user.client)] [src] pings.")) else if(istype(A, /obj/structure/boulder)) var/obj/structure/boulder/B = A if(B.artifact_find) //create a new scanlog entry var/datum/depth_scan/D = new() D.coords = "[B.x]:[B.y]:[B.z]" D.time = stationtime2text() D.record_index = positive_locations.len + 1 //these values are arbitrary D.depth = rand(150, 200) positive_locations.Add(D) to_chat(user, span_notice("[icon2html(src, user.client)] [src] pings [pick("madly","wildly","excitedly","crazily")]!")) /obj/item/depth_scanner/attack_self(mob/user) . = ..(user) if(.) return TRUE tgui_interact(user) /obj/item/depth_scanner/tgui_state(mob/user) return GLOB.tgui_deep_inventory_state /obj/item/depth_scanner/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "XenoarchDepthScanner", name) ui.open() /obj/item/depth_scanner/tgui_static_data(mob/user) . = ..() if(isrobot(loc)) var/mob/living/silicon/robot/robot_owner = loc .["theme"] = robot_owner.get_ui_theme() /obj/item/depth_scanner/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() data["current"] = list() if(current) data["current"] = list( "time" = current.time, "coords" = current.coords, "depth" = current.depth, "index" = current.record_index, ) data["current"]["material"] = "Unknown" var/index = GLOB.responsive_carriers.Find(current.material) if(index > 0 && index <= LAZYLEN(GLOB.finds_as_strings)) data["current"]["material"] = GLOB.finds_as_strings[index] var/list/plocs = list() data["positive_locations"] = plocs for(var/i in 1 to LAZYLEN(positive_locations)) var/datum/depth_scan/D = positive_locations[i] plocs.Add(list(list( "index" = i, "time" = D.time, "coords" = D.coords, ))) return data /obj/item/depth_scanner/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return TRUE switch(action) if("select") var/index = text2num(params["select"]) if(index && index <= LAZYLEN(positive_locations)) current = positive_locations[index] return TRUE if("clear") var/index = text2num(params["clear"]) if(index) if(index <= LAZYLEN(positive_locations)) var/datum/depth_scan/D = positive_locations[index] positive_locations.Remove(D) qdel(D) current = null else QDEL_LIST_NULL(positive_locations) positive_locations = list() QDEL_NULL(current) return TRUE /obj/item/beacon_locator name = "locater device" desc = "Used to scan and locate signals on a particular frequency." icon = 'icons/obj/device.dmi' icon_state = "pinoff" //pinonfar, pinonmedium, pinonclose, pinondirect, pinonnull item_state = "electronic" origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) matter = list(MAT_STEEL = 1000,MAT_GLASS = 500) var/frequency = PUB_FREQ var/scan_ticks = 0 var/obj/item/radio/target_radio /obj/item/beacon_locator/Initialize(mapload) . = ..() START_PROCESSING(SSobj, src) /obj/item/beacon_locator/Destroy() STOP_PROCESSING(SSobj, src) . = ..() /obj/item/beacon_locator/process() if(target_radio) set_dir(get_dir(src,target_radio)) switch(get_dist(src,target_radio)) if(0 to 3) icon_state = "pinondirect" if(4 to 10) icon_state = "pinonclose" if(11 to 30) icon_state = "pinonmedium" if(31 to INFINITY) icon_state = "pinonfar" else if(scan_ticks) icon_state = "pinonnull" scan_ticks++ if(prob(scan_ticks * 10)) spawn(0) set background = 1 if(datum_flags & DF_ISPROCESSING) //scan radios in the world to try and find one var/turf/T = get_turf(src) var/cur_dist = 999 for(var/obj/item/radio/beacon/R in GLOB.all_beacons) if(R.z == T.z && R.frequency == src.frequency) var/check_dist = get_dist(T,R) if(check_dist < cur_dist) cur_dist = check_dist target_radio = R scan_ticks = 0 if(target_radio) T.visible_message("[icon2html(src,viewers(src))] [src] [pick("chirps","chirrups","cheeps")] happily.") else T.visible_message("[icon2html(src,viewers(src))] [src] [pick("chirps","chirrups","cheeps")] sadly.") else icon_state = "pinoff" /obj/item/beacon_locator/attack_self(mob/user) . = ..(user) if(.) return TRUE return tgui_interact(user) /obj/item/beacon_locator/tgui_state(mob/user) return GLOB.tgui_inventory_state /obj/item/beacon_locator/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "BeaconLocator", name) ui.open() /obj/item/beacon_locator/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() data["scan_ticks"] = scan_ticks data["degrees"] = null if(target_radio) data["degrees"] = round(Get_Angle(get_turf(src), get_turf(target_radio))) data["rawfreq"] = frequency data["minFrequency"] = RADIO_LOW_FREQ data["maxFrequency"] = RADIO_HIGH_FREQ return data /obj/item/beacon_locator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) return TRUE switch(action) if("reset_tracking") scan_ticks = 1 target_radio = null return TRUE if("setFrequency") var/new_frequency = (text2num(params["freq"])) new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) frequency = new_frequency return TRUE /obj/item/xenoarch_multi_tool name = "xenoarcheology multitool" desc = "Has the features of the Alden-Saraspova counter, a measuring tape, and a depth analysis scanner all in one!" icon_state = "ano_scanner2" item_state = "lampgreen" icon = 'icons/obj/xenoarchaeology.dmi' origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2) matter = list(MAT_STEEL = 10000,MAT_GLASS = 5000) w_class = ITEMSIZE_SMALL slot_flags = SLOT_BELT var/mode = 1 //Start off scanning. 1 = scanning, 0 = measuring var/obj/item/ano_scanner/anomaly_scanner = null var/obj/item/depth_scanner/depth_scanner = null /obj/item/xenoarch_multi_tool/Initialize(mapload) . = ..() anomaly_scanner = new/obj/item/ano_scanner(src) depth_scanner = new/obj/item/depth_scanner(src) /obj/item/xenoarch_multi_tool/attack_self(mob/user) . = ..(user) if(.) return TRUE depth_scanner.tgui_interact(user) /obj/item/xenoarch_multi_tool/verb/swap_settings() var/mob/living/user = usr set name = "Swap Functionality" set desc = "Swap between the scanning and measuring functionality.." mode = !mode if(mode) to_chat(user, "The device will now scan for artifacts.") else to_chat(user, "The device will now measure depth dug.") /obj/item/xenoarch_multi_tool/verb/scan_for_anomalies() var/mob/living/user = usr set name = "Scan for Anomalies" set desc = "Scan for artifacts and anomalies within your vicinity." anomaly_scanner.interact(user)