diff --git a/baystation12.dme b/baystation12.dme index 2a699386a9..39a562a6a3 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1190,22 +1190,18 @@ #include "code\modules\research\xenoarchaeology\finds\finds_fossils.dm" #include "code\modules\research\xenoarchaeology\finds\finds_misc.dm" #include "code\modules\research\xenoarchaeology\finds\finds_talkingitem.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_accelerator.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_base.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_fourier_transform.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_gas_chromatography.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_hyperspectral.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_ion_mobility.dm" -#include "code\modules\research\xenoarchaeology\machinery\analysis_isotope_ratio.dm" #include "code\modules\research\xenoarchaeology\machinery\artifact_analyser.dm" #include "code\modules\research\xenoarchaeology\machinery\artifact_harvester.dm" #include "code\modules\research\xenoarchaeology\machinery\artifact_scanner.dm" +#include "code\modules\research\xenoarchaeology\machinery\coolant.dm" +#include "code\modules\research\xenoarchaeology\machinery\geosample_scanner.dm" #include "code\modules\research\xenoarchaeology\tools\ano_device_battery.dm" #include "code\modules\research\xenoarchaeology\tools\anomaly_suit.dm" #include "code\modules\research\xenoarchaeology\tools\bunsen_burner.dm" #include "code\modules\research\xenoarchaeology\tools\gearbelt.dm" #include "code\modules\research\xenoarchaeology\tools\suspension_generator.dm" #include "code\modules\research\xenoarchaeology\tools\tools.dm" +#include "code\modules\research\xenoarchaeology\tools\tools_anoscanner.dm" #include "code\modules\research\xenoarchaeology\tools\tools_coresampler.dm" #include "code\modules\research\xenoarchaeology\tools\tools_depthscanner.dm" #include "code\modules\research\xenoarchaeology\tools\tools_locater.dm" @@ -1291,7 +1287,6 @@ #include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen.dm" #include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen_external.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\LaserComputer.dm" -#include "code\WorkInProgress\Cael_Aislinn\Supermatter\SuperMatter.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm" #include "code\WorkInProgress\Chinsky\ashtray.dm" #include "code\WorkInProgress\Cib\MedicalSideEffects.dm" @@ -1300,6 +1295,7 @@ #include "code\WorkInProgress\Ported\policetape.dm" #include "code\WorkInProgress\SkyMarshal\officer_stuff.dm" #include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm" +#include "code\WorkInProgress\Yinadele\Supermatter.dm" #include "code\ZAS\Airflow.dm" #include "code\ZAS\Connection.dm" #include "code\ZAS\Debug.dm" diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/fusion_reactions.dm b/code/WorkInProgress/Cael_Aislinn/Rust/fusion_reactions.dm index c083cad713..8293e060f4 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/fusion_reactions.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/fusion_reactions.dm @@ -145,14 +145,14 @@ datum/fusion_reaction/pergium_tritium energy_production = 0 radiation = 5 -datum/fusion_reaction/pergium_deuterium +datum/fusion_reaction/pergium_obdurium primary_reactant = "Pergium" secondary_reactant = "Obdurium" energy_consumption = 5 energy_production = 0 radiation = 5 -datum/fusion_reaction/pergium_tritium +datum/fusion_reaction/pergium_solonium primary_reactant = "Pergium" secondary_reactant = "Solonium" energy_consumption = 5 diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 74f94ec82c..664b065d1c 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -456,6 +456,14 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "fuel tank crate" group = "Engineering" +/datum/supply_packs/coolanttank + name = "Coolant tank crate" + contains = list(/obj/structure/reagent_dispensers/coolanttank) + cost = 16 + containertype = /obj/structure/largecrate + containername = "coolant tank crate" + group = "Medical / Science" + /datum/supply_packs/solar name = "Solar Pack crate" contains = list(/obj/item/solar_assembly, diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 8cee9f811c..911ccace95 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -152,7 +152,7 @@ carddesc += "" carddesc += "" carddesc += "Stored account number: " - carddesc += "" + carddesc += "" carddesc += "" carddesc += "Assignment: " diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm index 54630d3c4a..d1435d383d 100644 --- a/code/game/objects/structures/transit_tubes.dm +++ b/code/game/objects/structures/transit_tubes.dm @@ -99,6 +99,16 @@ obj/structure/ex_act(severity) +/obj/structure/transit_tube/Bumped(mob/AM as mob|obj) + var/obj/structure/transit_tube/T = locate() in AM.loc + if(T) + AM << "The tube's support pylons block your way." + return ..() + else + AM.loc = src.loc + AM << "You slip under the tube." + + /obj/structure/transit_tube/station/New(loc) ..(loc) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 9db503f93a..2abfe0f4fc 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -251,6 +251,7 @@ 'nano/css/icons.css', 'nano/templates/chem_dispenser.tmpl', 'nano/templates/cryo.tmpl', + 'nano/templates/geoscanner.tmpl', 'nano/templates/dna_modifier.tmpl', 'nano/images/uiBackground.png', 'nano/images/uiIcons16.png', @@ -298,9 +299,5 @@ 'icons/spideros_icons/sos_11.png', 'icons/spideros_icons/sos_12.png', 'icons/spideros_icons/sos_13.png', - 'icons/spideros_icons/sos_14.png', - 'icons/xenoarch_icons/chart1.jpg', - 'icons/xenoarch_icons/chart2.jpg', - 'icons/xenoarch_icons/chart3.jpg', - 'icons/xenoarch_icons/chart4.jpg' + 'icons/spideros_icons/sos_14.png' ) diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 0eb859083a..0300c757f8 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -4,6 +4,8 @@ #define XENOARCH_SPREAD_CHANCE 15 #define ARTIFACT_SPAWN_CHANCE 20 +var/list/artifact_spawning_turfs = list() + /turf/simulated/mineral //wall piece name = "Rock" icon = 'icons/turf/walls.dmi' @@ -369,29 +371,25 @@ commented out in r5061, I left it because of the shroom thingies //just pull the surrounding rock out excavate_find(0, F) - if( src.excavation_level + P.excavation_amount >= 100 || (!finds.len && !excavation_minerals.len) ) - //if players have been excavating this turf, have a chance to leave some rocky debris behind - var/boulder_prob = 0 + if( src.excavation_level + P.excavation_amount >= 100 ) + //if players have been excavating this turf, leave some rocky debris behind var/obj/structure/boulder/B - - if(src.excavation_level > 15) - boulder_prob = 10 if(artifact_find) - boulder_prob += 25 - if(src.excavation_level >= 100) - boulder_prob += 40 - else if(src.excavation_level > 95) - boulder_prob += 25 - else if(src.excavation_level > 90) - boulder_prob += 10 - if(prob(boulder_prob)) + if( src.excavation_level > 0 || prob(15) ) + //boulder with an artifact inside + B = new(src) + if(artifact_find) + B.artifact_find = artifact_find + else + artifact_debris(1) + else if(prob(15)) + //empty boulder B = new(src) - if(artifact_find) - B.artifact_find = artifact_find - else if(artifact_find && src.excavation_level + P.excavation_amount >= 100) - artifact_debris(1) - gets_drilled(B ? 0 : 1) + if(B) + gets_drilled(0) + else + gets_drilled(1) return else src.excavation_level += P.excavation_amount @@ -475,7 +473,7 @@ commented out in r5061, I left it because of the shroom thingies if(prob(50)) pain = 1 for(var/mob/living/M in range(src, 200)) - M << "[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fadaing away!" + M << "[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!" if(pain) flick("pain",M.pain) if(prob(50)) diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index ce4fef22d8..2aa1679d07 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -19,6 +19,8 @@ var/list/dispensable_reagents = list("hydrogen","lithium","carbon","nitrogen","oxygen","fluorine", "sodium","aluminum","silicon","phosphorus","sulfur","chlorine","potassium","iron", "copper","mercury","radium","water","ethanol","sugar","sacid","tungsten") + var/list/broken_requirements = list() + var/broken_on_spawn = 0 /obj/machinery/chem_dispenser/proc/recharge() if(stat & (BROKEN|NOPOWER)) return @@ -50,6 +52,28 @@ recharge() dispensable_reagents = sortList(dispensable_reagents) + if(broken_on_spawn) + var/amount = pick(1,2,2,3,4) + var/list/options = list() + options[/obj/item/weapon/stock_parts/capacitor/adv] = "Add an advanced capacitor to fix it." + options[/obj/item/weapon/stock_parts/console_screen] = "Replace the console screen to fix it." + options[/obj/item/weapon/stock_parts/manipulator/pico] = "Upgrade to a pico manipulator to fix it." + options[/obj/item/weapon/stock_parts/matter_bin/adv] = "Give it an advanced matter bin to fix it." + options[/obj/item/stack/sheet/mineral/diamond] = "Line up a cut diamond with the nozzle to fix it." + options[/obj/item/stack/sheet/mineral/uranium] = "Position a uranium sheet inside to fix it." + options[/obj/item/stack/sheet/mineral/plasma] = "Enter a block of plasma to fix it." + options[/obj/item/stack/sheet/mineral/silver] = "Cover the internals with a silver lining to fix it." + options[/obj/item/stack/sheet/mineral/gold] = "Wire a golden filament to fix it." + options[/obj/item/stack/sheet/plasteel] = "Surround the outside with a plasteel cover to fix it." + options[/obj/item/stack/sheet/rglass] = "Insert a pane of reinforced glass to fix it." + + while(amount > 0) + amount -= 1 + + var/index = pick(options) + broken_requirements[index] = options[index] + options -= index + /obj/machinery/chem_dispenser/ex_act(severity) switch(severity) if(1.0) @@ -82,6 +106,10 @@ if(stat & (BROKEN|NOPOWER)) return if(user.stat || user.restrained()) return + if(broken_requirements.len) + user << "[src] is broken. [broken_requirements[broken_requirements[1]]]" + return + // this is the data which will be sent to the ui var/data[0] data["amount"] = amount @@ -156,6 +184,19 @@ if(isrobot(user)) return + if(broken_requirements.len && B.type == broken_requirements[1]) + broken_requirements -= broken_requirements[1] + user << "You fix [src]." + if(istype(B,/obj/item/stack)) + var/obj/item/stack/S = B + S.use(1) + else + user.drop_item() + del(B) + return + + if(!istype(B, /obj/item/weapon/reagent_containers/glass)) + return if(src.beaker) user << "Something is already loaded into the machine." return diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index f5052c47c3..b4a7ecf209 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -122,7 +122,7 @@ else if(istype(target, /obj/machinery/bunsen_burner)) return - else if(istype(target, /obj/machinery/anomaly)) + else if(istype(target, /obj/machinery/radiocarbon_spectrometer)) return else if(reagents.total_volume) @@ -223,6 +223,7 @@ possible_transfer_amounts = list(5,10,15,25,30,50,100,300) flags = FPRINT | TABLEPASS | OPENCONTAINER + /obj/item/weapon/reagent_containers/glass/beaker/vial name = "vial" desc = "A small glass vial. Can hold up to 25 units." diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 9ba14f5d74..52f37b9dd2 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -211,6 +211,10 @@ // attack with hand, switch position /obj/machinery/conveyor_switch/attack_hand(mob/user) + if(!allowed(user)) + user << "Access denied." + return + if(position == 0) if(last_pos < 0) position = 1 diff --git a/code/modules/research/xenoarchaeology/artifact/artifact.dm b/code/modules/research/xenoarchaeology/artifact/artifact.dm index 1ff8a220f3..6300a6d71a 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact.dm @@ -35,6 +35,7 @@ icon_state = "boulder1" density = 1 opacity = 1 + anchored = 1 var/excavation_level = 0 var/datum/geosample/geological_data var/datum/artifact_find/artifact_find @@ -75,17 +76,14 @@ user << "\blue You finish [P.drill_verb] [src]." excavation_level += P.excavation_amount - var/reveal_prob = 1 - if(excavation_level >= 95) - reveal_prob = 50 + (excavation_level - 90) * (excavation_level - 90) - else if(excavation_level >= 90) - reveal_prob = 5 - if(excavation_level >= 100) + if(excavation_level > 100) //failure user.visible_message("[src] suddenly crumbles away.",\ - "\red [src] has disintegrated under your onslaught, any secrets it was holding long gone.") + "\red [src] has disintegrated under your onslaught, any secrets it was holding are long gone.") del(src) - else if(prob(reveal_prob)) + return + + if(prob(excavation_level)) //success if(artifact_find) var/spawn_type = artifact_find.artifact_find_type diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_unknown_old.dm b/code/modules/research/xenoarchaeology/artifact/artifact_unknown_old.dm deleted file mode 100644 index 3c779caa96..0000000000 --- a/code/modules/research/xenoarchaeology/artifact/artifact_unknown_old.dm +++ /dev/null @@ -1,242 +0,0 @@ -//Part of ISaidNo's public release around July 2011(ish), multiple changes -//many thanks - -#define PLASMA_SPAWN 1 -#define N2_SPAWN 2 -#define CO2_SPAWN 3 -#define RADIATE 4 -#define VIRUS 5 -#define HEAT 6 -#define COLD 7 - -/obj/machinery/artifact - name = "alien artifact" - desc = "A large alien device." - icon = 'icons/obj/xenoarchaeology.dmi' - icon_state = "ano00" - var/icon_num = 0 - anchored = 0 - density = 1 - var/origin = null // Used in the randomisation/research of the artifact. - var/activated = 0 // Whether or not the artifact has been unlocked. - var/charged = 1 // Whether the artifact is ready to have it's effect. - var/chargetime = 0 // How much time until the artifact is charged. - var/recharge = 5 // How long does it take this artifact to recharge? - var/display_id = "" // Artifact ID to display once successfully scanned - var/datum/artifact_effect/my_effect = null - var/being_used = 0 - -/obj/machinery/artifact/New() - ..() - // Origin and appearance randomisation - - my_effect = new() - - - icon_num = rand(0,5) - icon_state = "ano[icon_num]0" - - // Power randomisation - my_effect.trigger = pick("force","energy","chemical","heat","touch","presence") - if (my_effect.trigger == "chemical") - my_effect.triggerX = pick("hydrogen","corrosive","volatile","toxic") - - my_effect.effecttype = pick("healing","injure","stun","roboheal","robohurt","cellcharge","celldrain","planthelper","forcefield","teleport","dnaswitch","emp","sleepy") - - // Select range based on the power - var/canworldpulse = 1 - switch(my_effect.effecttype) - if("healing") - my_effect.effectmode = pick("aura","pulse","contact") - if("injure") - my_effect.effectmode = pick("aura","pulse","contact") - if("stun") - my_effect.effectmode = pick("aura","pulse","contact") - if("roboheal") - my_effect.effectmode = pick("aura","pulse","contact") - if("robohurt") - my_effect.effectmode = pick("aura","pulse","contact") - if("sleepy") - my_effect.effectmode = pick("aura","pulse","contact") - if("cellcharge") - my_effect.effectmode = pick("aura","pulse") - if("celldrain") - my_effect.effectmode = pick("aura","pulse") - if("planthelper") - my_effect.effectmode = pick("aura","pulse") - canworldpulse = 0 - if("forcefield") - my_effect.effectmode = "contact" - canworldpulse = 0 - if("teleport") - my_effect.effectmode = pick("pulse","contact") - if("genderswitch") - my_effect.effectmode = pick("pulse","contact") - if("emp") - my_effect.effectmode = pick("pulse","contact") - - // Recharge timer & range setup - if (my_effect.effectmode == "aura") - my_effect.aurarange = rand(1,4) - if (my_effect.effectmode == "contact") - src.recharge = rand(5,15) - if (my_effect.effectmode == "pulse") - my_effect.aurarange = rand(2,14) - src.recharge = rand(5,20) - if (canworldpulse == 1 && prob(1)) - my_effect.effectmode = "worldpulse" - src.recharge = rand(40,120) - - /* - display_id += pick("kappa","sigma","antaeres","beta","lorard","omicron","iota","upsilon","omega","gamma","delta") - display_id += "-" - display_id += num2text(rand(100,999)) - */ - -/obj/machinery/artifact/Del() - ..() - my_effect.HaltEffect() - -/obj/machinery/artifact/attack_hand(var/mob/user as mob) - if (istype(user, /mob/living/silicon/ai) || istype(user, /mob/dead/)) return - if (istype(user, /mob/living/silicon/robot)) - if (get_dist(user, src) > 1) - user << "\red You can't reach [src] from here." - return - if(ishuman(user) && istype(user:gloves,/obj/item/clothing/gloves)) - return ..() - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] touches [].", user, src), 1) - src.add_fingerprint(user) - src.Artifact_Contact(user) - -/obj/machinery/artifact/attackby(obj/item/weapon/W as obj, mob/living/user as mob) - /*if (istype(W, /obj/item/weapon/cargotele)) - W:cargoteleport(src, user) - return*/ - if (my_effect.trigger == "chemical" && istype(W, /obj/item/weapon/reagent_containers/)) - switch(my_effect.triggerX) - if("hydrogen") - if (W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1)) - src.Artifact_Activate() - return - if("corrosive") - if (W.reagents.has_reagent("acid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1)) - src.Artifact_Activate() - return - if("volatile") - if (W.reagents.has_reagent("plasma", 1) || W.reagents.has_reagent("thermite", 1)) - src.Artifact_Activate() - return - if("toxic") - if (W.reagents.has_reagent("toxin", 1) || W.reagents.has_reagent("cyanide", 1) || W.reagents.has_reagent("amanitin", 1) || W.reagents.has_reagent("neurotoxin", 1)) - src.Artifact_Activate() - return - ..() - if (my_effect.trigger == "force" && W.force >= 10 && !src.activated) src.Artifact_Activate() - if (my_effect.trigger == "energy") - if (istype(W,/obj/item/weapon/melee/baton) && W:status) src.Artifact_Activate() - if (istype(W,/obj/item/weapon/melee/energy)) src.Artifact_Activate() - if (istype(W,/obj/item/weapon/melee/cultblade)) src.Artifact_Activate() - if (istype(W,/obj/item/weapon/gun/energy/)) src.Artifact_Activate() - if (istype(W,/obj/item/device/multitool)) src.Artifact_Activate() - if (istype(W,/obj/item/weapon/card/emag)) src.Artifact_Activate() - if (my_effect.trigger == "heat") - if (istype(W,/obj/item/weapon/match) && W:lit) src.Artifact_Activate() - if (istype(W, /obj/item/weapon/weldingtool) && W:welding) src.Artifact_Activate() - if (istype(W, /obj/item/weapon/lighter) && W:lit) src.Artifact_Activate() - - //Bump(atom/A) - -/obj/machinery/artifact/Bumped(M as mob|obj) - if (istype(M,/obj/item/weapon/) && my_effect.trigger == "force" && M:throwforce >= 10) src.Artifact_Activate() - -/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P) - if (my_effect.trigger == "force") - if(istype(P,/obj/item/projectile/bullet)) src.Artifact_Activate() - else if(istype(P,/obj/item/projectile/hivebotbullet)) src.Artifact_Activate() - if (my_effect.trigger == "energy") - if(istype(P,/obj/item/projectile/beam)) src.Artifact_Activate() - else if(istype(P,/obj/item/projectile/ion)) src.Artifact_Activate() - else if(istype(P,/obj/item/projectile/energy)) src.Artifact_Activate() - if (my_effect.trigger == "heat") - if(istype(P,/obj/item/projectile/temp)) src.Artifact_Activate() - -/obj/machinery/artifact/ex_act(severity) - switch(severity) - if(1.0) del src - if(2.0) - if (prob(50)) del src - if (my_effect.trigger == "force") src.Artifact_Activate() - if (my_effect.trigger == "heat") src.Artifact_Activate() - if(3.0) - if (my_effect.trigger == "force") src.Artifact_Activate() - if (my_effect.trigger == "heat") src.Artifact_Activate() - return - -/obj/machinery/artifact/temperature_expose(null, temp, volume) - if (my_effect.trigger == "heat") src.Artifact_Activate() - -/obj/machinery/artifact/process() - if (!src.activated) - return - if (chargetime > 0) - chargetime -= 1 - else - src.charged = 1 - - my_effect.UpdateEffect(src.loc) - - //activate - if( (my_effect.effectmode == "pulse" || my_effect.effecttype == "worldpulse") && activated) - if(src.charged && my_effect.DoEffect(src)) - src.charged = 0 - src.chargetime = src.recharge - -/obj/machinery/artifact/proc/Artifact_Activate() - src.activated = !src.activated - var/display_msg = "" - if(activated) - if(prob(30)) - switch(rand(4)) - if(0) - display_msg = "momentarily glows brightly!" - if(1) - display_msg = "distorts slightly for a moment!" - if(2) - display_msg = "makes a slightly clicking noise!" - if(3) - display_msg = "flickers slightly!" - if(4) - display_msg = "vibrates!" - else - my_effect.HaltEffect() - if(prob(30)) - switch(rand(2)) - if(0) - display_msg = "grows dull!" - if(1) - display_msg = "fades in intensity!" - if(2) - display_msg = "suddenly becomes very quiet!" - - icon_state = "ano[icon_num][activated]" - for(var/mob/O in viewers(src, null)) - O.show_message(text("[] [display_msg]", src), 1) - -/obj/machinery/artifact/proc/Artifact_Contact(var/mob/user as mob) - // Trigger Code - if (istype (user,/mob/living/carbon/) && my_effect.trigger == "touch" && !src.activated) src.Artifact_Activate() - else if (my_effect.trigger != "touch" && !src.activated) user << "Nothing happens." - - if (my_effect.effectmode == "contact" && src.activated && src.charged) - my_effect.DoEffect(user) - src.charged = 0 - src.chargetime = src.recharge - -// this was used in QM for a time but it fell into disuse and wasn't removed, the purpose being to check if an artifact -// was benevolent or malicious, to determine whether QMs would be paid or punished for shipping it - -/obj/machinery/artifact/Move() - ..() - my_effect.update_move(src, src.loc) diff --git a/code/modules/research/xenoarchaeology/artifact/effect_old.dm b/code/modules/research/xenoarchaeology/artifact/effect_old.dm deleted file mode 100644 index 092cb0d0f5..0000000000 --- a/code/modules/research/xenoarchaeology/artifact/effect_old.dm +++ /dev/null @@ -1,542 +0,0 @@ -// - -/datum/artifact_effect - var/artifact_id = "" // Display ID of the spawning artifact - var/trigger = "touch" // What activates it? - var/triggerX = "none" // Used for more varied triggers - var/effecttype = "healing" // What does it do? - var/effectmode = "aura" // How does it carry out the effect? - var/aurarange = 4 // How far the artifact will extend an aura effect. - var/list/created_field - var/archived_loc - -/datum/artifact_effect/New() - // - created_field = new() - -/datum/artifact_effect/proc/GetOriginString(var/origin) - -/datum/artifact_effect/proc/GetEffectString(var/effect) - -/datum/artifact_effect/proc/GetTriggerString(var/trigger) - -/datum/artifact_effect/proc/GetRangeString(var/range) - switch(effectmode) - if("aura") return "Constant Short-Range Energy Field" - if("pulse") - if(aurarange > 7) return "Long Range Energy Pulses" - else return "Medium Range Energy Pulses" - if("worldpulse") return "Extreme Range Energy Pulses" - if("contact") return "Requires contact with subject" - else return "Unknown Range" - -/datum/artifact_effect/proc/HaltEffect() - for(var/obj/effect/energy_field/F in created_field) - created_field.Remove(F) - del F - -/datum/artifact_effect/proc/UpdateEffect(var/atom/originator) - /*for(var/obj/effect/energy_field/F in created_field) - created_field.Remove(F) - del F*/ - if(originator.loc != archived_loc) - archived_loc = originator.loc - update_move(originator) - - for(var/obj/effect/energy_field/E in created_field) - if(E.strength < 5) - E.Strengthen(0.2) - -/datum/artifact_effect/proc/DoEffect(var/atom/originator) - archived_loc = originator.loc - if (src.effectmode == "contact") - var/mob/living/user = originator - if(!user) - return - switch(src.effecttype) - if("healing") - //caeltodo - if (istype(user, /mob/living/carbon/human/)) - user << "\blue You feel a soothing energy invigorate you." - - var/mob/living/carbon/human/H = user - for(var/datum/organ/external/affecting in H.organs) - if(!affecting) continue - if(!istype(affecting, /datum/organ/external)) continue - affecting.heal_damage(25, 25) //fixes getting hit after ingestion, killing you when game updates organ health - //user:heal_organ_damage(25, 25) - // - user.adjustOxyLoss(-25) - user.adjustToxLoss(-25) - user.adjustBruteLoss(-25) - user.adjustFireLoss(-25) - user.adjustBrainLoss(-25) - user.radiation -= min(user.radiation, 25) - user.nutrition += 50 - H.bodytemperature = initial(H.bodytemperature) - // - H.vessel.add_reagent("blood",50) - spawn(1) - H.fixblood() - H.regenerate_icons() - return 1 - // - if (istype(user, /mob/living/carbon/monkey/)) - user << "\blue You feel a soothing energy invigorate you." - user.adjustOxyLoss(-25) - user.adjustToxLoss(-25) - user.adjustBruteLoss(-25) - user.adjustFireLoss(-25) - user.adjustBrainLoss(-25) - return 1 - else user << "Nothing happens." - if("injure") - if (istype(user, /mob/living/carbon/)) - user << "\red A painful discharge of energy strikes you!" - user.adjustOxyLoss(rand(5,25)) - user.adjustToxLoss(rand(5,25)) - user.adjustBruteLoss(rand(5,25)) - user.adjustFireLoss(rand(5,25)) - user.adjustBrainLoss(rand(5,25)) - user.radiation += 25 - user.nutrition -= min(50, user.nutrition) - user.make_dizzy(6) - user.weakened += 6 - return 1 - else user << "Nothing happens." - if("stun") - if (istype(user, /mob/living/carbon/)) - user << "\red A powerful force overwhelms your consciousness." - user.weakened += 45 - user.stuttering += 45 - if(prob(50)) - user.stunned += rand(1,10) - return 1 - else user << "Nothing happens." - if("roboheal") - if (istype(user, /mob/living/silicon/robot)) - user << "\blue Your systems report damaged components mending by themselves!" - user.adjustBruteLoss(rand(-10,-30)) - user.adjustFireLoss(rand(-10,-30)) - return 1 - else user << "Nothing happens." - if("robohurt") - if (istype(user, /mob/living/silicon/robot)) - user << "\red Your systems report severe damage has been inflicted!" - user.adjustBruteLoss(rand(10,50)) - user.adjustFireLoss(rand(10,50)) - return 1 - else user << "Nothing happens." - if("forcefield") - while(created_field.len < 16) - var/obj/effect/energy_field/E = new (locate(user.x,user.y,user.z)) - created_field.Add(E) - E.strength = 1 - E.density = 1 - E.anchored = 1 - E.invisibility = 0 - return 1 - if("teleport") - var/list/randomturfs = new/list() - for(var/turf/T in orange(user, 50)) - if(!istype(T, /turf/simulated/floor) || T.density) - continue - randomturfs.Add(T) - if(randomturfs.len > 0) - user << "\red You are suddenly zapped away elsewhere!" - if (user.buckled) - user.buckled.unbuckle() - user.loc = pick(randomturfs) - var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() - sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is - sparks.start() - return 1 - if("sleepy") - user << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.") - user.drowsyness = min(user.drowsyness + rand(5,25), 50) - user.eye_blurry = min(user.eye_blurry + rand(1,3), 50) - return 1 - else if (src.effectmode == "aura") - switch(src.effecttype) - //caeltodo - if("healing") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - if(prob(10)) M << "\blue You feel a soothing energy radiating from something nearby." - M.adjustBruteLoss(-1) - M.adjustFireLoss(-1) - M.adjustToxLoss(-1) - M.adjustOxyLoss(-1) - M.adjustBrainLoss(-1) - M.updatehealth() - return 1 - if("injure") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - if(prob(10)) M << "\red You feel a painful force radiating from something nearby." - M.adjustBruteLoss(1) - M.adjustFireLoss(1) - M.adjustToxLoss(1) - M.adjustOxyLoss(1) - M.adjustBrainLoss(1) - M.updatehealth() - return 1 - if("stun") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - if(prob(10)) M << "\red Energy radiating from the [originator] is making you feel numb." - if(prob(20)) - M << "\red Your body goes numb for a moment." - M.stunned += 2 - M.weakened += 2 - M.stuttering += 2 - return 1 - if("roboheal") - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - if(prob(10)) M << "\blue SYSTEM ALERT: Beneficial energy field detected!" - M.adjustBruteLoss(-1) - M.adjustFireLoss(-1) - M.updatehealth() - return 1 - if("robohurt") - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - if(prob(10)) M << "\red SYSTEM ALERT: Harmful energy field detected!" - M.adjustBruteLoss(1) - M.adjustFireLoss(1) - M.updatehealth() - return 1 - if("cellcharge") - for (var/obj/machinery/power/apc/C in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge += 10 - for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) S.charge += 20 - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge += 10 - if(prob(10)) M << "\blue SYSTEM ALERT: Energy boosting field detected!" - return 1 - if("celldrain") - for (var/obj/machinery/power/apc/C in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge = max(B.charge-10,0) - for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) - S.charge = max(S.charge-20,0) - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge = max(D.charge-10,0) - if(prob(10)) M << "\red SYSTEM ALERT: Energy draining field detected!" - return 1 - if("planthelper") - for (var/obj/machinery/hydroponics/H in range(src.aurarange,originator)) - //makes weeds and shrooms and stuff more potent too - if(H.planted) - H.waterlevel += 2 - H.nutrilevel += 2 - if(H.toxic > 0) - H.toxic -= 1 - H.health += 1 - if(H.pestlevel > 0) - H.pestlevel -= 1 - if(H.weedlevel > 0) - H.weedlevel -= 1 - H.lastcycle += 5 - return 1 - if("sleepy") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(prob(10)) - M << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.") - M.drowsyness = min(M.drowsyness + 1, 25) - M.eye_blurry = min(M.eye_blurry + 1, 25) - return 1 - else if (src.effectmode == "pulse") - for(var/mob/O in viewers(originator, null)) - O.show_message(text("[] emits a pulse of energy!", originator), 1) - switch(src.effecttype) - //caeltodo - if("healing") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - M << "\blue A wave of energy invigorates you." - M.adjustBruteLoss(-5) - M.adjustFireLoss(-5) - M.adjustToxLoss(-5) - M.adjustOxyLoss(-5) - M.adjustBrainLoss(-5) - M.updatehealth() - return 1 - if("injure") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - M << "\red A wave of energy causes you great pain!" - M.adjustBruteLoss(5) - M.adjustFireLoss(5) - M.adjustToxLoss(5) - M.adjustOxyLoss(5) - M.adjustBrainLoss(5) - M.make_dizzy(6) - M.weakened += 3 - M.updatehealth() - return 1 - if("stun") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - M << "\red A wave of energy overwhelms your senses!" - M.paralysis += 3 - M.weakened += 4 - M.stuttering += 4 - return 1 - if("roboheal") - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - M << "\blue SYSTEM ALERT: Structural damage has been repaired by energy pulse!" - M.adjustBruteLoss(-10) - M.adjustFireLoss(-10) - M.updatehealth() - return 1 - if("robohurt") - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - M << "\red SYSTEM ALERT: Structural damage inflicted by energy pulse!" - M.adjustBruteLoss(10) - M.adjustFireLoss(10) - M.updatehealth() - return 1 - if("cellcharge") - for (var/obj/machinery/power/apc/C in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge += 250 - for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) S.charge += 400 - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge += 250 - M << "\blue SYSTEM ALERT: Large energy boost detected!" - return 1 - if("celldrain") - for (var/obj/machinery/power/apc/C in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge = max(B.charge-500,0) - for (var/obj/machinery/power/smes/S in range (src.aurarange,originator)) - S.charge = max(S.charge-400,0) - for (var/mob/living/silicon/robot/M in range(src.aurarange,originator)) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge = max(D.charge-500,0) - M << "\red SYSTEM ALERT: Severe energy drain detected!" - return 1 - if("planthelper") - //makes weeds and shrooms and stuff more potent too - for (var/obj/machinery/hydroponics/H in range(src.aurarange,originator)) - if(H.planted) - H.dead = 0 - H.waterlevel = 200 - H.nutrilevel = 200 - H.toxic = 0 - H.health = 100 - H.pestlevel = 0 - H.weedlevel = 0 - H.lastcycle = H.cycledelay - return 1 - if("teleport") - for (var/mob/living/M in range(src.aurarange,originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - var/list/randomturfs = new/list() - for(var/turf/T in orange(M, 30)) - if(!istype(T, /turf/simulated/floor) || T.density) - continue - randomturfs.Add(T) - if(randomturfs.len > 0) - M << "\red You are displaced by a strange force!" - if(M.buckled) - M.buckled.unbuckle() - M.loc = pick(randomturfs) - var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() - sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is - sparks.start() - return 1 - if("dnaswitch") - for(var/mob/living/H in range(src.aurarange,originator)) - if(ishuman(H) && istype(H:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(H:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - - if(prob(30)) - H << pick("\green You feel a little different.","\green You feel strange.","\green You feel different.") - //todo - if (H.gender == FEMALE) - H.gender = MALE - else - H.gender = FEMALE - /*H.dna.ready_dna(H) - H.update_body() - H.update_face()*/ - return 1 - if("emp") - empulse(get_turf(originator), aurarange/2, aurarange) - return 1 - if("sleepy") - for (var/mob/living/carbon/M in range(src.aurarange,originator)) - if(prob(30)) - M << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.") - if(prob(50)) - M.drowsyness = min(M.drowsyness + rand(1,5), 25) - if(prob(50)) - M.eye_blurry = min(M.eye_blurry + rand(1,5), 25) - return 1 - else if (src.effectmode == "worldpulse") - for(var/mob/O in viewers(originator, null)) - O.show_message(text("[] emits a powerful burst of energy!", originator), 1) - switch(src.effecttype) - if("healing") - for (var/mob/living/carbon/M in range(200, originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - M << "\blue Waves of soothing energy wash over you." - M.adjustBruteLoss(-3) - M.adjustFireLoss(-3) - M.adjustToxLoss(-3) - M.adjustOxyLoss(-3) - M.adjustBrainLoss(-3) - M.updatehealth() - return 1 - if("injure") - for (var/mob/living/carbon/human/M in range(200, originator)) - M << "\red A wave of painful energy strikes you!" - M.adjustBruteLoss(3) - M.adjustFireLoss(3) - M.adjustToxLoss(3) - M.adjustOxyLoss(3) - M.adjustBrainLoss(3) - M.updatehealth() - return 1 - if("stun") - for (var/mob/living/carbon/M in range(200, originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - M << "\red A powerful force causes you to black out momentarily." - M.paralysis += 5 - M.weakened += 8 - M.stuttering += 8 - return 1 - if("roboheal") - for (var/mob/living/silicon/robot/M in range(200, originator)) - M << "\blue SYSTEM ALERT: Structural damage has been repaired by energy pulse!" - M.adjustBruteLoss(-5) - M.adjustFireLoss(-5) - M.updatehealth() - return 1 - if("robohurt") - for (var/mob/living/silicon/robot/M in range(200, originator)) - M << "\red SYSTEM ALERT: Structural damage inflicted by energy pulse!" - M.adjustBruteLoss(5) - M.adjustFireLoss(5) - M.updatehealth() - return 1 - if("cellcharge") - for (var/obj/machinery/power/apc/C in range(200, originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge += 100 - for (var/obj/machinery/power/smes/S in range (src.aurarange,src)) S.charge += 250 - for (var/mob/living/silicon/robot/M in world) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge += 100 - M << "\blue SYSTEM ALERT: Energy boost detected!" - return 1 - if("celldrain") - for (var/obj/machinery/power/apc/C in range(200, originator)) - for (var/obj/item/weapon/cell/B in C.contents) - B.charge = max(B.charge-250,0) - for (var/obj/machinery/power/smes/S in range (src.aurarange,src)) - S.charge = max(S.charge-250,0) - for (var/mob/living/silicon/robot/M in world) - for (var/obj/item/weapon/cell/D in M.contents) - D.charge = max(D.charge-250,0) - M << "\red SYSTEM ALERT: Energy drain detected!" - return 1 - if("teleport") - for (var/mob/living/M in range(200, originator)) - if(ishuman(M) && istype(M:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(M:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - var/list/randomturfs = new/list() - for(var/turf/T in orange(M, 15)) - if(!istype(T, /turf/simulated/floor) || T.density) - continue - randomturfs.Add(T) - if(randomturfs.len > 0) - M << "\red You are displaced by a strange force!" - if(M.buckled) - M.buckled.unbuckle() - M.loc = pick(randomturfs) - var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() - sparks.set_up(3, 0, get_turf(originator)) //no idea what the 0 is - sparks.start() - return 1 - if("dnaswitch") - for(var/mob/living/H in range(200, originator)) - if(ishuman(H) && istype(H:wear_suit,/obj/item/clothing/suit/bio_suit/anomaly) && istype(H:head,/obj/item/clothing/head/bio_hood/anomaly)) - continue - - if(prob(30)) - H << pick("\green You feel a little different.","\green You feel strange.","\green You feel different.") - //todo - if (H.gender == FEMALE) - H.gender = MALE - else - H.gender = FEMALE - /*H.dna.ready_dna(H) - H.update_body() - H.update_face()*/ - return 1 - if("sleepy") - for(var/mob/living/H in range(200, originator)) - H.drowsyness = min(H.drowsyness + rand(5,15), 50) - H.eye_blurry = min(H.eye_blurry + rand(5,15), 50) - return 1 - -//initially for the force field artifact -/datum/artifact_effect/proc/update_move(var/atom/originator) - switch(effecttype) - if("forcefield") - while(created_field.len < 16) - //for now, just instantly respawn the fields when they get destroyed - var/obj/effect/energy_field/E = new (locate(originator.x,originator.y,originator)) - created_field.Add(E) - E.strength = 1 - E.density = 1 - E.anchored = 1 - E.invisibility = 0 - - var/obj/effect/energy_field/E = created_field[1] - E.loc = locate(originator.x + 2,originator.y + 2,originator.z) - E = created_field[2] - E.loc = locate(originator.x + 2,originator.y + 1,originator.z) - E = created_field[3] - E.loc = locate(originator.x + 2,originator.y,originator.z) - E = created_field[4] - E.loc = locate(originator.x + 2,originator.y - 1,originator.z) - E = created_field[5] - E.loc = locate(originator.x + 2,originator.y - 2,originator.z) - E = created_field[6] - E.loc = locate(originator.x + 1,originator.y + 2,originator.z) - E = created_field[7] - E.loc = locate(originator.x + 1,originator.y - 2,originator.z) - E = created_field[8] - E.loc = locate(originator.x,originator.y + 2,originator.z) - E = created_field[9] - E.loc = locate(originator.x,originator.y - 2,originator.z) - E = created_field[10] - E.loc = locate(originator.x - 1,originator.y + 2,originator.z) - E = created_field[11] - E.loc = locate(originator.x - 1,originator.y - 2,originator.z) - E = created_field[12] - E.loc = locate(originator.x - 2,originator.y + 2,originator.z) - E = created_field[13] - E.loc = locate(originator.x - 2,originator.y + 1,originator.z) - E = created_field[14] - E.loc = locate(originator.x - 2,originator.y,originator.z) - E = created_field[15] - E.loc = locate(originator.x - 2,originator.y - 1,originator.z) - E = created_field[16] - E.loc = locate(originator.x - 2,originator.y - 2,originator.z) diff --git a/code/modules/research/xenoarchaeology/finds/finds.dm b/code/modules/research/xenoarchaeology/finds/finds.dm index 7464e7c8b0..0b776ca91f 100644 --- a/code/modules/research/xenoarchaeology/finds/finds.dm +++ b/code/modules/research/xenoarchaeology/finds/finds.dm @@ -324,26 +324,27 @@ if(26) //energy gun var/spawn_type = pick(\ - /obj/item/weapon/gun/energy/laser/practice;100,\ - /obj/item/weapon/gun/energy/laser;75,\ - /obj/item/weapon/gun/energy/xray;50,\ - /obj/item/weapon/gun/energy/laser/captain;25,\ - ) - var/obj/item/weapon/gun/energy/new_gun = new spawn_type(src.loc) - new_item = new_gun - new_item.icon_state = "egun[rand(1,6)]" + /obj/item/weapon/gun/energy/laser/practice,\ + /obj/item/weapon/gun/energy/laser,\ + /obj/item/weapon/gun/energy/xray,\ + /obj/item/weapon/gun/energy/laser/captain) + if(spawn_type) + var/obj/item/weapon/gun/energy/new_gun = new spawn_type(src.loc) + new_item = new_gun + new_item.icon_state = "egun[rand(1,6)]" + new_gun.desc = "This is an antique energy weapon, you're not sure if it will fire or not." - //5% chance to explode when first fired - //10% chance to have an unchargeable cell - //15% chance to gain a random amount of starting energy, otherwise start with an empty cell - if(prob(5)) - new_gun.power_supply.rigged = 1 - if(prob(10)) - new_gun.power_supply.maxcharge = 0 - if(prob(15)) - new_gun.power_supply.charge = rand(0, new_gun.power_supply.maxcharge) - else - new_gun.power_supply.charge = 0 + //5% chance to explode when first fired + //10% chance to have an unchargeable cell + //15% chance to gain a random amount of starting energy, otherwise start with an empty cell + if(prob(5)) + new_gun.power_supply.rigged = 1 + if(prob(10)) + new_gun.power_supply.maxcharge = 0 + if(prob(15)) + new_gun.power_supply.charge = rand(0, new_gun.power_supply.maxcharge) + else + new_gun.power_supply.charge = 0 item_type = "gun" if(27) diff --git a/code/modules/research/xenoarchaeology/finds/finds_defines.dm b/code/modules/research/xenoarchaeology/finds/finds_defines.dm index b9649d074b..6de9b4c806 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_defines.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_defines.dm @@ -206,6 +206,28 @@ ) return find_type +var/list/responsive_carriers = list( \ + "carbon", \ + "potassium", \ + "hydrogen", \ + "nitrogen", \ + "mercury", \ + "iron", \ + "chlorine", \ + "phosphorus", \ + "plasma") + +var/list/finds_as_strings = list( \ + "Trace organic cells", \ + "Long exposure particles", \ + "Trace water particles", \ + "Crystalline structures", \ + "Metallic derivative", \ + "Metallic composite", \ + "Metamorphic/igneous rock composite", \ + "Metamorphic/sedimentary rock composite", \ + "Anomalous material" ) + #undef ARCHAEO_BOWL #undef ARCHAEO_URN #undef ARCHAEO_CUTLERY diff --git a/code/modules/research/xenoarchaeology/geosample.dm b/code/modules/research/xenoarchaeology/geosample.dm index 91d5f1bd62..b12298c916 100644 --- a/code/modules/research/xenoarchaeology/geosample.dm +++ b/code/modules/research/xenoarchaeology/geosample.dm @@ -29,30 +29,6 @@ pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 -var/list/responsive_carriers = list( \ - "carbon", \ - "potassium", \ - "hydrogen", \ - "nitrogen", \ - "mercury", \ - "iron", \ - "chlorine", \ - "phosphorus", \ - "plasma") - -var/list/finds_as_strings = list( \ - "Trace organic cells", \ - "Long exposure particles", \ - "Trace water particles", \ - "Crystalline structures", \ - "Metallic derivative", \ - "Metallic composite", \ - "Metamorphic/igneous rock composite", \ - "Metamorphic/sedimentary rock composite", \ - "Anomalous material" ) - -var/list/artifact_spawning_turfs = list() - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Geosample datum @@ -64,7 +40,6 @@ var/list/artifact_spawning_turfs = list() var/artifact_id = "" //id of a nearby artifact, if there is one var/artifact_distance = -1 //proportional to distance var/source_mineral = "chlorine" //machines will pop up a warning telling players that the sample may be confused - var/total_spread = 0 // //var/source_mineral //all potential finds are initialised to null, so nullcheck before you access them @@ -76,11 +51,11 @@ var/list/artifact_spawning_turfs = list() //this should only need to be called once /datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container) + set background = 1 if(!container || !istype(container)) return age = rand(1,999) - total_spread = 0 switch(container.mineralName) if("Uranium") @@ -132,8 +107,15 @@ var/list/artifact_spawning_turfs = list() var/responsive_reagent = get_responsive_reagent(F.find_type) find_presence[responsive_reagent] = F.dissonance_spread - for(var/entry in find_presence) - total_spread += find_presence[entry] + //loop over again to reset values to percentages + var/total_presence = 0 + for(var/carrier in find_presence) + total_presence += find_presence[carrier] + for(var/carrier in find_presence) + find_presence[carrier] = find_presence[carrier] / total_presence + + /*for(var/entry in find_presence) + total_spread += find_presence[entry]*/ //have this separate from UpdateTurf() so that we dont have a billion turfs being updated (redundantly) every time an artifact spawns /datum/geosample/proc/UpdateNearbyArtifactInfo(var/turf/simulated/mineral/container) @@ -146,7 +128,7 @@ var/list/artifact_spawning_turfs = list() else for(var/turf/simulated/mineral/holder in artifact_spawning_turfs) if(holder.artifact_find) - var/dist = get_dist(container, holder) + var/dist = get_dist(container, holder) * 2 if(dist < holder.artifact_find.artifact_detect_range && dist < src.artifact_distance) src.artifact_distance = dist src.artifact_id = holder.artifact_find.artifact_id diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_accelerator.dm b/code/modules/research/xenoarchaeology/machinery/analysis_accelerator.dm deleted file mode 100644 index 74ac904dc9..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_accelerator.dm +++ /dev/null @@ -1,44 +0,0 @@ - -// This machine shows the age for extremely old finds - -obj/machinery/anomaly/accelerator - name = "Accelerator spectrometer" - -obj/machinery/anomaly/accelerator/ScanResults() - var/results = "The scan was inconclusive. Check sample integrity and carrier consistency." - - var/datum/geosample/scanned_sample - var/carrier_name - var/num_reagents = 0 - - for(var/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier_name = R.id - num_reagents++ - - if(num_reagents == 2 && scanned_sample && carrier_name) - var/specifity = GetResultSpecifity(scanned_sample, carrier_name) - results = "Kinetic acceleration of carrier ([carrier_name]) indicates age ([100 * specifity]% accuracy):

" - - if(scanned_sample.age_billion) - var/displayed_age_millions = scanned_sample.age_million + max(scanned_sample.age_million * ((1 - specifity) * (2 * rand() - 1)), 0) - var/displayed_age_billions = scanned_sample.age_billion + max(scanned_sample.age_billion * ((1 - specifity) * (2 * rand() - 1)), 0) - results += "[displayed_age_billions + displayed_age_millions / 1000] billion years.
" - else if(scanned_sample.age_million) - var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age_thousand * ((1 - specifity) * (4 * rand() - 2)), 0) - var/displayed_age_millions = scanned_sample.age_million + max(scanned_sample.age_million * ((1 - specifity) * (2 * rand() - 1)), 0) - results += "[displayed_age_millions + displayed_age_thousands / 1000] million years.
" - else if(scanned_sample.age_thousand) - var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - specifity) * (8 * rand() - 4)), 0) - var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age * ((1 - specifity) * (4 * rand() - 2)), 0) - results += "[displayed_age_thousands + displayed_age / 1000] thousand years.
" - else - var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - specifity) * (8 * rand() - 4)), 0) - results += "[displayed_age] years.
" - - results += "
Warning, results only valid for ages on the scale of billions of years." - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm b/code/modules/research/xenoarchaeology/machinery/analysis_base.dm deleted file mode 100644 index a462bd98fa..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm +++ /dev/null @@ -1,203 +0,0 @@ -//Handles how much the temperature changes on power use. (Joules/Kelvin) -//Equates to as much heat energy per kelvin as a quarter tile of air. -#define XENOARCH_HEAT_CAPACITY 5000 - -//Handles heat transfer to the air. (In watts) -//Can heat a single tile 2 degrees per tick. -#define XENOARCH_MAX_ENERGY_TRANSFER 4000 - -//How many joules of electrical energy produce how many joules of heat energy? -#define XENOARCH_HEAT_COEFFICIENT 3 - - -/obj/machinery/anomaly - name = "Analysis machine" - desc = "A specialised, complex analysis machine." - anchored = 1 - density = 1 - icon = 'icons/obj/virology.dmi' - icon_state = "analyser" - - idle_power_usage = 20 //watts - active_power_usage = 300 //Because I need to make up numbers~ - - var/obj/item/weapon/reagent_containers/glass/held_container - var/obj/item/weapon/tank/fuel_container - var/target_scan_ticks = 30 - var/report_num = 0 - var/scan_process = 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/max_temp = 450 - -/obj/machinery/anomaly/New() - ..() - - //for analysis debugging - /*var/obj/item/weapon/reagent_containers/glass/solution_tray/S = new(src.loc) - var/turf/simulated/mineral/diamond/D - for(var/turf/simulated/mineral/diamond/M in world) - D = M - break - S.reagents.add_reagent("analysis_sample", 1, D.geological_data) - S.reagents.add_reagent("chlorine", 1, null)*/ - -/obj/machinery/anomaly/process() - //not sure if everything needs to heat up, or just the GLPC - var/datum/gas_mixture/env = loc.return_air() - var/environmental_temp = env.temperature - if(scan_process) - if(scan_process++ > target_scan_ticks) - FinishScan() - else if(temperature > 400) - src.visible_message("\blue \icon[src] shuts down from the heat!", 2) - scan_process = 0 - else if(temperature > 350 && prob(10)) - src.visible_message("\blue \icon[src] bleets plaintively.", 2) - if(temperature > 400) - scan_process = 0 - - //show we're busy - if(prob(5)) - src.visible_message("\blue \icon[src] [pick("whirrs","chuffs","clicks")][pick(" quietly"," softly"," sadly"," excitedly"," energetically"," angrily"," plaintively")].", 2) - - use_power = 2 - - else - use_power = 1 - - auto_use_power() - - //Add 3000 joules when active. This is about 0.6 degrees per tick. - //May need adjustment - if(use_power == 1) - var/heat_added = active_power_usage *XENOARCH_HEAT_COEFFICIENT - - if(temperature < max_temp) - temperature += heat_added/XENOARCH_HEAT_CAPACITY - - var/temperature_difference = abs(environmental_temp-temperature) - var/datum/gas_mixture/removed = loc.remove_air(env.total_moles*0.25) - var/heat_capacity = removed.heat_capacity() - - heat_added = max(temperature_difference*heat_capacity, XENOARCH_MAX_ENERGY_TRANSFER) - - if(temperature > environmental_temp) - //cool down to match the air - temperature = max(TCMB, temperature - heat_added/XENOARCH_HEAT_CAPACITY) - removed.temperature = max(TCMB, removed.temperature + heat_added/heat_capacity) - - if(temperature_difference > 10 && prob(5)) - src.visible_message("\blue \icon[src] hisses softly.", 2) - - else - //heat up to match the air - temperature = max(TCMB, temperature + heat_added/XENOARCH_HEAT_CAPACITY) - removed.temperature = max(TCMB, removed.temperature - heat_added/heat_capacity) - - if(temperature_difference > 10 && prob(5)) - src.visible_message("\blue \icon[src] plinks quietly.", 2) - - env.merge(removed) - - -//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 += "Module heat level: [temperature] kelvin
" - dat += "Safeties set at 350k, shielding failure at 400k. Failure to maintain safe heat levels may result in equipment damage.
" - dat += "
" - if(scan_process) - dat += "Scan in progress


" - else - dat += "[held_container ? "Eject beaker" : "No beaker inserted."]
" - //dat += "[fuel_container ? "Eject fuel tank" : "No fuel tank inserted."]
" - dat += "[held_container ? "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 [W] into the [src]." - user.drop_item(W) - held_container = W - held_container.loc = src - 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/proc/ScanResults() - //instantiate in children to produce unique scan behaviour - return "\red Error initialising scanning components." - -obj/machinery/anomaly/proc/FinishScan() - scan_process = 0 - updateDialog() - - //determine the results and print a report - if(held_container) - src.visible_message("\blue \icon[src] makes an insistent chime.", 2) - var/obj/item/weapon/paper/P = new(src.loc) - P.name = "[src] 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("\blue \icon[src] makes a low buzzing noise.", 2) - -obj/machinery/anomaly/Topic(href, href_list) - ..() - usr.set_machine(src) - 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 >= 350) - var/proceed = input("Unsafe internal temperature detected, enter YES below to continue.","Warning") - if(proceed == "YES" && get_dist(src, usr) <= 1) - scan_process = 1 - else - scan_process = 1 - - updateUsrDialog() - -//whether the carrier sample matches the possible finds -//results greater than a threshold of 0.6 means a positive result -obj/machinery/anomaly/proc/GetResultSpecifity(var/datum/geosample/scanned_sample, var/carrier_name) - var/specifity = 0 - if(scanned_sample && carrier_name) - - if(scanned_sample.find_presence.Find(carrier_name)) - specifity = 0.75 * (scanned_sample.find_presence[carrier_name] / scanned_sample.total_spread) + 0.25 - else - specifity = rand(0, 0.5) - - return specifity diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_fourier_transform.dm b/code/modules/research/xenoarchaeology/machinery/analysis_fourier_transform.dm deleted file mode 100644 index 98c49b2372..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_fourier_transform.dm +++ /dev/null @@ -1,34 +0,0 @@ - -// This machine tells the distance to a nearby artifact, if there is one - -obj/machinery/anomaly/fourier_transform - name = "Fourier Transform spectroscope" - -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/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier = R.id - 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(distance > 0) - distance += (2 * rand() - 1) * distance * 0.05 - results = "Fourier transform analysis on anomalous energy absorption through carrier ([carrier]) indicates source located inside emission radius ([95 * specifity]% accuracy): [distance]." - else - results = "Energy dispersion detected throughout sample consistent with background readings.
" - if(carrier == scanned_sample.source_mineral) - results += "Warning, analysis may be contaminated by high quantities of molecular carrier present throughout sample." - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_gas_chromatography.dm b/code/modules/research/xenoarchaeology/machinery/analysis_gas_chromatography.dm deleted file mode 100644 index bd6dbeb9b3..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_gas_chromatography.dm +++ /dev/null @@ -1,39 +0,0 @@ - -// This machine shows the materials that are present - -obj/machinery/anomaly/gas_chromatography - name = "Gas Chromatography spectrometer" - -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/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier = R.id - num_reagents++ - - if(num_reagents == 2 && scanned_sample) - var/specifity = GetResultSpecifity(scanned_sample, carrier) - results = "Chromatography partitioning analysis over carrier ([carrier]) indicates the following elements present ([100 * specifity]% accuracy):

" - - var/num_found = 0 - for(var/index=1,index <= scanned_sample.find_presence.len, index++) - var/find = scanned_sample.find_presence[index] - if(find && prob(100 * specifity)) - results += " - " + finds_as_strings[index] + "
" - num_found++ - - if(!num_found) - results = "Chromatography partitioning results over carrier ([carrier]) to determine elemental makeup were inconclusive.
" - - if(!carrier) - results += "
No carrier detected, scan accuracy affected.
" - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_hyperspectral.dm b/code/modules/research/xenoarchaeology/machinery/analysis_hyperspectral.dm deleted file mode 100644 index a070a61a5d..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_hyperspectral.dm +++ /dev/null @@ -1,55 +0,0 @@ - -obj/machinery/anomaly/hyperspectral - name = "Hyperspectral Imager" - icon = 'icons/obj/xenoarchaeology.dmi' - icon_state = "scanner" - -obj/machinery/anomaly/hyperspectral/process() - ..() - if(scan_process) - icon_state = "scanner_active" - else if(prob(10)) - icon_state = "scanner" - flick(src, "scanner_active") - -obj/machinery/anomaly/hyperspectral/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/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier = R.id - num_reagents++ - - if(num_reagents == 2 && scanned_sample && carrier) - //all necessary components are present - var/specifity = GetResultSpecifity(scanned_sample, carrier) - results = "Spectral signature over carrier ([carrier]):
" - if(specifity <= 0.25) - //results += "
" - results += "" - else if(specifity <= 0.5) - //results += "
" - results += "" - else if(specifity <= 0.75) - //results += "
" - results += "" - else - //results += "
" - results += "" - - results += "
" - if(scanned_sample.artifact_id) - results += "Detected energy signatures [100 * (1 - specifity)]% consistent with standard background readings.
" - if(prob( (specifity + 0.5 * (1 - specifity)) * 100)) - results += "Anomalous exotic energy signature isolated: [scanned_sample.artifact_id]." - else - results += "Detected energy signatures [95 + 5 * (2 * rand() - 1) * (1 - specifity)]% consistent with standard background readings." - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_ion_mobility.dm b/code/modules/research/xenoarchaeology/machinery/analysis_ion_mobility.dm deleted file mode 100644 index 9b37d20df9..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_ion_mobility.dm +++ /dev/null @@ -1,47 +0,0 @@ - -// This machine shows the amount of a certain material that is present - -obj/machinery/anomaly/ion_mobility - name = "Ion Mobility Spectrometer" - desc = "A specialised, complex analysis machine." - icon = 'icons/obj/virology.dmi' - icon_state = "analyser" - -obj/machinery/anomaly/ion_mobility/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/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier = R.id - num_reagents++ - - if(num_reagents == 2 && scanned_sample && carrier) - //all necessary components are present - results = "Kinetic analysis on sample's ionic residue in carrier ([carrier]) indicates the dissonance spread:

" - var/found = 0 - if(scanned_sample.find_presence.Find(carrier)) - var/dis_ratio = scanned_sample.find_presence[carrier] - var/desc_index = responsive_carriers.Find(carrier) - results += " - [finds_as_strings[desc_index]]: [dis_ratio]
" - found++ - /* - for(var/index=1,index <= scanned_sample.find_presence.len, index++) - var/find = scanned_sample.find_presence[index] - //world << "index: [index], find: [find], response: [responsive_carriers[index]], carrier: [carrier]" - if(find && responsive_carriers[index] == carrier) - results += " - [finds_as_strings[index]] [find * 100]%
" - found++ - */ - if(!found) - results = "Kinetic analysis on sample's ionic residue in carrier ([carrier]) to determine composition were inconclusive.
" - if(carrier == scanned_sample.source_mineral) - results += "Warning, analysis may be contaminated by high quantities of molecular carrier present throughout sample." - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_isotope_ratio.dm b/code/modules/research/xenoarchaeology/machinery/analysis_isotope_ratio.dm deleted file mode 100644 index 04efb278ad..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/analysis_isotope_ratio.dm +++ /dev/null @@ -1,51 +0,0 @@ - -// This machine shows the age for newer finds - -obj/machinery/anomaly/isotope_ratio - name = "Isotope ratio spectrometer" - desc = "A specialised, complex analysis machine." - icon = 'icons/obj/virology.dmi' - icon_state = "analyser" - -obj/machinery/anomaly/isotope_ratio/ScanResults() - var/results = "The scan was inconclusive. Check sample integrity and carrier consistency." - - var/datum/geosample/scanned_sample - var/carrier_name - var/num_reagents = 0 - - for(var/datum/reagent/A in held_container.reagents.reagent_list) - var/datum/reagent/R = A - if(istype(R, /datum/reagent/analysis_sample)) - scanned_sample = R.data - else - carrier_name = R.id - num_reagents++ - - if(num_reagents == 2 && scanned_sample && carrier_name) - var/accuracy = GetResultSpecifity(scanned_sample, carrier_name) - accuracy += 0.5 * (1 - accuracy) / scanned_sample.total_spread - if(!accuracy) - accuracy = rand(0.01, 0.5) - results = "Isotope decay analysis in carrier ([carrier_name]) indicates age ([100 * accuracy]% accuracy):

" - - if(scanned_sample.age_billion) - //scramble the results - var/displayed_age_thousands = rand(0, 999) - var/displayed_age_millions = rand(0, 999) - results += "[displayed_age_millions + displayed_age_thousands / 1000] million years.
" - else if(scanned_sample.age_million) - var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age_thousand * ((1 - accuracy) * (2 * rand() - 1)), 0) - var/displayed_age_millions = scanned_sample.age_million + max(scanned_sample.age_million * ((1 - accuracy) * (4 * rand() - 2)), 0) - results += "[displayed_age_millions + displayed_age_thousands / 1000] million years.
" - else if(scanned_sample.age_thousand) - var/displayed_age = scanned_sample.age + scanned_sample.age * ((1 - accuracy) * (2 * rand() - 1)) - var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age_thousand * ((1 - accuracy) * (2 * rand() - 1)), 0) - results += "[displayed_age_thousands + displayed_age / 1000] thousand years.
" - else - var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - accuracy) * (2 * rand() - 1)), 0) - results += "[displayed_age] years.
" - - results += "
Warning, results only valid up to ages of one billion years." - - return results diff --git a/code/modules/research/xenoarchaeology/machinery/artifact_analyser_old.dm b/code/modules/research/xenoarchaeology/machinery/artifact_analyser_old.dm deleted file mode 100644 index ff1415997b..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/artifact_analyser_old.dm +++ /dev/null @@ -1,318 +0,0 @@ - -//cael - some changes here. the analysis pad is entirely new - -/obj/machinery/artifact_analyser - name = "Artifact Analyser" - desc = "Studies the structure of artifacts to discover their uses." - icon = 'icons/obj/virology.dmi' - icon_state = "analyser" - anchored = 1 - density = 1 - var/working = 0 - var/accuO = 0 - var/accuT = 0 - var/accuE1 = 0 - var/accuE2 = 0 - var/aorigin = "None" - var/atrigger = "None" - var/aeffect1 = "None" - var/aeffect2 = "None" - var/list/origin_bonuses - var/list/trigger_bonuses - var/list/function_bonuses - var/list/range_bonuses - var/cur_id = "" - var/scan_num = 0 - var/obj/machinery/artifact/cur_artifact = null - var/obj/machinery/analyser_pad/owned_pad = null - var/list/allorigins = list("Ancient Robots","Martian","Wizard Federation","Extradimensional","Precursor") - var/list/alltriggers = list("Contact with Living Organism","Heavy Impact","Contact with Energy Source","Contact with Hydrogen","Contact with Corrosive Substance","Contact with Volatile Substance","Contact with Toxins","Exposure to Heat") - var/list/alleffects = list("Healing Device","Anti-biological Weapon","Non-lethal Stunning Trap","Mechanoid Repair Module","Mechanoid Deconstruction Device","Power Generator","Power Drain","Stellar Mineral Attractor","Agriculture Regulator","Shield Generator","Space-Time Displacer") - var/list/allranges = list("Constant Short-Range Energy Field","Medium Range Energy Pulses","Long Range Energy Pulses","Extreme Range Energy Pulses","Requires contact with subject") - -/obj/machinery/artifact_analyser/New() - ..() - origin_bonuses = new/list() - origin_bonuses["ancient"] = 0 - origin_bonuses["martian"] = 0 - origin_bonuses["wizard"] = 0 - origin_bonuses["eldritch"] = 0 - origin_bonuses["precursor"] = 0 - trigger_bonuses = new/list() - trigger_bonuses["ancient"] = 0 - trigger_bonuses["martian"] = 0 - trigger_bonuses["wizard"] = 0 - trigger_bonuses["eldritch"] = 0 - trigger_bonuses["precursor"] = 0 - function_bonuses = new/list() - function_bonuses["ancient"] = 0 - function_bonuses["martian"] = 0 - function_bonuses["wizard"] = 0 - function_bonuses["eldritch"] = 0 - function_bonuses["precursor"] = 0 - range_bonuses = new/list() - range_bonuses["ancient"] = 0 - range_bonuses["martian"] = 0 - range_bonuses["wizard"] = 0 - range_bonuses["eldritch"] = 0 - range_bonuses["precursor"] = 0 - // - spawn(10) - owned_pad = locate() in orange(1, src) - -/obj/machinery/artifact_analyser/attack_hand(var/mob/user as mob) - if(stat & (NOPOWER|BROKEN)) - return - user.machine = src - var/dat = "Artifact Analyser
" - dat += "

" - if(!owned_pad) - dat += "Unable to locate analysis pad.
" - dat += "

" - else if (!src.working) - dat += "Artifact ID: [cur_id]
" - dat += "Artifact Origin: [aorigin] ([accuO]%)
" - dat += "Activation Trigger: [atrigger] ([accuT]%)
" - dat += "Artifact Function: [aeffect1] ([accuE1]%)
" - dat += "Artifact Range: [aeffect2] ([accuE2]%)

" - dat += "

" - dat += "Artifact ID is determined from unique energy emission signatures.
" - dat += "Analyse Artifact (Scan number #[scan_num+1])
" - dat += "Upload/update artifact scan
" - dat += "Print Page
" - else - dat += "Please wait. Analysis in progress.
" - dat += "

" - // - dat += "Close
" - user << browse(dat, "window=artanalyser;size=450x500") - onclose(user, "artanalyser") - -/obj/machinery/artifact_analyser/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(350) - // - if(!owned_pad) - for(var/obj/machinery/analyser_pad/pad in range(1)) - owned_pad = pad - break - -/obj/machinery/artifact_analyser/proc/AA_FailedAnalysis(var/failtype) - switch(failtype) - if(1) - src.aorigin = "Failed to Identify" - if (prob(20)) src.aorigin = pick(src.allorigins) - if(2) - src.atrigger = "Failed to Identify" - if (prob(20)) src.atrigger = pick(src.alltriggers) - if(3) - src.aeffect1 = "Failed to Identify" - if (prob(20)) src.aeffect1 = pick(src.alleffects) - if(4) - src.aeffect2 = "Failed to Identify" - if (prob(20)) src.aeffect2 = pick(src.allranges) - -/obj/machinery/artifact_analyser/proc/AA_Analyse() - if(!cur_artifact) - return - src.accuO = 5 + rand(0,10) + origin_bonuses[cur_artifact.origin] + cur_artifact.activated * 50 - src.accuT = 5 + rand(0,10) + trigger_bonuses[cur_artifact.origin] + cur_artifact.activated * 50 - src.accuE1 = 5 + rand(0,10) + function_bonuses[cur_artifact.origin] + cur_artifact.activated * 50 - src.accuE2 = 5 + rand(0,10) + range_bonuses[cur_artifact.origin] + cur_artifact.activated * 50 - - //keep any correctly determined properties the same - var/origin_correct = 0 - var/trigger_correct = 0 - var/function_correct = 0 - var/range_correct = 0 - if(cur_id == cur_artifact.display_id) - if(src.aorigin == cur_artifact.origin) - origin_correct = 1 - - if(src.atrigger == cur_artifact.my_effect.trigger) - trigger_correct = 1 - else if(src.atrigger == cur_artifact.my_effect.triggerX) - trigger_correct = 1 - - if(src.aeffect1 == cur_artifact.my_effect.effecttype) - function_correct = 1 - - if(src.aeffect2 == cur_artifact.my_effect.effectmode) - range_correct = 1 - - if (src.accuO > 100) src.accuO = 100 - if (src.accuT > 100) src.accuT = 100 - if (src.accuE1 > 100) src.accuE1 = 100 - if (src.accuE2 > 100) src.accuE2 = 100 - // Roll to generate report - if (prob(accuO) || origin_correct) - switch(cur_artifact.origin) - if("ancient") src.aorigin = "Ancient Robots" - if("martian") src.aorigin = "Martian" - if("wizard") src.aorigin = "Wizard Federation" - if("eldritch") src.aorigin = "Extradimensional" - if("precursor") src.aorigin = "Precursor" - else src.aorigin = "Unknown Origin" - origin_bonuses[cur_artifact.origin] += 10 - else - AA_FailedAnalysis(1) - origin_bonuses[cur_artifact.origin] += 5 - if (prob(accuT) || trigger_correct) - switch(cur_artifact.my_effect.trigger) - if("touch") src.atrigger = "Contact with Living Organism" - if("force") src.atrigger = "Heavy Impact" - if("energy") src.atrigger = "Contact with Energy Source" - if("chemical") - switch(cur_artifact.my_effect.triggerX) - if("hydrogen") src.atrigger = "Contact with Hydrogen" - if("corrosive") src.atrigger = "Contact with Corrosive Substance" - if("volatile") src.atrigger = "Contact with Volatile Substance" - if("toxin") src.atrigger = "Contact with Toxins" - if("heat") src.atrigger = "Exposure to Heat" - else src.atrigger = "Unknown Trigger" - trigger_bonuses[cur_artifact.origin] += 5 - else - AA_FailedAnalysis(2) - trigger_bonuses[cur_artifact.origin] += 1 - if (prob(accuE1) || function_correct) - switch(cur_artifact.my_effect.effecttype) - if("healing") src.aeffect1 = "Healing Device" - if("injure") src.aeffect1 = "Anti-biological Weapon" - // if("stun") src.aeffect1 = "Non-lethal Stunning Trap" - if("roboheal") src.aeffect1 = "Mechanoid Repair Module" - if("robohurt") src.aeffect1 = "Mechanoid Deconstruction Device" - if("cellcharge") src.aeffect1 = "Power Generator" - if("celldrain") src.aeffect1 = "Power Drain" - if("planthelper") src.aeffect1 = "Agriculture Regulator" - if("forcefield") src.aeffect1 = "Shield Generator" - if("teleport") src.aeffect1 = "Space-Time Displacer" - else src.aeffect1 = "Unknown Effect" - function_bonuses[cur_artifact.origin] += 5 - else - AA_FailedAnalysis(3) - function_bonuses[cur_artifact.origin] += 1 - if (prob(accuE2) || range_correct) - switch(cur_artifact.my_effect.effectmode) - if("aura") src.aeffect2 = "Constant Short-Range Energy Field" - if("pulse") - if(cur_artifact.my_effect.aurarange > 7) src.aeffect2 = "Long Range Energy Pulses" - else src.aeffect2 = "Medium Range Energy Pulses" - if("worldpulse") src.aeffect2 = "Extreme Range Energy Pulses" - if("contact") src.aeffect2 = "Requires contact with subject" - else src.aeffect2 = "Unknown Range" - range_bonuses[cur_artifact.origin] += 5 - else - AA_FailedAnalysis(4) - range_bonuses[cur_artifact.origin] += 1 - - cur_artifact.name = "alien artifact ([cur_artifact.display_id])" - cur_artifact.desc = "A large alien device. It has a small tag near the bottom that reads \"[cur_artifact.display_id]\"." - cur_id = cur_artifact.display_id - cur_artifact.my_effect.artifact_id = cur_artifact.display_id - -/obj/machinery/artifact_analyser/Topic(href, href_list) - - if(href_list["analyse"]) - if(owned_pad) - var/turf/pad_turf = get_turf(owned_pad) - var/findarti = 0 - for(var/obj/machinery/artifact/A in pad_turf.contents) - findarti++ - cur_artifact = A - if (findarti == 1) - if(cur_artifact && cur_artifact.being_used) - var/message = "[src] states, \"Cannot analyse. Excess energy drain is disrupting signal.\"" - src.visible_message(message, message) - else - cur_artifact.anchored = 1 - cur_artifact.being_used = 1 - src.working = 1 - src.icon_state = "analyser_processing" - var/time = rand(30,50) + max(0, 300 - scan_num * 10) - /*for(var/i = artifact_research.starting_tier, i <= artifact_research.max_tiers, i++) - for(var/datum/artiresearch/R in artifact_research.researched_items[i]) - if (R.bonustype == "analyser") time -= R.bonusTime*/ - time *= 10 - var/message = "[src] states, \"Commencing analysis.\"" - src.visible_message(message, message) - use_power(500) - spawn(time) - src.working = 0 - icon_state = "analyser" - cur_artifact.anchored = 0 - cur_artifact.being_used = 0 - if(cur_artifact.loc == pad_turf) - AA_Analyse() - scan_num++ - message = "[src] states, \"Analysis complete.\"" - src.visible_message(message, message) - use_power(500) - else if (findarti > 1) - var/message = "[src] states, \"Cannot analyse. Error isolating energy signature.\"" - src.visible_message(message, message) - else - var/message = "[src] states, \"Cannot analyse. No noteworthy energy signature isolated.\"" - src.visible_message(message, message) - - if(href_list["upload"] && cur_id != "") - //add new datum to every DB in the world - for(var/obj/machinery/computer/artifact_database/DB in world) - var/update = 0 - for(var/datum/catalogued_artifact/CA in DB.catalogued_artifacts) - if(CA.display_id == cur_id) - //already there, so update it - update = 1 - CA.origin = aorigin + " ([accuO]%)" - CA.trigger = atrigger + " ([accuT]%)" - CA.effecttype = aeffect1 + " ([accuE1]%)" - CA.effectmode = aeffect2 + " ([accuE2]%)" - if(!update) - //not there, so add it - var/datum/catalogued_artifact/CA = new() - CA.display_id = cur_id - CA.origin = aorigin + " ([accuO]%)" - CA.trigger = atrigger + " ([accuT]%)" - CA.effecttype = aeffect1 + " ([accuE1]%)" - CA.effectmode = aeffect2 + " ([accuE2]%)" - DB.catalogued_artifacts.Add(CA) - use_power(100) - - if(href_list["print"]) - var/r = "Artifact Analysis Report (Scan #[scan_num])
" - r += "Artifact ID: [cur_id] (determined from unique energy emission signatures)
" - r += "Artifact Origin: [aorigin] ([accuO]%)
" - r += "Activation Trigger: [atrigger] ([accuT]%)
" - r += "Artifact Function: [aeffect1] ([accuE1]%)
" - r += "Artifact Range: [aeffect2] ([accuE2]%)

" - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src.loc) - P.name = "Artifact Analysis Report #[scan_num]" - P.info = r - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue The [src.name] prints a sheet of paper", 3) - use_power(10) - - if(href_list["close"]) - usr << browse(null, "window=artanalyser") - usr.machine = null - - src.updateDialog() - -//stick artifacts onto this then switch the analyser on -/obj/machinery/analyser_pad - name = "artifact analysis pad" - desc = "Studies the structure of artifacts to discover their uses." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "tele0" - anchored = 1 - density = 0 - -/obj/machinery/analyser_pad/New() - ..() - /*spawn(10) - for(var/obj/machinery/artifact_analyser/analyser in orange(1)) - world << "pad found analyser" - if(!analyser.owned_pad) - analyser.owned_pad = src - world << "pad set analyser to self" - break*/ diff --git a/code/modules/research/xenoarchaeology/machinery/artifact_db_old.dm b/code/modules/research/xenoarchaeology/machinery/artifact_db_old.dm deleted file mode 100644 index c6e0d1fb3f..0000000000 --- a/code/modules/research/xenoarchaeology/machinery/artifact_db_old.dm +++ /dev/null @@ -1,58 +0,0 @@ - -/datum/catalogued_artifact - var/trigger = "touch" // What activates it? - var/effecttype = "healing" // What does it do? - var/effectmode = "aura" // How does it carry out the effect? - var/display_id = "" // Artifact ID to display once successfully scanned - var/origin = "" - -/obj/machinery/computer/artifact_database - name = "Artifact Database" - icon_state = "rdcomp" - var/list/catalogued_artifacts - -/obj/machinery/computer/artifact_database/New() - ..() - catalogued_artifacts = new/list - -/obj/machinery/computer/artifact_database/Topic(href, href_list) - ..() - if( href_list["close"] ) - usr << browse(null, "window=artifact_db") - usr.machine = null - updateDialog() - -/obj/machinery/computer/artifact_database/process() - ..() - updateDialog() - -/obj/machinery/computer/artifact_database/interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) - if (!istype(user, /mob/living/silicon)) - user.machine = null - user << browse(null, "window=artifact_db") - return - var/t = "Artifact Database
" - t += "
" - for(var/datum/catalogued_artifact/CA in catalogued_artifacts) - t += "Artifact ID: [CA.display_id] (determined from unique energy emission signatures)
" - t += "Artifact Origin: [CA.origin]
" - t += "Activation Trigger: [CA.trigger]
" - t += "Artifact Function: [CA.effecttype]
" - t += "Artifact Range: [CA.effectmode]

" - t += "
" - t += "
Refresh Close
" - user << browse(t, "window=artifact_db;size=500x800") - user.machine = src - -/* -/datum/artifact_effect - var/origin = null // Used in the randomisation/research of the artifact. - var/trigger = "touch" // What activates it? - var/triggerX = "none" // Used for more varied triggers - var/effecttype = "healing" // What does it do? - var/effectmode = "aura" // How does it carry out the effect? - var/aurarange = 4 // How far the artifact will extend an aura effect. - var/display_id = "" // Artifact ID to display once successfully scanned - var/list/created_field -*/ \ No newline at end of file diff --git a/code/modules/research/xenoarchaeology/machinery/coolant.dm b/code/modules/research/xenoarchaeology/machinery/coolant.dm new file mode 100644 index 0000000000..bc03553bee --- /dev/null +++ b/code/modules/research/xenoarchaeology/machinery/coolant.dm @@ -0,0 +1,59 @@ + +datum/reagent/coolant + name = "Coolant" + id = "coolant" + description = "Industrial cooling substance." + reagent_state = LIQUID + color = "#C8A5DC" // rgb: 200, 165, 220 + +datum/chemical_reaction/coolant + name = "Coolant" + id = "coolant" + result = "coolant" + required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1) + result_amount = 3 + + + +/obj/structure/reagent_dispensers/coolanttank + name = "coolant tank" + desc = "A tank of industrial coolant" + icon = 'icons/obj/objects.dmi' + icon_state = "coolanttank" + amount_per_transfer_from_this = 10 + New() + ..() + reagents.add_reagent("coolant",1000) + +/obj/structure/reagent_dispensers/coolanttank/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)) + if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) + explode() + +/obj/structure/reagent_dispensers/coolanttank/blob_act() + explode() + +/obj/structure/reagent_dispensers/coolanttank/ex_act() + explode() + +/obj/structure/reagent_dispensers/coolanttank/proc/explode() + var/datum/effect/effect/system/harmless_smoke_spread/S = new /datum/effect/effect/system/harmless_smoke_spread + //S.attach(src) + S.set_up(5, 0, src.loc) + + playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + spawn(0) + S.start() + + var/datum/gas_mixture/env = src.loc.return_air() + if(env) + if (reagents.total_volume > 750) + env.temperature = 0 + else if (reagents.total_volume > 500) + env.temperature -= 100 + else + env.temperature -= 50 + + sleep(10) + if(src) + del(src) diff --git a/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm b/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm new file mode 100644 index 0000000000..74d886edb6 --- /dev/null +++ b/code/modules/research/xenoarchaeology/machinery/geosample_scanner.dm @@ -0,0 +1,355 @@ + +/obj/machinery/radiocarbon_spectrometer + name = "Radiocarbon spectrometer" + desc = "A specialised, complex scanner for gleaning information on all manner of small things." + anchored = 1 + density = 1 + icon = 'icons/obj/virology.dmi' + icon_state = "analyser" + + use_power = 1 //1 = idle, 2 = active + idle_power_usage = 20 + active_power_usage = 300 + + //var/obj/item/weapon/reagent_containers/glass/coolant_container + var/scanning = 0 + var/report_num = 0 + // + var/obj/item/scanned_item + var/last_scan_data = "No scans on record." + // + var/last_process_worldtime = 0 + // + var/scanner_progress = 0 + var/scanner_rate = 1.25 //80 seconds per scan + var/scanner_rpm = 0 + var/scanner_rpm_dir = 1 + var/scanner_temperature = 0 + var/scanner_seal_integrity = 100 + // + var/coolant_usage_rate = 0 //measured in u/microsec + var/fresh_coolant = 0 + var/coolant_purity = 0 + var/datum/reagents/coolant_reagents + var/used_coolant = 0 + var/list/coolant_reagents_purity = list() + // + var/maser_wavelength = 0 + var/optimal_wavelength = 0 + var/optimal_wavelength_target = 0 + var/tleft_retarget_optimal_wavelength = 0 + var/maser_efficiency = 0 + // + var/radiation = 0 //0-100 mSv + var/t_left_radspike = 0 + var/rad_shield = 0 + +/obj/machinery/radiocarbon_spectrometer/New() + ..() + create_reagents(500) + coolant_reagents_purity["water"] = 0.5 + coolant_reagents_purity["icecoffee"] = 0.6 + coolant_reagents_purity["icetea"] = 0.6 + coolant_reagents_purity["milkshake"] = 0.6 + coolant_reagents_purity["leporazine"] = 0.7 + coolant_reagents_purity["kelotane"] = 0.7 + coolant_reagents_purity["sterilizine"] = 0.7 + coolant_reagents_purity["dermaline"] = 0.7 + coolant_reagents_purity["hyperzine"] = 0.8 + coolant_reagents_purity["cryoxadone"] = 0.9 + coolant_reagents_purity["coolant"] = 1 + coolant_reagents_purity["adminordrazine"] = 2 + +/obj/machinery/radiocarbon_spectrometer/attack_hand(var/mob/user as mob) + ui_interact(user) + +/obj/machinery/radiocarbon_spectrometer/attackby(var/obj/I as obj, var/mob/user as mob) + if(scanning) + user << "You can't do that while [src] is scanning!" + else + if(istype(I, /obj/item/stack/nanopaste)) + var/choice = alert("What do you want to do with the nanopaste?","Radiometric Scanner","Add nanopaste","Fix seal integrity") + if(choice == "Fix seal integrity") + var/obj/item/stack/nanopaste/N = I + var/amount_used = min(N.amount, 10 - scanner_seal_integrity / 10) + N.use(amount_used) + scanner_seal_integrity = round(scanner_seal_integrity + amount_used * 10) + return + if(istype(I, /obj/item/weapon/reagent_containers/glass)) + var/choice = alert("What do you want to do with the container?","Radiometric Scanner","Add coolant","Empty coolant","Scan container") + if(choice == "Add coolant") + var/obj/item/weapon/reagent_containers/glass/G = I + G.reagents.trans_to(src, min(src.reagents.maximum_volume - src.reagents.total_volume, G.reagents.total_volume)) + update_coolant() + return + else if(choice == "Empty coolant") + var/obj/item/weapon/reagent_containers/glass/G = I + src.reagents.trans_to(G, min(G.reagents.maximum_volume - G.reagents.total_volume, src.reagents.total_volume)) + update_coolant() + return + user.drop_item() + I.loc = src + scanned_item = I + +/obj/machinery/radiocarbon_spectrometer/proc/update_coolant() + var/total_purity = 0 + fresh_coolant = 0 + coolant_purity = 0 + for (var/datum/reagent/current_reagent in src.reagents.reagent_list) + if (!current_reagent) + continue + var/cur_purity = coolant_reagents_purity[current_reagent.id] + if(!cur_purity) + cur_purity = 0.1 + total_purity += cur_purity + fresh_coolant += current_reagent.volume + if(total_purity && fresh_coolant) + coolant_purity = total_purity / fresh_coolant + +/obj/machinery/radiocarbon_spectrometer/ui_interact(mob/user, ui_key = "radio_spectro") + + if(user.stat) + return + + // this is the data which will be sent to the ui + var/data[0] + data["scanned_item"] = (scanned_item ? scanned_item.name : "") + data["scanned_item_desc"] = (scanned_item ? (scanned_item.desc ? scanned_item.desc : "No information on record.") : "") + data["last_scan_data"] = last_scan_data + // + data["scan_progress"] = round(scanner_progress) + data["scanning"] = scanning + // + data["scanner_seal_integrity"] = round(scanner_seal_integrity) + data["scanner_rpm"] = round(scanner_rpm) + data["scanner_temperature"] = round(scanner_temperature) + // + data["coolant_usage_rate"] = "[coolant_usage_rate]" + data["unused_coolant_abs"] = round(fresh_coolant) + data["unused_coolant_per"] = round(fresh_coolant / reagents.maximum_volume * 100) + data["coolant_purity"] = "[coolant_purity * 100]" + // + data["optimal_wavelength"] = round(optimal_wavelength) + data["maser_wavelength"] = round(maser_wavelength) + data["maser_efficiency"] = round(maser_efficiency * 100) + // + data["radiation"] = round(radiation) + data["t_left_radspike"] = round(t_left_radspike) + data["rad_shield_on"] = rad_shield + + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key) + if (!ui) + // the ui does not exist, so we'll create a new one + ui = new(user, src, ui_key, "geoscanner.tmpl", "High Res Radiocarbon Spectrometer", 900, 825) + // When the UI is first opened this is the data it will use + ui.set_initial_data(data) + ui.open() + // Auto update every Master Controller tick + ui.set_auto_update(1) + else + // The UI is already open so push the new data to it + ui.push_data(data) + return + +/obj/machinery/radiocarbon_spectrometer/process() + if(scanning) + if(!scanned_item || scanned_item.loc != src) + scanned_item = null + stop_scanning() + else if(scanner_progress >= 100) + complete_scan() + else + //calculate time difference + var/deltaT = (world.time - last_process_worldtime) * 0.1 + + //modify the RPM over time + //i want 1u to last for 10 sec at 500 RPM, scaling linearly + scanner_rpm += scanner_rpm_dir * 50 * deltaT + if(scanner_rpm > 1000) + scanner_rpm = 1000 + scanner_rpm_dir = -1 * pick(0.5, 2.5, 5.5) + else if(scanner_rpm < 1) + scanner_rpm = 1 + scanner_rpm_dir = 1 * pick(0.5, 2.5, 5.5) + + //heat up according to RPM + //each unit of coolant + scanner_temperature += scanner_rpm * deltaT * 0.05 + + //radiation + t_left_radspike -= deltaT + if(t_left_radspike > 0) + //ordinary radiation + radiation = rand() * 15 + else + //radspike + if(t_left_radspike > -5) + radiation = rand() * 15 + 85 + if(!rad_shield) + //irradiate nearby mobs + for(var/mob/living/M in view(7,src)) + M.apply_effect(radiation / 25, IRRADIATE, 0) + else + t_left_radspike = pick(10,15,25) + + //use some coolant to cool down + if(coolant_usage_rate > 0) + var/coolant_used = min(fresh_coolant, coolant_usage_rate * deltaT) + if(coolant_used > 0) + fresh_coolant -= coolant_used + used_coolant += coolant_used + scanner_temperature = max(scanner_temperature - coolant_used * coolant_purity * 20, 0) + + //modify the optimal wavelength + tleft_retarget_optimal_wavelength -= deltaT + if(tleft_retarget_optimal_wavelength <= 0) + tleft_retarget_optimal_wavelength = pick(4,8,15) + optimal_wavelength_target = rand() * 9900 + 100 + // + if(optimal_wavelength < optimal_wavelength_target) + optimal_wavelength = min(optimal_wavelength + 700 * deltaT, optimal_wavelength_target) + else if(optimal_wavelength > optimal_wavelength_target) + optimal_wavelength = max(optimal_wavelength - 700 * deltaT, optimal_wavelength_target) + // + maser_efficiency = 1 - max(min(10000, abs(optimal_wavelength - maser_wavelength) * 3), 1) / 10000 + + //make some scan progress + if(!rad_shield) + scanner_progress = min(100, scanner_progress + scanner_rate * maser_efficiency * deltaT) + + //degrade the seal over time according to temperature + //i want temperature of 50K to degrade at 1%/sec + scanner_seal_integrity -= (max(scanner_temperature, 1) / 1000) * deltaT + + //emergency stop if seal integrity reaches 0 + if(scanner_seal_integrity <= 0 || (scanner_temperature >= 1273 && !rad_shield)) + stop_scanning() + src.visible_message("\blue \icon[src] buzzes unhappily. It has failed mid-scan!", 2) + + if(prob(5)) + src.visible_message("\blue \icon[src] [pick("whirrs","chuffs","clicks")][pick(" excitedly"," energetically"," busily")].", 2) + else + //gradually cool down over time + if(scanner_temperature > 0) + scanner_temperature = max(scanner_temperature - 5 - 10 * rand(), 0) + if(prob(0.75)) + src.visible_message("\blue \icon[src] [pick("plinks","hisses")][pick(" quietly"," softly"," sadly"," plaintively")].", 2) + last_process_worldtime = world.time + +/obj/machinery/radiocarbon_spectrometer/proc/stop_scanning() + scanning = 0 + scanner_rpm_dir = 1 + scanner_rpm = 0 + optimal_wavelength = 0 + maser_efficiency = 0 + maser_wavelength = 0 + coolant_usage_rate = 0 + radiation = 0 + t_left_radspike = 0 + if(used_coolant) + src.reagents.remove_any(used_coolant) + used_coolant = 0 + +/obj/machinery/radiocarbon_spectrometer/proc/complete_scan() + src.visible_message("\blue \icon[src] makes an insistent chime.", 2) + + if(scanned_item) + //create report + var/obj/item/weapon/paper/P = new(src) + P.name = "[src] report #[++report_num]: [scanned_item.name]" + P.stamped = list(/obj/item/weapon/stamp) + P.overlays = list("paper_stamped") + + //work out data + var/data = " - Mundane object: [scanned_item.desc ? scanned_item.desc : "No information on record."]
" + var/datum/geosample/G + switch(scanned_item.type) + if(/obj/item/weapon/ore) + var/obj/item/weapon/ore/O = scanned_item + if(O.geological_data) + G = O.geological_data + + if(/obj/item/weapon/rocksliver) + var/obj/item/weapon/rocksliver/O = scanned_item + if(O.geological_data) + G = O.geological_data + + if(/obj/item/weapon/archaeological_find) + data = " - Mundane object (archaic xenos origins)
" + + var/obj/item/weapon/archaeological_find/A = scanned_item + if(A.speaking_to_players) + data = " - Exhibits properties consistent with sonic reproduction.
" + if(A.listening_to_players) + data = " - Exhibits properties similar to audio capture technology.
" + + var/anom_found = 0 + if(G) + data = " - Spectometric analysis on mineral sample has determined type [finds_as_strings[responsive_carriers.Find(G.source_mineral)]]
" + if(G.age_billion > 0) + data += " - Radiometric dating shows age of [G.age_billion].[G.age_million] billion years
" + else if(G.age_million > 0) + data += " - Radiometric dating shows age of [G.age_million].[G.age_thousand] million years
" + else + data += " - Radiometric dating shows age of [G.age_thousand * 1000 + G.age] years
" + data += " - Chromatographic analysis shows the following materials present:
" + for(var/carrier in G.find_presence) + if(G.find_presence[carrier]) + var/index = responsive_carriers.Find(carrier) + if(index > 0 && index <= finds_as_strings.len) + data += " > [100 * G.find_presence[carrier]]% [finds_as_strings[index]]
" + + if(G.artifact_id && G.artifact_distance >= 0) + anom_found = 1 + data += " - Hyperspectral imaging reveals exotic energy wavelength detected with ID: [G.artifact_id]
" + data += " - Fourier transform analysis on anomalous energy absorption indicates energy source located inside emission radius of [G.artifact_distance]m
" + + if(!anom_found) + data += " - No anomalous data
" + + P.info = "[src] analysis report #[report_num]
" + P.info += "Scanned item: [scanned_item.name]

" + data + last_scan_data = P.info + P.loc = src.loc + + scanned_item.loc = src.loc + scanned_item = null + +/obj/machinery/radiocarbon_spectrometer/Topic(href, href_list) + if(stat & (NOPOWER|BROKEN)) + return 0 // don't update UIs attached to this object + + if(href_list["scanItem"]) + if(scanning) + stop_scanning() + else + if(scanned_item) + if(scanner_seal_integrity > 0) + scanner_progress = 0 + scanning = 1 + t_left_radspike = pick(5,10,15) + usr << "Scan initiated." + else + usr << "Could not initiate scan, seal requires replacing." + else + usr << "Insert an item to scan." + + if(href_list["maserWavelength"]) + maser_wavelength = max(min(maser_wavelength + 1000 * text2num(href_list["maserWavelength"]), 10000), 1) + + if(href_list["coolantRate"]) + coolant_usage_rate = max(min(coolant_usage_rate + text2num(href_list["coolantRate"]), 10000), 0) + + if(href_list["toggle_rad_shield"]) + if(rad_shield) + rad_shield = 0 + else + rad_shield = 1 + + if(href_list["ejectItem"]) + if(scanned_item) + scanned_item.loc = src.loc + scanned_item = null + + add_fingerprint(usr) + return 1 // update UIs attached to this object diff --git a/code/modules/research/xenoarchaeology/manuals.dm b/code/modules/research/xenoarchaeology/manuals.dm index ceaa3d036e..99be3a6849 100644 --- a/code/modules/research/xenoarchaeology/manuals.dm +++ b/code/modules/research/xenoarchaeology/manuals.dm @@ -49,6 +49,8 @@
  • Core sampler - use this to take core samples from rock faces, which you can then run to the lab for analysis.
  • Depth scanner - uses x-ray diffraction to locate anomalous densities in rock, indicating archaeological deposits or mineral veins. Comes with a handy reference log containing co-ordinates and time of each scan.
  • +
  • Alden-Saraspova counter - uses a patented application of Fourier Transform analysis to determine the difference between background and + exotic radiation. Use it to determine how far you are from anomalous energy sources.
  • Radio beacon locater - leave a beacon at an item of interest, then track it down later with this handy gadget. Watch for interference from other devices though.
  • Flashlight or portable light source - Self explanatory, I hope.
  • @@ -129,51 +131,50 @@

    Contents

    1. A note on terms
    2. -
    3. Isotope ratio spectrometer
    4. -
    5. Accelerator spectrometer
    6. -
    7. Gas chromatography spectrometer
    8. -
    9. Ion mobility spectrometer
    10. +
    11. Analysis progression
    12. +
    13. Heat management
    14. +
    15. Ambient radiation

    A note on terms

    -
  • Dissonance ratio - This is a pseudoarbitrary value indicating the overal presence of a particular element in a greater composite. - It takes into account volume, density, molecular excitation and isotope spread.
  • Mass spectrometry - MS is the procedure used used to measure and quantify the components of matter. The most prized tool in the field of 'Materials analysis'
  • Radiometric dating - MS applied using the right carrier reagents can be used to accurately determine the age of a sample.
  • -
  • Sample specifity - A pseudoarbitrary value used to indicate how well a sample resonates with the employed carrier reagent. Great specifity - (material resonance) indicates that there is much of the carrier reagent present in the sample.
  • +
  • Dissonance ratio - This is a pseudoarbitrary value indicating the overal presence of a particular element in a greater composite. + It takes into account volume, density, molecular excitation and isotope spread.
  • +
  • Vacuum seal integrity - A reference to how close an airtight seal is to failure.

  • Contents -

    Isotope ratio spectrometer

    - Isotope ratio mass spectrometers work by coating a small surface with a semiliquid stationary phase consisting of the sample to be - analysed, and recording it's interactions with a gaseous mobile phase comprised of an inert or nonreactive gas such as helium or nitrogen.
    +

    Analysis progression

    + Modern mass spectrometry requires constant attention from the diligant researcher in order to be successul. There are many different elements to juggle, + and later chapters will delve into them. For the spectrometry assistant, the first thing you need to know is that the scanner wavelength is automatically + calculated for you. Just tweak the settings and try to match it with the actual wavelength as closely as possible.

    - IRMS are employed as radiometric daters, extremely accurate but only so up to ages of one billion years.
    Contents -

    Accelerator spectrometer

    - The accelerator mass spectrometer works by accelerating ions to extraordinarily high kinetic energies before mass analysis. The special strength of AMS is - isolate rare or low-strength isotopes, making it able to determine much greater ages with reasonable accuracy.
    +

    Seal integrity

    + In order to maintain sterile and environmentally static procedures, a special chamber is setup inside the spectrometer. It's protected by a proprietary vacuum seal + produced by top tier industrial science. It will only last for a certain number of scans before failing outright, but it can be resealed through use of nanite paste. + Unfortunately, it's susceptible to malforming under heat stress so exposing it to higher temperatures will cause it's operation life to drop significantly.

    - AMS are employed as extreme age radiometric daters, able to determine the age of the sample on a scale of billions of years. - They are commonly located in geology and archaeology laboratories.
    Contents -

    Gas chromatography spectrometer

    - Gas-liquid chromatography mass spectrometers work by coating a small surface with a semiliquid stationary phase consisting of the sample to be - analysed, and recording it's interactions with a gaseous mobile phase comprised of an inert or nonreactive gas such as helium or nitrogen.
    +

    Heat management

    + The scanner relies on a gyro-rotational system that varies in speed and intensity. Over the course of an ordinary scan, the RPMs can change dramatically. Higher RPMs + means greater heat generation, but is necessary for the ongoing continuation of the scan. To offset heat production, spectrometers have an inbuilt cooling system. + Researchers can modify the flow rate of coolant to aid in dropping temperature as necessary, but are advised that frequent coolant replacements may be necessary + depending on coolant purity. Water and substances such as cryoxadone are viable substitutes, but nowhere near as effective as pure coolant itself.

    - GLCS are employed in forensic and geological analysis to determine what elements are present in a sample.
    Contents -

    Ion mobility spectrometer

    - Ion mobility mass spectrometers work by examining the mobility of ionized molecules in an inert carrier gas
    +

    Ambient radiation

    + Researchers are warned that while operational, mass spectrometers emit period bursts of radiation and are thus advised to wear protective gear. In the event of + radiation spikes, there is also a special shield that can be lowered to block emissions. Lowering this, however, will have the effect of blocking the scanner + so use it sparingly.

    - IMS returns a dissonance ratio over the scanned sample and carrier reagent, indicating the average total presence of the sample.
    Contents @@ -197,67 +198,17 @@ -

    Contents

    -
      -
    1. Some useful phrases for you
    2. -
    3. Sample preparation and analysis
    4. -
    5. Fourier transform spectroscope
    6. -
    7. Hyperspectral Imager
    8. -
    - -
    -

    Some useful phrases for you

    - -
  • Spectroscopy - Spectroscopy is the study of the behaviour of light, commonly used in the 26th century for analysis of anomalous - behaviour of energy or light.
  • -
  • Sample specifity - A pseudoarbitrary value used to indicate how well a sample resonates with the employed carrier reagent. Great specifity - (material resonance) indicates that there is much of the carrier reagent present in the sample.
  • -
  • Anomalies - Inexplicable or uncategorised occurrences in the cosmos. A fascinating and dangerous study is made to determine the function of - these rare finds, and the term is often applied to describe technology left behind by vastly superior ancient alien forerunners.
  • -

    - Contents - -

    Sample preparation and analysis

    - When you are readying your spectrometry lab for analysis, you'll need to make sure the sample is in a form the machines can glean data from. - -
  • Obtain material sample - This should be an ordinary chunk of matter the size of your finger, a good example is a 6mm rock core.
  • -
  • Run density separation treatment - Perform the DST procedure on your sample, following generic specifications.
  • -
  • Ensure sample purity - DST can sometimes leave behind chemical waste or chunks of matter, make sure there aren't any before proceeding.
  • -
  • Prepare analysis tray - A sample tray holds a miniscule amount of liquid (2u), but that's all that our spectrometers require for a good reading.
  • -
  • Choose carrier reagent - Standard spectrometers require 1u of the material sample, and 1u of a 'carrier' reagent to provide control comparison - and to enable refraction inferencing.
  • -
  • Insert sample tray into machine - And press the 'Go' button. Now go make a cup of coffee.
  • -
  • Monitor machine heat levels - The upper end mass spectrometers have quite complex internals, and have a tendency to critically overheat. - Make sure the heat limit isn't exceeded, or there may be potentially disastrous consequences.
  • -
  • Examine analysis report - it won't always make sense or provide the information you hoped for, but if you've been careful during DST and ensured - sample integrity, then there's always something to be learnt. Just don't lose the paperwork!
  • -

    - Contents - -

    Fourier transform spectroscope

    - The FTS measures temporal coherence of radiating energy, then applies time-and-space domain measurements on the collected emission data. The collective - procedure is known as the Fourier Transform Procedure, with the mathematical algorithms dating back to the 19th century on Earth.
    -
    - As well as providing background energy readings, an FTS calculates the approximate distance and direction towards any anomalous energy signatures from - the location the scanned sample was taken from.
    - Contents - -

    Hyperspectral Imager

    - The imager scans and collates spectral energy signatures from across the electromagnetic spectrum. The collected data is then presented to the viewer in - graph form, with any anomalous (uncatalogued or unidentified) energy signatures highlighted.
    -
    - As well as visualising background energy readings, a hyperspectral imager will isolate and identify any anomalous energy signatures in the sample.
    - Contents - - - + It's perhaps one of the most exciting times to be alive, with the recent breakthroughs in understanding and categorisation of things we may one day no longer call + 'anomalies,' but rather 'infrequent or rare occurrences of certain celestial weather or phenomena.' Perhaps a little more long winded, but no less eloquent all the + same! Why, look at the strides we're making in piercing the walls of bluespace or our steadily improving ability to clarify and stabilise subspace emissions; it's + certainly an exciting time to be alive. For the moment the Hydrolian hasn't seen two spatial anomalies alike but the day will come and it is soon, I can feel it. "} /obj/item/weapon/book/manual/materials_chemistry_analysis - name = "Chemical preparation for materials analysis" + name = "Materials analysis and the chemical implications" icon_state = "chemistry" author = "Jasper Pascal, Senior Lecturer in Materials Analysis at the University of Jol'Nar" - title = "Chemical preparation for materials analysis" + title = "Materials analysis and the chemical implications" dat = {"