diff --git a/baystation12.dme b/baystation12.dme
index 9063b0fda61..8a293d2f4e6 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -7,229 +7,11 @@
// BEGIN_FILE_DIR
#define FILE_DIR .
#define FILE_DIR "code"
-#define FILE_DIR "code/ATMOSPHERICS"
-#define FILE_DIR "code/ATMOSPHERICS/components"
-#define FILE_DIR "code/ATMOSPHERICS/components/binary_devices"
-#define FILE_DIR "code/ATMOSPHERICS/components/trinary_devices"
-#define FILE_DIR "code/ATMOSPHERICS/components/unary"
-#define FILE_DIR "code/controllers"
-#define FILE_DIR "code/datums"
-#define FILE_DIR "code/datums/diseases"
-#define FILE_DIR "code/datums/helper_datums"
-#define FILE_DIR "code/datums/organs"
-#define FILE_DIR "code/datums/spells"
-#define FILE_DIR "code/defines"
-#define FILE_DIR "code/defines/obj"
-#define FILE_DIR "code/defines/obj/clothing"
-#define FILE_DIR "code/defines/procs"
-#define FILE_DIR "code/defines/sd_procs"
-#define FILE_DIR "code/FEA"
-#define FILE_DIR "code/game"
-#define FILE_DIR "code/game/area"
-#define FILE_DIR "code/game/events"
-#define FILE_DIR "code/game/events/EventProcs"
-#define FILE_DIR "code/game/events/Events"
-#define FILE_DIR "code/game/gamemodes"
-#define FILE_DIR "code/game/gamemodes/autotraitor"
-#define FILE_DIR "code/game/gamemodes/blob"
-#define FILE_DIR "code/game/gamemodes/blob/blobs"
-#define FILE_DIR "code/game/gamemodes/changeling"
-#define FILE_DIR "code/game/gamemodes/cult"
-#define FILE_DIR "code/game/gamemodes/epidemic"
-#define FILE_DIR "code/game/gamemodes/events"
-#define FILE_DIR "code/game/gamemodes/events/holidays"
-#define FILE_DIR "code/game/gamemodes/extended"
-#define FILE_DIR "code/game/gamemodes/malfunction"
-#define FILE_DIR "code/game/gamemodes/meme"
-#define FILE_DIR "code/game/gamemodes/meteor"
-#define FILE_DIR "code/game/gamemodes/nuclear"
-#define FILE_DIR "code/game/gamemodes/revolution"
-#define FILE_DIR "code/game/gamemodes/sandbox"
-#define FILE_DIR "code/game/gamemodes/traitor"
-#define FILE_DIR "code/game/gamemodes/wizard"
-#define FILE_DIR "code/game/jobs"
-#define FILE_DIR "code/game/jobs/job"
-#define FILE_DIR "code/game/machinery"
-#define FILE_DIR "code/game/machinery/atmoalter"
-#define FILE_DIR "code/game/machinery/bots"
-#define FILE_DIR "code/game/machinery/camera"
-#define FILE_DIR "code/game/machinery/computer"
-#define FILE_DIR "code/game/machinery/doors"
-#define FILE_DIR "code/game/machinery/embedded_controller"
-#define FILE_DIR "code/game/machinery/kitchen"
-#define FILE_DIR "code/game/machinery/pipe"
-#define FILE_DIR "code/game/machinery/telecomms"
-#define FILE_DIR "code/game/magic"
-#define FILE_DIR "code/game/mecha"
-#define FILE_DIR "code/game/mecha/combat"
-#define FILE_DIR "code/game/mecha/equipment"
-#define FILE_DIR "code/game/mecha/equipment/tools"
-#define FILE_DIR "code/game/mecha/equipment/weapons"
-#define FILE_DIR "code/game/mecha/medical"
-#define FILE_DIR "code/game/mecha/working"
-#define FILE_DIR "code/game/objects"
-#define FILE_DIR "code/game/objects/closets"
-#define FILE_DIR "code/game/objects/closets/secure"
-#define FILE_DIR "code/game/objects/effects"
-#define FILE_DIR "code/game/objects/effects/decals"
-#define FILE_DIR "code/game/objects/effects/decals/Cleanable"
-#define FILE_DIR "code/game/objects/effects/spawners"
-#define FILE_DIR "code/game/objects/items"
-#define FILE_DIR "code/game/objects/items/devices"
-#define FILE_DIR "code/game/objects/items/devices/PDA"
-#define FILE_DIR "code/game/objects/items/devices/radio"
-#define FILE_DIR "code/game/objects/items/robot"
-#define FILE_DIR "code/game/objects/items/stacks"
-#define FILE_DIR "code/game/objects/items/stacks/sheets"
-#define FILE_DIR "code/game/objects/items/stacks/tiles"
-#define FILE_DIR "code/game/objects/items/weapons"
-#define FILE_DIR "code/game/objects/items/weapons/grenades"
-#define FILE_DIR "code/game/objects/items/weapons/implants"
-#define FILE_DIR "code/game/objects/items/weapons/secstorage"
-#define FILE_DIR "code/game/objects/items/weapons/storage"
-#define FILE_DIR "code/game/objects/items/weapons/tanks"
-#define FILE_DIR "code/game/objects/storage"
-#define FILE_DIR "code/game/objects/structures"
-#define FILE_DIR "code/game/objects/structures/crates_lockers"
-#define FILE_DIR "code/game/objects/structures/crates_lockers/closets"
-#define FILE_DIR "code/game/objects/structures/crates_lockers/closets/secure"
-#define FILE_DIR "code/game/objects/structures/stool_bed_chair_nest"
-#define FILE_DIR "code/game/player"
-#define FILE_DIR "code/game/structure"
-#define FILE_DIR "code/game/turfs"
-#define FILE_DIR "code/game/turfs/simulated"
-#define FILE_DIR "code/game/turfs/space"
-#define FILE_DIR "code/game/turfs/unsimulated"
-#define FILE_DIR "code/game/vehicles"
-#define FILE_DIR "code/game/vehicles/airtight"
-#define FILE_DIR "code/game/verbs"
-#define FILE_DIR "code/js"
-#define FILE_DIR "code/modules"
-#define FILE_DIR "code/modules/admin"
-#define FILE_DIR "code/modules/admin/DB ban"
-#define FILE_DIR "code/modules/admin/permissionverbs"
-#define FILE_DIR "code/modules/admin/verbs"
-#define FILE_DIR "code/modules/assembly"
-#define FILE_DIR "code/modules/awaymissions"
-#define FILE_DIR "code/modules/awaymissions/maploader"
-#define FILE_DIR "code/modules/chemical"
-#define FILE_DIR "code/modules/client"
-#define FILE_DIR "code/modules/clothing"
-#define FILE_DIR "code/modules/clothing/glasses"
-#define FILE_DIR "code/modules/clothing/gloves"
-#define FILE_DIR "code/modules/clothing/head"
-#define FILE_DIR "code/modules/clothing/masks"
-#define FILE_DIR "code/modules/clothing/shoes"
-#define FILE_DIR "code/modules/clothing/spacesuits"
-#define FILE_DIR "code/modules/clothing/suits"
-#define FILE_DIR "code/modules/clothing/under"
-#define FILE_DIR "code/modules/clothing/under/jobs"
-#define FILE_DIR "code/modules/clothing/uniforms"
-#define FILE_DIR "code/modules/critters"
-#define FILE_DIR "code/modules/critters/hivebots"
-#define FILE_DIR "code/modules/customitems"
-#define FILE_DIR "code/modules/DetectiveWork"
-#define FILE_DIR "code/modules/flufftext"
-#define FILE_DIR "code/modules/food"
-#define FILE_DIR "code/modules/genetics"
-#define FILE_DIR "code/modules/icon generation"
-#define FILE_DIR "code/modules/library"
-#define FILE_DIR "code/modules/liquid"
-#define FILE_DIR "code/modules/maps"
-#define FILE_DIR "code/modules/mining"
-#define FILE_DIR "code/modules/mob"
-#define FILE_DIR "code/modules/mob/dead"
-#define FILE_DIR "code/modules/mob/dead/observer"
-#define FILE_DIR "code/modules/mob/living"
-#define FILE_DIR "code/modules/mob/living/blob"
-#define FILE_DIR "code/modules/mob/living/carbon"
-#define FILE_DIR "code/modules/mob/living/carbon/alien"
-#define FILE_DIR "code/modules/mob/living/carbon/alien/humanoid"
-#define FILE_DIR "code/modules/mob/living/carbon/alien/humanoid/caste"
-#define FILE_DIR "code/modules/mob/living/carbon/alien/larva"
-#define FILE_DIR "code/modules/mob/living/carbon/alien/special"
-#define FILE_DIR "code/modules/mob/living/carbon/amorph"
-#define FILE_DIR "code/modules/mob/living/carbon/brain"
-#define FILE_DIR "code/modules/mob/living/carbon/human"
-#define FILE_DIR "code/modules/mob/living/carbon/metroid"
-#define FILE_DIR "code/modules/mob/living/carbon/monkey"
-#define FILE_DIR "code/modules/mob/living/parasite"
-#define FILE_DIR "code/modules/mob/living/silicon"
-#define FILE_DIR "code/modules/mob/living/silicon/ai"
-#define FILE_DIR "code/modules/mob/living/silicon/ai/freelook"
-#define FILE_DIR "code/modules/mob/living/silicon/decoy"
-#define FILE_DIR "code/modules/mob/living/silicon/pai"
-#define FILE_DIR "code/modules/mob/living/silicon/robot"
-#define FILE_DIR "code/modules/mob/living/simple_animal"
-#define FILE_DIR "code/modules/mob/living/simple_animal/friendly"
-#define FILE_DIR "code/modules/mob/living/simple_animal/hostile"
-#define FILE_DIR "code/modules/mob/new_player"
-#define FILE_DIR "code/modules/mob/simple_animal"
-#define FILE_DIR "code/modules/paperwork"
-#define FILE_DIR "code/modules/power"
-#define FILE_DIR "code/modules/power/antimatter"
-#define FILE_DIR "code/modules/power/singularity"
-#define FILE_DIR "code/modules/power/singularity/particle_accelerator"
-#define FILE_DIR "code/modules/projectiles"
-#define FILE_DIR "code/modules/projectiles/ammunition"
-#define FILE_DIR "code/modules/projectiles/guns"
-#define FILE_DIR "code/modules/projectiles/guns/energy"
-#define FILE_DIR "code/modules/projectiles/guns/projectile"
-#define FILE_DIR "code/modules/projectiles/projectile"
-#define FILE_DIR "code/modules/reagents"
-#define FILE_DIR "code/modules/reagents/reagent_containers"
-#define FILE_DIR "code/modules/reagents/reagent_containers/food"
-#define FILE_DIR "code/modules/reagents/reagent_containers/food/drinks"
-#define FILE_DIR "code/modules/reagents/reagent_containers/food/drinks/bottle"
-#define FILE_DIR "code/modules/reagents/reagent_containers/food/snacks"
-#define FILE_DIR "code/modules/reagents/reagent_containers/glass"
-#define FILE_DIR "code/modules/reagents/reagent_containers/glass/bottle"
-#define FILE_DIR "code/modules/recycling"
-#define FILE_DIR "code/modules/research"
-#define FILE_DIR "code/modules/research/xenoarchaeology"
-#define FILE_DIR "code/modules/scripting"
-#define FILE_DIR "code/modules/scripting/AST"
-#define FILE_DIR "code/modules/scripting/AST/Operators"
-#define FILE_DIR "code/modules/scripting/Implementations"
-#define FILE_DIR "code/modules/scripting/Interpreter"
-#define FILE_DIR "code/modules/scripting/Parser"
-#define FILE_DIR "code/modules/scripting/Scanner"
-#define FILE_DIR "code/modules/security levels"
#define FILE_DIR "code/TriDimension"
-#define FILE_DIR "code/unused"
-#define FILE_DIR "code/unused/beast"
-#define FILE_DIR "code/unused/computer2"
-#define FILE_DIR "code/unused/disease2"
-#define FILE_DIR "code/unused/gamemodes"
-#define FILE_DIR "code/unused/hivebot"
-#define FILE_DIR "code/unused/mining"
-#define FILE_DIR "code/unused/optics"
-#define FILE_DIR "code/unused/pda2"
-#define FILE_DIR "code/unused/powerarmor"
-#define FILE_DIR "code/unused/spacecraft"
#define FILE_DIR "code/WorkInProgress"
-#define FILE_DIR "code/WorkInProgress/AI_Visibility"
-#define FILE_DIR "code/WorkInProgress/animusstation"
-#define FILE_DIR "code/WorkInProgress/Apples"
#define FILE_DIR "code/WorkInProgress/Cael_Aislinn"
#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Rust"
#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Supermatter"
-#define FILE_DIR "code/WorkInProgress/carn"
-#define FILE_DIR "code/WorkInProgress/Chinsky"
-#define FILE_DIR "code/WorkInProgress/mapload"
-#define FILE_DIR "code/WorkInProgress/Mini"
-#define FILE_DIR "code/WorkInProgress/Mloc"
-#define FILE_DIR "code/WorkInProgress/organs"
-#define FILE_DIR "code/WorkInProgress/Ported"
-#define FILE_DIR "code/WorkInProgress/Ported/Abi79"
-#define FILE_DIR "code/WorkInProgress/Ported/Bureaucracy"
-#define FILE_DIR "code/WorkInProgress/Ported/Spawners"
-#define FILE_DIR "code/WorkInProgress/SkyMarshal"
-#define FILE_DIR "code/WorkInProgress/Tastyfish"
-#define FILE_DIR "code/WorkInProgress/virus2"
-#define FILE_DIR "code/WorkInProgress/virus2/Disease2"
-#define FILE_DIR "code/WorkInProgress/Wrongnumber"
-#define FILE_DIR "code/ZAS"
#define FILE_DIR "html"
#define FILE_DIR "icons"
#define FILE_DIR "icons/48x48"
@@ -238,6 +20,7 @@
#define FILE_DIR "icons/misc"
#define FILE_DIR "icons/mob"
#define FILE_DIR "icons/mob/human_races"
+#define FILE_DIR "icons/mob/skin"
#define FILE_DIR "icons/obj"
#define FILE_DIR "icons/obj/assemblies"
#define FILE_DIR "icons/obj/atmospherics"
@@ -251,9 +34,7 @@
#define FILE_DIR "icons/turf"
#define FILE_DIR "icons/vehicles"
#define FILE_DIR "icons/vending_icons"
-#define FILE_DIR "interface"
#define FILE_DIR "maps"
-#define FILE_DIR "maps/RandomZLevels"
#define FILE_DIR "sound"
#define FILE_DIR "sound/AI"
#define FILE_DIR "sound/ambience"
@@ -268,8 +49,6 @@
#define FILE_DIR "sound/violin"
#define FILE_DIR "sound/voice"
#define FILE_DIR "sound/weapons"
-#define FILE_DIR "tools"
-#define FILE_DIR "tools/Redirector"
// END_FILE_DIR
// BEGIN_PREFERENCES
@@ -1293,9 +1072,16 @@
#include "code\modules\research\research.dm"
#include "code\modules\research\research_shuttle.dm"
#include "code\modules\research\server.dm"
+#include "code\modules\research\xenoarchaeology\analysis.dm"
+#include "code\modules\research\xenoarchaeology\analysis_accelerator.dm"
+#include "code\modules\research\xenoarchaeology\analysis_fourier_transform.dm"
+#include "code\modules\research\xenoarchaeology\analysis_gas_chromatography.dm"
+#include "code\modules\research\xenoarchaeology\analysis_hyperspectral.dm"
+#include "code\modules\research\xenoarchaeology\analysis_ion_mobility.dm"
+#include "code\modules\research\xenoarchaeology\analysis_radiometric.dm"
+#include "code\modules\research\xenoarchaeology\analysis_scanner.dm"
#include "code\modules\research\xenoarchaeology\archaeo_chem.dm"
#include "code\modules\research\xenoarchaeology\archaeo_excavate.dm"
-#include "code\modules\research\xenoarchaeology\archaeo_machinery.dm"
#include "code\modules\research\xenoarchaeology\archaeo_tools.dm"
#include "code\modules\research\xenoarchaeology\artifact.dm"
#include "code\modules\research\xenoarchaeology\artifact_analysis.dm"
@@ -1306,8 +1092,11 @@
#include "code\modules\research\xenoarchaeology\artifact_synthetic.dm"
#include "code\modules\research\xenoarchaeology\bunsen_burner.dm"
#include "code\modules\research\xenoarchaeology\core_sampler.dm"
+#include "code\modules\research\xenoarchaeology\crystal.dm"
#include "code\modules\research\xenoarchaeology\finds.dm"
+#include "code\modules\research\xenoarchaeology\fossils.dm"
#include "code\modules\research\xenoarchaeology\geosample.dm"
+#include "code\modules\research\xenoarchaeology\global_placeholder.dm"
#include "code\modules\research\xenoarchaeology\readme.dm"
#include "code\modules\research\xenoarchaeology\tools.dm"
#include "code\modules\scripting\Errors.dm"
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 192446d262b..39a7add1dba 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -36,6 +36,8 @@
/turf/simulated/mineral/New()
+ src.geological_data = new /datum/geosample(src)
+
spawn(1)
var/turf/T
if((istype(get_step(src, NORTH), /turf/simulated/floor)) || (istype(get_step(src, NORTH), /turf/space)) || (istype(get_step(src, NORTH), /turf/simulated/shuttle/floor)))
@@ -55,9 +57,6 @@
if (T)
T.overlays += image('icons/turf/walls.dmi', "rock_side_e", layer=6)
- src.geological_data = new /datum/geosample
- src.geological_data.UpdateTurf(src)
-
if (mineralName && mineralAmt && spread && spreadChance)
if(prob(spreadChance))
if(istype(get_step(src, SOUTH), /turf/simulated/mineral/random))
@@ -286,8 +285,7 @@
O = new /obj/item/weapon/ore/clown(src)
if(O)
if(!src.geological_data)
- src.geological_data = new /datum/geosample
- src.geological_data.UpdateTurf(src)
+ src.geological_data = new /datum/geosample(src)
O.geological_data = src.geological_data
if (prob(src.artifactChance))
diff --git a/code/modules/research/xenoarchaeology/analysis.dm b/code/modules/research/xenoarchaeology/analysis.dm
new file mode 100644
index 00000000000..0dc309a3d39
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis.dm
@@ -0,0 +1,140 @@
+
+/obj/machinery/anomaly
+ anchored = 1
+ density = 1
+ //
+ var/obj/item/weapon/reagent_containers/glass/held_container
+ var/obj/item/weapon/tank/fuel_container
+ var/scan_time = 30 //change to 300 later
+ var/report_num = 0
+ var/scanning = 0
+ var/safety_enabled = 1
+ var/warning_given = 0
+ var/heat_accumulation_rate = 0
+ var/temperature = 273 //measured in kelvin, if this exceeds 1200, the machine is damaged and requires repairs
+ //if this exceeds 600 and safety is enabled it will shutdown
+ //temp greater than 600 also requires a safety prompt to initiate scanning
+ var/scanner_dir = 0
+ var/obj/machinery/anomaly/scanner/owned_scanner = null
+
+/obj/machinery/anomaly/New()
+ //connect to a nearby scanner pad
+ if(scanner_dir)
+ scanner = locate(/obj/machinery/anomaly/scanner) in get_step(src, scanner_dir)
+ if(!scanner)
+ scanner = locate(/obj/machinery/anomaly/scanner) in orange(1)
+
+//this proc should be overriden by each individual machine
+/obj/machinery/anomaly/attack_hand(var/mob/user as mob)
+ if(stat & (NOPOWER|BROKEN))
+ return
+ user.machine = src
+ var/dat = "[src.name]
"
+ dat += "[scanner ? "Scanner connected." : "Scanner disconnected."]"
+ dat += "Module heat level:[temperature] kelvin
"
+ dat += "Safeties set at 600k, shielding failure at 1200k. Failure to maintain safe heat levels may result in equipment damage.
"
+ dat += "
"
+ dat += "[held_container ? "Eject beaker" : "No beaker inserted."]
"
+ dat += "[held_container ? "Eject fuel tank" : "No fuel tank inserted."]
"
+ dat += "Begin scanning"
+ dat += "
"
+ dat += "Refresh
"
+ dat += "Close
"
+ user << browse(dat, "window=anomaly;size=450x500")
+ onclose(user, "anomaly")
+
+obj/machinery/anomaly/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
+ if(istype(W, /obj/item/weapon/reagent_containers/glass))
+ //var/obj/item/weapon/reagent_containers/glass/G = W
+ if(held_container)
+ user << "\red You must remove the [held_container] first."
+ else
+ user << "\blue You put the [held_container] into the [src]."
+ user.drop_item(W)
+ held_container.loc = src
+ held_container = W
+ updateDialog()
+
+ else if(istype(W, /obj/item/weapon/tank))
+ //var/obj/item/weapon/reagent_containers/glass/G = W
+ if(fuel_container)
+ user << "\red You must remove the [fuel_container] first."
+ else
+ user << "\blue You put the [fuel_container] into the [src]."
+ user.drop_item(W)
+ fuel_container.loc = src
+ fuel_container = W
+ updateDialog()
+ else
+ return ..()
+
+/obj/machinery/anomaly/process()
+ //not sure if everything needs to heat up, or just the GLPC
+ var/environmental_temp = loc.return_air().temperature
+ if(scanning)
+ //heat up as we go, but if the air is freezing then heat up much slower
+ var/new_heat = heat_accumulation_rate + heat_accumulation_rate * rand(-0.5,0.5)
+ if(environmental_temp < 273)
+ new_heat /= 2
+ temperature += new_heat
+ if(temperature >= 600)
+ if(!warning_given || temperature >= 1200)
+ src.visible_message("The [src] bleets.", 2)
+ warning_given = 1
+ if(safety_enabled)
+ scanning = 0
+ else if(temperature > environmental_temp)
+ //cool down to match the air
+ temperature -= 10 + rand(-5,5)
+ if(temperature < environmental_temp
+ temperature = environmental_temp
+ else if(temperature < environmental_temp)
+ //heat up to match the air
+ temperature += 10 + rand(-5,5)
+ if(temperature > environmental_temp
+ temperature = environmental_temp
+
+obj/machinery/anomaly/proc/ScanResults()
+ //instantiate in children to produce unique scan behaviour
+ return "Error initialising scanning components."
+
+obj/machinery/anomaly/proc/BeginScan()
+ var/total_scan_time = scan_time + scan_time * rand(-0.5, 0.5)
+
+ scanning = 1
+ spawn(total_scan_time)
+ if(scanning)
+ scanning = 0
+
+ //determine the results and print a report
+ if(held_container)
+ src.visible_message("The [src] chimes.", 2)
+ var/obj/item/weapon/paper/P = new(src.loc)
+ P.name = "[src] analysis report #[++report_num]"
+ P.info = "[src] analysis report #[report_num]
" + ScanResults()
+ P.stamped = list(/obj/item/weapon/stamp)
+ P.overlays = list("paper_stamped")
+ else
+ src.visible_message("The [src] buzzes.", 2)
+
+obj/machinery/anomaly/Topic(href, href_list)
+ if(href_list["close"])
+ usr << browse(null, "window=anomaly")
+ usr.machine = null
+ if(href_list["eject_beaker"])
+ held_container.loc = src.loc
+ held_container = null
+ if(href_list["eject_fuel"])
+ fuel_container.loc = src.loc
+ fuel_container = null
+ if(href_list["begin"])
+ if(temperature >= 600)
+ var/proceed = input("Unsafe internal temperature detected, do you wish to continue?","Warning")
+ if(proceed)
+ safety_enabled = 0
+ BeginScan()
+ else
+ BeginScan()
+
+ ..()
+ updateDialog()
diff --git a/code/modules/research/xenoarchaeology/analysis_accelerator.dm b/code/modules/research/xenoarchaeology/analysis_accelerator.dm
new file mode 100644
index 00000000000..1e15854e847
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_accelerator.dm
@@ -0,0 +1,6 @@
+
+obj/machinery/anomaly/accelerator
+ name = "Accelerator Spectrometer"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
diff --git a/code/modules/research/xenoarchaeology/analysis_fourier_transform.dm b/code/modules/research/xenoarchaeology/analysis_fourier_transform.dm
new file mode 100644
index 00000000000..597ee1817be
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_fourier_transform.dm
@@ -0,0 +1,36 @@
+
+obj/machinery/anomaly/fourier_transform
+ name = "Fourier Transform spectroscope"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
+
+obj/machinery/anomaly/fourier_transform/ScanResults()
+ var/results = "The scan was inconclusive. Check sample integrity and carrier consistency."
+
+ var/datum/geosample/scanned_sample
+ var/carrier
+ var/num_reagents = 0
+
+ for(var/reagent/A in held_container.reagents.reagent_list)
+ var/datum/reagent/R = A
+ if(istype(R,datum/reagent/density_separated_liquid))
+ scanned_sample = R.data
+ else if(istype(R,datum/reagent/analysis_sample))
+ scanned_sample = R.data
+ else
+ carrier = R.type
+ num_reagents++
+
+ if(num_reagents == 2 && scanned_sample && carrier)
+ //all necessary components are present
+ var/specifity = GetResultSpecifity(scanned_sample, carrier)
+ var/distance = scanned_sample.artifact_distance
+ if(specifity > 0.6)
+ artifact_distance += rand(-0.1, 0.1) * artifact_distance
+ else
+ var/offset = 1 - specifity
+ artifact_distance += rand(-offset, offset) * artifact_distance
+ results = "Anomalous energy absorption through carrier ([carrier.id]) indicates emission radius: [artifact_distance]"
+
+ return results
diff --git a/code/modules/research/xenoarchaeology/analysis_gas_chromatography.dm b/code/modules/research/xenoarchaeology/analysis_gas_chromatography.dm
new file mode 100644
index 00000000000..fbbb7fe47e4
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_gas_chromatography.dm
@@ -0,0 +1,80 @@
+
+obj/machinery/anomaly/gas_chromatography
+ name = "Gas Chromatography Spectrometer"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
+
+obj/machinery/anomaly/gas_chromatography/ScanResults()
+ var/results = "The scan was inconclusive. Check sample integrity and carrier consistency."
+
+ var/datum/geosample/scanned_sample
+ var/carrier
+ var/num_reagents = 0
+
+ for(var/reagent/A in held_container.reagents.reagent_list)
+ var/datum/reagent/R = A
+ if(istype(R,datum/reagent/density_separated_liquid))
+ scanned_sample = R.data
+ else if(istype(R,datum/reagent/analysis_sample))
+ scanned_sample = R.data
+ else
+ carrier = R.type
+ num_reagents++
+
+ if(num_reagents == 2 && scanned_sample && carrier)
+ //all necessary components are present
+ results = "Carrier ([carrier.id]) specifity: [GetResultSpecifity(scanned_sample, carrier)]"
+
+ return results
+
+obj/machinery/anomaly/proc/GetResultSpecifity(var/datum/geosample/scanned_sample, var/datum/reagent/carrier)
+ var/specifity = 0
+ if(scanned_sample && carrier)
+ var/threshold = 0.6
+
+ if(scanned_sample.main_find == carrier.id)
+ specifity += threshold + rand(0, 1 - threshold)
+ if(scanned_sample.secondary_find == carrier.id)
+ specifity += threshold + rand(0, 1 - threshold)
+
+ /*
+ //check the main turf
+ if(scanned_sample.main_find == FIND_NOTHING)
+ //nothing?
+ else if(scanned_sample.main_find == FIND_PLANT || scanned_sample.main_find == FIND_BIO || scanned_sample.main_find == FIND_SKULL)
+ //preserved plant or animal
+ if(carrier.id == "carbon")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_METEORIC)
+ //deep space
+ if(carrier.id == "neon")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_ICE)
+ //solid h20
+ if(carrier.id == "beryllium")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_IGNEOUS || scanned_sample.main_find == FIND_METAMORPHIC || scanned_sample.main_find == FIND_CARBONATE)
+ //rock
+ if(carrier.id == "calcium" || carrier.id == "chlorine")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_CRYSTALLINE)
+ //some kind of refractive, crystalline matter
+ if(carrier.id == "helium")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_METALLIC)
+ //something metal (could be just ores, not necessarily a synthetic artifact)
+ if(carrier.id == "silicon")
+ specifity += threshold + rand(0,1 - threshold)
+ else if(scanned_sample.main_find == FIND_SEDIMENTARY)
+ //sandy rock
+ if(carrier.id == "aluminium")
+ specifity += threshold + rand(0,1 - threshold)
+ */
+
+ if(specifity > 1)
+ specifity = 0.9 + rand(0,0.1)
+ else if(specifity <= 0)
+ specifity += rand(0, threshold)
+
+ return specifity
diff --git a/code/modules/research/xenoarchaeology/analysis_hyperspectral.dm b/code/modules/research/xenoarchaeology/analysis_hyperspectral.dm
new file mode 100644
index 00000000000..08f1d85cded
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_hyperspectral.dm
@@ -0,0 +1,6 @@
+
+obj/machinery/anomaly/hyperspectral
+ name = "Hypospectral Imager"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
diff --git a/code/modules/research/xenoarchaeology/analysis_ion_mobility.dm b/code/modules/research/xenoarchaeology/analysis_ion_mobility.dm
new file mode 100644
index 00000000000..21dc0ad52fc
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_ion_mobility.dm
@@ -0,0 +1,6 @@
+
+obj/machinery/anomaly/ion_mobility
+ name = "Ion Mobility Spectrometer"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
diff --git a/code/modules/research/xenoarchaeology/analysis_radiometric.dm b/code/modules/research/xenoarchaeology/analysis_radiometric.dm
new file mode 100644
index 00000000000..9b9b280b2c4
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_radiometric.dm
@@ -0,0 +1,6 @@
+
+obj/machinery/anomaly/radiometric
+ name = "Isotope ratio spectrometre"
+ desc = "A specialised, complex analysis machine."
+ icon = 'virology.dmi'
+ icon_state = "analyser"
diff --git a/code/modules/research/xenoarchaeology/analysis_scanner.dm b/code/modules/research/xenoarchaeology/analysis_scanner.dm
new file mode 100644
index 00000000000..9c5bfa0fa47
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/analysis_scanner.dm
@@ -0,0 +1,8 @@
+
+/obj/machinery/anomaly/scanner
+ name = "scanner pad"
+ desc = "Place larger objects here for scanning."
+ icon = 'stationobjs.dmi'
+ icon_state = "tele0"
+ anchored = 1
+ density = 0
diff --git a/code/modules/research/xenoarchaeology/archaeo_chem.dm b/code/modules/research/xenoarchaeology/archaeo_chem.dm
index 1ebbe66111e..c12a530a7ff 100644
--- a/code/modules/research/xenoarchaeology/archaeo_chem.dm
+++ b/code/modules/research/xenoarchaeology/archaeo_chem.dm
@@ -2,19 +2,45 @@
//chemistry stuff here so that it can be easily viewed/modified
datum
reagent
- tungsten //used purely to make lith-sodi-tungs
+ tungsten //purely used to make lith-sodi-tungs
name = "Tungsten"
id = "tungsten"
description = "A chemical element, and a strong oxidising agent."
reagent_state = SOLID
- color = "#808080" // rgb: 128, 128, 128, meant to be a silvery grey but idrc
+ color = "#808080" // rgb: 128, 128, 128
+ //todo: make this silvery grey
+
+ neon //purely used as a carrier
+ name = "Neon"
+ id = "neon"
+ description = "A chemical element, commonly used in lighting."
+ reagent_state = LIQUID
+ color = "#808080" // rgb: 128, 128, 128,
+ //todo: make this fluro/bright purple
+
+ beryllium //purely used as a carrier
+ name = "Beryllium"
+ id = "beryllium"
+ description = "A chemical element, prized for it's rigidity, thermal stability and low density when used in alloys."
+ reagent_state = LIQUID
+ color = "#808080" // rgb: 128, 128, 128,
+ //todo: make this dark grey
+
+ calcium //purely used as a carrier
+ name = "Calcium"
+ id = "calcium"
+ description = "An extremely common chemical element found throughout living organisms."
+ reagent_state = LIQUID
+ color = "#808080" // rgb: 128, 128, 128,
+ //todo: make this bone-white colour
lithiumsodiumtungstate
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
description = "A reducing agent for geological compounds."
reagent_state = LIQUID
- color = "#808080" // rgb: 128, 128, 128, again, silvery grey
+ color = "#808080" // rgb: 128, 128, 128
+ //todo: make this silvery grey
ground_rock
name = "Ground Rock"
@@ -25,7 +51,7 @@ datum
//todo: make this brown
density_separated_sample
- name = "Analysis sample"
+ name = "Analysis liquid"
id = "density_separated_sample"
description = "A watery paste used in chemical analysis."
reagent_state = LIQUID
@@ -33,7 +59,7 @@ datum
//todo: make this browny-white
analysis_sample
- name = "Analysis sample"
+ name = "Analysis liquid"
id = "analysis_sample"
description = "A watery paste used in chemical analysis."
reagent_state = LIQUID
@@ -73,3 +99,15 @@ datum
required_reagents = list("density_separated_sample" = 5)
result_amount = 4
requires_heating = 1
+
+/obj/item/weapon/reagent_containers/glass/solution_tray
+ icon = 'icons/obj/device.dmi'
+ icon_state = "solution_tray"
+ desc = "A small, open-topped glass container for delicate research samples."
+ m_amt = 0
+ g_amt = 5
+ w_class = 1.0
+ amount_per_transfer_from_this = 1
+ possible_transfer_amounts = list(1)
+ volume = 2
+ flags = FPRINT | OPENCONTAINER
diff --git a/code/modules/research/xenoarchaeology/archaeo_machinery.dm b/code/modules/research/xenoarchaeology/archaeo_machinery.dm
deleted file mode 100644
index c0534a43a65..00000000000
--- a/code/modules/research/xenoarchaeology/archaeo_machinery.dm
+++ /dev/null
@@ -1,119 +0,0 @@
-obj/machinery/gas_chromatography
- name = "Gas Chromatography Spectrometer"
- desc = "A specialised mass spectrometer."
- icon = 'virology.dmi'
- icon_state = "analyser"
-
-obj/machinery/gas_chromatography/Topic(href, href_list)
- if(href_list["close"])
- usr << browse(null, "window=artanalyser")
- usr.machine = null
-
- updateDialog()
-
-obj/machinery/gas_chromatography/attack_hand(var/mob/user as mob)
- if(stat & (NOPOWER|BROKEN))
- return
- user.machine = src
- var/dat = "Gas Chromatography Spectrometer
"
- dat += "
"
- dat += "Refresh
"
- dat += "Close
"
- user << browse(dat, "window=artanalyser;size=450x500")
- onclose(user, "artanalyser")
-
-obj/machinery/accelerator
- name = "Accelerator Spectrometer"
- desc = "A specialised mass spectrometer."
- icon = 'virology.dmi'
- icon_state = "analyser"
-
-obj/machinery/accelerator/Topic(href, href_list)
- if(href_list["close"])
- usr << browse(null, "window=artanalyser")
- usr.machine = null
-
- updateDialog()
-
-obj/machinery/accelerator/attack_hand(var/mob/user as mob)
- if(stat & (NOPOWER|BROKEN))
- return
- user.machine = src
- var/dat = "Accelerator Spectrometer
"
- dat += "
"
- dat += "Refresh
"
- dat += "Close
"
- user << browse(dat, "window=artanalyser;size=450x500")
- onclose(user, "artanalyser")
-
-obj/machinery/fourier_transform
- name = "Fourier Transform Spectroscope"
- desc = "A specialised geochemical analysis device."
- icon = 'virology.dmi'
- icon_state = "analyser"
-
-obj/machinery/fourier_transform/Topic(href, href_list)
- if(href_list["close"])
- usr << browse(null, "window=artanalyser")
- usr.machine = null
-
- updateDialog()
-
-obj/machinery/fourier_transform/attack_hand(var/mob/user as mob)
- if(stat & (NOPOWER|BROKEN))
- return
- user.machine = src
- var/dat = "Fourier Transform Spectroscope
"
- dat += "
"
- dat += "Refresh
"
- dat += "Close
"
- user << browse(dat, "window=artanalyser;size=450x500")
- onclose(user, "artanalyser")
-
-obj/machinery/radiometric
- name = "Radiometric Exposure Spectrometer"
- desc = "A specialised mass spectrometer, able to radiometrically date inserted materials."
- icon = 'virology.dmi'
- icon_state = "analyser"
-
-obj/machinery/radiometric/Topic(href, href_list)
- if(href_list["close"])
- usr << browse(null, "window=artanalyser")
- usr.machine = null
-
- updateDialog()
-
-obj/machinery/radiometric/attack_hand(var/mob/user as mob)
- if(stat & (NOPOWER|BROKEN))
- return
- user.machine = src
- var/dat = "Radiometric Exposure Spectrometer
"
- dat += "
"
- dat += "Refresh
"
- dat += "Close
"
- user << browse(dat, "window=artanalyser;size=450x500")
- onclose(user, "artanalyser")
-
-obj/machinery/ion_mobility
- name = "Ion Mobility Spectrometer"
- desc = "A specialised mass spectrometer."
- icon = 'virology.dmi'
- icon_state = "analyser"
-
-obj/machinery/ion_mobility/Topic(href, href_list)
- if(href_list["close"])
- usr << browse(null, "window=artanalyser")
- usr.machine = null
-
- updateDialog()
-
-obj/machinery/ion_mobility/attack_hand(var/mob/user as mob)
- if(stat & (NOPOWER|BROKEN))
- return
- user.machine = src
- var/dat = "Ion Mobility Spectrometer
"
- dat += "
"
- dat += "Refresh
"
- dat += "Close
"
- user << browse(dat, "window=artanalyser;size=450x500")
- onclose(user, "artanalyser")
diff --git a/code/modules/research/xenoarchaeology/crystal.dm b/code/modules/research/xenoarchaeology/crystal.dm
new file mode 100644
index 00000000000..ec2aaff7761
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/crystal.dm
@@ -0,0 +1,213 @@
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// crystals
+
+/obj/item/weapon/crystal
+ name = "Crystal"
+ icon = 'mining.dmi'
+ icon_state = "crystal"
+
+//needs to be solid to have collision, but shouldn't block movement
+/*/obj/item/weapon/crystal/bullet_act(var/obj/item/projectile/P)
+ if(istype(P,/obj/item/projectile/beam/emitter))
+ switch(rand(0,3))
+ if(0)
+ var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
+ A.dir = 1
+ A.yo = 20
+ A.xo = 0
+ if(0)
+ var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
+ A.dir = 2
+ A.yo = -20
+ A.xo = 0
+ if(0)
+ var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
+ A.dir = 4
+ A.yo = 0
+ A.xo = 20
+ if(0)
+ var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
+ A.dir = 8
+ A.yo = 0
+ A.xo = -20
+ else
+ ..()*/
+
+/obj/item/weapon/talkingcrystal
+ name = "Crystal"
+ icon = 'mining.dmi'
+ icon_state = "crystal2"
+ var/list/list/words = list()
+ var/lastsaid
+
+/obj/item/weapon/talkingcrystal/New()
+ spawn(100)
+ process()
+
+//needs to be solid to have collision, but shouldn't block movement
+/*/obj/item/weapon/talkingcrystal/bullet_act(var/obj/item/projectile/P)
+ if(istype(P,/obj/item/projectile/beam))
+ switch(rand(0,3))
+ if(0)
+ var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
+ A.dir = pick(alldirs)
+ A.yo = 20
+ A.xo = 0
+ if(0)
+ var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
+ A.dir = pick(alldirs)
+ A.yo = -20
+ A.xo = 0
+ if(0)
+ var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
+ A.dir = pick(alldirs)
+ A.yo = 0
+ A.xo = 20
+ if(0)
+ var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
+ A.dir = pick(alldirs)
+ A.yo = 0
+ A.xo = -20
+ var/word = pick("pain","hurt","masochism","sadist","rage","repressed","ouch","evil","void","kill","destroy")
+ SaySomething(word)
+ else
+ ..()*/
+
+/obj/item/weapon/talkingcrystal/proc/catchMessage(var/msg, var/mob/source)
+ var/list/seperate = list()
+ if(findtext(msg,"(("))
+ return
+ else if(findtext(msg,"))"))
+ return
+ else if(findtext(msg," ")==0)
+ return
+ else
+ /*var/l = lentext(msg)
+ if(findtext(msg," ",l,l+1)==0)
+ msg+=" "*/
+ seperate = stringsplit(msg, " ")
+
+ var/addressing_crystal = 0
+ if("crystal" in seperate || "gem" in seperate)
+ addressing_crystal = 1
+
+ for(var/Xa = 1,Xa 20 + rand(10,20))
+ words.Remove(words[1])
+ if(!words["[lowertext(seperate[Xa])]"])
+ words["[lowertext(seperate[Xa])]"] = list()
+ var/list/w = words["[lowertext(seperate[Xa])]"]
+ if(w)
+ w.Add("[lowertext(seperate[next])]")
+ //world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]"
+
+ for(var/mob/O in viewers(src))
+ O.show_message("\blue The crystal hums for bit then stops...", 1)
+ if(!rand(0, 5 - addressing_crystal * 3))
+ spawn(2) SaySomething(pick(seperate))
+
+/obj/item/weapon/talkingcrystal/proc/debug()
+ //set src in view()
+ for(var/v in words)
+ world << "[uppertext(v)]"
+ var/list/d = words["[v]"]
+ for(var/X in d)
+ world << "[X]"
+
+/obj/item/weapon/talkingcrystal/proc/SaySomething(var/word = null)
+
+ var/msg
+ var/limit = rand(max(5,words.len/2))+3
+ var/text
+ if(!word)
+ text = "[pick(words)]"
+ else
+ text = pick(stringsplit(word, " "))
+ if(lentext(text)==1)
+ text=uppertext(text)
+ else
+ var/cap = copytext(text,1,2)
+ cap = uppertext(cap)
+ cap += copytext(text,2,lentext(text)+1)
+ text=cap
+ var/q = 0
+ msg+=text
+ if(msg=="What" | msg == "Who" | msg == "How" | msg == "Why" | msg == "Are")
+ q=1
+
+ text=lowertext(text)
+ for(var/ya,ya <= limit,ya++)
+
+ if(words.Find("[text]"))
+ var/list/w = words["[text]"]
+ text=pick(w)
+ else
+ text = "[pick(words)]"
+ msg+=" [text]"
+ if(q)
+ msg+="?"
+ else
+ if(rand(0,10))
+ msg+="."
+ else
+ msg+="!"
+
+ var/list/listening = viewers(src)
+ for(var/mob/M in world)
+ if (!M.client)
+ continue //skip monkeys and leavers
+ if (istype(M, /mob/new_player))
+ continue
+ if(M.stat == 2 && M.client.ghost_ears)
+ listening|=M
+
+ for(var/mob/M in listening)
+ M << "The crystal reverberates, \blue\"[msg]\""
+ lastsaid = world.timeofday + rand(300,800)
+
+/obj/item/weapon/talkingcrystal/process()
+ if(prob(25) && world.timeofday >= lastsaid && words.len >= 1)
+ SaySomething()
+ spawn(100)
+ process()
+
+
+
+
+//sentient crystals
+/mob/sentient_crystal
+ name = "Crystal"
+ icon = 'mining.dmi'
+ icon_state = "crystal2"
+ var/list/list/words = list()
+ var/lastsaid
+
+/mob/sentient_crystal/proc/catchMessage(var/msg, var/mob/source)
+ var/list/seperate = list()
+ if(findtext(msg,"(("))
+ return
+ else if(findtext(msg,"))"))
+ return
+ else
+ /*var/l = lentext(msg)
+ if(findtext(msg," ",l,l+1)==0)
+ msg+=" "*/
+ seperate = stringsplit(msg, " ")
+
+ for(var/Xa = 1,Xa 20 + rand(10,20))
+ words.Remove(words[1])
+ if(!words["[lowertext(seperate[Xa])]"])
+ words["[lowertext(seperate[Xa])]"] = list()
+ var/list/w = words["[lowertext(seperate[Xa])]"]
+ if(w)
+ w.Add("[lowertext(seperate[next])]")
+ //world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]"
+
+ for(var/mob/O in viewers(src))
+ O.show_message("\blue The crystal hums for bit then stops...", 1)
+
+/mob/sentient_crystal/Life()
\ No newline at end of file
diff --git a/code/modules/research/xenoarchaeology/finds.dm b/code/modules/research/xenoarchaeology/finds.dm
index 082f20ebb32..2521f8bcf4f 100644
--- a/code/modules/research/xenoarchaeology/finds.dm
+++ b/code/modules/research/xenoarchaeology/finds.dm
@@ -83,265 +83,3 @@
M.show_message("\blue The acid splashes harmlessly off the rock, nothing else interesting happens.",1)
return 1
*/
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// crystals
-
-/obj/item/weapon/crystal
- name = "Crystal"
- icon = 'mining.dmi'
- icon_state = "crystal"
-
-/obj/item/weapon/crystal/bullet_act(var/obj/item/projectile/P)
- if(istype(P,/obj/item/projectile/beam/emitter))
- switch(rand(0,3))
- if(0)
- var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
- A.dir = 1
- A.yo = 20
- A.xo = 0
- if(0)
- var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
- A.dir = 2
- A.yo = -20
- A.xo = 0
- if(0)
- var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
- A.dir = 4
- A.yo = 0
- A.xo = 20
- if(0)
- var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
- A.dir = 8
- A.yo = 0
- A.xo = -20
- else
- ..()
-
-/obj/item/weapon/talkingcrystal
- name = "Crystal"
- icon = 'mining.dmi'
- icon_state = "crystal2"
- var/list/list/words = list()
- var/lastsaid
-
-/obj/item/weapon/talkingcrystal/New()
- spawn(100)
- process()
-
-/obj/item/weapon/talkingcrystal/bullet_act(var/obj/item/projectile/P)
- if(istype(P,/obj/item/projectile/beam))
- switch(rand(0,3))
- if(0)
- var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
- A.dir = pick(alldirs)
- A.yo = 20
- A.xo = 0
- if(0)
- var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
- A.dir = pick(alldirs)
- A.yo = -20
- A.xo = 0
- if(0)
- var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
- A.dir = pick(alldirs)
- A.yo = 0
- A.xo = 20
- if(0)
- var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
- A.dir = pick(alldirs)
- A.yo = 0
- A.xo = -20
- var/word = pick("pain","hurt","masochism","sadist","rage","repressed","ouch","evil","void","kill","destroy")
- SaySomething(word)
- else
- ..()
-
-/obj/item/weapon/talkingcrystal/proc/catchMessage(var/msg, var/mob/source)
- var/list/seperate = list()
- if(findtext(msg,"(("))
- return
- else if(findtext(msg,"))"))
- return
- else if(findtext(msg," ")==0)
- return
- else
- /*var/l = lentext(msg)
- if(findtext(msg," ",l,l+1)==0)
- msg+=" "*/
- seperate = stringsplit(msg, " ")
-
- var/addressing_crystal = 0
- if("crystal" in seperate || "gem" in seperate)
- addressing_crystal = 1
-
- for(var/Xa = 1,Xa 20 + rand(10,20))
- words.Remove(words[1])
- if(!words["[lowertext(seperate[Xa])]"])
- words["[lowertext(seperate[Xa])]"] = list()
- var/list/w = words["[lowertext(seperate[Xa])]"]
- if(w)
- w.Add("[lowertext(seperate[next])]")
- //world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]"
-
- for(var/mob/O in viewers(src))
- O.show_message("\blue The crystal hums for bit then stops...", 1)
- if(!rand(0, 5 - addressing_crystal * 3))
- spawn(2) SaySomething(pick(seperate))
-
-/obj/item/weapon/talkingcrystal/proc/debug()
- //set src in view()
- for(var/v in words)
- world << "[uppertext(v)]"
- var/list/d = words["[v]"]
- for(var/X in d)
- world << "[X]"
-
-/obj/item/weapon/talkingcrystal/proc/SaySomething(var/word = null)
-
- var/msg
- var/limit = rand(max(5,words.len/2))+3
- var/text
- if(!word)
- text = "[pick(words)]"
- else
- text = pick(stringsplit(word, " "))
- if(lentext(text)==1)
- text=uppertext(text)
- else
- var/cap = copytext(text,1,2)
- cap = uppertext(cap)
- cap += copytext(text,2,lentext(text)+1)
- text=cap
- var/q = 0
- msg+=text
- if(msg=="What" | msg == "Who" | msg == "How" | msg == "Why" | msg == "Are")
- q=1
-
- text=lowertext(text)
- for(var/ya,ya <= limit,ya++)
-
- if(words.Find("[text]"))
- var/list/w = words["[text]"]
- text=pick(w)
- else
- text = "[pick(words)]"
- msg+=" [text]"
- if(q)
- msg+="?"
- else
- if(rand(0,10))
- msg+="."
- else
- msg+="!"
-
- var/list/listening = viewers(src)
- for(var/mob/M in world)
- if (!M.client)
- continue //skip monkeys and leavers
- if (istype(M, /mob/new_player))
- continue
- if(M.stat == 2 && M.client.ghost_ears)
- listening|=M
-
- for(var/mob/M in listening)
- M << "The crystal reverberates, \blue\"[msg]\""
- lastsaid = world.timeofday + rand(300,800)
-
-/obj/item/weapon/talkingcrystal/process()
- if(prob(25) && world.timeofday >= lastsaid && words.len >= 1)
- SaySomething()
- spawn(100)
- process()
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// fossils
-
-/obj/item/weapon/fossil
- name = "Fossil"
- icon = 'fossil.dmi'
- icon_state = "bone"
- desc = "It's a fossil."
-
-/obj/item/weapon/fossil/base/New()
- spawn(0)
- var/list/l = list("/obj/item/weapon/fossil/bone"=8,"/obj/item/weapon/fossil/skull"=2,
- "/obj/item/weapon/fossil/skull/horned"=2,"/obj/item/weapon/fossil/shell"=1)
- var/t = pickweight(l)
- new t(src.loc)
- del src
-
-/obj/item/weapon/fossil/bone
- name = "Fossilised bone"
- icon_state = "bone"
- desc = "It's a fossilised bone."
-
-/obj/item/weapon/fossil/shell
- name = "Fossilised shell"
- icon_state = "shell"
- desc = "It's a fossilised shell."
-
-/obj/item/weapon/fossil/skull/horned
- icon_state = "hskull"
- desc = "It's a fossilised, horned skull."
-
-/obj/item/weapon/fossil/skull
- name = "Fossilised skull"
- icon_state = "skull"
- desc = "It's a fossilised skull."
-
-/obj/item/weapon/fossil/skull/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/fossil/bone))
- var/obj/o = new /obj/skeleton(get_turf(src))
- var/a = new /obj/item/weapon/fossil/bone
- var/b = new src.type
- o.contents.Add(a)
- o.contents.Add(b)
- del W
- del src
-
-/obj/skeleton
- name = "Incomplete skeleton"
- icon = 'fossil.dmi'
- icon_state = "uskel"
- desc = "Incomplete skeleton."
- var/bnum = 1
- var/breq
- var/bstate = 0
-
-/obj/skeleton/New()
- src.breq = rand(6)+3
- src.desc = "An incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
-
-/obj/skeleton/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/fossil/bone))
- if(!bstate)
- bnum++
- src.contents.Add(new/obj/item/weapon/fossil/bone)
- del W
- if(bnum==breq)
- usr = user
- icon_state = "skel"
- var/creaturename = input("Input a name for your discovery:","Name your discovery","Spaceosaurus")
- src.bstate = 1
- src.density = 1
- src.name = "[creaturename] skeleton"
- if(src.contents.Find(/obj/item/weapon/fossil/skull/horned))
- src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull, the plaque reads [creaturename]."
- else
- src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull, the plaque reads [creaturename]."
- else
- src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
- user << "Looks like it could use [src.breq-src.bnum] more bones."
- else
- ..()
- else
- ..()
diff --git a/code/modules/research/xenoarchaeology/fossils.dm b/code/modules/research/xenoarchaeology/fossils.dm
new file mode 100644
index 00000000000..cb8f88b6661
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/fossils.dm
@@ -0,0 +1,84 @@
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// fossils
+
+/obj/item/weapon/fossil
+ name = "Fossil"
+ icon = 'fossil.dmi'
+ icon_state = "bone"
+ desc = "It's a fossil."
+
+/obj/item/weapon/fossil/base/New()
+ spawn(0)
+ var/list/l = list("/obj/item/weapon/fossil/bone"=8,"/obj/item/weapon/fossil/skull"=2,
+ "/obj/item/weapon/fossil/skull/horned"=2,"/obj/item/weapon/fossil/shell"=1)
+ var/t = pickweight(l)
+ new t(src.loc)
+ del src
+
+/obj/item/weapon/fossil/bone
+ name = "Fossilised bone"
+ icon_state = "bone"
+ desc = "It's a fossilised bone."
+
+/obj/item/weapon/fossil/shell
+ name = "Fossilised shell"
+ icon_state = "shell"
+ desc = "It's a fossilised shell."
+
+/obj/item/weapon/fossil/skull/horned
+ icon_state = "hskull"
+ desc = "It's a fossilised, horned skull."
+
+/obj/item/weapon/fossil/skull
+ name = "Fossilised skull"
+ icon_state = "skull"
+ desc = "It's a fossilised skull."
+
+/obj/item/weapon/fossil/skull/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/fossil/bone))
+ var/obj/o = new /obj/skeleton(get_turf(src))
+ var/a = new /obj/item/weapon/fossil/bone
+ var/b = new src.type
+ o.contents.Add(a)
+ o.contents.Add(b)
+ del W
+ del src
+
+/obj/skeleton
+ name = "Incomplete skeleton"
+ icon = 'fossil.dmi'
+ icon_state = "uskel"
+ desc = "Incomplete skeleton."
+ var/bnum = 1
+ var/breq
+ var/bstate = 0
+
+/obj/skeleton/New()
+ src.breq = rand(6)+3
+ src.desc = "An incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
+
+/obj/skeleton/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/fossil/bone))
+ if(!bstate)
+ bnum++
+ src.contents.Add(new/obj/item/weapon/fossil/bone)
+ del W
+ if(bnum==breq)
+ usr = user
+ icon_state = "skel"
+ var/creaturename = input("Input a name for your discovery:","Name your discovery","Spaceosaurus")
+ src.bstate = 1
+ src.density = 1
+ src.name = "[creaturename] skeleton"
+ if(src.contents.Find(/obj/item/weapon/fossil/skull/horned))
+ src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull, the plaque reads [creaturename]."
+ else
+ src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull, the plaque reads [creaturename]."
+ else
+ src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
+ user << "Looks like it could use [src.breq-src.bnum] more bones."
+ else
+ ..()
+ else
+ ..()
diff --git a/code/modules/research/xenoarchaeology/geosample.dm b/code/modules/research/xenoarchaeology/geosample.dm
index a3d64309464..43da9ccb142 100644
--- a/code/modules/research/xenoarchaeology/geosample.dm
+++ b/code/modules/research/xenoarchaeology/geosample.dm
@@ -1,22 +1,25 @@
+
datum/geosample
- var/scrambled = 0 //if this sample has been mixed with other samples
+ var/scrambled = 0 //if this sample has been mixed with other samples
//
- var/age = 0
- var/age_thousand = 0 //age can correspond to different artifacts
+ var/age = 0 //age can correspond to different archaeological finds
+ var/age_thousand = 0
var/age_million = 0
var/age_billion = 0
var/artifact_id = "" //id of a nearby artifact, if there is one
- var/artifact_strength = 0 //proportional to distance
- var/responsive_reagent = "" ///each reagent corresponds to a different type of find
- var/reagent_response = "" //likelihood of there being finds there
+ var/artifact_distance = 0 //proportional to distance
+ var/main_find = "" //carrier reagent that the main body of the tile responds to
+ var/secondary_find = "" //carrier reagent that the floor of the turf responds to
//
var/source_mineral
+ var/list/specifity_offsets = list()
datum/geosample/New(var/turf/simulated/mineral/container)
UpdateTurf(container)
+ artifact_distance = rand(500,999999)
-//this function should only be called once. it's here just in case
+//this should only need to be called once
datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container)
source_mineral = container.mineralName
age = rand(1,999)
@@ -42,7 +45,7 @@ datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container)
age_million = rand(1,999)
age_billion = rand(10, 13)
if("Clown")
- age = rand(-1,-999)
+ age = rand(-1,-999) //thats_the_joke.mp4
age_thousand = rand(-1,-999)
/*if("Archaeo")
//snowflake
diff --git a/code/modules/research/xenoarchaeology/global_placeholder.dm b/code/modules/research/xenoarchaeology/global_placeholder.dm
new file mode 100644
index 00000000000..c1291abc016
--- /dev/null
+++ b/code/modules/research/xenoarchaeology/global_placeholder.dm
@@ -0,0 +1,13 @@
+//todo: move these into global.dm
+
+var/FIND_NOTHING = 0
+var/FIND_PLANT = 1
+var/FIND_BIO = 2
+var/FIND_METEORIC = 3
+var/FIND_ICE = 4
+var/FIND_CRYSTALLINE = 6
+var/FIND_METALLIC = 7
+var/FIND_IGNEOUS = 8
+var/FIND_METAMORPHIC = 9
+var/FIND_CARBONATE = 10
+var/FIND_SEDIMENTARY = 11
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 1104878db8e..4cbc91d9f8f 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ