From e3d326a199543214bac8fe70819a558cdf1de074 Mon Sep 17 00:00:00 2001 From: Cael_Aislinn Date: Tue, 11 Dec 2012 12:34:39 +1000 Subject: [PATCH] new analysis machines, fleshed out some existing ones to be functional, new chemical reagents, Signed-off-by: Cael_Aislinn --- baystation12.dme | 235 +--------------- code/modules/mining/mine_turfs.dm | 8 +- .../research/xenoarchaeology/analysis.dm | 140 ++++++++++ .../xenoarchaeology/analysis_accelerator.dm | 6 + .../analysis_fourier_transform.dm | 36 +++ .../analysis_gas_chromatography.dm | 80 ++++++ .../xenoarchaeology/analysis_hyperspectral.dm | 6 + .../xenoarchaeology/analysis_ion_mobility.dm | 6 + .../xenoarchaeology/analysis_radiometric.dm | 6 + .../xenoarchaeology/analysis_scanner.dm | 8 + .../research/xenoarchaeology/archaeo_chem.dm | 48 +++- .../xenoarchaeology/archaeo_machinery.dm | 119 -------- .../research/xenoarchaeology/crystal.dm | 213 ++++++++++++++ .../modules/research/xenoarchaeology/finds.dm | 262 ------------------ .../research/xenoarchaeology/fossils.dm | 84 ++++++ .../research/xenoarchaeology/geosample.dm | 19 +- .../xenoarchaeology/global_placeholder.dm | 13 + icons/obj/device.dmi | Bin 17186 -> 17214 bytes 18 files changed, 667 insertions(+), 622 deletions(-) create mode 100644 code/modules/research/xenoarchaeology/analysis.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_accelerator.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_fourier_transform.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_gas_chromatography.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_hyperspectral.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_ion_mobility.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_radiometric.dm create mode 100644 code/modules/research/xenoarchaeology/analysis_scanner.dm delete mode 100644 code/modules/research/xenoarchaeology/archaeo_machinery.dm create mode 100644 code/modules/research/xenoarchaeology/crystal.dm create mode 100644 code/modules/research/xenoarchaeology/fossils.dm create mode 100644 code/modules/research/xenoarchaeology/global_placeholder.dm 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 1104878db8eb2dad919372af91df2a915f8a8b4d..4cbc91d9f8fca6a33b923e6d2b4f2f2def648cbd 100644 GIT binary patch literal 17214 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 literal 17186 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