Merge branch 'bleeding-edge-freeze' of https://github.com/Baystation12/Baystation12 into bleeding-edge-freeze

This commit is contained in:
Chinsky
2013-03-16 21:06:57 +04:00
124 changed files with 18717 additions and 12986 deletions

View File

@@ -166,11 +166,6 @@
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\organs\organ.dm"
#include "code\datums\organs\organ_external.dm"
#include "code\datums\organs\organ_internal.dm"
#include "code\datums\organs\pain.dm"
#include "code\datums\organs\wound.dm"
#include "code\datums\spells\area_teleport.dm"
#include "code\datums\spells\conjure.dm"
#include "code\datums\spells\dumbfire.dm"
@@ -1030,6 +1025,12 @@
#include "code\modules\mob\new_player\preferences_setup.dm"
#include "code\modules\mob\new_player\skill.dm"
#include "code\modules\mob\new_player\sprite_accessories.dm"
#include "code\modules\organs\blood.dm"
#include "code\modules\organs\organ.dm"
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_internal.dm"
#include "code\modules\organs\pain.dm"
#include "code\modules\organs\wound.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\filingcabinet.dm"
#include "code\modules\paperwork\folders.dm"
@@ -1145,22 +1146,67 @@
#include "code\modules\research\research.dm"
#include "code\modules\research\research_shuttle.dm"
#include "code\modules\research\server.dm"
#include "code\modules\research\xenoarchaeology\archaeo_chem.dm"
#include "code\modules\research\xenoarchaeology\archaeo_excavate.dm"
#include "code\modules\research\xenoarchaeology\archaeo_machinery.dm"
#include "code\modules\research\xenoarchaeology\archaeo_tools.dm"
#include "code\modules\research\xenoarchaeology\artifact.dm"
#include "code\modules\research\xenoarchaeology\artifact_analysis.dm"
#include "code\modules\research\xenoarchaeology\artifact_db.dm"
#include "code\modules\research\xenoarchaeology\artifact_effect.dm"
#include "code\modules\research\xenoarchaeology\artifact_harvester.dm"
#include "code\modules\research\xenoarchaeology\artifact_misc.dm"
#include "code\modules\research\xenoarchaeology\artifact_synthetic.dm"
#include "code\modules\research\xenoarchaeology\core_sampler.dm"
#include "code\modules\research\xenoarchaeology\finds.dm"
#include "code\modules\research\xenoarchaeology\areas.dm"
#include "code\modules\research\xenoarchaeology\chemistry.dm"
#include "code\modules\research\xenoarchaeology\geosample.dm"
#include "code\modules\research\xenoarchaeology\manuals.dm"
#include "code\modules\research\xenoarchaeology\misc.dm"
#include "code\modules\research\xenoarchaeology\readme.dm"
#include "code\modules\research\xenoarchaeology\tools.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_autocloner.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_crystal.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_gigadrill.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_hoverpod.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_replicator.dm"
#include "code\modules\research\xenoarchaeology\artifact\artifact_unknown.dm"
#include "code\modules\research\xenoarchaeology\artifact\effect.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_affect_cold.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_badfeeling.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_cellcharge.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_celldrain.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_dnaswitch.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_emp.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_forcefield.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gasco2.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gasnitro.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gasoxy.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gasplasma.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_gassleeping.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_goodfeeling.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_heal.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_heat.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_hurt.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_radiate.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_roboheal.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_robohurt.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_sleepy.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_stun.dm"
#include "code\modules\research\xenoarchaeology\artifact\effects\unknown_effect_teleport.dm"
#include "code\modules\research\xenoarchaeology\finds\finds.dm"
#include "code\modules\research\xenoarchaeology\finds\finds_defines.dm"
#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\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_coresampler.dm"
#include "code\modules\research\xenoarchaeology\tools\tools_depthscanner.dm"
#include "code\modules\research\xenoarchaeology\tools\tools_locater.dm"
#include "code\modules\research\xenoarchaeology\tools\tools_pickaxe.dm"
#include "code\modules\scripting\Errors.dm"
#include "code\modules\scripting\IDE.dm"
#include "code\modules\scripting\Options.dm"

View File

@@ -1,55 +1,55 @@
//---------- actual energy field
/obj/effect/energy_field
name = "energy field"
desc = "Impenetrable field of energy, capable of blocking anything as long as it's active."
icon = 'shielding.dmi'
icon_state = "shieldsparkles"
anchored = 1
layer = 2.1
density = 0
invisibility = 101
var/strength = 0
/obj/effect/energy_field/ex_act(var/severity)
Stress(0.5 + severity)
/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj)
Stress(Proj.damage / 10)
/obj/effect/energy_field/meteorhit(obj/effect/meteor/M as obj)
if(M)
walk(M,0)
Stress(2)
/obj/effect/energy_field/proc/Stress(var/severity)
strength -= severity
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
if(strength < 1)
invisibility = 101
density = 0
else if(strength >= 1)
invisibility = 0
density = 1
/obj/effect/energy_field/proc/Strengthen(var/severity)
strength += severity
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
if(strength >= 1)
invisibility = 0
density = 1
else if(strength < 1)
invisibility = 101
density = 0
/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
//Purpose: Determines if the object (or airflow) can pass this atom.
//Called by: Movement, airflow.
//Inputs: The moving atom (optional), target turf, "height" and air group
//Outputs: Boolean if can pass.
//return (!density || !height || air_group)
return !density
//---------- actual energy field
/obj/effect/energy_field
name = "energy field"
desc = "Impenetrable field of energy, capable of blocking anything as long as it's active."
icon = 'shielding.dmi'
icon_state = "shieldsparkles"
anchored = 1
layer = 4.1 //just above mobs
density = 0
invisibility = 101
var/strength = 0
/obj/effect/energy_field/ex_act(var/severity)
Stress(0.5 + severity)
/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj)
Stress(Proj.damage / 10)
/obj/effect/energy_field/meteorhit(obj/effect/meteor/M as obj)
if(M)
walk(M,0)
Stress(2)
/obj/effect/energy_field/proc/Stress(var/severity)
strength -= severity
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
if(strength < 1)
invisibility = 101
density = 0
else if(strength >= 1)
invisibility = 0
density = 1
/obj/effect/energy_field/proc/Strengthen(var/severity)
strength += severity
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
if(strength >= 1)
invisibility = 0
density = 1
else if(strength < 1)
invisibility = 101
density = 0
/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
//Purpose: Determines if the object (or airflow) can pass this atom.
//Called by: Movement, airflow.
//Inputs: The moving atom (optional), target turf, "height" and air group
//Outputs: Boolean if can pass.
//return (!density || !height || air_group)
return !density

View File

@@ -146,11 +146,12 @@ proc/listclearnulls(list/list)
* Sorting
*/
//Reverses the order of items in the list (Turning a stack into a queue)
/proc/reverselist(var/list/input)
var/list/output = new/list()
for(var/A in input)
output += A
//Reverses the order of items in the list
/proc/reverselist(list/L)
var/list/output = list()
if(L)
for(var/i = L.len; i >= 1; i--)
output += L[i]
return output
//Randomize: Return the list in a random order
@@ -320,4 +321,28 @@ proc/listclearnulls(list/list)
for(var/T in L)
if(istype(T, type))
i++
return i
return i
//Don't use this on lists larger than half a dozen or so
/proc/insertion_sort_numeric_list_ascending(var/list/L)
//world.log << "ascending len input: [L.len]"
var/list/out = list(pop(L))
for(var/entry in L)
if(isnum(entry))
var/success = 0
for(var/i=1, i<=out.len, i++)
if(entry <= out[i])
success = 1
out.Insert(i, entry)
break
if(!success)
out.Add(entry)
//world.log << " output: [out.len]"
return out
/proc/insertion_sort_numeric_list_descending(var/list/L)
//world.log << "descending len input: [L.len]"
var/list/out = insertion_sort_numeric_list_ascending(L)
//world.log << " output: [out.len]"
return reverselist(out)

View File

@@ -130,9 +130,10 @@ datum/shuttle_controller
start_location.move_contents_to(end_location, null, NORTH)
for(var/obj/machinery/door/D in world)
for(var/obj/machinery/door/unpowered/D in world)
if( get_area(D) == end_location )
spawn(0)
D.locked = 0
D.open()
for(var/mob/M in end_location)
@@ -291,9 +292,10 @@ datum/shuttle_controller
// Just before it leaves, close the damn doors!
if(timeleft == 2 || timeleft == 1)
var/area/start_location = locate(/area/shuttle/escape/station)
for(var/obj/machinery/door/D in start_location)
for(var/obj/machinery/door/unpowered/shuttle/D in start_location)
spawn(0)
D.close()
D.locked = 1
if(timeleft>0)
return 0

View File

@@ -1,20 +0,0 @@
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
var/list/datum/autopsy_data/autopsy_data = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
///datum/organ/proc/process()
// return 0
///datum/organ/proc/receive_chem(chemical as obj)
// return 0
proc/process()
return 0
proc/receive_chem(chemical as obj)
return 0

View File

@@ -12,11 +12,11 @@
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat)
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat)
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
minimal_player_age = 7

View File

@@ -45,12 +45,6 @@ var/const/ASSISTANT =(1<<13)
var/list/assistant_occupations = list(
"Assistant",
"Atmospheric Technician",
"Cargo Technician",
"Chaplain",
"Lawyer",
"Librarian"
)
@@ -68,7 +62,6 @@ var/list/engineering_positions = list(
"Chief Engineer",
"Station Engineer",
"Atmospheric Technician",
"Roboticist"
)
@@ -85,7 +78,7 @@ var/list/science_positions = list(
"Research Director",
"Scientist",
"Geneticist", //Part of both medical and science
"Roboticist" //Part of both engineering and science
"Roboticist"
)
//BS12 EDIT

View File

@@ -194,6 +194,10 @@
name = "Circuit board (Mining Shuttle)"
build_path = "/obj/machinery/computer/mining_shuttle"
origin_tech = "programming=2"
/obj/item/weapon/circuitboard/research_shuttle
name = "Circuit board (Research Shuttle)"
build_path = "/obj/machinery/computer/research_shuttle"
origin_tech = "programming=2"
/obj/item/weapon/circuitboard/HolodeckControl // Not going to let people get this, but it's just here for future
name = "Circuit board (Holodeck Control)"
build_path = "/obj/machinery/computer/HolodeckControl"

View File

@@ -122,15 +122,6 @@
if(emergency_shuttle.online)
post_status("shuttle")
src.state = STATE_DEFAULT
if("crewtransfer")
src.state= STATE_DEFAULT
if(src.authenticated)
src.state = STATE_CREWTRANSFER
if("crewtransfer2")
if(src.authenticated)
init_shift_change(usr) //key difference here
if(emergency_shuttle.online)
post_status("shuttle")
if("cancelshuttle")
src.state = STATE_DEFAULT
if(src.authenticated)
@@ -323,7 +314,6 @@
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=cancelshuttle'>Cancel Shuttle Call</A> \]"
else
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=callshuttle'>Call Emergency Shuttle</A> \]"
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=crewtransfer'>Initiate Crew Transfer</A> \]"
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=status'>Set Status Display</A> \]"
else
@@ -331,8 +321,6 @@
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=messagelist'>Message List</A> \]"
if(STATE_CALLSHUTTLE)
dat += "Are you sure you want to call the shuttle? \[ <A HREF='?src=\ref[src];operation=callshuttle2'>OK</A> | <A HREF='?src=\ref[src];operation=main'>Cancel</A> \]"
if(STATE_CREWTRANSFER) // this is the shiftchage screen.
dat += "Are you sure you want to initiate a crew transfer? This will call the shuttle. \[ <a HREF='?src=\ref[src];operation=crewtransfer2'>OK</a> | <A HREF='?src=\ref[src];operation=main'>Cancel</A> \]"
if(STATE_CANCELSHUTTLE)
dat += "Are you sure you want to cancel the shuttle? \[ <A HREF='?src=\ref[src];operation=cancelshuttle2'>OK</A> | <A HREF='?src=\ref[src];operation=main'>Cancel</A> \]"
if(STATE_MESSAGELIST)

View File

@@ -6,66 +6,58 @@
icon_state = "flood00"
density = 1
var/on = 0
var/obj/item/weapon/cell/cell = null
var/use = 1
var/obj/item/weapon/cell/high/cell = null
var/use = 5
var/unlocked = 0
var/open = 0
var/brightness_on = 999 //can't remember what the maxed out value is
/obj/machinery/floodlight/New()
src.cell = new(src)
..()
/obj/machinery/floodlight/proc/updateicon()
icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]"
/obj/machinery/floodlight/process()
if (!on)
if (luminosity)
if(on)
cell.charge -= use
if(cell.charge <= 0)
on = 0
updateicon()
//sd_SetLuminosity(0)
return
if(!luminosity && cell && cell.charge > 0)
//sd_SetLuminosity(10)
updateicon()
if(!cell && luminosity)
on = 0
updateicon()
//sd_SetLuminosity(0)
return
cell.charge -= use
if(cell.charge <= 0 && luminosity)
on = 0
updateicon()
//sd_SetLuminosity(0)
return
SetLuminosity(0)
src.visible_message("<span class='warning'>[src] shuts down due to lack of power!</span>")
return
/obj/machinery/floodlight/attack_hand(mob/user as mob)
if(open && cell)
cell.loc = usr
cell.layer = 20
if (user.hand )
user.l_hand = cell
if(ishuman(user))
if(!user.get_active_hand())
user.put_in_hands(cell)
cell.loc = user.loc
else
user.r_hand = cell
cell.loc = loc
cell.add_fingerprint(user)
updateicon()
cell.updateicon()
src.cell = null
user << "You remove the power cell"
updateicon()
return
if(on)
on = 0
user << "You turn off the light"
user << "\blue You turn off the light"
SetLuminosity(0)
else
if(!cell)
return
if(cell.charge <= 0)
return
on = 1
user << "You turn on the light"
user << "\blue You turn on the light"
SetLuminosity(brightness_on)
updateicon()
@@ -101,10 +93,3 @@
cell = W
user << "You insert the power cell."
updateicon()
/obj/machinery/floodlight/New()
src.cell = new/obj/item/weapon/cell(src)
cell.maxcharge = 1000
cell.charge = 1000
..()

View File

@@ -84,7 +84,7 @@
if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood))
// speed up transfer on blood packs
transfer_amount = 4
src.beaker.reagents.trans_to(src.attached, transfer_amount)
attached.inject_blood(beaker,transfer_amount)
update_icon()
// Take blood
@@ -99,52 +99,23 @@
var/mob/living/carbon/human/T = attached
if(!istype(T)) return
var/datum/reagent/B
for(var/datum/reagent/blood/Blood in beaker.reagents.reagent_list)
if(Blood.data && Blood.data["blood_type"]==T.dna.b_type)
B = Blood
break
if(!B) B = new /datum/reagent/blood
if(!T.dna)
return
if(NOCLONE in T.mutations)
return
// If the human is losing too much blood, beep.
if(T.vessel.get_reagent_amount("blood") < BLOOD_VOLUME_SAFE) if(prob(5))
visible_message("\The [src] beeps loudly.")
if(T.vessel.get_reagent_amount("blood") < amount)
return
B.holder = beaker
B.volume += amount
//set reagent data
B.data["donor"] = T
if(T.virus2)
B.data["virus2"] = T.virus2.getcopy()
var/datum/reagent/B = T.take_blood(beaker,amount)
B.data["blood_DNA"] = copytext(T.dna.unique_enzymes,1,0)
if(T.resistances && T.resistances.len)
if(B.data["resistances"])
B.data["resistances"] |= T.resistances.Copy()
else
B.data["resistances"] = T.resistances.Copy()
B.data["blood_type"] = copytext(T.dna.b_type,1,0)
var/list/temp_chem = list()
for(var/datum/reagent/R in T.reagents.reagent_list)
temp_chem += R.name
temp_chem[R.name] = R.volume
B.data["trace_chem"] = list2params(temp_chem)
B.data["antibodies"] |= T.antibodies
T.vessel.remove_reagent("blood",amount) // Removes blood if human
beaker.reagents.reagent_list |= B
beaker.reagents.update_total()
beaker.on_reagent_change()
beaker.reagents.handle_reactions()
update_icon()
if (B)
beaker.reagents.reagent_list |= B
beaker.reagents.update_total()
beaker.on_reagent_change()
beaker.reagents.handle_reactions()
update_icon()
/obj/machinery/iv_drip/attack_hand(mob/user as mob)
if(src.beaker)

View File

@@ -85,6 +85,8 @@
M << "<B>You have joined the ranks of the Syndicate and become a traitor to the station!</B>"
message_admins("[N]/([N.ckey]) has accepted a traitor objective from a syndicate beacon.")
var/obj_count = 1
for(var/datum/objective/OBJ in M.mind.objectives)
M << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"

View File

@@ -20,6 +20,9 @@ proc/empulse(turf/epicenter, heavy_range, light_range, log=0)
if(heavy_range > light_range)
light_range = heavy_range
for(var/mob/M in range(heavy_range, epicenter))
M << 'sound/effects/EMPulse.ogg'
for(var/atom/T in range(light_range, epicenter))
var/distance = get_dist(epicenter, T)
if(distance < 0)

View File

@@ -4,7 +4,7 @@
icon_state = "intercom"
anchored = 1
w_class = 4.0
canhear_range = 7
canhear_range = 2
var/number = 0
var/anyai = 1
var/mob/living/silicon/ai/ai = list()

View File

@@ -287,7 +287,7 @@
var/datum/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot"))
if(affecting.status & ORGAN_ROBOT)
return
H.Weaken(3)
if(affecting.take_damage(5, 0))
H.UpdateDamageIcon()

View File

@@ -34,7 +34,7 @@
/*
* Spoons
*/
/obj/item/weapon/kitchen/utensil/spoon
/obj/item/weapon/kitchen/utensil/spoon
name = "spoon"
desc = "SPOON!"
icon_state = "spoon"

View File

@@ -193,6 +193,10 @@ proc/move_mining_shuttle()
var/digspeed = 40 //moving the delay to an item var so R&D can make improved picks. --NEO
origin_tech = "materials=1;engineering=1"
attack_verb = list("hit", "pierced", "sliced", "attacked")
var/drill_sound = 'sound/weapons/Genhit.ogg'
var/drill_verb = "picking"
var/excavation_amount = 100
hammer
name = "sledgehammer"

View File

@@ -1,5 +1,9 @@
/**********************Mineral deposits**************************/
#define XENOARCH_SPAWN_CHANCE 0.5
#define XENOARCH_SPREAD_CHANCE 15
#define ARTIFACT_SPAWN_CHANCE 20
/turf/simulated/mineral //wall piece
name = "Rock"
icon = 'icons/turf/walls.dmi'
@@ -14,9 +18,18 @@
var/mineralAmt = 0
var/spread = 0 //will the seam spread?
var/spreadChance = 0 //the percentual chance of an ore spreading to the neighbouring tiles
var/artifactChance = 0.3 //percent chance to spawn a xenoarchaelogical artifact
var/last_act = 0
var/datum/geosample/geological_data
var/excavation_level = 0
var/list/finds = list()
var/list/excavation_minerals = list()
var/next_rock = 0
var/archaeo_overlay = ""
var/excav_overlay = ""
var/obj/item/weapon/last_find
var/datum/artifact_find/artifact_find
/turf/simulated/mineral/Del()
return
@@ -55,24 +68,89 @@
T.overlays += image('icons/turf/walls.dmi', "rock_side_e", layer=6)
if (mineralName && mineralAmt && spread && spreadChance)
if(prob(spreadChance))
if(istype(get_step(src, SOUTH), /turf/simulated/mineral/random))
new src.type(get_step(src, SOUTH))
if(prob(spreadChance))
if(istype(get_step(src, NORTH), /turf/simulated/mineral/random))
new src.type(get_step(src, NORTH))
if(prob(spreadChance))
if(istype(get_step(src, WEST), /turf/simulated/mineral/random))
new src.type(get_step(src, WEST))
if(prob(spreadChance))
if(istype(get_step(src, EAST), /turf/simulated/mineral/random))
new src.type(get_step(src, EAST))
for(var/trydir in list(1,2,4,8))
if(prob(spreadChance))
if(istype(get_step(src, trydir), /turf/simulated/mineral/random))
var/turf/simulated/mineral/T = get_step(src, trydir)
var/turf/simulated/mineral/M = new src.type(T)
//keep any digsite data as constant as possible
if(T.finds.len && !M.finds.len)
M.finds = T.finds
if(T.archaeo_overlay)
M.overlays += archaeo_overlay
//---- Xenoarchaeology BEGIN
//put into spawn so that digsite data can be preserved over the turf replacements via spreading mineral veins
spawn(0)
if(mineralAmt > 0 && !excavation_minerals.len)
for(var/i=0, i<mineralAmt, i++)
excavation_minerals.Add(rand(5,95))
excavation_minerals = insertion_sort_numeric_list_descending(excavation_minerals)
if(!finds.len && prob(XENOARCH_SPAWN_CHANCE))
//create a new archaeological deposit
var/digsite = get_random_digsite_type()
var/list/turfs_to_process = list(src)
var/list/processed_turfs = list()
while(turfs_to_process.len)
var/turf/simulated/mineral/M = turfs_to_process[1]
for(var/turf/simulated/mineral/T in orange(1, M))
if(T.finds.len)
continue
if(T in processed_turfs)
continue
if(prob(XENOARCH_SPREAD_CHANCE))
turfs_to_process.Add(T)
turfs_to_process.Remove(M)
processed_turfs.Add(M)
if(!M.finds.len)
if(prob(50))
M.finds.Add(new/datum/find(digsite, rand(5,95)))
else if(prob(75))
M.finds.Add(new/datum/find(digsite, rand(5,45)))
M.finds.Add(new/datum/find(digsite, rand(55,95)))
else
M.finds.Add(new/datum/find(digsite, rand(5,30)))
M.finds.Add(new/datum/find(digsite, rand(35,75)))
M.finds.Add(new/datum/find(digsite, rand(75,95)))
//sometimes a find will be close enough to the surface to show
var/datum/find/F = M.finds[1]
if(F.excavation_required <= F.view_range)
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
M.overlays += archaeo_overlay
//dont create artifact machinery in animal or plant digsites, or if we already have one
if(!artifact_find && digsite != 1 && digsite != 2 && prob(ARTIFACT_SPAWN_CHANCE))
artifact_find = new()
artifact_spawning_turfs.Add(src)
if(!src.geological_data)
src.geological_data = new/datum/geosample(src)
src.geological_data.UpdateTurf(src)
//for excavated turfs placeable in the map editor
/*if(excavation_level > 0)
if(excavation_level < 25)
src.overlays += image('icons/obj/xenoarchaeology.dmi', "overlay_excv1_[rand(1,3)]")
else if(excavation_level < 50)
src.overlays += image('icons/obj/xenoarchaeology.dmi', "overlay_excv2_[rand(1,3)]")
else if(excavation_level < 75)
src.overlays += image('icons/obj/xenoarchaeology.dmi', "overlay_excv3_[rand(1,3)]")
else
src.overlays += image('icons/obj/xenoarchaeology.dmi', "overlay_excv4_[rand(1,3)]")
desc = "It appears to be partially excavated."*/
return
/turf/simulated/mineral/random
name = "Mineral deposit"
var/mineralAmtList = list("Uranium" = 5, "Iron" = 5, "Diamond" = 5, "Gold" = 5, "Silver" = 5, "Plasma" = 5, "Archaeo" = 3/*, "Adamantine" = 5*/)
var/mineralSpawnChanceList = list("Uranium" = 5, "Iron" = 50, "Diamond" = 1, "Gold" = 5, "Silver" = 5, "Plasma" = 25, "Archaeo" = 5/*, "Adamantine" =5*/)//Currently, Adamantine won't spawn as it has no uses. -Durandan
var/mineralAmtList = list("Uranium" = 5, "Iron" = 5, "Diamond" = 5, "Gold" = 5, "Silver" = 5, "Plasma" = 5/*, "Adamantine" = 5*/)
var/mineralSpawnChanceList = list("Uranium" = 5, "Iron" = 50, "Diamond" = 1, "Gold" = 5, "Silver" = 5, "Plasma" = 25/*, "Adamantine" =5*/)//Currently, Adamantine won't spawn as it has no uses. -Durandan
var/mineralChance = 10 //means 10% chance of this plot changing to a mineral deposit
/turf/simulated/mineral/random/New()
@@ -95,16 +173,22 @@
M = new/turf/simulated/mineral/silver(src)
if("Plasma")
M = new/turf/simulated/mineral/plasma(src)
if("Archaeo")
M = new/turf/simulated/mineral/archaeo(src)
/*if("Adamantine")
M = new/turf/simulated/mineral/adamantine(src)*/
if(M)
src = M
M.levelupdate()
else if (prob(artifactChance))
//spawn a rare, xeno-arch artifact here
new/obj/machinery/artifact(src)
//preserve archaeo data
M.geological_data = src.geological_data
M.excavation_minerals = src.excavation_minerals
M.overlays = src.overlays
M.artifact_find = src.artifact_find
M.archaeo_overlay = src.archaeo_overlay
M.excav_overlay = src.excav_overlay
/*else if (prob(artifactChance))
new/obj/machinery/artifact(src)*/
return
/turf/simulated/mineral/random/high_chance
@@ -169,15 +253,6 @@
spread = 1
/turf/simulated/mineral/archaeo
name = "Strange rock formation"
icon_state = "rock_Archaeo"
mineralName = "Archaeo"
mineralAmt = 3
spreadChance = 25
spread = 1
/turf/simulated/mineral/clown
name = "Bananium deposit"
icon_state = "rock_Clown"
@@ -222,6 +297,24 @@ commented out in r5061, I left it because of the shroom thingies
usr << "\red You don't have the dexterity to do this!"
return
if (istype(W, /obj/item/device/core_sampler))
src.geological_data.UpdateNearbyArtifactInfo(src)
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
return
if (istype(W, /obj/item/device/depth_scanner))
var/obj/item/device/depth_scanner/C = W
C.scan_atom(user, src)
return
if (istype(W, /obj/item/device/measuring_tape))
var/obj/item/device/measuring_tape/P = W
user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].")
if(do_after(user,40))
user << "\blue \icon[P] [src] has been excavated to a depth of [2*src.excavation_level]cm."
return
if (istype(W, /obj/item/weapon/pickaxe))
var/turf/T = user.loc
if (!( istype(T, /turf) ))
@@ -233,56 +326,276 @@ commented out in r5061, I left it because of the shroom thingies
return
*/
//Watch your tabbing, microwave. --NEO
if(last_act+W:digspeed > world.time)//prevents message spam
var/obj/item/weapon/pickaxe/P = W
if(last_act+P.digspeed > world.time)//prevents message spam
return
last_act = world.time
user << "\red You start picking."
playsound(user, 'sound/weapons/Genhit.ogg', 20, 1)
if(do_after(user,W:digspeed))
user << "\blue You finish cutting into the rock."
gets_drilled()
playsound(user, P.drill_sound, 20, 1)
//handle any archaeological finds we might uncover
var/fail_message
if(src.finds.len)
var/datum/find/F = src.finds[1]
if(src.excavation_level + P.excavation_amount > F.excavation_required)
//Chance to destroy / extract any finds here
fail_message = ", <b>[pick("there is a crunching noise","[W] collides with some different rock","part of the rock face crumbles away","something breaks under [W]")]</b>"
user << "\red You start [P.drill_verb][fail_message ? fail_message : ""]."
if(fail_message)
if(prob(50))
if(prob(25))
excavate_find(5, src.finds[1])
else if(prob(50))
src.finds.Remove(src.finds[1])
if(do_after(user,P.digspeed))
user << "\blue You finish [P.drill_verb] the rock."
if(finds.len)
var/datum/find/F = src.finds[1]
if(round(src.excavation_level + P.excavation_amount) == F.excavation_required)
//Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them
if(src.excavation_level + P.excavation_amount > F.excavation_required)
//if you can get slightly over, perfect extraction
excavate_find(100, F)
else
excavate_find(80, F)
else if(src.excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)
//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
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))
B = new(src)
if(artifact_find)
B.artifact_find = artifact_find
else if(src.excavation_level + P.excavation_amount >= 100)
spawn(0)
artifact_debris()
gets_drilled(B ? 0 : 1)
return
else
src.excavation_level += P.excavation_amount
//archaeo overlays
if(!archaeo_overlay && finds.len)
var/datum/find/F = src.finds[1]
if(F.excavation_required <= src.excavation_level + F.view_range)
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
overlays += archaeo_overlay
//there's got to be a better way to do this
var/update_excav_overlay = 0
if(src.excavation_level >= 75)
if(src.excavation_level - P.excavation_amount < 75)
update_excav_overlay = 1
else if(src.excavation_level >= 50)
if(src.excavation_level - P.excavation_amount < 50)
update_excav_overlay = 1
else if(src.excavation_level >= 25)
if(src.excavation_level - P.excavation_amount < 25)
update_excav_overlay = 1
//update overlays displaying excavation level
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
var/excav_quadrant = round(excavation_level / 25) + 1
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
overlays += excav_overlay
//extract pesky minerals while we're excavating
while(excavation_minerals.len && src.excavation_level > excavation_minerals[excavation_minerals.len])
drop_mineral()
//have a 50% chance to extract bonus minerals this way
//if(prob(50))
pop(excavation_minerals)
mineralAmt--
//drop some rocks
next_rock += P.excavation_amount * 10
while(next_rock > 100)
next_rock -= 100
var/obj/item/weapon/ore/O = new(src)
src.geological_data.UpdateNearbyArtifactInfo(src)
O.geological_data = src.geological_data
else
return attack_hand(user)
return
/turf/simulated/mineral/proc/gets_drilled()
var/destroyed = 0 //used for breaking strange rocks
/turf/simulated/mineral/proc/drop_mineral()
var/obj/item/weapon/ore/O
if (src.mineralName == "Uranium")
O = new /obj/item/weapon/ore/uranium(src)
if (src.mineralName == "Iron")
O = new /obj/item/weapon/ore/iron(src)
if (src.mineralName == "Gold")
O = new /obj/item/weapon/ore/gold(src)
if (src.mineralName == "Silver")
O = new /obj/item/weapon/ore/silver(src)
if (src.mineralName == "Plasma")
O = new /obj/item/weapon/ore/plasma(src)
if (src.mineralName == "Diamond")
O = new /obj/item/weapon/ore/diamond(src)
/*if (src.mineralName == "Archaeo")
//new /obj/item/weapon/archaeological_find(src)
//if(prob(10) || delicate)
if(prob(50)) //Don't have delicate tools (hand pick/excavation tool) yet, temporarily change to 50% instead of 10% -Mij
O = new /obj/item/weapon/ore/strangerock(src)
else
destroyed = 1*/
if (src.mineralName == "Clown")
O = new /obj/item/weapon/ore/clown(src)
if(O)
src.geological_data.UpdateNearbyArtifactInfo(src)
O.geological_data = src.geological_data
return O
/turf/simulated/mineral/proc/gets_drilled(var/artifact_fail = 0)
//var/destroyed = 0 //used for breaking strange rocks
if ((src.mineralName != "") && (src.mineralAmt > 0) && (src.mineralAmt < 11))
var/i
for (i=0;i<mineralAmt;i++)
if (src.mineralName == "Uranium")
new /obj/item/weapon/ore/uranium(src)
if (src.mineralName == "Iron")
new /obj/item/weapon/ore/iron(src)
if (src.mineralName == "Gold")
new /obj/item/weapon/ore/gold(src)
if (src.mineralName == "Silver")
new /obj/item/weapon/ore/silver(src)
if (src.mineralName == "Plasma")
new /obj/item/weapon/ore/plasma(src)
if (src.mineralName == "Diamond")
new /obj/item/weapon/ore/diamond(src)
if (src.mineralName == "Archaeo")
//spawn strange rocks here
//if(prob(10) || delicate)
if(prob(50)) //Don't have delicate tools (hand pick/excavation tool) yet, temporarily change to 50% instead of 10% -Mij
new /obj/item/weapon/ore/strangerock(src)
else
destroyed = 1
if (src.mineralName == "Clown")
new /obj/item/weapon/ore/clown(src)
if (prob(src.artifactChance))
//if the turf has already been excavated, some of it's ore has been removed
for (var/i=0;i<mineralAmt;i++)
drop_mineral()
/*if (prob(src.artifactChance))
//spawn a rare artifact here
new /obj/machinery/artifact(src)
new /obj/machinery/artifact(src)*/
var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
N.fullUpdateMineralOverlays()
if(destroyed) //Display message about being a terrible miner
usr << "\red You destroy some of the rocks!"
//destroyed artifacts have weird, unpleasant effects
if(artifact_find && artifact_fail)
var/pain = 0
if(prob(50))
pain = 1
for(var/mob/living/M in range(src, 200))
M << "<font color='red'><b>[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fadaing away!</b></font>"
if(pain)
flick("pain",M.pain)
if(prob(50))
M.adjustBruteLoss(5)
else
flick("flash",M.flash)
if(prob(50))
M.Stun(5)
M.apply_effect(25, IRRADIATE)
/*if(destroyed) //Display message about being a terrible miner
usr << "\red You destroy some of the rocks!"*/
return
/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F)
//with skill and luck, players can cleanly extract finds
//otherwise, they come out inside a chunk of rock
var/obj/item/weapon/X
if(prob_clean)
X = new/obj/item/weapon/archaeological_find(src, new_item_type = F.find_type)
else
X = new/obj/item/weapon/ore/strangerock(src, inside_item_type = F.find_type)
src.geological_data.UpdateNearbyArtifactInfo(src)
X:geological_data = src.geological_data
//some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens
//yuck
var/display_name = "something"
if(!X)
X = last_find
if(X)
display_name = X.name
//many finds are ancient and thus very delicate - luckily there is a specialised energy suspension field which protects them when they're being extracted
if(prob(F.prob_delicate))
var/obj/effect/suspension_field/S = locate() in src
if(!S || S.field_type != get_responsive_reagent(F.find_type))
if(X)
src.visible_message("\red<b>[pick("[display_name] crumbles away into dust","[display_name] breaks apart","[display_name] collapses onto itself")].</b>")
del(X)
src.finds.Remove(F)
/turf/simulated/mineral/proc/artifact_debris()
//cael's patented random limited drop componentized loot system!
var/materials = 0
var/list/viable_materials = list(1,2,4,8,16,32,64,128,256)
var/num_materials = rand(1,5)
for(var/i=0, i<num_materials, i++)
var/chosen = pick(viable_materials)
materials |= chosen
viable_materials.Remove(chosen)
if(materials & 1)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/rods/R = new(src)
R.amount = rand(5,25)
if(materials & 2)
var/quantity = pick(0, 0, 1)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/tile/R = new(src)
R.amount = rand(1,5)
if(materials & 4)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/sheet/metal/R = new(src)
R.amount = rand(5,25)
if(materials & 8)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/sheet/plasteel/R = new(src)
R.amount = rand(5,25)
if(materials & 16)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
new /obj/item/weapon/shard(src)
if(materials & 32)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
new /obj/item/weapon/shard/plasma(src)
if(materials & 64)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/sheet/mineral/uranium/R = new(src)
R.amount = rand(5,25)
if(materials & 128)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/sheet/mineral/mythril/R = new(src)
R.amount = rand(5,25)
if(materials & 256)
var/quantity = rand(0,3)
for(var/i=0, i<quantity, i++)
var/obj/item/stack/sheet/mineral/adamantine/R = new(src)
R.amount = rand(5,25)
/*
/turf/simulated/mineral/proc/setRandomMinerals()
var/s = pickweight(list("uranium" = 5, "iron" = 50, "gold" = 5, "silver" = 5, "plasma" = 50, "diamond" = 1))
@@ -448,7 +761,6 @@ commented out in r5061, I left it because of the shroom thingies
if(istype(get_step(src, WEST), /turf/simulated/mineral))
src.overlays += image('icons/turf/walls.dmi', "rock_side_w", layer=6)
/turf/simulated/floor/plating/airless/asteroid/proc/fullUpdateMineralOverlays()
var/turf/simulated/floor/plating/airless/asteroid/A
if(istype(get_step(src, WEST), /turf/simulated/floor/plating/airless/asteroid))

View File

@@ -3,8 +3,8 @@
/obj/item/weapon/ore
name = "Rock"
icon = 'icons/obj/mining.dmi'
icon_state = "ore"
icon_state = "ore2"
var/datum/geosample/geological_data
/obj/item/weapon/ore/uranium
name = "Uranium ore"
@@ -59,19 +59,16 @@
desc = "Completely useless"
icon_state = "slag"
/obj/item/weapon/ore/strangerock //see artifact_archaeo.dm in modules/research for more info
name = "Strange rock"
desc = "Seems to have some unusal strata evident throughout it."
icon_state = "strange"
var/obj/inside
var/method // 0 = fire, 1+ = acid
origin_tech = "materials=5"
//unacidable = 1 //This can prevent acid from gooey grey massing
/obj/item/weapon/ore/New()
pixel_x = rand(0,16)-8
pixel_y = rand(0,8)-8
/obj/item/weapon/ore/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/device/core_sampler))
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
else
return ..()
/*****************************Coin********************************/
@@ -152,4 +149,4 @@
overlays = list()
string_attached = null
user << "\blue You detach the string from the coin."
else ..()
else ..()

View File

@@ -5,10 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "body_m_s"
var/datum/reagents/vessel
// TODO: make this actually affect the way the mob is rendered
var/pale = 0
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
@@ -24,78 +20,14 @@
if(!dna)
dna = new /datum/dna(null)
//initialise organs
organs = list()
organs_by_name["chest"] = new/datum/organ/external/chest()
organs_by_name["groin"] = new/datum/organ/external/groin(organs_by_name["chest"])
organs_by_name["head"] = new/datum/organ/external/head(organs_by_name["chest"])
organs_by_name["l_arm"] = new/datum/organ/external/l_arm(organs_by_name["chest"])
organs_by_name["r_arm"] = new/datum/organ/external/r_arm(organs_by_name["chest"])
organs_by_name["r_leg"] = new/datum/organ/external/r_leg(organs_by_name["groin"])
organs_by_name["l_leg"] = new/datum/organ/external/l_leg(organs_by_name["groin"])
organs_by_name["l_hand"] = new/datum/organ/external/l_hand(organs_by_name["l_arm"])
organs_by_name["r_hand"] = new/datum/organ/external/r_hand(organs_by_name["r_arm"])
organs_by_name["l_foot"] = new/datum/organ/external/l_foot(organs_by_name["l_leg"])
organs_by_name["r_foot"] = new/datum/organ/external/r_foot(organs_by_name["r_leg"])
new/datum/organ/internal/heart(src)
new/datum/organ/internal/lungs(src)
new/datum/organ/internal/liver(src)
new/datum/organ/internal/kidney(src)
new/datum/organ/internal/brain(src)
for(var/name in organs_by_name)
organs += organs_by_name[name]
for(var/datum/organ/external/O in organs)
O.owner = src
..()
if(dna)
dna.real_name = real_name
prev_gender = gender // Debug for plural genders
vessel = new/datum/reagents(600)
vessel.my_atom = src
vessel.add_reagent("blood",560)
spawn(1)
fixblood()
/mob/living/carbon/human/proc/drip(var/amt as num)
if(!amt)
return
var/amm = 0.1 * amt
var/turf/T = get_turf(src)
var/list/obj/effect/decal/cleanable/blood/drip/nums = list()
var/list/iconL = list("1","2","3","4","5")
vessel.remove_reagent("blood",amm)
for(var/obj/effect/decal/cleanable/blood/drip/G in T)
nums += G
iconL.Remove(G.icon_state)
if (nums.len < 5)
var/obj/effect/decal/cleanable/blood/drip/this = new(T)
this.icon_state = pick(iconL)
this.blood_DNA = list()
this.blood_DNA[dna.unique_enzymes] = dna.b_type
else
for(var/obj/effect/decal/cleanable/blood/drip/G in nums)
del G
T.add_blood(src)
/mob/living/carbon/human/proc/fixblood()
for(var/datum/reagent/blood/B in vessel.reagent_list)
if(B.id == "blood")
B.data = list("donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_type"=dna.b_type,"resistances"=null,"trace_chem"=null, "virus2" = null, "antobodies" = null)
make_organs()
make_blood()
/mob/living/carbon/human/Bump(atom/movable/AM as mob|obj, yes)
if ((!( yes ) || now_pushing))

View File

@@ -47,9 +47,6 @@
var/icon/stand_icon = null
var/icon/lying_icon = null
var/list/organs = list() //Gets filled up in the constructor (human.dm, New() proc, line 24. I'm sick and tired of missing comments. -Agouri
var/list/organs_by_name = list() // map organ names to organs
var/miming = null //Toggle for the mime's abilities.
var/special_voice = "" // For changing our voice. Used by a symptom.

View File

@@ -21,11 +21,6 @@
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
var/const/BLOOD_VOLUME_SAFE = 501
var/const/BLOOD_VOLUME_OKAY = 336
var/const/BLOOD_VOLUME_BAD = 224
var/const/BLOOD_VOLUME_SURVIVE = 122
/mob/living/carbon/human
var/oxygen_alert = 0
var/toxins_alert = 0
@@ -133,100 +128,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
/mob/living/carbon/human
proc/handle_blood()
// take care of blood and blood loss
if(stat < 2 && bodytemperature >= 170)
var/blood_volume = round(vessel.get_reagent_amount("blood"))
if(blood_volume < 560 && blood_volume)
var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood
if(B) // Make sure there's some blood at all
if(B.data["donor"] != src) //If it's not theirs, then we look for theirs
for(var/datum/reagent/blood/D in vessel.reagent_list)
if(D.data["donor"] == src)
B = D
break
var/datum/reagent/nutriment/F = locate() in reagents.reagent_list
if(F != null)
if(F.volume >= 1)
// nutriment speeds it up quite a bit
B.volume += 0.4
F.volume -= 0.1
else
//At this point, we dun care which blood we are adding to, as long as they get more blood.
B.volume = B.volume + 0.1 // regenerate blood VERY slowly
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
var/datum/organ/internal/heart/heart = internal_organs["heart"]
switch(heart.damage)
if(5 to 10)
blood_volume *= 0.8
if(11 to 20)
blood_volume *= 0.5
if(21 to INFINITY)
blood_volume *= 0.3
switch(blood_volume)
if(BLOOD_VOLUME_SAFE to 10000)
if(pale)
pale = 0
update_body()
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
if(!pale)
pale = 1
update_body()
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(prob(1))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(oxyloss < 20)
// hint that they're getting close to suffocation
oxyloss += 3
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
if(!pale)
pale = 1
update_body()
eye_blurry += 6
if(oxyloss < 50)
oxyloss += 10
oxyloss += 1
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
oxyloss += 5
toxloss += 5
if(prob(15))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(0 to BLOOD_VOLUME_SURVIVE)
// There currently is a strange bug here. If the mob is not below -100 health
// when death() is called, apparently they will be just fine, and this way it'll
// spam deathgasp. Adjusting toxloss ensures the mob will stay dead.
toxloss += 300 // just to be safe!
death()
// Without enough blood you slowly go hungry.
if(blood_volume < BLOOD_VOLUME_SAFE)
if(nutrition >= 300)
nutrition -= 10
else if(nutrition >= 200)
nutrition -= 3
var/blood_max = 0
for(var/datum/organ/external/temp in organs)
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
continue
for(var/datum/wound/W in temp.wounds) if(W.bleeding())
blood_max += W.damage / 4
if(temp.status & ORGAN_DESTROYED && !(temp.status & ORGAN_GAUZED) && !temp.amputated)
blood_max += 20 //Yer missing a fucking limb.
if (temp.open)
blood_max += 2 //Yer stomach is cut open
drip(blood_max)
proc/handle_disabilities()
if (disabilities & EPILEPSY)
if ((prob(1) && paralysis < 1))
@@ -293,108 +194,6 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
src << "\red Your legs won't respond properly, you fall down."
lying = 1
proc/handle_organs()
// take care of organ related updates, such as broken and missing limbs
// recalculate number of wounds
number_wounds = 0
for(var/datum/organ/external/E in organs)
if(!E)
world << name
continue
number_wounds += E.number_wounds
var/leg_tally = 2
var/canstand_l = 1 //Can stand on left leg
var/canstand_r = 1 //Can stand on right leg
var/hasleg_l = 1 //Have left leg
var/hasleg_r = 1 //Have right leg
var/hasarm_l = 1 //Have left arm
var/hasarm_r = 1 //Have right arm
for(var/datum/organ/external/E in organs)
E.process()
if(E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam))
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
drop_item()
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
drop_item()
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
leg_tally-- // let it fail even if just foot&leg
if(E.status & ORGAN_BROKEN || (E.status & ORGAN_DESTROYED && !E.amputated))
if(E.name == "l_hand" || E.name == "l_arm")
if(hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "r_hand" || E.name == "r_arm")
if(!hand && equipped())
if(E.status & ORGAN_SPLINTED && prob(10))
drop_item()
emote("scream")
else
drop_item()
emote("scream")
else if(E.name == "l_leg" || E.name == "l_foot" \
|| E.name == "r_leg" || E.name == "r_foot" && !lying)
if(!(E.status & ORGAN_SPLINTED))
leg_tally-- // let it fail even if just foot&leg
// standing is poor
if(leg_tally <= 0 && !paralysis && !(lying || resting) && prob(5))
emote("scream")
emote("collapse")
paralysis = 10
//Check arms and legs for existence
var/datum/organ/external/E
E = get_organ("l_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
hasleg_l = 0
E = get_organ("r_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
hasleg_r = 0
E = get_organ("l_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
E = get_organ("r_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
E = get_organ("l_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_l = 0
E = get_organ("r_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_r = 0
// Can stand if have at least one full leg (with leg and foot parts present)
// Has limbs to move around if at least one arm or leg is at least partially there
can_stand = canstand_l||canstand_r
has_limbs = hasleg_l||hasleg_r||hasarm_l||hasarm_r
proc/handle_mutations_and_radiation()
if(getFireLoss())
if((COLD_RESISTANCE in mutations) || (prob(1)))
@@ -457,20 +256,14 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
if(reagents.has_reagent("lexorin")) return
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
var/lung_ruptured = is_lung_ruptured()
if(lung_ruptured && prob(2))
spawn emote("me", 1, "coughs up blood!")
src.drip(10)
var/datum/organ/internal/lungs/L = internal_organs["lungs"]
L.process()
var/datum/gas_mixture/environment = loc.return_air()
var/datum/gas_mixture/breath
// HACK NEED CHANGING LATER
if(health < 0)
losebreath++
if(lung_ruptured && prob(4))
spawn emote("me", 1, "gasps for air!")
losebreath += 5
if(losebreath>0) //Suffocating so do not take a breath
losebreath--
if (prob(10)) //Gasp per 10 ticks? Sounds about right.
@@ -500,7 +293,7 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
breath = loc.remove_air(breath_moles)
if(!lung_ruptured)
if(!is_lung_ruptured())
if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)
if(prob(5))
rupture_lung()
@@ -1063,34 +856,10 @@ var/const/BLOOD_VOLUME_SURVIVE = 122
dizziness = max(0, dizziness - 3)
jitteriness = max(0, jitteriness - 3)
handle_trace_chems()
if(life_tick % 10 == 0)
// handle trace chemicals for autopsy
for(var/datum/organ/O in organs)
for(var/chemID in O.trace_chemicals)
O.trace_chemicals[chemID] = O.trace_chemicals[chemID] - 1
if(O.trace_chemicals[chemID] <= 0)
O.trace_chemicals.Remove(chemID)
for(var/datum/reagent/A in reagents.reagent_list)
// add chemistry traces to a random organ
var/datum/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
var/damaged_liver_process_accuracy = 10
if(life_tick % damaged_liver_process_accuracy == 0)
// Damaged liver means some chemicals are very dangerous
var/datum/organ/internal/liver/liver = internal_organs["liver"]
if(liver.damage >= liver.min_bruised_damage)
for(var/datum/reagent/R in src.reagents.reagent_list)
// Ethanol and all drinks are bad
if(istype(R, /datum/reagent/ethanol))
adjustToxLoss(0.1 * damaged_liver_process_accuracy)
// Can't cope with toxins at all
for(var/toxin in list("toxin", "plasma", "sacid", "pacid", "cyanide", "lexorin", "amatoxin", "chloralhydrate", "carpotoxin", "zombiepowder", "mindbreaker"))
if(src.reagents.has_reagent(toxin))
adjustToxLoss(0.3 * damaged_liver_process_accuracy)
var/datum/organ/internal/liver/liver = internal_organs["liver"]
liver.process()
updatehealth()

View File

@@ -450,9 +450,10 @@ var/list/department_radio_keys = list(
del(B)
*/
//talking crystals
for(var/obj/item/weapon/talkingcrystal/O in view(3,src))
O.catchMessage(message,src)
//talking items
for(var/obj/item/weapon/O in view(3,src))
if(O.listening_to_players)
O.catchMessage(message, src)
log_say("[name]/[key] : [message]")

View File

@@ -0,0 +1,213 @@
/****************************************************
BLOOD SYSTEM
****************************************************/
//Blood levels
var/const/BLOOD_VOLUME_SAFE = 501
var/const/BLOOD_VOLUME_OKAY = 336
var/const/BLOOD_VOLUME_BAD = 224
var/const/BLOOD_VOLUME_SURVIVE = 122
/mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here.
/mob/living/carbon/human/var/var/pale = 0 //Should affect how mob sprite is drawn, but currently doesn't.
//Initializes blood vessels
/mob/living/carbon/human/proc/make_blood()
if (vessel)
return
vessel = new/datum/reagents(600)
vessel.my_atom = src
vessel.add_reagent("blood",560)
spawn(1)
fixblood()
//Resets blood data
/mob/living/carbon/human/proc/fixblood()
for(var/datum/reagent/blood/B in vessel.reagent_list)
if(B.id == "blood")
B.data = list( "donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_type"=dna.b_type, \
"resistances"=null,"trace_chem"=null, "virus2" = null, "antobodies" = null)
// Takes care blood loss and regeneration
/mob/living/carbon/human/proc/handle_blood()
if(stat != DEAD && bodytemperature >= 170) //Dead or cryosleep people do not pump the blood.
var/blood_volume = round(vessel.get_reagent_amount("blood"))
//Blood regeneration if there is some space
if(blood_volume < 560 && blood_volume)
var/datum/reagent/blood/B = locate() in vessel.reagent_list //Grab some blood
if(B) // Make sure there's some blood at all
if(B.data["donor"] != src) //If it's not theirs, then we look for theirs
for(var/datum/reagent/blood/D in vessel.reagent_list)
if(D.data["donor"] == src)
B = D
break
B.volume += 0.1 // regenerate blood VERY slowly
if (reagents.has_reagent("nutriment")) //Getting food speeds it up
B.volume += 0.4
reagents.remove_reagent("nutriment", 0.1)
if (reagents.has_reagent("iron")) //Hematogen candy anyone?
B.volume += 0.8
reagents.remove_reagent("iron", 0.1)
// Damaged heart virtually reduces the blood volume, as the blood isn't
// being pumped properly anymore.
var/datum/organ/internal/heart/heart = internal_organs["heart"]
switch(heart.damage)
if(5 to 10)
blood_volume *= 0.8
if(11 to 20)
blood_volume *= 0.5
if(21 to INFINITY)
blood_volume *= 0.3
//Effects of bloodloss
switch(blood_volume)
if(BLOOD_VOLUME_SAFE to 10000)
if(pale)
pale = 0
update_body()
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
if(!pale)
pale = 1
update_body()
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(prob(1))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel [word]"
if(oxyloss < 20)
oxyloss += 3
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
if(!pale)
pale = 1
update_body()
eye_blurry += 6
if(oxyloss < 50)
oxyloss += 10
oxyloss += 1
if(prob(15))
Paralyse(rand(1,3))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
oxyloss += 5
toxloss += 5
if(prob(15))
var/word = pick("dizzy","woosey","faint")
src << "\red You feel extremely [word]"
if(0 to BLOOD_VOLUME_SURVIVE)
// There currently is a strange bug here. If the mob is not below -100 health
// when death() is called, apparently they will be just fine, and this way it'll
// spam deathgasp. Adjusting toxloss ensures the mob will stay dead.
toxloss += 300 // just to be safe!
death()
// Without enough blood you slowly go hungry.
if(blood_volume < BLOOD_VOLUME_SAFE)
if(nutrition >= 300)
nutrition -= 10
else if(nutrition >= 200)
nutrition -= 3
//Bleeding out
var/blood_max = 0
for(var/datum/organ/external/temp in organs)
if(!(temp.status & ORGAN_BLEEDING) || temp.status & ORGAN_ROBOT)
continue
for(var/datum/wound/W in temp.wounds) if(W.bleeding())
blood_max += W.damage / 4
if(temp.status & ORGAN_DESTROYED && !(temp.status & ORGAN_GAUZED) && !temp.amputated)
blood_max += 20 //Yer missing a fucking limb.
if (temp.open)
blood_max += 2 //Yer stomach is cut open
drip(blood_max)
//Makes a blood drop, leaking certain amount of blood from the mob
/mob/living/carbon/human/proc/drip(var/amt as num)
if(!amt)
return
var/amm = 0.1 * amt
var/turf/T = get_turf(src)
var/list/obj/effect/decal/cleanable/blood/drip/nums = list()
var/list/iconL = list("1","2","3","4","5")
vessel.remove_reagent("blood",amm)
for(var/obj/effect/decal/cleanable/blood/drip/G in T)
nums += G
iconL.Remove(G.icon_state)
if (nums.len < 5)
var/obj/effect/decal/cleanable/blood/drip/this = new(T)
this.icon_state = pick(iconL)
this.blood_DNA = list()
this.blood_DNA[dna.unique_enzymes] = dna.b_type
else
for(var/obj/effect/decal/cleanable/blood/drip/G in nums)
del G
T.add_blood(src)
/****************************************************
BLOOD TRANSFERS
****************************************************/
//Gets blood from mob to the container, preserving all data in it.
/mob/living/carbon/proc/take_blood(obj/item/weapon/reagent_containers/container, var/amount)
var/datum/reagent/B = get_blood(container.reagents)
if(!B) B = new /datum/reagent/blood
B.holder = container
B.volume += amount
//set reagent data
B.data["donor"] = src
if(src.virus2)
B.data["virus2"] = src.virus2.getcopy()
B.data["antibodies"] |= src.antibodies
B.data["blood_DNA"] = copytext(src.dna.unique_enzymes,1,0)
if(src.resistances && src.resistances.len)
if(B.data["resistances"])
B.data["resistances"] |= src.resistances.Copy()
else
B.data["resistances"] = src.resistances.Copy()
B.data["blood_type"] = copytext(src.dna.b_type,1,0)
var/list/temp_chem = list()
for(var/datum/reagent/R in src.reagents.reagent_list)
temp_chem += R.name
temp_chem[R.name] = R.volume
B.data["trace_chem"] = list2params(temp_chem)
return B
//For humans, blood does not appear from blue, it comes from vessels.
/mob/living/carbon/human/take_blood(obj/item/weapon/reagent_containers/container, var/amount)
if(vessel.get_reagent_amount("blood") < amount)
return null
. = ..()
vessel.remove_reagent("blood",amount) // Removes blood if human
//Transfers blood from container ot vessels, respecting blood types compatability.
/mob/living/carbon/human/proc/inject_blood(obj/item/weapon/reagent_containers/container, var/amount)
var/datum/reagent/blood/our = get_blood(vessel)
var/datum/reagent/blood/injected = get_blood(container.reagents)
if(blood_incompatible(injected.data["blood_type"],our.data["blood_type"]) )
reagents.add_reagent("toxin",amount * 0.5)
reagents.update_total()
else
vessel.add_reagent("blood", amount)
vessel.update_total()
container.reagents.remove_reagent("blood", amount)
//Gets human's own blood.
/mob/living/carbon/proc/get_blood(datum/reagents/container)
var/datum/reagent/blood/res = locate() in container.reagent_list //Grab some blood
if(res) // Make sure there's some blood at all
if(res.data["donor"] != src) //If it's not theirs, then we look for theirs
for(var/datum/reagent/blood/D in container.reagent_list)
if(D.data["donor"] == src)
return D
return res

View File

@@ -0,0 +1,148 @@
/datum/organ
var/name = "organ"
var/mob/living/carbon/human/owner = null
var/list/datum/autopsy_data/autopsy_data = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
proc/process()
return 0
proc/receive_chem(chemical as obj)
return 0
//Handles chem traces
/mob/living/carbon/human/proc/handle_trace_chems()
//New are added for reagents to random organs.
for(var/datum/reagent/A in reagents.reagent_list)
var/datum/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
//Adds autopsy data for used_weapon.
/datum/organ/proc/add_autopsy_data(var/used_weapon, var/damage)
var/datum/autopsy_data/W = autopsy_data[used_weapon]
if(!W)
W = new()
W.weapon = used_weapon
autopsy_data[used_weapon] = W
W.hits += 1
W.damage += damage
W.time_inflicted = world.time
/mob/living/carbon/human/var/list/organs = list()
/mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs
//Creates and initializes and connects external and internal organs
/mob/living/carbon/human/proc/make_organs()
organs = list()
organs_by_name["chest"] = new/datum/organ/external/chest()
organs_by_name["groin"] = new/datum/organ/external/groin(organs_by_name["chest"])
organs_by_name["head"] = new/datum/organ/external/head(organs_by_name["chest"])
organs_by_name["l_arm"] = new/datum/organ/external/l_arm(organs_by_name["chest"])
organs_by_name["r_arm"] = new/datum/organ/external/r_arm(organs_by_name["chest"])
organs_by_name["r_leg"] = new/datum/organ/external/r_leg(organs_by_name["groin"])
organs_by_name["l_leg"] = new/datum/organ/external/l_leg(organs_by_name["groin"])
organs_by_name["l_hand"] = new/datum/organ/external/l_hand(organs_by_name["l_arm"])
organs_by_name["r_hand"] = new/datum/organ/external/r_hand(organs_by_name["r_arm"])
organs_by_name["l_foot"] = new/datum/organ/external/l_foot(organs_by_name["l_leg"])
organs_by_name["r_foot"] = new/datum/organ/external/r_foot(organs_by_name["r_leg"])
new/datum/organ/internal/heart(src)
new/datum/organ/internal/lungs(src)
new/datum/organ/internal/liver(src)
new/datum/organ/internal/kidney(src)
new/datum/organ/internal/brain(src)
for(var/name in organs_by_name)
organs += organs_by_name[name]
for(var/datum/organ/external/O in organs)
O.owner = src
// Takes care of organ related updates, such as broken and missing limbs
/mob/living/carbon/human/proc/handle_organs()
number_wounds = 0
var/leg_tally = 2
for(var/datum/organ/external/E in organs)
if(!E)
continue
E.process()
number_wounds += E.number_wounds
//Robotic limb malfunctions
var/malfunction = 0
if (E.status & ORGAN_ROBOT && prob(E.brute_dam + E.burn_dam))
malfunction = 1
//Broken limbs hurt too
var/broken = 0
if(E.status & ORGAN_BROKEN && !(E.status & ORGAN_SPLINTED && prob(10)) )
broken = 1
//Special effects for limbs.
if(E.name in list("l_hand","l_arm","r_hand","r_arm"))
var/obj/item/c_hand //Getting what's in this hand
if(E.name == "l_hand" || E.name == "l_arm")
c_hand = l_hand
if(E.name == "r_hand" || E.name == "r_arm")
c_hand = r_hand
if (c_hand)
if (broken||malfunction)
u_equip(c_hand)
if(broken)
emote("me", 1, "screams in pain and drops what they were holding in their [E.display_name?"[E.display_name]":"[E]"]!")
if(malfunction)
emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
spark_system.start()
spawn(10)
del(spark_system)
else if(E.name in list("l_leg","l_foot","r_leg","r_foot") && !lying)
if (E.status & ORGAN_DESTROYED || malfunction || (broken && !(E.status & ORGAN_SPLINTED)))
leg_tally-- // let it fail even if just foot&leg
// standing is poor
if(leg_tally <= 0 && !paralysis && !(lying || resting) && prob(5))
emote("scream")
emote("collapse")
paralysis = 10
//Check arms and legs for existence
var/canstand_l = 1 //Can stand on left leg
var/canstand_r = 1 //Can stand on right leg
var/hasleg_l = 1 //Have left leg
var/hasleg_r = 1 //Have right leg
var/hasarm_l = 1 //Have left arm
var/hasarm_r = 1 //Have right arm
var/datum/organ/external/E
E = get_organ("l_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
hasleg_l = 0
E = get_organ("r_leg")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
hasleg_r = 0
E = get_organ("l_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_l = 0
E = get_organ("r_foot")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
canstand_r = 0
E = get_organ("l_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_l = 0
E = get_organ("r_arm")
if(E.status & ORGAN_DESTROYED && !(E.status & ORGAN_SPLINTED))
hasarm_r = 0
// Can stand if have at least one full leg (with leg and foot parts present)
// Has limbs to move around if at least one arm or leg is at least partially there
can_stand = canstand_l||canstand_r
has_limbs = hasleg_l||hasleg_r||hasarm_l||hasarm_r

View File

@@ -1,120 +1,83 @@
/****************************************************
INTERNAL ORGANS
****************************************************/
/*
/datum/organ/internal
name = "internal"
var/damage = 0
var/max_damage = 100
/datum/organ/internal/skeleton
name = "spooky scary skeleton"
max_damage = 200
/datum/organ/internal/skin
name = "skin"
max_damage = 100
/datum/organ/internal/blood_vessels
name = "blood vessels"
var/heart = null
var/lungs = null
var/kidneys = null
/datum/organ/internal/brain
name = "brain"
var/head = null
/datum/organ/internal/excretory
name = "excretory"
var/excretory = 7.0
var/blood_vessels = null
/datum/organ/internal/heart
name = "heart"
/datum/organ/internal/immune_system
name = "immune system"
var/blood_vessels = null
var/isys = null
/datum/organ/internal/intestines
name = "intestines"
var/intestines = 3.0
var/blood_vessels = null
/datum/organ/internal/liver
name = "liver"
var/intestines = null
var/blood_vessels = null
/datum/organ/internal/lungs
name = "lungs"
var/lungs = 3.0
var/throat = null
var/blood_vessels = null
/datum/organ/internal/stomach
name = "stomach"
var/intestines = null
/datum/organ/internal/throat
name = "throat"
var/lungs = null
var/stomach = null
*/
/mob/living/carbon/human/var/list/internal_organs = list()
/datum/organ/internal
// amount of damage to the organ
var/damage = 0
var/min_bruised_damage = 10
var/min_broken_damage = 30
var/parent_organ = "chest"
/datum/organ/internal/proc/is_bruised()
return damage >= min_bruised_damage
/datum/organ/internal/proc/is_broken()
return damage >= min_broken_damage
/datum/organ/internal/New(mob/living/carbon/human/H)
..()
var/datum/organ/external/E = H.organs_by_name[src.parent_organ]
if(E.internal_organs == null)
E.internal_organs = list()
E.internal_organs += src
H.internal_organs[src.name] = src
src.owner = H
/datum/organ/internal/proc/take_damage(amount)
src.damage += amount
var/datum/organ/external/parent = owner.get_organ(parent_organ)
owner.custom_pain("Something inside your [parent.display_name] hurts a lot.", 1)
/datum/organ/internal/heart
name = "heart"
parent_organ = "chest"
/datum/organ/internal/lungs
name = "lungs"
parent_organ = "chest"
/datum/organ/internal/liver
name = "liver"
parent_organ = "chest"
/datum/organ/internal/kidney
name = "kidney"
parent_organ = "chest"
/datum/organ/internal/brain
name = "brain"
/****************************************************
INTERNAL ORGANS
****************************************************/
/mob/living/carbon/human/var/list/internal_organs = list()
/datum/organ/internal
// amount of damage to the organ
var/damage = 0
var/min_bruised_damage = 10
var/min_broken_damage = 30
var/parent_organ = "chest"
/datum/organ/internal/proc/is_bruised()
return damage >= min_bruised_damage
/datum/organ/internal/proc/is_broken()
return damage >= min_broken_damage
/datum/organ/internal/New(mob/living/carbon/human/H)
..()
var/datum/organ/external/E = H.organs_by_name[src.parent_organ]
if(E.internal_organs == null)
E.internal_organs = list()
E.internal_organs += src
H.internal_organs[src.name] = src
src.owner = H
/datum/organ/internal/proc/take_damage(amount)
src.damage += amount
var/datum/organ/external/parent = owner.get_organ(parent_organ)
owner.custom_pain("Something inside your [parent.display_name] hurts a lot.", 1)
/****************************************************
INTERNAL ORGANS DEFINES
****************************************************/
/datum/organ/internal/heart
name = "heart"
parent_organ = "chest"
/datum/organ/internal/lungs
name = "lungs"
parent_organ = "chest"
process()
if(is_bruised())
if(prob(2))
spawn owner.emote("me", 1, "coughs up blood!")
owner.drip(10)
if(prob(4))
spawn owner.emote("me", 1, "gasps for air!")
owner.losebreath += 5
/datum/organ/internal/liver
name = "liver"
parent_organ = "chest"
var/process_accuracy = 10
process()
if(owner.life_tick % process_accuracy == 0)
// Damaged liver means some chemicals are very dangerous
if(src.damage >= src.min_bruised_damage)
for(var/datum/reagent/R in owner.reagents.reagent_list)
// Ethanol and all drinks are bad
if(istype(R, /datum/reagent/ethanol))
owner.adjustToxLoss(0.1 * process_accuracy)
// Can't cope with toxins at all
for(var/toxin in list("toxin", "plasma", "sacid", "pacid", "cyanide", "lexorin", "amatoxin", "chloralhydrate", "carpotoxin", "zombiepowder", "mindbreaker"))
if(owner.reagents.has_reagent(toxin))
owner.adjustToxLoss(0.3 * process_accuracy)
/datum/organ/internal/kidney
name = "kidney"
parent_organ = "chest"
/datum/organ/internal/brain
name = "brain"
parent_organ = "head"

View File

@@ -502,13 +502,7 @@
if(prot > 0 || (COLD_RESISTANCE in user.mutations))
user << "You remove the light [fitting]"
else
user << "You try to remove the light [fitting], but you burn your hand on it!"
var/datum/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_arm")
if(affecting.take_damage( 0, 5 )) // 5 burn damage
H.UpdateDamageIcon()
H.updatehealth()
user << "You try to remove the light [fitting], but it's too hot and you don't want to burn your hand."
return // if burned, don't remove the light
// create a light tube/bulb item and put it in the user's hand

View File

@@ -107,30 +107,9 @@ datum
var/current_reagent_transfer = current_reagent.volume * part
if(preserve_data)
trans_data = current_reagent.data
if(current_reagent.id == "blood" && ishuman(target)) // can never be sure
var/mob/living/carbon/human/H = target
var/datum/reagent/blood/HisBlood = locate() in H.vessel.reagent_list //Grab some blood
if(HisBlood) // Make sure there's some blood at all
if(HisBlood.data["donor"] != H) //If it's not theirs, then we look for theirs
for(var/datum/reagent/blood/D in H.vessel.reagent_list)
if(D.data["donor"] == H)
HisBlood = D
break
if(HisBlood && HisBlood.data && trans_data)
if(blood_incompatible(trans_data["blood_type"],HisBlood.data["blood_type"]))
H.reagents.add_reagent("toxin",(current_reagent_transfer * multiplier * 0.5))
H.reagents.update_total()
else
H.vessel.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
H.vessel.update_total()
else
H.vessel.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
H.vessel.update_total()
src.remove_reagent(current_reagent.id, current_reagent_transfer)
else
R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
src.remove_reagent(current_reagent.id, current_reagent_transfer)
R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data)
src.remove_reagent(current_reagent.id, current_reagent_transfer)
src.update_total()
R.update_total()
@@ -246,6 +225,15 @@ datum
continue
var/datum/chemical_reaction/C = reaction
//check if this recipe needs to be heated to mix
if(C.requires_heating)
if(istype(my_atom.loc, /obj/machinery/bunsen_burner))
if(!my_atom.loc:heated)
continue
else
continue
var/total_required_reagents = C.required_reagents.len
var/total_matching_reagents = 0
var/total_required_catalysts = C.required_catalysts.len
@@ -289,7 +277,10 @@ datum
if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other)
var/multiplier = min(multipliers)
var/preserved_data = null
for(var/B in C.required_reagents)
if(!preserved_data)
preserved_data = get_data(B)
remove_reagent(B, (multiplier * C.required_reagents[B]), safety = 1)
var/created_volume = C.result_amount*multiplier
@@ -297,6 +288,11 @@ datum
feedback_add_details("chemical_reaction","[C.result]|[C.result_amount*multiplier]")
multiplier = max(multiplier, 1) //this shouldnt happen ...
add_reagent(C.result, C.result_amount*multiplier)
set_data(C.result, preserved_data)
//add secondary products
for(var/S in C.secondary_results)
add_reagent(S, C.result_amount * C.secondary_results[S] * multiplier)
var/list/seen = viewers(4, get_turf(my_atom))
for(var/mob/M in seen)
@@ -506,6 +502,19 @@ datum
return res
//two helper functions to preserve data across reactions (needed for xenoarch)
get_data(var/reagent_id)
for(var/datum/reagent/D in reagent_list)
if(D.id == reagent_id)
//world << "proffering a data-carrying reagent ([reagent_id])"
return D.data
set_data(var/reagent_id, var/new_data)
for(var/datum/reagent/D in reagent_list)
if(D.id == reagent_id)
//world << "reagent data set ([reagent_id])"
D.data = new_data
///////////////////////////////////////////////////////////////////////////////////

View File

@@ -17,7 +17,7 @@
var/recharged = 0
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")
"copper","mercury","radium","water","ethanol","sugar","sacid","tungsten")
/obj/machinery/chem_dispenser/proc/recharge()
if(stat & (BROKEN|NOPOWER)) return
@@ -779,6 +779,9 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0),
//archaeology!
/obj/item/weapon/rocksliver = list("ground_rock" = 50),
//All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.!
@@ -1106,6 +1109,20 @@
break
remove_object(O)
//xenoarch
for(var/obj/item/weapon/rocksliver/O in holdingitems)
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
var/allowed = get_allowed_by_id(O)
for (var/r_id in allowed)
var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
var/amount = allowed[r_id]
beaker.reagents.add_reagent(r_id,min(amount, space), O.geological_data)
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
remove_object(O)
//Everything else - Transfers reagents from it into beaker
for (var/obj/item/weapon/reagent_containers/O in holdingitems)
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)

View File

@@ -13,6 +13,8 @@ datum
var/result_amount = 0
var/secondary = 0 // set to nonzero if secondary reaction
var/list/secondary_results = list() //additional reagents produced by the reaction
var/requires_heating = 0
proc
on_reaction(var/datum/reagents/holder, var/created_volume)

View File

@@ -94,6 +94,12 @@
else if(istype(target, /obj/item/clothing/suit/space/space_ninja))
return
else if(istype(target, /obj/machinery/bunsen_burner))
return
else if(istype(target, /obj/machinery/anomaly))
return
else if(reagents.total_volume)
user << "\blue You splash the solution onto [target]."
src.reagents.reaction(target, TOUCH)

View File

@@ -80,57 +80,20 @@
if(istype(target, /mob/living/carbon))//maybe just add a blood reagent to all mobs. Then you can suck them dry...With hundreds of syringes. Jolly good idea.
var/amount = src.reagents.maximum_volume - src.reagents.total_volume
var/mob/living/carbon/T = target
var/datum/reagent/B = new /datum/reagent/blood
if(!T.dna)
usr << "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum)"
return
if(NOCLONE in T.mutations) //target done been et, no more blood in him
user << "\red You are unable to locate any blood."
return
if(ishuman(T))
if(T:vessel.get_reagent_amount("blood") < amount)
return
B.holder = src
B.volume = amount
//set reagent data
B.data["donor"] = T
/*
if(T.virus && T.virus.spread_type != SPECIAL)
B.data["virus"] = new T.virus.type(0)
*/
var/datum/reagent/B = T.take_blood(src,amount)
for(var/datum/disease/D in T.viruses)
if(!B.data["viruses"])
B.data["viruses"] = list()
B.data["viruses"] += new D.type(0, D, 1)
if(T.virus2)
B.data["virus2"] = T.virus2.getcopy()
B.data["blood_DNA"] = copytext(T.dna.unique_enzymes,1,0)
if(T.resistances&&T.resistances.len)
B.data["resistances"] = T.resistances.Copy()
if(istype(target, /mob/living/carbon/human))//I wish there was some hasproperty operation...
var/mob/living/carbon/human/HT = target
B.data["blood_type"] = copytext(HT.dna.b_type,1,0)
var/list/temp_chem = list()
for(var/datum/reagent/R in target.reagents.reagent_list)
temp_chem += R.name
temp_chem[R.name] = R.volume
B.data["trace_chem"] = list2params(temp_chem)
B.data["antibodies"] = T.antibodies
if(ishuman(T))
T:vessel.remove_reagent("blood",amount) // Removes blood if human
src.reagents.reagent_list += B
src.reagents.update_total()
src.on_reagent_change()
src.reagents.handle_reactions()
if (B)
src.reagents.reagent_list += B
src.reagents.update_total()
src.on_reagent_change()
src.reagents.handle_reactions()
user << "\blue You take a blood sample from [target]"
for(var/mob/O in viewers(4, user))
O.show_message("\red [user] takes a blood sample from [target].", 1)
@@ -182,9 +145,7 @@
var/trans
if(B && ishuman(target))
var/mob/living/carbon/human/H = target
trans = B.volume > 5? 5 : B.volume
H.vessel.add_reagent("blood",trans,B.data)
src.reagents.remove_reagent("blood",trans)
H.inject_blood(src,5)
else
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
user << "\blue You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."

View File

@@ -1,77 +0,0 @@
//chemistry stuff here so that it can be easily viewed/modified
/*
datum
reagent
tungsten //used purely to make lith-sodi-tungs
name = "Tungsten"
id = "tungsten"
description = "A chemical element, and a strong oxidising agent."
reagent_state = SOLID
color = "#808080" // rgb: 128, 128, 128, meant to be a silvery grey but idrc
lithiumsodiumtungstate
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
description = "A reducing agent for geological compounds."
reagent_state = LIQUID
color = "#808080" // rgb: 128, 128, 128, again, silvery grey
ground_rock
name = "Ground Rock"
id = "ground_rock"
description = "A fine dust made of ground up geological samples."
reagent_state = SOLID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this brown
density_separated_sample
name = "Density separated sample"
id = "density_separated_sample"
description = "A watery paste which has had density separation applied to its contents."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this white
analysis_sample
name = "Analysis sample"
id = "analysis_sample"
description = "A watery paste used in chemical analysis."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this white
chemical_waste
name = "Chemical Waste"
id = "chemical_waste"
description = "A viscous, toxic liquid left over from many chemical processes."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this fluoro/bright green
datum
chemical_reaction
lithiumsodiumtungstate //LiNa2WO4, not the easiest chem to mix
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
result = "lithiumsodiumtungstate"
required_reagents = list("lithium" = 1, "sodium" = 2, "tungsten" = 1, "oxygen" = 4)
result_amount = 8
density_separated_liquid
name = "Density separated sample"
id = "density_separated_sample"
result = "density_separated_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("ground_rock" = 1, "lithiumsodiumtungstate" = 2)
result_amount = 2
analysis_liquid
name = "Analysis sample"
id = "analysis_sample"
result = "analysis_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("density_separated_sample" = 5)
result_amount = 4
requires_heating = 1
*/

View File

@@ -1 +0,0 @@
//todo: tape, methods for excavation?

View File

@@ -1,119 +0,0 @@
obj/machinery/gas_chromatography
name = "Gas Chromatography Spectrometer"
desc = "A specialised mass spectrometer."
icon = 'virology.dmi'
icon_state = "analyser"
obj/machinery/gas_chromatography/Topic(href, href_list)
if(href_list["close"])
usr << browse(null, "window=artanalyser")
usr.machine = null
updateDialog()
obj/machinery/gas_chromatography/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Gas Chromatography Spectrometer</B><BR>"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artanalyser;size=450x500")
onclose(user, "artanalyser")
obj/machinery/accelerator
name = "Accelerator Spectrometer"
desc = "A specialised mass spectrometer."
icon = 'virology.dmi'
icon_state = "analyser"
obj/machinery/accelerator/Topic(href, href_list)
if(href_list["close"])
usr << browse(null, "window=artanalyser")
usr.machine = null
updateDialog()
obj/machinery/accelerator/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Accelerator Spectrometer</B><BR>"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artanalyser;size=450x500")
onclose(user, "artanalyser")
obj/machinery/fourier_transform
name = "Fourier Transform Spectroscope"
desc = "A specialised geochemical analysis device."
icon = 'virology.dmi'
icon_state = "analyser"
obj/machinery/fourier_transform/Topic(href, href_list)
if(href_list["close"])
usr << browse(null, "window=artanalyser")
usr.machine = null
updateDialog()
obj/machinery/fourier_transform/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Fourier Transform Spectroscope</B><BR>"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artanalyser;size=450x500")
onclose(user, "artanalyser")
obj/machinery/radiometric
name = "Radiometric Exposure Spectrometer"
desc = "A specialised mass spectrometer, able to radiometrically date inserted materials."
icon = 'virology.dmi'
icon_state = "analyser"
obj/machinery/radiometric/Topic(href, href_list)
if(href_list["close"])
usr << browse(null, "window=artanalyser")
usr.machine = null
updateDialog()
obj/machinery/radiometric/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Radiometric Exposure Spectrometer</B><BR>"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artanalyser;size=450x500")
onclose(user, "artanalyser")
obj/machinery/ion_mobility
name = "Ion Mobility Spectrometer"
desc = "A specialised mass spectrometer."
icon = 'virology.dmi'
icon_state = "analyser"
obj/machinery/ion_mobility/Topic(href, href_list)
if(href_list["close"])
usr << browse(null, "window=artanalyser")
usr.machine = null
updateDialog()
obj/machinery/ion_mobility/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Ion Mobility Spectrometer</B><BR>"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh<BR>"
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artanalyser;size=450x500")
onclose(user, "artanalyser")

View File

@@ -1,40 +0,0 @@
/obj/item/device/depth_scanner
name = "depth analysis scanner"
desc = "Used to check mass spatial depth and density."
icon = 'pda.dmi'
icon_state = "crap"
item_state = "analyzer"
w_class = 1.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
/obj/item/weapon/pickaxe/hand_pick
name = "hand pick"
//icon_state = "excavation"
//item_state = "minipick"
digspeed = 50
desc = "A smaller, more precise version of the pickaxe."
/obj/item/weapon/pickaxe/mini_pick
name = "mini pick"
//icon_state = "excavation"
//item_state = "minipick"
digspeed = 60
desc = "A miniature excavation tool for precise digging around delicate finds."
/obj/item/device/core_sampler
name = "core sampler"
desc = "Used to extract cores from geological samples."
icon = 'device.dmi'
icon_state = "core_sampler"
item_state = "screwdriver_brown"
w_class = 1.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
/obj/item/device/beacon_locator
name = "locater device"
desc = "Used to scan and locate signals on a particular frequency."
icon = 'device.dmi'
icon_state = "pinoff" //pinonfar, pinonmedium, pinonclose, pinondirect, pinonnull
item_state = "electronic"

View File

@@ -0,0 +1,76 @@
/area/research_outpost
name = "Research Outpost"
icon_state = "anomaly"
/area/research_outpost/hallway
name = "Research Outpost Hallway"
icon_state = "hallC"
/area/research_outpost/gearstore
name = "Expedition Preparation"
icon_state = "anog"
/area/research_outpost/power
name = "Research Outpost Power"
icon_state = "engine"
/area/research_outpost/atmos
name = "Research Outpost Atmospherics"
icon_state = "atmos"
/area/research_outpost/maint
name = "Research Outpost Maintenance"
icon_state = "maintcentral"
/area/research_outpost/iso1
name = "Isolation Cell"
icon_state = "iso1"
/area/research_outpost/iso2
name = "Isolation Cell"
icon_state = "iso2"
/area/research_outpost/iso3
name = "Isolation Cell"
icon_state = "iso3"
/area/research_outpost/harvesting
name = "Exotic Particles Collection"
icon_state = "anolab"
/area/research_outpost/sample
name = "Sample Preparation Room"
icon_state = "anosample"
/area/research_outpost/spectro
name = "Mass Spectrometry Lab"
icon_state = "anospectro"
/area/research_outpost/anomaly
name = "Anomalous Materials Lab"
icon_state = "anolab"
/area/research_outpost/med
name = "Research Outpost Medbay"
icon_state = "medbay3"
/area/research_outpost/entry
name = "Research Outpost Shuttle Dock"
icon_state = "entry"
/area/research_outpost/longtermstorage
name = "Long-Term Storage"
icon_state = "primarystorage"
/area/research_outpost/tempstorage
name = "Temporary Storage"
icon_state = "storage"
/area/research_outpost/maintstore1
name = "Auxiliary Storage"
icon_state = "auxstorage"
/area/research_outpost/maintstore2
name = "Maintenance Storage"
icon_state = "auxstorage"

View File

@@ -0,0 +1,101 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Large finds - (Potentially) active alien machinery from the dawn of time
/datum/artifact_find
var/artifact_id
var/artifact_find_type
var/artifact_detect_range
/datum/artifact_find/New()
artifact_detect_range = rand(5,300)
artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]"
artifact_find_type = pick(\
5;/obj/machinery/power/supermatter,\
5;/obj/structure/constructshell,\
5;/obj/machinery/syndicate_beacon,\
25;/obj/machinery/power/supermatter/shard,\
50;/obj/structure/cult/pylon,\
100;/obj/machinery/auto_cloner,\
100;/obj/machinery/giga_drill,\
100;/obj/mecha/working/hoverpod,\
100;/obj/machinery/replicator,\
150;/obj/structure/crystal,\
1000;/obj/machinery/artifact)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Boulders - sometimes turn up after excavating turf - excavate further to try and find large xenoarch finds
/obj/structure/boulder
name = "rocky debris"
desc = "Leftover rock from an excavation, it's been partially dug out already but there's still a lot to go."
icon = 'icons/obj/mining.dmi'
icon_state = "boulder1"
density = 1
opacity = 1
var/excavation_level = 0
var/datum/geosample/geological_data
var/datum/artifact_find/artifact_find
/obj/structure/boulder/New()
icon_state = "boulder[rand(1,4)]"
excavation_level = rand(5,50)
/obj/structure/boulder/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/device/core_sampler))
src.geological_data.artifact_distance = rand(-100,100) / 100
src.geological_data.artifact_id = artifact_find.artifact_id
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
return
if (istype(W, /obj/item/device/depth_scanner))
var/obj/item/device/depth_scanner/C = W
C.scan_atom(user, src)
return
if (istype(W, /obj/item/device/measuring_tape))
var/obj/item/device/measuring_tape/P = W
user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].")
if(do_after(user,40))
user << "\blue \icon[P] [src] has been excavated to a depth of [2*src.excavation_level]cm."
return
if (istype(W, /obj/item/weapon/pickaxe))
var/obj/item/weapon/pickaxe/P = W
user << "\red You start [P.drill_verb] [src]."
if(!do_after(user,P.digspeed))
return
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)
//failure
user.visible_message("<font color='red'><b>[src] suddenly crumbles away.</b></font>",\
"\red [src] has disintegrated under your onslaught, any secrets it was holding long gone.")
del(src)
else if(prob(reveal_prob))
//success
if(artifact_find)
var/spawn_type = artifact_find.artifact_find_type
var/obj/O = new spawn_type(get_turf(src))
if(istype(O,/obj/machinery/artifact))
var/obj/machinery/artifact/X = O
if(X.my_effect)
X.my_effect.artifact_id = artifact_find.artifact_id
src.visible_message("<font color='red'><b>[src] suddenly crumbles away.</b></font>")
else
user.visible_message("<font color='red'><b>[src] suddenly crumbles away.</b></font>",\
"\blue [src] has been whittled away under your careful excavation, but there was nothing of interest inside.")
del(src)

View File

@@ -0,0 +1,87 @@
/obj/machinery/auto_cloner
name = "mysterious pod"
desc = "It's full of a viscous liquid, but appears dark and silent."
icon = 'icons/obj/cryogenics.dmi'
icon_state = "cellold0"
var/spawn_type
var/current_ticks_spawning = 0
var/ticks_required_to_spawn
density = 1
var/previous_power_state = 0
use_power = 1
active_power_usage = 2000
idle_power_usage = 1000
/obj/machinery/auto_cloner/New()
..()
ticks_required_to_spawn = rand(240,1440)
//33% chance to spawn nasties
if(prob(33))
spawn_type = pick(\
/mob/living/simple_animal/hostile/giant_spider/nurse,\
/mob/living/simple_animal/hostile/alien,\
/mob/living/simple_animal/hostile/bear,\
/mob/living/simple_animal/hostile/creature,\
/mob/living/simple_animal/hostile/panther,\
/mob/living/simple_animal/hostile/snake\
)
else
spawn_type = pick(\
/mob/living/simple_animal/cat,\
/mob/living/simple_animal/corgi,\
/mob/living/simple_animal/corgi/puppy,\
/mob/living/simple_animal/chicken,\
/mob/living/simple_animal/cow,\
/mob/living/simple_animal/parrot,\
/mob/living/simple_animal/slime,\
/mob/living/simple_animal/crab,\
/mob/living/simple_animal/mouse,\
/mob/living/simple_animal/hostile/retaliate/goat,\
/mob/living/carbon/monkey\
)
//todo: how the hell is the asteroid permanently powered?
/obj/machinery/auto_cloner/process()
if(powered(power_channel))
if(!previous_power_state)
previous_power_state = 1
icon_state = "cellold1"
src.visible_message("\blue \icon[src] [src] suddenly comes to life!")
//slowly grow a mob
current_ticks_spawning++
if(prob(5))
src.visible_message("\blue \icon[src] [src] [pick("gloops","glugs","whirrs","whooshes","hisses","purrs","hums","gushes")].")
//if we've finished growing...
if(current_ticks_spawning >= ticks_required_to_spawn)
current_ticks_spawning = 0
use_power = 1
src.visible_message("\blue \icon[src] [src] pings!")
icon_state = "cellold1"
desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow."
if(spawn_type)
new spawn_type(src.loc)
//if we're getting close to finished, kick into overdrive power usage
if(current_ticks_spawning / ticks_required_to_spawn > 0.75)
use_power = 2
icon_state = "cellold2"
desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow. A dark shape appears to be forming inside..."
else
use_power = 1
icon_state = "cellold1"
desc = "It's full of a bubbling viscous liquid, and is lit by a mysterious glow."
else
if(previous_power_state)
previous_power_state = 0
icon_state = "cellold0"
src.visible_message("\blue \icon[src] [src] suddenly shuts down.")
//cloned mob slowly breaks down
if(current_ticks_spawning > 0)
current_ticks_spawning--

View File

@@ -0,0 +1,36 @@
/obj/structure/crystal
name = "large crystal"
icon = 'xenoarchaeology.dmi'
icon_state = "crystal"
density = 1
/obj/structure/crystal/New()
..()
icon_state = pick("ano70","ano80")
desc = pick(\
"It shines faintly as it catches the light.",\
"It appears to have a faint inner glow.",\
"It seems to draw you inward as you look it at.",\
"Something twinkles faintly as you look at it.",\
"It's mesmerizing to behold.")
/obj/structure/crystal/Del()
src.visible_message("\red<b>[src] shatters!</b>")
if(prob(75))
new /obj/item/weapon/shard/plasma(src.loc)
if(prob(50))
new /obj/item/weapon/shard/plasma(src.loc)
if(prob(25))
new /obj/item/weapon/shard/plasma(src.loc)
if(prob(75))
new /obj/item/weapon/shard(src.loc)
if(prob(50))
new /obj/item/weapon/shard(src.loc)
if(prob(25))
new /obj/item/weapon/shard(src.loc)
..()
//todo: laser_act

View File

@@ -0,0 +1,35 @@
/obj/machinery/giga_drill
name = "alien drill"
desc = "A giant, alien drill mounted on long treads."
icon = 'icons/obj/mining.dmi'
icon_state = "gigadrill"
var/active = 0
var/drill_time = 10
var/turf/drilling_turf
density = 1
layer = 3.1 //to go over ores
/obj/machinery/giga_drill/attack_hand(mob/user as mob)
if(active)
active = 0
icon_state = "gigadrill"
user << "\blue You press a button and [src] slowly spins down."
else
active = 1
icon_state = "gigadrill_mov"
user << "\blue You press a button and [src] shudders to life."
/obj/machinery/giga_drill/Bump(atom/A)
if(active && !drilling_turf)
if(istype(A,/turf/simulated/mineral))
var/turf/simulated/mineral/M = A
drilling_turf = get_turf(src)
src.visible_message("\red <b>[src] begins to drill into [M]!</b>")
anchored = 1
spawn(drill_time)
if(get_turf(src) == drilling_turf && active)
M.gets_drilled()
src.loc = M
drilling_turf = null
anchored = 0

View File

@@ -0,0 +1,67 @@
/obj/mecha/working/hoverpod
name = "hover pod"
icon_state = "engineering_pod"
desc = "Stubby and round, it has a human sized access hatch on the top."
wreckage = /obj/effect/decal/mecha_wreckage/hoverpod
//duplicate of parent proc, but without space drifting
/obj/mecha/working/hoverpod/dyndomove(direction)
if(!can_move)
return 0
if(src.pr_inertial_movement.active())
return 0
if(!has_charge(step_energy_drain))
return 0
var/move_result = 0
if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
move_result = mechsteprand()
else if(src.dir!=direction)
move_result = mechturn(direction)
else
move_result = mechstep(direction)
if(move_result)
can_move = 0
use_power(step_energy_drain)
/*if(istype(src.loc, /turf/space))
if(!src.check_for_support())
src.pr_inertial_movement.start(list(src,direction))
src.log_message("Movement control lost. Inertial movement started.")*/
if(do_after(step_in))
can_move = 1
return 1
return 0
//these three procs overriden to play different sounds
/obj/mecha/mechturn(direction)
dir = direction
//playsound(src,'sound/machines/hiss.ogg',40,1)
return 1
/obj/mecha/mechstep(direction)
var/result = step(src,direction)
if(result)
playsound(src,'sound/machines/hiss.ogg',40,1)
return result
/obj/mecha/mechsteprand()
var/result = step_rand(src)
if(result)
playsound(src,'sound/machines/hiss.ogg',40,1)
return result
/obj/effect/decal/mecha_wreckage/hoverpod
name = "Hover pod wreckage"
icon_state = "engineering_pod-broken"
/*New()
..()
var/list/parts = list(
for(var/i=0;i<2;i++)
if(!isemptylist(parts) && prob(40))
var/part = pick(parts)
welder_salvage += part
parts -= part
return*/

View File

@@ -0,0 +1,119 @@
/obj/machinery/replicator
name = "alien machine"
desc = "It's some kind of pod with strange wires and gadgets all over it."
icon = 'xenoarchaeology.dmi'
icon_state = "borgcharger0(old)"
density = 1
idle_power_usage = 100
active_power_usage = 1000
use_power = 1
var/spawn_progress = 0
var/max_spawn_ticks = 5
var/list/construction = list()
var/list/spawning_types = list()
/obj/machinery/replicator/New()
..()
var/list/viables = list(\
/obj/item/roller,\
/obj/structure/closet/crate,\
/obj/structure/closet/acloset,\
/mob/living/simple_animal/hostile/mimic,\
/mob/living/simple_animal/hostile/viscerator,\
/mob/living/simple_animal/hostile/hivebot,\
/obj/item/device/analyzer,\
/obj/item/device/camera,\
/obj/item/device/flash,\
/obj/item/device/flashlight,\
/obj/item/device/healthanalyzer,\
/obj/item/device/multitool,\
/obj/item/device/paicard,\
/obj/item/device/radio,\
/obj/item/device/radio/headset,\
/obj/item/device/radio/beacon,\
/obj/item/weapon/autopsy_scanner,\
/obj/item/weapon/bikehorn,\
/obj/item/weapon/bonesetter,\
/obj/item/weapon/butch,\
/obj/item/weapon/caution,\
/obj/item/weapon/caution/cone,\
/obj/item/weapon/crowbar,\
/obj/item/weapon/clipboard,\
/obj/item/weapon/cell,\
/obj/item/weapon/circular_saw,\
/obj/item/weapon/hatchet,\
/obj/item/weapon/handcuffs,\
/obj/item/weapon/hemostat,\
/obj/item/weapon/kitchenknife,\
/obj/item/weapon/lighter,\
/obj/item/weapon/lighter,\
/obj/item/weapon/light/bulb,\
/obj/item/weapon/light/tube,\
/obj/item/weapon/pickaxe,\
/obj/item/weapon/shovel,\
/obj/item/weapon/table_parts,\
/obj/item/weapon/weldingtool,\
/obj/item/weapon/wirecutters,\
/obj/item/weapon/wrench,\
/obj/item/weapon/screwdriver,\
/obj/item/weapon/grenade/chem_grenade/cleaner,\
/obj/item/weapon/grenade/chem_grenade/metalfoam\
)
var/quantity = rand(5,15)
for(var/i=0, i<quantity, i++)
var/button_desc = "[pick("a yellow","a purple","a green","a blue","a red","an orange","a white")], "
button_desc += "[pick("round","square","diamond","heart","dog","human")] shaped "
button_desc += "[pick("toggle","switch","lever","button","pad","hole")]"
var/type = pick(viables)
viables.Remove(type)
construction[button_desc] = type
/obj/machinery/replicator/process()
if(spawning_types.len && powered())
spawn_progress++
if(spawn_progress > max_spawn_ticks)
src.visible_message("\blue \icon[src] [src] pings!")
var/spawn_type = spawning_types[1]
new spawn_type(src.loc)
spawning_types.Remove(spawning_types[1])
spawn_progress = 0
max_spawn_ticks = rand(5,30)
if(!spawning_types.len)
use_power = 1
icon_state = "borgcharger0(old)"
else if(prob(5))
src.visible_message("\blue \icon[src] [src] [pick("clicks","whizzes","whirrs","whooshes","clanks","clongs","clonks","bangs")].")
/obj/machinery/replicator/attack_hand(mob/user as mob)
interact(user)
/obj/machinery/replicator/interact(mob/user)
var/dat = "The control panel displays an incomprehensible selection of controls, many with unusual markings or text around them.<br>"
dat += "<br>"
for(var/index=1, index<=construction.len, index++)
dat += "<A href='?src=\ref[src];activate=[index]'>\[[construction[index]]\]</a><br>"
user << browse(dat, "window=alien_replicator")
/obj/machinery/replicator/Topic(href, href_list)
if(href_list["activate"])
var/index = text2num(href_list["activate"])
if(index > 0 && index <= construction.len)
if(spawning_types.len)
src.visible_message("\blue \icon[src] a [pick("light","dial","display","meter","pad")] on [src]'s front [pick("blinks","flashes")] [pick("red","yellow","blue","orange","purple","green","white")].")
else
src.visible_message("\blue \icon[src] [src]'s front compartment slides shut.")
spawning_types.Add(construction[construction[index]])
spawn_progress = 0
use_power = 2
icon_state = "borgcharger1(old)"

View File

@@ -0,0 +1,362 @@
#define EFFECT_TOUCH 0
#define EFFECT_AURA 1
#define EFFECT_PULSE 2
#define MAX_EFFECT 2
#define TRIGGER_TOUCH 0
#define TRIGGER_WATER 1
#define TRIGGER_ACID 2
#define TRIGGER_VOLATILE 3
#define TRIGGER_TOXIN 4
#define TRIGGER_FORCE 5
#define TRIGGER_ENERGY 6
#define TRIGGER_HEAT 7
#define TRIGGER_COLD 8
#define TRIGGER_PLASMA 9
#define TRIGGER_OXY 10
#define TRIGGER_CO2 11
#define TRIGGER_NITRO 12
#define MAX_TRIGGER 12
/*
//sleeping gas appears to be bugged, currently
var/list/valid_primary_effect_types = list(\
/datum/artifact_effect/cellcharge,\
/datum/artifact_effect/celldrain,\
/datum/artifact_effect/forcefield,\
/datum/artifact_effect/gasoxy,\
/datum/artifact_effect/gasplasma,\
/* /datum/artifact_effect/gassleeping,\*/
/datum/artifact_effect/heal,\
/datum/artifact_effect/hurt,\
/datum/artifact_effect/emp,\
/datum/artifact_effect/teleport,\
/datum/artifact_effect/robohurt,\
/datum/artifact_effect/roboheal)
var/list/valid_secondary_effect_types = list(\
/datum/artifact_effect/cold,\
/datum/artifact_effect/badfeeling,\
/datum/artifact_effect/cellcharge,\
/datum/artifact_effect/celldrain,\
/datum/artifact_effect/dnaswitch,\
/datum/artifact_effect/emp,\
/datum/artifact_effect/gasco2,\
/datum/artifact_effect/gasnitro,\
/datum/artifact_effect/gasoxy,\
/datum/artifact_effect/gasplasma,\
/* /datum/artifact_effect/gassleeping,\*/
/datum/artifact_effect/goodfeeling,\
/datum/artifact_effect/heal,\
/datum/artifact_effect/hurt,\
/datum/artifact_effect/radiate,\
/datum/artifact_effect/roboheal,\
/datum/artifact_effect/robohurt,\
/datum/artifact_effect/sleepy,\
/datum/artifact_effect/stun,\
/datum/artifact_effect/teleport)
*/
/obj/machinery/artifact
name = "alien artifact"
desc = "A large alien device."
icon = 'xenoarchaeology.dmi'
icon_state = "ano00"
var/icon_num = 0
density = 1
var/datum/artifact_effect/my_effect
var/datum/artifact_effect/secondary_effect
var/being_used = 0
/obj/machinery/artifact/New()
..()
//setup primary effect - these are the main ones (mixed)
var/effecttype = pick(typesof(/datum/artifact_effect) - /datum/artifact_effect)
my_effect = new effecttype(src)
//75% chance to have a secondary stealthy (and mostly bad) effect
if(prob(75))
effecttype = pick(typesof(/datum/artifact_effect) - /datum/artifact_effect)
secondary_effect = new effecttype(src)
if(prob(75))
secondary_effect.ToggleActivate(0)
icon_num = rand(0,11)
icon_state = "ano[icon_num]0"
if(icon_num == 7 || icon_num == 8)
name = "large crystal"
desc = pick("It shines faintly as it catches the light.",\
"It appears to have a faint inner glow.",\
"It seems to draw you inward as you look it at.",\
"Something twinkles faintly as you look at it.",\
"It's mesmerizing to behold.")
if(prob(50))
my_effect.trigger = TRIGGER_ENERGY
else if(icon_num == 9)
name = "alien computer"
desc = "It is covered in strange markings."
if(prob(75))
my_effect.trigger = TRIGGER_TOUCH
else if(icon_num == 10)
desc = "A large alien device, there appear to be some kind of vents in the side."
if(prob(50))
my_effect.trigger = rand(6,12)
else if(icon_num == 11)
name = "sealed alien pod"
desc = "A strange alien device."
if(prob(25))
my_effect.trigger = rand(1,4)
#define TRIGGER_PLASMA 9
#define TRIGGER_OXY 10
#define TRIGGER_CO2 11
#define TRIGGER_NITRO 12
/obj/machinery/artifact/process()
if(my_effect)
my_effect.process()
if(secondary_effect)
secondary_effect.process()
if(pulledby)
Bumped(pulledby)
//if either of our effects rely on environmental factors, work that out
var/trigger_cold = 0
var/trigger_hot = 0
var/trigger_plasma = 0
var/trigger_oxy = 0
var/trigger_co2 = 0
var/trigger_nitro = 0
if( (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) || (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) )
var/turf/T = get_turf(src)
var/datum/gas_mixture/env = T.return_air()
if(env)
if(env.temperature < 225)
trigger_cold = 1
else if(env.temperature > 375)
trigger_hot = 1
if(env.toxins >= 10)
trigger_plasma = 1
if(env.oxygen >= 10)
trigger_oxy = 1
if(env.carbon_dioxide >= 10)
trigger_co2 = 1
if(env.nitrogen >= 10)
trigger_nitro = 1
//COLD ACTIVATION
if(trigger_cold)
if(my_effect.trigger == TRIGGER_COLD && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_COLD && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
//HEAT ACTIVATION
if(trigger_hot)
if(my_effect.trigger == TRIGGER_HEAT && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_HEAT && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
//PLASMA GAS ACTIVATION
if(trigger_plasma)
if(my_effect.trigger == TRIGGER_PLASMA && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_PLASMA && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_PLASMA && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_PLASMA && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
//OXYGEN GAS ACTIVATION
if(trigger_oxy)
if(my_effect.trigger == TRIGGER_OXY && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_OXY && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
//CO2 GAS ACTIVATION
if(trigger_co2)
if(my_effect.trigger == TRIGGER_CO2 && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_CO2 && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
//NITROGEN GAS ACTIVATION
if(trigger_nitro)
if(my_effect.trigger == TRIGGER_NITRO && !my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
else
if(my_effect.trigger == TRIGGER_NITRO && my_effect.activated)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
secondary_effect.ToggleActivate(0)
/obj/machinery/artifact/attack_hand(var/mob/user as mob)
if (get_dist(user, src) > 1)
user << "\red You can't reach [src] from here."
return
if(ishuman(user) && user:gloves)
user << "<b>You touch [src]</b> with your gloved hands, [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")]."
return
src.add_fingerprint(user)
if(my_effect.trigger == TRIGGER_TOUCH)
user << "<b>You touch [src].<b>"
my_effect.ToggleActivate()
else
user << "<b>You touch [src],</b> [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")]."
if(prob(25) && secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH)
secondary_effect.ToggleActivate(0)
if (my_effect.effect == EFFECT_TOUCH)
my_effect.DoEffectTouch(user)
if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated)
secondary_effect.DoEffectTouch(user)
/obj/machinery/artifact/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
if (istype(W, /obj/item/weapon/reagent_containers/))
if(W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1))
if(my_effect.trigger == TRIGGER_WATER)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_WATER && prob(25))
secondary_effect.ToggleActivate(0)
else if(W.reagents.has_reagent("acid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1))
if(my_effect.trigger == TRIGGER_ACID)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_ACID && prob(25))
secondary_effect.ToggleActivate(0)
else if(W.reagents.has_reagent("plasma", 1) || W.reagents.has_reagent("thermite", 1))
if(my_effect.trigger == TRIGGER_VOLATILE)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_VOLATILE && prob(25))
secondary_effect.ToggleActivate(0)
else 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))
if(my_effect.trigger == TRIGGER_TOXIN)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_TOXIN && prob(25))
secondary_effect.ToggleActivate(0)
else if(istype(W,/obj/item/weapon/melee/baton) && W:status ||\
istype(W,/obj/item/weapon/melee/energy) ||\
istype(W,/obj/item/weapon/melee/cultblade) ||\
istype(W,/obj/item/weapon/card/emag) ||\
istype(W,/obj/item/device/multitool))
if (my_effect.trigger == TRIGGER_ENERGY)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
secondary_effect.ToggleActivate(0)
else if (istype(W,/obj/item/weapon/match) && W:lit ||\
istype(W,/obj/item/weapon/weldingtool) && W:welding ||\
istype(W,/obj/item/weapon/lighter) && W:lit)
if(my_effect.trigger == TRIGGER_HEAT)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && prob(25))
secondary_effect.ToggleActivate(0)
else
..()
if (my_effect.trigger == TRIGGER_FORCE && W.force >= 10)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
secondary_effect.ToggleActivate(0)
/obj/machinery/artifact/Bumped(M as mob|obj)
..()
if(istype(M,/obj))
if(M:throwforce >= 10)
if(my_effect.trigger == TRIGGER_FORCE)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
secondary_effect.ToggleActivate(0)
else if(ishuman(M) && !istype(M:gloves,/obj/item/clothing/gloves))
var/warn = 0
if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
my_effect.ToggleActivate()
warn = 1
if(secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH && prob(25))
secondary_effect.ToggleActivate(0)
warn = 1
if (my_effect.effect == EFFECT_TOUCH && prob(50))
my_effect.DoEffectTouch(M)
warn = 1
if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated && prob(50))
secondary_effect.DoEffectTouch(M)
warn = 1
if(warn)
M << "<b>You accidentally touch [src].<b>"
..()
/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
if(istype(P,/obj/item/projectile/bullet) ||\
istype(P,/obj/item/projectile/hivebotbullet))
if(my_effect.trigger == TRIGGER_FORCE)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
secondary_effect.ToggleActivate(0)
else if(istype(P,/obj/item/projectile/beam) ||\
istype(P,/obj/item/projectile/ion) ||\
istype(P,/obj/item/projectile/energy))
if(my_effect.trigger == TRIGGER_ENERGY)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
secondary_effect.ToggleActivate(0)
/obj/machinery/artifact/ex_act(severity)
switch(severity)
if(1.0) del src
if(2.0)
if (prob(50))
del src
else
if(my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
my_effect.ToggleActivate()
if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
secondary_effect.ToggleActivate(0)
if(3.0)
if (my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
my_effect.ToggleActivate()
if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
secondary_effect.ToggleActivate(0)
return
/obj/machinery/artifact/Move()
..()
if(my_effect)
my_effect.UpdateMove()
if(secondary_effect)
secondary_effect.UpdateMove()

View File

@@ -1,10 +1,18 @@
//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 = 'anomaly.dmi'
icon = 'xenoarchaeology.dmi'
icon_state = "ano00"
var/icon_num = 0
anchored = 0
@@ -21,55 +29,51 @@
/obj/machinery/artifact/New()
..()
// Origin and appearance randomisation
// cael - need some more icons
my_effect = new()
src.origin = pick("ancient","martian","wizard","eldritch","precursor")
switch(src.origin)
if("ancient") icon_num = pick(2)//src.icon_state = pick("ano2")
if("martian") icon_num = pick(4)//src.icon_state = pick("ano4")
if("wizard") icon_num = pick(0,1)//src.icon_state = pick("ano0","ano1")
if("eldritch") icon_num = pick(3)//src.icon_state = pick("ano3")
if("precursor") icon_num = pick(5)//src.icon_state = pick("ano5")
icon_num = rand(0,5)
icon_state = "ano[icon_num]0"
// Low-ish random chance to not look like it's origin
if(prob(20)) src.icon_state = pick("ano00","ano10","ano20","ano30","ano40","ano50")
// Power randomisation
my_effect.trigger = pick("force","energy","chemical","heat","touch")
if (my_effect.trigger == "chemical") my_effect.triggerX = pick("hydrogen","corrosive","volatile","toxic")
my_effect.trigger = pick("force","energy","chemical","heat","touch","presence")
if (my_effect.trigger == "chemical")
my_effect.triggerX = pick("hydrogen","corrosive","volatile","toxic")
// Ancient Artifacts focus on robotic/technological effects
// Martian Artifacts focus on biological effects
// Wizard Artifacts focus on weird shit
// Eldritch Artifacts are 100% bad news
// Precursor Artifacts do everything
switch(src.origin)
if("ancient") my_effect.effecttype = pick("roboheal","robohurt","cellcharge","celldrain")
if("martian") my_effect.effecttype = pick("healing","injure"/*,"stun"*/,"planthelper")
if("wizard") my_effect.effecttype = pick(/*"stun",*/"forcefield","teleport")
if("eldritch") my_effect.effecttype = pick("injure",/*"stun",*/"robohurt","celldrain")
if("precursor") my_effect.effecttype = pick("healing","injure",/*"stun",*/"roboheal","robohurt","cellcharge","celldrain","planthelper","forcefield","teleport")
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("cellcharge") my_effect.effectmode = pick("aura","pulse")
if("celldrain") my_effect.effectmode = pick("aura","pulse")
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("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")
@@ -83,9 +87,11 @@
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()
..()
@@ -191,26 +197,28 @@
src.activated = !src.activated
var/display_msg = ""
if(activated)
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!"
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()
switch(rand(2))
if(0)
display_msg = "grows dull!"
if(1)
display_msg = "fades in intensity!"
if(2)
display_msg = "suddenly becomes very quiet!"
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))
@@ -232,17 +240,3 @@
/obj/machinery/artifact/Move()
..()
my_effect.update_move(src, src.loc)
/proc/artifact_checkgood(var/datum/artifact_effect/A)
switch(A.effecttype)
if("healing") return 1
if("injure") return 0
// if("stun") return 0
if("roboheal") return 1
if("robohurt") return 0
if("cellcharge") return 1
if("celldrain") return 1
if("planthelper") return 1
if("forcefield") return 1
if("teleport") return 0

View File

@@ -0,0 +1,110 @@
//override procs in children as necessary
/datum/artifact_effect
var/effecttype = "unknown" //purely used for admin checks ingame, not needed any more
var/effect = EFFECT_TOUCH
var/effectrange = 4
var/trigger = TRIGGER_TOUCH
var/atom/holder
var/activated = 0
var/chargelevel = 0
var/chargelevelmax = 10
var/artifact_id = ""
var/effect_type = 0
//0 = Unknown / none detectable
//1 = Concentrated energy
//2 = Intermittent psionic wavefront
//3 = Electromagnetic energy
//4 = Particle field
//5 = Organically reactive exotic particles
//6 = Interdimensional/bluespace? phasing
//7 = Atomic synthesis
/datum/artifact_effect/New(var/atom/location)
..()
holder = location
effect = rand(0,MAX_EFFECT)
trigger = rand(0,MAX_TRIGGER)
//this will be replaced by the excavation code later, but it's here just in case
artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]"
//random charge time and distance
switch(pick(100;1, 50;2, 25;3))
if(1)
//short range, short charge time
chargelevelmax = rand(3, 20)
effectrange = rand(1, 3)
if(2)
//medium range, medium charge time
chargelevelmax = rand(15, 40)
effectrange = rand(5, 15)
if(3)
//large range, long charge time
chargelevelmax = rand(20, 120)
effectrange = rand(20, 200)
/datum/artifact_effect/proc/ToggleActivate(var/reveal_toggle = 1)
//so that other stuff happens first
spawn(0)
if(activated)
activated = 0
else
activated = 1
if(reveal_toggle && holder)
if(istype(holder, /obj/machinery/artifact))
var/obj/machinery/artifact/A = holder
A.icon_state = "ano[A.icon_num][activated]"
var/display_msg
if(activated)
display_msg = pick("momentarily glows brightly!","distorts slightly for a moment!","flickers slightly!","vibrates!","shimmers slightly for a moment!")
else
display_msg = pick("grows dull!","fades in intensity!","suddenly becomes very still!","suddenly becomes very quiet!")
var/atom/toplevelholder = holder
while(!istype(toplevelholder.loc, /turf))
toplevelholder = toplevelholder.loc
toplevelholder.visible_message("\red \icon[toplevelholder] [toplevelholder] [display_msg]")
/datum/artifact_effect/proc/DoEffectTouch(var/mob/user)
/datum/artifact_effect/proc/DoEffectAura(var/atom/holder)
/datum/artifact_effect/proc/DoEffectPulse(var/atom/holder)
/datum/artifact_effect/proc/UpdateMove()
/datum/artifact_effect/proc/process()
if(chargelevel < chargelevelmax)
chargelevel++
if(activated)
if(effect == EFFECT_AURA)
DoEffectAura()
else if(effect == EFFECT_PULSE && chargelevel >= chargelevelmax)
chargelevel = 0
DoEffectPulse()
//returns 0..1, with 1 being no protection and 0 being fully protected
proc/GetAnomalySusceptibility(var/mob/living/carbon/human/H)
if(!H || !istype(H))
return 1
var/protected = 0
//anomaly suits give best protection, but excavation suits are almost as good
if(istype(H.wear_suit,/obj/item/clothing/suit/bio_suit/anomaly))
protected += 0.6
else if(istype(H.wear_suit,/obj/item/clothing/suit/space/anomaly))
protected += 0.5
if(istype(H.head,/obj/item/clothing/head/bio_hood/anomaly))
protected += 0.3
else if(istype(H.head,/obj/item/clothing/head/helmet/space/anomaly))
protected += 0.2
//latex gloves and science goggles also give a bit of bonus protection
if(istype(H.gloves,/obj/item/clothing/gloves/latex))
protected += 0.1
if(istype(H.glasses,/obj/item/clothing/glasses/science))
protected += 0.1
return 1 - protected

View File

@@ -0,0 +1,23 @@
//inverse of /datum/artifact_effect/heat, the two effects split up for neatness' sake
/datum/artifact_effect/cold
effecttype = "cold"
var/target_temp
/datum/artifact_effect/cold/New()
..()
target_temp = rand(0, 250)
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
effect_type = pick(5,6,7)
/datum/artifact_effect/cold/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.temperature = max(env.temperature - rand(5,50), 0)
/datum/artifact_effect/cold/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.temperature > target_temp)
env.temperature -= pick(0, 0, 1)

View File

@@ -0,0 +1,68 @@
/datum/artifact_effect/badfeeling
effecttype = "badfeeling"
effect_type = 2
var/list/messages = list("You feel worried.",\
"Something doesn't feel right.",\
"You get a strange feeling in your gut.",\
"Your instincts are trying to warn you about something.",\
"Someone just walked over your grave.",\
"There's a strange feeling in the air.",\
"There's a strange smell in the air.",\
"The tips of your fingers feel tingly.",\
"You feel witchy.",\
"You have a terrible sense of foreboding.",\
"You've got a bad feeling about this.",\
"Your scalp prickles.",\
"The light seems to flicker.",\
"The shadows seem to lengthen.",\
"The walls are getting closer.",\
"Something is wrong")
var/list/drastic_messages = list("You've got to get out of here!",\
"Someone's trying to kill you!",\
"There's something out there!",\
"What's happening to you?",\
"OH GOD!",\
"HELP ME!")
/datum/artifact_effect/badfeeling/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(prob(50))
if(prob(75))
H << "<b><font color='red' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
else
H << "<font color='red'>[pick(messages)]</font>"
if(prob(50))
H.dizziness += rand(3,5)
/datum/artifact_effect/badfeeling/DoEffectAura()
if(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
if(prob(5))
if(prob(75))
H << "<font color='red'>[pick(messages)]</font>"
else
H << "<font color='red' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
if(prob(10))
H.dizziness += rand(3,5)
return 1
/datum/artifact_effect/badfeeling/DoEffectPulse()
if(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
if(prob(50))
if(prob(95))
H << "<font color='red' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
else
H << "<font color='red'>[pick(messages)]</font>"
if(prob(50))
H.dizziness += rand(3,5)
else if(prob(25))
H.dizziness += rand(5,15)
return 1

View File

@@ -0,0 +1,40 @@
//todo
/datum/artifact_effect/cellcharge
effecttype = "cellcharge"
effect_type = 3
/datum/artifact_effect/cellcharge/DoEffectTouch(var/mob/user)
if(user)
if(istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
for (var/obj/item/weapon/cell/D in R.contents)
D.charge += rand() * 100 + 50
R << "\blue SYSTEM ALERT: Large energy boost detected!"
return 1
/datum/artifact_effect/cellcharge/DoEffectAura()
if(holder)
for (var/obj/machinery/power/apc/C in range(200, holder))
for (var/obj/item/weapon/cell/B in C.contents)
B.charge += 25
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
S.charge += 25
for (var/mob/living/silicon/robot/M in world)
for (var/obj/item/weapon/cell/D in M.contents)
D.charge += 25
M << "\blue SYSTEM ALERT: Energy boost detected!"
return 1
/datum/artifact_effect/cellcharge/DoEffectPulse()
if(holder)
for (var/obj/machinery/power/apc/C in range(200, holder))
for (var/obj/item/weapon/cell/B in C.contents)
B.charge += rand() * 100
for (var/obj/machinery/power/smes/S in range (src.effectrange,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 += rand() * 100
M << "\blue SYSTEM ALERT: Energy boost detected!"
return 1

View File

@@ -0,0 +1,42 @@
//todo
/datum/artifact_effect/celldrain
effecttype = "celldrain"
effect_type = 3
/datum/artifact_effect/celldrain/DoEffectTouch(var/mob/user)
if(user)
if(istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
for (var/obj/item/weapon/cell/D in R.contents)
D.charge = max(D.charge - rand() * 100, 0)
R << "\blue SYSTEM ALERT: Energy drain detected!"
return 1
return 1
/datum/artifact_effect/celldrain/DoEffectAura()
if(holder)
for (var/obj/machinery/power/apc/C in range(200, holder))
for (var/obj/item/weapon/cell/B in C.contents)
B.charge = max(B.charge - 50,0)
for (var/obj/machinery/power/smes/S in range (src.effectrange,src))
S.charge = max(S.charge - 100,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 - 50,0)
M << "\red SYSTEM ALERT: Energy drain detected!"
return 1
/datum/artifact_effect/celldrain/DoEffectPulse()
if(holder)
for (var/obj/machinery/power/apc/C in range(200, holder))
for (var/obj/item/weapon/cell/B in C.contents)
B.charge = max(B.charge - rand() * 150,0)
for (var/obj/machinery/power/smes/S in range (src.effectrange,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 - rand() * 150,0)
M << "\red SYSTEM ALERT: Energy drain detected!"
return 1

View File

@@ -0,0 +1,66 @@
//todo
/datum/artifact_effect/dnaswitch
effecttype = "dnaswitch"
effect_type = 5
var/severity
/datum/artifact_effect/dnaswitch/New()
..()
if(effect == EFFECT_AURA)
severity = rand(5,30)
else
severity = rand(25,95)
/datum/artifact_effect/dnaswitch/DoEffectTouch(var/mob/toucher)
var/weakness = GetAnomalySusceptibility(toucher)
if(ishuman(toucher) && prob(weakness * 100))
toucher << pick("\green You feel a little different.",\
"\green You feel very strange.",\
"\green Your stomach churns.",\
"\green Your skin feels loose.",\
"\green You feel a stabbing pain in your head.",\
"\green You feel a tingling sensation in your chest.",\
"\green Your entire body vibrates.")
if(prob(75))
scramble(1, toucher, weakness * severity)
else
scramble(0, toucher, weakness * severity)
return 1
/datum/artifact_effect/dnaswitch/DoEffectAura()
if(holder)
for(var/mob/living/carbon/human/H in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(H)
if(prob(weakness * 100))
if(prob(30))
H << pick("\green You feel a little different.",\
"\green You feel very strange.",\
"\green Your stomach churns.",\
"\green Your skin feels loose.",\
"\green You feel a stabbing pain in your head.",\
"\green You feel a tingling sensation in your chest.",\
"\green Your entire body vibrates.")
if(prob(50))
scramble(1, H, weakness * severity)
else
scramble(0, H, weakness * severity)
/datum/artifact_effect/dnaswitch/DoEffectPulse()
if(holder)
for(var/mob/living/carbon/human/H in range(200, holder))
var/weakness = GetAnomalySusceptibility(H)
if(prob(weakness * 100))
if(prob(75))
H << pick("\green You feel a little different.",\
"\green You feel very strange.",\
"\green Your stomach churns.",\
"\green Your skin feels loose.",\
"\green You feel a stabbing pain in your head.",\
"\green You feel a tingling sensation in your chest.",\
"\green Your entire body vibrates.")
if(prob(25))
if(prob(75))
scramble(1, H, weakness * severity)
else
scramble(0, H, weakness * severity)

View File

@@ -0,0 +1,13 @@
/datum/artifact_effect/emp
effecttype = "emp"
effect_type = 3
/datum/artifact_effect/emp/New()
..()
effect = EFFECT_PULSE
/datum/artifact_effect/emp/DoEffectPulse()
if(holder)
empulse(get_turf(holder), effectrange/2, effectrange)
return 1

View File

@@ -0,0 +1,80 @@
/datum/artifact_effect/forcefield
effecttype = "forcefield"
var/list/created_field = list()
effect_type = 4
/datum/artifact_effect/forcefield/New()
..()
trigger = TRIGGER_TOUCH
/datum/artifact_effect/forcefield/ToggleActivate()
..()
if(created_field.len)
for(var/obj/effect/energy_field/F in created_field)
created_field.Remove(F)
del F
else if(holder)
var/turf/T = get_turf(holder)
while(created_field.len < 16)
var/obj/effect/energy_field/E = new (locate(T.x,T.y,T.z))
created_field.Add(E)
E.strength = 1
E.density = 1
E.anchored = 1
E.invisibility = 0
spawn(10)
UpdateMove()
return 1
/datum/artifact_effect/forcefield/process()
..()
for(var/obj/effect/energy_field/E in created_field)
if(E.strength < 1)
E.Strengthen(0.15)
else if(E.strength < 5)
E.Strengthen(0.25)
/datum/artifact_effect/forcefield/UpdateMove()
if(created_field.len && holder)
var/turf/T = get_turf(holder)
while(created_field.len < 16)
//for now, just instantly respawn the fields when they get destroyed
var/obj/effect/energy_field/E = new (locate(T.x,T.y,T))
created_field.Add(E)
E.anchored = 1
E.density = 1
E.invisibility = 0
var/obj/effect/energy_field/E = created_field[1]
E.loc = locate(T.x + 2,T.y + 2,T.z)
E = created_field[2]
E.loc = locate(T.x + 2,T.y + 1,T.z)
E = created_field[3]
E.loc = locate(T.x + 2,T.y,T.z)
E = created_field[4]
E.loc = locate(T.x + 2,T.y - 1,T.z)
E = created_field[5]
E.loc = locate(T.x + 2,T.y - 2,T.z)
E = created_field[6]
E.loc = locate(T.x + 1,T.y + 2,T.z)
E = created_field[7]
E.loc = locate(T.x + 1,T.y - 2,T.z)
E = created_field[8]
E.loc = locate(T.x,T.y + 2,T.z)
E = created_field[9]
E.loc = locate(T.x,T.y - 2,T.z)
E = created_field[10]
E.loc = locate(T.x - 1,T.y + 2,T.z)
E = created_field[11]
E.loc = locate(T.x - 1,T.y - 2,T.z)
E = created_field[12]
E.loc = locate(T.x - 2,T.y + 2,T.z)
E = created_field[13]
E.loc = locate(T.x - 2,T.y + 1,T.z)
E = created_field[14]
E.loc = locate(T.x - 2,T.y,T.z)
E = created_field[15]
E.loc = locate(T.x - 2,T.y - 1,T.z)
E = created_field[16]
E.loc = locate(T.x - 2,T.y - 2,T.z)

View File

@@ -0,0 +1,26 @@
/datum/artifact_effect/gasco2
effecttype = "gasco2"
var/max_pressure
var/target_percentage
/datum/artifact_effect/heat/New()
..()
effect_type = pick(6,7)
/datum/artifact_effect/gasco2/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
max_pressure = rand(115,1000)
/datum/artifact_effect/gasco2/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.carbon_dioxide += rand(2,15)
/datum/artifact_effect/gasco2/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.total_moles < max_pressure)
env.carbon_dioxide += pick(0, 0, 0.1, rand())

View File

@@ -0,0 +1,23 @@
/datum/artifact_effect/gasnitro
effecttype = "gasnitro"
var/max_pressure
var/target_percentage
/datum/artifact_effect/gasnitro/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
effect_type = pick(6,7)
max_pressure = rand(115,1000)
/datum/artifact_effect/gasnitro/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.nitrogen += rand(2,15)
/datum/artifact_effect/gasnitro/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.total_moles < max_pressure)
env.nitrogen += pick(0, 0, 0.1, rand())

View File

@@ -0,0 +1,23 @@
/datum/artifact_effect/gasoxy
effecttype = "gasoxy"
var/max_pressure
/datum/artifact_effect/gasoxy/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
max_pressure = rand(115,1000)
effect_type = pick(6,7)
/datum/artifact_effect/gasoxy/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.oxygen += rand(2,15)
/datum/artifact_effect/gasoxy/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.total_moles < max_pressure)
env.oxygen += pick(0, 0, 0.1, rand())

View File

@@ -0,0 +1,23 @@
/datum/artifact_effect/gasplasma
effecttype = "gasplasma"
var/max_pressure
var/target_percentage
/datum/artifact_effect/gasplasma/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
max_pressure = rand(115,1000)
effect_type = pick(6,7)
/datum/artifact_effect/gasplasma/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.toxins += rand(2,15)
/datum/artifact_effect/gasplasma/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.total_moles < max_pressure)
env.toxins += pick(0, 0, 0.1, rand())

View File

@@ -0,0 +1,31 @@
/datum/artifact_effect/gassleeping
effecttype = "gassleeping"
var/max_pressure
var/target_percentage
/datum/artifact_effect/gassleeping/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
max_pressure = rand(115,1000)
effect_type = pick(6,7)
/datum/artifact_effect/gassleeping/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
var/datum/gas/sleeping_agent/trace_gas = new
env.trace_gases += trace_gas
trace_gas.moles = rand(2,15)
env.update_values()
/datum/artifact_effect/gassleeping/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.total_moles < max_pressure)
var/datum/gas/sleeping_agent/trace_gas = new
env.trace_gases += trace_gas
trace_gas.moles = pick(0, 0, 0.1, rand())
env.update_values()

View File

@@ -0,0 +1,66 @@
/datum/artifact_effect/goodfeeling
effecttype = "goodfeeling"
effect_type = 2
var/list/messages = list("You feel good.",\
"Everything seems to be going alright",\
"You've got a good feeling about this",\
"Your instincts tell you everything is going to be getting better.",\
"There's a good feeling in the air.",\
"Something smells... good.",\
"The tips of your fingers feel tingly.",\
"You've got a good feeling about this.",\
"You feel happy.",\
"You fight the urge to smile.",\
"Your scalp prickles.",\
"All the colours seem a bit more vibrant.",\
"Everything seems a little lighter.",\
"The troubles of the world seem to fade away.")
var/list/drastic_messages = list("You want to hug everyone you meet!",\
"Everything is going so well!",\
"You feel euphoric.",\
"You feel giddy.",\
"You're so happy suddenly, you almost want to dance and sing.",\
"You feel like the world is out to help you.")
/datum/artifact_effect/goodfeeling/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(prob(50))
if(prob(75))
H << "<b><font color='blue' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
else
H << "<font color='blue'>[pick(messages)]</font>"
if(prob(50))
H.dizziness += rand(3,5)
/datum/artifact_effect/goodfeeling/DoEffectAura()
if(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
if(prob(5))
if(prob(75))
H << "<font color='blue'>[pick(messages)]</font>"
else
H << "<font color='blue' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
if(prob(5))
H.dizziness += rand(3,5)
return 1
/datum/artifact_effect/goodfeeling/DoEffectPulse()
if(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
if(prob(50))
if(prob(95))
H << "<font color='blue' size='[num2text(rand(1,5))]'><b>[pick(drastic_messages)]</b></font>"
else
H << "<font color='blue'>[pick(messages)]</font>"
if(prob(50))
H.dizziness += rand(3,5)
else if(prob(25))
H.dizziness += rand(5,15)
return 1

View File

@@ -0,0 +1,63 @@
/datum/artifact_effect/heal
effecttype = "heal"
effect_type = 5
/datum/artifact_effect/heal/DoEffectTouch(var/mob/toucher)
//todo: check over this properly
if(toucher && iscarbon(toucher))
var/weakness = GetAnomalySusceptibility(toucher)
if(prob(weakness * 100))
var/mob/living/carbon/C = toucher
C << "\blue You feel a soothing energy invigorate you."
if(ishuman(toucher))
var/mob/living/carbon/human/H = toucher
for(var/datum/organ/external/affecting in H.organs)
if(affecting && istype(affecting))
affecting.heal_damage(25 * weakness, 25 * weakness)
//H:heal_organ_damage(25, 25)
H.vessel.add_reagent("blood",5)
H.nutrition += 50 * weakness
H.adjustBrainLoss(-25 * weakness)
H.radiation -= min(H.radiation, 25 * weakness)
H.bodytemperature = initial(H.bodytemperature)
spawn(1)
H.fixblood()
//
C.adjustOxyLoss(-25 * weakness)
C.adjustToxLoss(-25 * weakness)
C.adjustBruteLoss(-25 * weakness)
C.adjustFireLoss(-25 * weakness)
//
C.regenerate_icons()
return 1
/datum/artifact_effect/heal/DoEffectAura()
//todo: check over this properly
if(holder)
for (var/mob/living/carbon/C in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(weakness * 100))
if(prob(10))
C << "\blue You feel a soothing energy radiating from something nearby."
C.adjustBruteLoss(-1 * weakness)
C.adjustFireLoss(-1 * weakness)
C.adjustToxLoss(-1 * weakness)
C.adjustOxyLoss(-1 * weakness)
C.adjustBrainLoss(-1 * weakness)
C.updatehealth()
/datum/artifact_effect/heal/DoEffectPulse()
//todo: check over this properly
if(holder)
for (var/mob/living/carbon/C in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(weakness * 100))
C << "\blue A wave of energy invigorates you."
C.adjustBruteLoss(-5 * weakness)
C.adjustFireLoss(-5 * weakness)
C.adjustToxLoss(-5 * weakness)
C.adjustOxyLoss(-5 * weakness)
C.adjustBrainLoss(-5 * weakness)
C.updatehealth()

View File

@@ -0,0 +1,26 @@
//inverse of /datum/artifact_effect/cold, the two effects split up for neatness' sake
/datum/artifact_effect/heat
effecttype = "heat"
var/target_temp
/datum/artifact_effect/heat/New()
..()
effect_type = pick(5,6,7)
/datum/artifact_effect/heat/New()
..()
target_temp = rand(300,600)
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
/datum/artifact_effect/heat/DoEffectTouch(var/mob/user)
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env)
env.temperature += rand(5,50)
/datum/artifact_effect/heat/DoEffectAura()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.temperature < target_temp)
env.temperature += pick(0, 0, 1)

View File

@@ -0,0 +1,47 @@
/datum/artifact_effect/hurt
effecttype = "hurt"
effect_type = 5
/datum/artifact_effect/hurt/DoEffectTouch(var/mob/toucher)
if(toucher)
var/weakness = GetAnomalySusceptibility(toucher)
if(iscarbon(toucher) && prob(weakness * 100))
var/mob/living/carbon/C = toucher
C << "\red A painful discharge of energy strikes you!"
C.adjustOxyLoss(rand(5,25) * weakness)
C.adjustToxLoss(rand(5,25) * weakness)
C.adjustBruteLoss(rand(5,25) * weakness)
C.adjustFireLoss(rand(5,25) * weakness)
C.adjustBrainLoss(rand(5,25) * weakness)
C.radiation += 25 * weakness
C.nutrition -= min(50 * weakness, C.nutrition)
C.make_dizzy(6 * weakness)
C.weakened += 6 * weakness
/datum/artifact_effect/hurt/DoEffectAura()
if(holder)
for (var/mob/living/carbon/C in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(weakness * 100))
if(prob(10))
C << "\red You feel a painful force radiating from something nearby."
C.adjustBruteLoss(1 * weakness)
C.adjustFireLoss(1 * weakness)
C.adjustToxLoss(1 * weakness)
C.adjustOxyLoss(1 * weakness)
C.adjustBrainLoss(1 * weakness)
C.updatehealth()
/datum/artifact_effect/hurt/DoEffectPulse()
if(holder)
for (var/mob/living/carbon/C in range(effectrange, holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(weakness * 100))
C << "\red A wave of painful energy strikes you!"
C.adjustBruteLoss(3 * weakness)
C.adjustFireLoss(3 * weakness)
C.adjustToxLoss(3 * weakness)
C.adjustOxyLoss(3 * weakness)
C.adjustBrainLoss(3 * weakness)
C.updatehealth()

View File

@@ -0,0 +1,29 @@
/datum/artifact_effect/radiate
effecttype = "radiate"
var/radiation_amount
/datum/artifact_effect/radiate/New()
..()
radiation_amount = rand(1, 10)
effect_type = pick(4,5)
/datum/artifact_effect/radiate/DoEffectTouch(var/mob/living/user)
if(user)
user.apply_effect(radiation_amount * 5,IRRADIATE,0)
user.updatehealth()
return 1
/datum/artifact_effect/radiate/DoEffectAura()
if(holder)
for (var/mob/living/M in range(src.effectrange,holder))
M.apply_effect(radiation_amount,IRRADIATE,0)
M.updatehealth()
return 1
/datum/artifact_effect/radiate/DoEffectPulse()
if(holder)
for (var/mob/living/M in range(src.effectrange,holder))
M.apply_effect(radiation_amount * 25,IRRADIATE,0)
M.updatehealth()
return 1

View File

@@ -0,0 +1,35 @@
/datum/artifact_effect/roboheal
effecttype = "roboheal"
/datum/artifact_effect/roboheal/New()
..()
effect_type = pick(3,4)
/datum/artifact_effect/roboheal/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
R << "\blue Your systems report damaged components mending by themselves!"
R.adjustBruteLoss(rand(-10,-30))
R.adjustFireLoss(rand(-10,-30))
return 1
/datum/artifact_effect/roboheal/DoEffectAura()
if(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
if(prob(10))
M << "\blue SYSTEM ALERT: Beneficial energy field detected!"
M.adjustBruteLoss(-1)
M.adjustFireLoss(-1)
M.updatehealth()
return 1
/datum/artifact_effect/roboheal/DoEffectPulse()
if(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
M << "\blue SYSTEM ALERT: Structural damage has been repaired by energy pulse!"
M.adjustBruteLoss(-10)
M.adjustFireLoss(-10)
M.updatehealth()
return 1

View File

@@ -0,0 +1,34 @@
/datum/artifact_effect/robohurt
effecttype = "robohurt"
/datum/artifact_effect/robohurt/New()
..()
effect_type = pick(3,4)
/datum/artifact_effect/robohurt/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
R << "\red Your systems report severe damage has been inflicted!"
R.adjustBruteLoss(rand(10,50))
R.adjustFireLoss(rand(10,50))
return 1
/datum/artifact_effect/robohurt/DoEffectAura()
if(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
if(prob(10)) M << "\red SYSTEM ALERT: Harmful energy field detected!"
M.adjustBruteLoss(1)
M.adjustFireLoss(1)
M.updatehealth()
return 1
/datum/artifact_effect/robohurt/DoEffectPulse()
if(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,holder))
M << "\red SYSTEM ALERT: Structural damage inflicted by energy pulse!"
M.adjustBruteLoss(10)
M.adjustFireLoss(10)
M.updatehealth()
return 1

View File

@@ -0,0 +1,46 @@
//todo
/datum/artifact_effect/sleepy
effecttype = "sleepy"
/datum/artifact_effect/sleepy/New()
..()
effect_type = pick(5,2)
/datum/artifact_effect/sleepy/DoEffectTouch(var/mob/toucher)
if(toucher)
var/weakness = GetAnomalySusceptibility(toucher)
if(ishuman(toucher) && prob(weakness * 100))
var/mob/living/carbon/human/H = toucher
H << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.")
H.drowsyness = min(H.drowsyness + rand(5,25) * weakness, 50 * weakness)
H.eye_blurry = min(H.eye_blurry + rand(1,3) * weakness, 50 * weakness)
return 1
else if(isrobot(toucher))
toucher << "\red SYSTEM ALERT: CPU cycles slowing down."
return 1
/datum/artifact_effect/sleepy/DoEffectAura()
if(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(H)
if(prob(weakness * 100))
if(prob(10))
H << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.")
H.drowsyness = min(H.drowsyness + 1 * weakness, 25 * weakness)
H.eye_blurry = min(H.eye_blurry + 1 * weakness, 25 * weakness)
for (var/mob/living/silicon/robot/R in range(src.effectrange,holder))
R << "\red SYSTEM ALERT: CPU cycles slowing down."
return 1
/datum/artifact_effect/sleepy/DoEffectPulse()
if(holder)
for(var/mob/living/carbon/human/H in range(src.effectrange, holder))
var/weakness = GetAnomalySusceptibility(H)
if(prob(weakness * 100))
H << pick("\blue You feel like taking a nap.","\blue You feel a yawn coming on.","\blue You feel a little tired.")
H.drowsyness = min(H.drowsyness + rand(5,15) * weakness, 50 * weakness)
H.eye_blurry = min(H.eye_blurry + rand(5,15) * weakness, 50 * weakness)
for (var/mob/living/silicon/robot/R in range(src.effectrange,holder))
R << "\red SYSTEM ALERT: CPU cycles slowing down."
return 1

View File

@@ -0,0 +1,41 @@
/datum/artifact_effect/stun
effecttype = "stun"
/datum/artifact_effect/stun/New()
..()
effect_type = pick(2,5)
/datum/artifact_effect/stun/DoEffectTouch(var/mob/toucher)
if(toucher && iscarbon(toucher))
var/mob/living/carbon/C = toucher
var/weakness = GetAnomalySusceptibility(C)
if(prob(weakness * 100))
C << "\red A powerful force overwhelms your consciousness."
C.weakened += 45 * weakness
C.stuttering += 45 * weakness
C.stunned += rand(1,10) * weakness
/datum/artifact_effect/stun/DoEffectAura()
if(holder)
for (var/mob/living/carbon/C in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(10 * weakness))
C << "\red Your body goes numb for a moment."
C.weakened += 2
C.stuttering += 2
if(prob(10))
C.stunned += 1
else if(prob(10))
C << "\red You feel numb."
/datum/artifact_effect/stun/DoEffectPulse()
if(holder)
for (var/mob/living/carbon/C in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(C)
if(prob(100 * weakness))
C << "\red A wave of energy overwhelms your senses!"
C.weakened += 4 * weakness
C.stuttering += 4 * weakness
if(prob(10))
C.stunned += 1 * weakness

View File

@@ -0,0 +1,65 @@
/datum/artifact_effect/teleport
effecttype = "teleport"
effect_type = 6
/datum/artifact_effect/teleport/DoEffectTouch(var/mob/user)
var/weakness = GetAnomalySusceptibility(user)
if(prob(100 * weakness))
var/list/randomturfs = new/list()
for(var/turf/simulated/floor/T in orange(user, 50))
randomturfs.Add(T)
if(randomturfs.len > 0)
user << "\red You are suddenly zapped away elsewhere!"
if (user.buckled)
user.buckled.unbuckle()
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(user))
sparks.start()
user.loc = pick(randomturfs)
sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(user))
sparks.start()
/datum/artifact_effect/teleport/DoEffectAura()
if(holder)
for (var/mob/living/M in range(src.effectrange,holder))
var/weakness = GetAnomalySusceptibility(M)
if(prob(100 * weakness))
var/list/randomturfs = new/list()
for(var/turf/simulated/floor/T in orange(M, 30))
randomturfs.Add(T)
if(randomturfs.len > 0)
M << "\red You are displaced by a strange force!"
if(M.buckled)
M.buckled.unbuckle()
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(M))
sparks.start()
M.loc = pick(randomturfs)
sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(M))
sparks.start()
/datum/artifact_effect/teleport/DoEffectPulse()
if(holder)
for (var/mob/living/M in range(src.effectrange, holder))
var/weakness = GetAnomalySusceptibility(M)
if(prob(100 * weakness))
var/list/randomturfs = new/list()
for(var/turf/simulated/floor/T in orange(M, 15))
randomturfs.Add(T)
if(randomturfs.len > 0)
M << "\red You are displaced by a strange force!"
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(M))
sparks.start()
if(M.buckled)
M.buckled.unbuckle()
M.loc = pick(randomturfs)
sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(M))
sparks.start()

View File

@@ -1,150 +0,0 @@
/obj/machinery/artifact_harvester
name = "Anomaly Power Collector"
icon = 'virology.dmi'
icon_state = "incubator" //incubator_on
anchored = 1
density = 1
var/harvesting = 0
var/obj/item/weapon/anobattery/inserted_battery
var/obj/machinery/artifact/cur_artifact
var/obj/machinery/analyser_pad/owned_pad = null
/obj/machinery/artifact_harvester/New()
..()
spawn(10)
owned_pad = locate() in orange(1, src)
/obj/machinery/artifact_harvester/attackby(var/obj/I as obj, var/mob/user as mob)
if(istype(I,/obj/item/weapon/anobattery))
if(!inserted_battery)
user << "You insert the battery."
user.drop_item()
I.loc = src
src.inserted_battery = I
return
else
return..()
/obj/machinery/artifact_harvester/process()
if(stat & (NOPOWER|BROKEN))
return
use_power(350)
if(harvesting)
use_power(250)
inserted_battery.stored_charge += 10
if(inserted_battery.stored_charge >= inserted_battery.capacity)
inserted_battery.stored_charge = inserted_battery.capacity
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
src.visible_message("<b>[name]</b> states, \"Battery is full.\"")
icon_state = "incubator"
return
/obj/machinery/artifact_harvester/interact(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>Artifact Power Harvester</B><BR>"
dat += "<HR><BR>"
//
if(owned_pad)
if(harvesting)
dat += "Please wait. Harvesting in progress ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%).<br>"
dat += "<A href='?src=\ref[src];stopharvest=1'>Halt early</A><BR>"
else
if(inserted_battery)
dat += "<b>[inserted_battery.name]</b> inserted, charge level: [inserted_battery.stored_charge]/[inserted_battery.capacity] ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%)<BR>"
dat += "<b>Energy signature ID:</b>[inserted_battery.battery_effect.artifact_id == "" ? "???" : "[inserted_battery.battery_effect.artifact_id]"]<BR>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
dat += "<A href='?src=\ref[src];drainbattery=1'>Drain battery of all charge</a><BR>"
dat += "<A href='?src=\ref[src];harvest=1'>Begin harvesting</a><BR>"
else
dat += "No battery inserted.<BR>"
else
dat += "<B><font color=red>Unable to locate analysis pad.</font><BR></b>"
//
dat += "<HR>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</A> <A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artharvester;size=450x500")
onclose(user, "artharvester")
/obj/machinery/artifact_harvester/Topic(href, href_list)
if (href_list["harvest"])
//locate artifact on analysis pad
cur_artifact = null
var/articount = 0
var/obj/machinery/artifact/analysed
for(var/obj/machinery/artifact/A in get_turf(owned_pad))
analysed = A
articount++
var/mundane = 0
for(var/obj/O in get_turf(owned_pad))
if(!istype(O, /obj/machinery/artifact) && !istype(O, /obj/machinery/analyser_pad))
mundane++
break
for(var/mob/O in get_turf(owned_pad))
if(!istype(O, /obj/machinery/artifact))
mundane++
break
if(articount == 1 && !mundane)
cur_artifact = analysed
//check to see if the battery is compatible
if(inserted_battery)
if(inserted_battery.battery_effect.artifact_id == cur_artifact.my_effect.artifact_id || inserted_battery.stored_charge == 0)
harvesting = 1
cur_artifact.anchored = 1
cur_artifact.being_used = 1
icon_state = "incubator_on"
var/message = "<b>[src]</b> states, \"Beginning artifact energy harvesting.\""
src.visible_message(message, message)
//
inserted_battery.battery_effect = cur_artifact.my_effect
else
var/message = "<b>[src]</b> states, \"Cannot harvest. Incompatible energy signatures detected.\""
src.visible_message(message, message)
else if(cur_artifact)
var/message = "<b>[src]</b> states, \"Cannot harvest. No battery inserted.\""
src.visible_message(message, message)
else if(articount > 1 || mundane)
var/message = "<b>[src]</b> states, \"Cannot harvest. Error isolating energy signature.\""
src.visible_message(message, message)
else if(!articount)
var/message = "<b>[src]</b> states, \"Cannot harvest. No noteworthy energy signature isolated.\""
src.visible_message(message, message)
else if (cur_artifact.being_used)
var/message = "<b>[src]</b> states, \"Cannot harvest. Too much interferance from energy scan.\""
src.visible_message(message, message)
if (href_list["stopharvest"])
if(harvesting)
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
src.visible_message("<b>[name]</b> states, \"Harvesting interrupted.\"")
icon_state = "incubator"
if (href_list["ejectbattery"])
src.inserted_battery.loc = src.loc
src.inserted_battery = null
if (href_list["drainbattery"])
use_power(100)
src.inserted_battery.battery_effect.artifact_id = ""
src.inserted_battery.stored_charge = 0
var/message = "<b>[src]</b> states, \"Battery drained of all charge.\""
src.visible_message(message, message)
if(href_list["close"])
usr << browse(null, "window=artharvester")
usr.machine = null
src.updateDialog()
return

View File

@@ -1,67 +0,0 @@
/obj/item/clothing/suit/bio_suit/anomaly
name = "Anomaly Suit"
desc = "A sealed bio suit capable of resisting exotic alien energies and low pressure environments."
icon_state = "engspace_suit"
item_state = "engspace_suit"
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen)
/obj/item/clothing/head/bio_hood/anomaly
name = "Anomaly Hood"
desc = "A sealed bio hood capable of resisting exotic alien energies and low pressure environments."
icon_state = "engspace_helmet"
item_state = "engspace_helmet"
/obj/structure/noticeboard/anomaly/New()
notices = 5
icon_state = "nboard05"
//add some memos
var/obj/item/weapon/paper/P = new()
P.name = "Memo RE: proper analysis procedure"
P.info = "Rose,<br>activate <i>then</i> analyse the anomalies, your results will come so much quicker. Remember to employ basic quasi-elemental forces such as heat, energy, force and various chemical mixes - who knows why those ancient aliens made such obscure activation indices.<br><br>And don't forget your suit this time, I can't afford to have any researchers out of commision for as long as that again!.<br>Ward"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Memo RE: materials gathering"
P.info = "Corasang,<br>the hands-on approach to gathering our samples may very well be slow at times, but it's safer than allowing the blundering miners to roll willy-nilly over our dig sites in their mechs, destroying everything in the process. And don't forget the escavation tools on your way out there!<br>- R.W"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Memo RE: ethical quandaries"
P.info = "Darion-<br><br>I don't care what his rank is, our business is that of science and knowledge - questions of moral application do not come into this. Sure, so there are those who would employ the energy-wave particles my modified device has managed to abscond for their own personal gain, but I can hardly see the practical benefits of some of those things our benefactors left behind. Ward--"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "READ ME! Before you people destroy any more samples"
P.info = "how many times do i have to tell you people, these xeno-arch samples are del-i-cate, and should be handled so! careful application of a focussed, ceoncentrated heat or some corrosive liquids should clear away the extraneous carbon matter, while application of an energy beam will most decidedly destroy it entirely! W, <b>the one who signs your paychecks</b>"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Reminder regarding the anomalous material suits"
P.info = "Do you people think the anomaly suits are cheap to come by? I'm about a hair trigger away from instituting a log book for the damn things. Only wear them if you're going out for a dig, and for god's sake don't go tramping around the station in them unless you're field testing something, R"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
//Anomaly
/area/anomaly
icon_state = "anomaly"
/area/anomaly/hallway
name = "Anomaly Hallway"
/area/anomaly/lab
name = "Anomaly Lab"
/area/anomaly/outpost
name = "Research Outpost"

View File

@@ -1,144 +0,0 @@
/obj/item/weapon/anobattery
name = "Anomaly power battery"
icon = 'anomaly.dmi'
icon_state = "anobattery0"
var/datum/artifact_effect/battery_effect
var/capacity = 200
var/stored_charge = 0
/obj/item/weapon/anobattery/New()
battery_effect = new()
/obj/item/weapon/anobattery/proc/UpdateSprite()
var/p = (stored_charge/capacity)*100
icon_state = "anobattery[round(p,25)]"
/obj/item/weapon/anodevice
name = "Anomaly power utilizer"
icon = 'anomaly.dmi'
icon_state = "anodev"
var/cooldown = 0
var/activated = 0
var/time = 50
var/obj/item/weapon/anobattery/inserted_battery
/obj/item/weapon/anodevice/New()
spawn(10)
pulse()
/obj/item/weapon/anodevice/proc/UpdateSprite()
if(!inserted_battery)
icon_state = "anodev"
return
var/p = (inserted_battery.stored_charge/inserted_battery.capacity)*100
var/s = round(p,25)
icon_state = "anodev[s]"
/obj/item/weapon/anodevice/interact(var/mob/user)
user.machine = src
var/dat = "<b>Anomalous Materials Energy Utiliser</b><br>"
if(activated)
dat += "Device active, stand by.<BR>"
else if(cooldown)
dat += "Cooldown in progress, please wait.<BR>"
else
if(!inserted_battery)
dat += "Please insert battery<BR>"
else
dat += "[inserted_battery] inserted, anomaly ID: [inserted_battery.battery_effect.artifact_id == "" ? "???" : "[inserted_battery.battery_effect.artifact_id]"]<BR>"
dat += "<b>Total Power:</b> [inserted_battery.stored_charge]/[inserted_battery.capacity]<BR><BR>"
dat += "<b>Timed activation:</b> <A href='?src=\ref[src];neg_changetime_max=-100'>--</a> <A href='?src=\ref[src];neg_changetime=-10'>-</a> [time >= 1000 ? "[time/10]" : time >= 100 ? " [time/10]" : " [time/10]" ] <A href='?src=\ref[src];changetime=10'>+</a> <A href='?src=\ref[src];changetime_max=100'>++</a><BR>"
if(cooldown && !activated)
dat += "<font color=red>Cooldown in progress.</font><BR>"
else if(activated)
dat += "<A href='?src=\ref[src];stoptimer=1'>Stop timer</a><BR>"
else
dat += "<A href='?src=\ref[src];starttimer=1'>Start timer</a><BR>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</a><BR>"
dat += "<A href='?src=\ref[src];close=1'>Close</a><BR>"
user << browse(dat, "window=anodevice;size=400x500")
onclose(user, "anodevice")
return
/obj/item/weapon/anodevice/attackby(var/obj/I as obj, var/mob/user as mob)
if(istype(I, /obj/item/weapon/anobattery))
if(!inserted_battery)
user << "\blue You insert the battery."
user.drop_item()
I.loc = src
inserted_battery = I
UpdateSprite()
else
return ..()
/obj/item/weapon/anodevice/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/weapon/anodevice/proc/pulse()
if(activated)
if(time <= 0 || !inserted_battery)
time = 0
activated = 0
var/turf/T = get_turf(src)
T.visible_message("\icon[src]\blue The utiliser device buzzes.", "\icon[src]\blue You hear something buzz.")
else
inserted_battery.battery_effect.DoEffect(src)
time -= 10
inserted_battery.stored_charge -= 10 + rand(-1,1)
cooldown += 10
else if(cooldown > 0)
cooldown -= 10
if(cooldown <= 0)
cooldown = 0
var/turf/T = get_turf(src)
T.visible_message("\icon[src]\blue The utiliser device chimes.", "\icon[src]\blue You hear something chime.")
spawn(10)
pulse()
/obj/item/weapon/anodevice/Topic(href, href_list)
if(href_list["neg_changetime_max"])
time += -100
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["neg_changetime"])
time += -10
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["changetime"])
time += 10
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["changetime_max"])
time += 100
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["stoptimer"])
activated = 0
if(href_list["starttimer"])
activated = 1
if(href_list["ejectbattery"])
inserted_battery.loc = get_turf(src)
inserted_battery = null
UpdateSprite()
if(href_list["close"])
usr << browse(null, "window=anodevice")
usr.machine = null
else if(usr)
src.interact(usr)

View File

@@ -0,0 +1,166 @@
//chemistry stuff here so that it can be easily viewed/modified
datum
reagent
tungsten
name = "Tungsten"
id = "tungsten"
description = "A chemical element, and a strong oxidising agent."
reagent_state = SOLID
color = "#808080" // rgb: 128, 128, 128
//todo: make this silvery grey
lithiumsodiumtungstate
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
description = "A reducing agent for geological compounds."
reagent_state = LIQUID
color = "#808080" // rgb: 128, 128, 128
//todo: make this silvery grey
ground_rock
name = "Ground Rock"
id = "ground_rock"
description = "A fine dust made of ground up rock."
reagent_state = SOLID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this brown
density_separated_sample
name = "Density separated sample"
id = "density_separated_sample"
description = "A watery paste used in chemical analysis, there are some chunks floating in it."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this browny-white
analysis_sample
name = "Analysis liquid"
id = "analysis_sample"
description = "A watery paste used in chemical analysis."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this white
chemical_waste
name = "Chemical Waste"
id = "chemical_waste"
description = "A viscous, toxic liquid left over from many chemical processes."
reagent_state = LIQUID
color = "#C81040" //rgb: 200, 16, 64
//todo: make this fluoro/bright green
datum
chemical_reaction
lithiumsodiumtungstate //LiNa2WO4, not the easiest chem to mix
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
result = "lithiumsodiumtungstate"
required_reagents = list("lithium" = 1, "sodium" = 2, "tungsten" = 1, "oxygen" = 4)
result_amount = 8
density_separated_liquid
name = "Density separated sample"
id = "density_separated_sample"
result = "density_separated_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("ground_rock" = 1, "lithiumsodiumtungstate" = 2)
result_amount = 2
analysis_liquid
name = "Analysis sample"
id = "analysis_sample"
result = "analysis_sample"
secondary_results = list("chemical_waste" = 1)
required_reagents = list("density_separated_sample" = 5)
result_amount = 4
requires_heating = 1
/obj/item/weapon/reagent_containers/glass/solution_tray
name = "solution tray"
desc = "A small, open-topped glass container for delicate research samples. It sports a re-useable strip for labelling with a pen."
icon = 'icons/obj/device.dmi'
icon_state = "solution_tray"
m_amt = 0
g_amt = 5
w_class = 1.0
amount_per_transfer_from_this = 1
possible_transfer_amounts = list(1, 2)
volume = 2
flags = FPRINT | OPENCONTAINER
obj/item/weapon/reagent_containers/glass/solution_tray/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/weapon/pen))
var/new_label = input("What should the new label be?","Label solution tray")
if(new_label)
name = "solution tray ([new_label])"
user << "\blue You write on the label of the solution tray."
else
..(W, user)
/obj/item/weapon/storage/box/solution_trays
name = "solution tray box"
icon_state = "solution_trays"
New()
..()
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
new /obj/item/weapon/reagent_containers/glass/solution_tray( src )
/obj/item/weapon/reagent_containers/glass/beaker/tungsten
name = "beaker 'tungsten'"
New()
..()
reagents.add_reagent("tungsten",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/oxygen
name = "beaker 'oxygen'"
New()
..()
reagents.add_reagent("oxygen",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/sodium
name = "beaker 'sodium'"
New()
..()
reagents.add_reagent("sodium",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/lithium
name = "beaker 'lithium'"
New()
..()
reagents.add_reagent("lithium",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/water
name = "beaker 'water'"
New()
..()
reagents.add_reagent("water",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/water
name = "beaker 'water'"
New()
..()
reagents.add_reagent("water",50)
update_icon()
/obj/item/weapon/reagent_containers/glass/beaker/fuel
name = "beaker 'fuel'"
New()
..()
reagents.add_reagent("fuel",50)
update_icon()

View File

@@ -1,69 +0,0 @@
//device to take core samples from mineral turfs - used for various types of analysis
/obj/item/weapon/storage/samplebag
name = "sample bag"
desc = "A geological sample bag."
icon_state = "evidenceobj"
w_class = 1
max_w_class = 1
max_combined_w_class = 7
storage_slots = 7
//////////////////////////////////////////////////////////////////
/turf/simulated/mineral
var/datum/geosample/geological_data
//////////////////////////////////////////////////////////////////
/obj/item/device/core_sampler
name = "core sampler"
desc = "Used to extract geological core samples."
icon = 'device.dmi'
icon_state = "sampler0"
item_state = "screwdriver_brown"
w_class = 1.0
flags = FPRINT | TABLEPASS
//slot_flags = SLOT_BELT
var/sampled_turf = ""
var/num_stored_bags = 10
var/obj/item/weapon/storage/samplebag/filled_bag
/obj/item/device/core_sampler/attack_hand(var/mob/user)
user << "\blue The core sampler is [sampled_turf ? "full" : "empty"], and has [num_stored_bags] sample bag[num_stored_bags != 1] remaining."
/obj/item/device/core_sampler/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/storage/samplebag))
if(num_stored_bags < 10)
del(W)
num_stored_bags += 1
user << "\blue You insert the sample bag into the core sampler."
else
user << "\red The core sampler can not fit any more sample bags!"
else
return ..()
/obj/item/device/core_sampler/proc/sample_turf(var/turf/simulated/mineral/T, var/mob/user as mob)
if(filled_bag)
user << "\red The core sampler is full!"
else if(num_stored_bags < 1)
user << "\red The core sampler is out of sample bags!"
else
filled_bag = new /obj/item/weapon/storage/samplebag(src)
icon_state = "sampler1"
for(var/i=0, i<7, i++)
var/obj/item/weapon/rocksliver/R = new(filled_bag)
R.source_rock = T.type
R.geological_data = T.geological_data
user << "\blue You take a core sample of the [T]."
/obj/item/device/core_sampler/examine()
if (!( usr ))
return
if(get_dist(src, usr) < 2)
usr << "That's \a [src]."
usr << "\blue Used to extract geological core samples - this one is [sampled_turf ? "full" : "empty"], and has [num_stored_bags] sample bag[num_stored_bags != 1] remaining."
else
return ..()

View File

@@ -1,364 +0,0 @@
//original code and idea from Alfie275 (luna) and ISaidNo (goon) - with thanks
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// samples
/obj/item/weapon/rocksliver
name = "rock sliver"
desc = "It looks extremely delicate."
icon = 'mining.dmi'
icon_state = "sliver0" //0-4
//item_state = "electronic"
var/source_rock = "/turf/simulated/mineral/archaeo"
item_state = ""
var/datum/geosample/geological_data
/obj/item/weapon/rocksliver/New()
icon_state = "sliver[rand(0,4)]"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// strange rocks
/obj/item/weapon/ore/strangerock
var/datum/geosample/geological_data
var/source_rock = "/turf/simulated/mineral"
/obj/item/weapon/ore/strangerock/New()
..()
//var/datum/reagents/r = new/datum/reagents(50)
//src.reagents = r
if(rand(3))
method = 0 // 0 = fire, 1+ = acid
else
method = 0 //currently always fire
// method = 1 //removed due to acid melting strange rocks to gooey grey -Mij
inside = pick(150;"", 50;"/obj/item/weapon/crystal", 25;"/obj/item/weapon/talkingcrystal", "/obj/item/weapon/fossil/base")
/obj/item/weapon/ore/strangerock/bullet_act(var/obj/item/projectile/P)
/obj/item/weapon/ore/strangerock/ex_act(var/severity)
src.visible_message("The [src] crumbles away, leaving some dust and gravel behind.")
/obj/item/weapon/ore/strangerock/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/weldingtool/))
var/obj/item/weapon/weldingtool/w = W
if(w.isOn() && (w.get_fuel() > 3))
if(!src.method) //0 = fire, 1+ = acid
if(inside)
var/obj/A = new src.inside(get_turf(src))
for(var/mob/M in viewers(world.view, user))
M.show_message("\blue The rock burns away revealing a [A.name].",1)
else
for(var/mob/M in viewers(world.view, user))
M.show_message("\blue The rock burns away into nothing.",1)
del src
else
for(var/mob/M in viewers(world.view, user))
M.show_message("\blue A few sparks fly off the rock, but otherwise nothing else happens.",1)
w.remove_fuel(4)
else if(istype(W,/obj/item/device/core_sampler/))
var/obj/item/device/core_sampler/S = W
if(S.filled_bag)
user << "\red The core sampler is full!"
else if(S.num_stored_bags < 1)
user << "\red The core sampler is out of sample bags!"
else
S.filled_bag = new /obj/item/weapon/storage/samplebag(S)
S.icon_state = "sampler1"
for(var/i=0, i<7, i++)
var/obj/item/weapon/rocksliver/R = new /obj/item/weapon/rocksliver(S.filled_bag)
R.source_rock = src.source_rock
R.geological_data = src.geological_data
user << "\blue You take a core sample of the [src]."
else
..()
/*Code does not work, likely due to removal/change of acid_act proc
//Strange rocks currently melt to gooey grey w/ acid application (see reactions)
//will fix when I get a chance to fiddle with it -Mij
/obj/item/weapon/ore/strangerock/acid_act(var/datum/reagent/R)
if(src.method)
if(inside)
var/obj/A = new src.inside(get_turf(src))
for(var/mob/M in viewers(world.view, get_turf(src)))
M.show_message("\blue The rock fizzes away revealing a [A.name].",1)
else
for(var/mob/M in viewers(world.view, get_turf(src)))
M.show_message("\blue The rock fizzes away into nothing.",1)
del src
else
for(var/mob/M in viewers(world.view, get_turf(src)))
M.show_message("\blue The acid splashes harmlessly off the rock, nothing else interesting happens.",1)
return 1
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// crystals
/obj/item/weapon/crystal
name = "Crystal"
icon = 'mining.dmi'
icon_state = "crystal"
/obj/item/weapon/crystal/bullet_act(var/obj/item/projectile/P)
if(istype(P,/obj/item/projectile/beam/emitter))
switch(rand(0,3))
if(0)
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
A.dir = 1
A.yo = 20
A.xo = 0
if(0)
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
A.dir = 2
A.yo = -20
A.xo = 0
if(0)
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
A.dir = 4
A.yo = 0
A.xo = 20
if(0)
var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc )
A.dir = 8
A.yo = 0
A.xo = -20
else
..()
/obj/item/weapon/talkingcrystal
name = "Crystal"
icon = 'mining.dmi'
icon_state = "crystal2"
var/list/list/words = list()
var/lastsaid
/obj/item/weapon/talkingcrystal/New()
spawn(100)
process()
/obj/item/weapon/talkingcrystal/bullet_act(var/obj/item/projectile/P)
if(istype(P,/obj/item/projectile/beam))
switch(rand(0,3))
if(0)
var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
A.dir = pick(alldirs)
A.yo = 20
A.xo = 0
if(0)
var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
A.dir = pick(alldirs)
A.yo = -20
A.xo = 0
if(0)
var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
A.dir = pick(alldirs)
A.yo = 0
A.xo = 20
if(0)
var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc )
A.dir = pick(alldirs)
A.yo = 0
A.xo = -20
var/word = pick("pain","hurt","masochism","sadist","rage","repressed","ouch","evil","void","kill","destroy")
SaySomething(word)
else
..()
/obj/item/weapon/talkingcrystal/proc/catchMessage(var/msg, var/mob/source)
var/list/seperate = list()
if(findtext(msg,"(("))
return
else if(findtext(msg,"))"))
return
else if(findtext(msg," ")==0)
return
else
/*var/l = lentext(msg)
if(findtext(msg," ",l,l+1)==0)
msg+=" "*/
seperate = stringsplit(msg, " ")
var/addressing_crystal = 0
if("crystal" in seperate || "gem" in seperate)
addressing_crystal = 1
for(var/Xa = 1,Xa<seperate.len,Xa++)
var/next = Xa + 1
if(words.len > 20 + rand(10,20))
words.Remove(words[1])
if(!words["[lowertext(seperate[Xa])]"])
words["[lowertext(seperate[Xa])]"] = list()
var/list/w = words["[lowertext(seperate[Xa])]"]
if(w)
w.Add("[lowertext(seperate[next])]")
//world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]"
for(var/mob/O in viewers(src))
O.show_message("\blue The crystal hums for bit then stops...", 1)
if(!rand(0, 5 - addressing_crystal * 3))
spawn(2) SaySomething(pick(seperate))
/obj/item/weapon/talkingcrystal/proc/debug()
//set src in view()
for(var/v in words)
world << "[uppertext(v)]"
var/list/d = words["[v]"]
for(var/X in d)
world << "[X]"
/obj/item/weapon/talkingcrystal/proc/SaySomething(var/word = null)
var/msg
var/limit = rand(max(5,words.len/2))+3
var/text
if(!word)
text = "[pick(words)]"
else
text = pick(stringsplit(word, " "))
if(lentext(text)==1)
text=uppertext(text)
else
var/cap = copytext(text,1,2)
cap = uppertext(cap)
cap += copytext(text,2,lentext(text)+1)
text=cap
var/q = 0
msg+=text
if(msg=="What" | msg == "Who" | msg == "How" | msg == "Why" | msg == "Are")
q=1
text=lowertext(text)
for(var/ya,ya <= limit,ya++)
if(words.Find("[text]"))
var/list/w = words["[text]"]
text=pick(w)
else
text = "[pick(words)]"
msg+=" [text]"
if(q)
msg+="?"
else
if(rand(0,10))
msg+="."
else
msg+="!"
var/list/listening = viewers(src)
for(var/mob/M in world)
if (!M.client)
continue //skip monkeys and leavers
if (istype(M, /mob/new_player))
continue
if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
listening |= M
for(var/mob/M in listening)
M << "<b>The crystal</b> reverberates, \blue\"[msg]\""
lastsaid = world.timeofday + rand(300,800)
/obj/item/weapon/talkingcrystal/process()
if(prob(25) && world.timeofday >= lastsaid && words.len >= 1)
SaySomething()
spawn(100)
process()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// fossils
/obj/item/weapon/fossil
name = "Fossil"
icon = 'fossil.dmi'
icon_state = "bone"
desc = "It's a fossil."
/obj/item/weapon/fossil/base/New()
spawn(0)
var/list/l = list("/obj/item/weapon/fossil/bone"=8,"/obj/item/weapon/fossil/skull"=2,
"/obj/item/weapon/fossil/skull/horned"=2,"/obj/item/weapon/fossil/shell"=1)
var/t = pickweight(l)
new t(src.loc)
del src
/obj/item/weapon/fossil/bone
name = "Fossilised bone"
icon_state = "bone"
desc = "It's a fossilised bone."
/obj/item/weapon/fossil/shell
name = "Fossilised shell"
icon_state = "shell"
desc = "It's a fossilised shell."
/obj/item/weapon/fossil/skull/horned
icon_state = "hskull"
desc = "It's a fossilised, horned skull."
/obj/item/weapon/fossil/skull
name = "Fossilised skull"
icon_state = "skull"
desc = "It's a fossilised skull."
/obj/item/weapon/fossil/skull/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/fossil/bone))
var/obj/o = new /obj/skeleton(get_turf(src))
var/a = new /obj/item/weapon/fossil/bone
var/b = new src.type
o.contents.Add(a)
o.contents.Add(b)
del W
del src
/obj/skeleton
name = "Incomplete skeleton"
icon = 'fossil.dmi'
icon_state = "uskel"
desc = "Incomplete skeleton."
var/bnum = 1
var/breq
var/bstate = 0
/obj/skeleton/New()
src.breq = rand(6)+3
src.desc = "An incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
/obj/skeleton/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/fossil/bone))
if(!bstate)
bnum++
src.contents.Add(new/obj/item/weapon/fossil/bone)
del W
if(bnum==breq)
usr = user
icon_state = "skel"
var/creaturename = input("Input a name for your discovery:","Name your discovery","Spaceosaurus")
src.bstate = 1
src.density = 1
src.name = "[creaturename] skeleton"
if(src.contents.Find(/obj/item/weapon/fossil/skull/horned))
src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull, the plaque reads [creaturename]."
else
src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull, the plaque reads [creaturename]."
else
src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
user << "Looks like it could use [src.breq-src.bnum] more bones."
else
..()
else
..()

View File

@@ -0,0 +1,532 @@
//original code and idea from Alfie275 (luna era) and ISaidNo (goonservers) - with thanks
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Xenoarchaeological finds
/datum/find
var/find_type = 0 //random according to the digsite type
var/excavation_required = 0 //random 5-95%
var/view_range = 20 //how close excavation has to come to show an overlay on the turf
var/clearance_range = 3 //how close excavation has to come to extract the item
//if excavation hits var/excavation_required exactly, it's contained find is extracted cleanly without the ore
var/prob_delicate = 75 //probability it requires an active suspension field to not insta-crumble
var/dissonance_spread = 1 //proportion of the tile that is affected by this find
//used in conjunction with analysis machines to determine correct suspension field type
/datum/find/New(var/digsite, var/exc_req)
excavation_required = exc_req
find_type = get_random_find_type(digsite)
clearance_range = rand(2,6)
dissonance_spread = rand(1500,2500) / 100
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Strange rocks
//have all strange rocks be cleared away using welders for now
/obj/item/weapon/ore/strangerock
name = "Strange rock"
desc = "Seems to have some unusal strata evident throughout it."
icon = 'xenoarchaeology.dmi'
icon_state = "strange"
var/obj/item/weapon/inside
var/method = 0// 0 = fire, 1 = brush, 2 = pick
origin_tech = "materials=5"
/obj/item/weapon/ore/strangerock/New(loc, var/inside_item_type = 0)
..(loc)
//method = rand(0,2)
if(inside_item_type)
inside = new/obj/item/weapon/archaeological_find(src, new_item_type = inside_item_type)
if(!inside)
inside = locate() in contents
/*/obj/item/weapon/ore/strangerock/ex_act(var/severity)
if(severity && prob(30))
src.visible_message("The [src] crumbles away, leaving some dust and gravel behind.")*/
/obj/item/weapon/ore/strangerock/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/weldingtool/))
var/obj/item/weapon/weldingtool/w = W
if(w.isOn())
if(w.get_fuel() >= 4 && !src.method)
if(inside)
inside.loc = src.loc
for(var/mob/M in viewers(world.view, user))
M.show_message("<span class='info'>[src] burns away revealing [inside].</span>",1)
else
for(var/mob/M in viewers(world.view, user))
M.show_message("<span class='info'>[src] burns away into nothing.</span>",1)
del(src)
w.remove_fuel(4)
else
for(var/mob/M in viewers(world.view, user))
M.show_message("<span class='info'>A few sparks fly off [src], but nothing else happens.</span>",1)
w.remove_fuel(1)
return
else if(istype(W,/obj/item/device/core_sampler/))
var/obj/item/device/core_sampler/S = W
S.sample_item(src, user)
return
..()
if(prob(33))
src.visible_message("<span class='warning'>[src] crumbles away, leaving some dust and gravel behind.</span>")
del(src)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Archaeological finds
/obj/item/weapon/archaeological_find
name = "object"
icon = 'xenoarchaeology.dmi'
icon_state = "ano01"
var/find_type = 0
/obj/item/weapon/archaeological_find/New(loc, var/new_item_type)
if(new_item_type)
find_type = new_item_type
else
find_type = rand(1,34) //update this when you add new find types
var/item_type = "object"
icon_state = "unknown[rand(1,4)]"
var/additional_desc = ""
var/obj/item/weapon/new_item
var/source_material = ""
var/apply_material_decorations = 1
var/apply_image_decorations = 0
var/material_descriptor = ""
var/apply_prefix = 1
if(prob(40))
material_descriptor = pick("rusted ","dusty ","archaic ","fragile ")
source_material = pick("cordite","quadrinium","steel","titanium","aluminium","ferritic-alloy","plasteel","duranium")
var/talkative = 0
if(prob(5))
talkative = 1
//for all items here:
//icon_state
//item_state
switch(find_type)
if(1)
item_type = "bowl"
new_item = new /obj/item/weapon/reagent_containers/glass(src.loc)
new_item.icon = 'xenoarchaeology.dmi'
new_item.icon_state = "bowl"
apply_image_decorations = 1
if(prob(20))
additional_desc = "There appear to be [pick("dark","faintly glowing","pungent","bright")] [pick("red","purple","green","blue")] stains inside."
if(2)
item_type = "urn"
new_item = new /obj/item/weapon/reagent_containers/glass(src.loc)
new_item.icon = 'xenoarchaeology.dmi'
new_item.icon_state = "urn"
apply_image_decorations = 1
if(prob(20))
additional_desc = "It [pick("whispers faintly","makes a quiet roaring sound","whistles softly","thrums quietly","throbs")] if you put it to your ear."
if(3)
item_type = "[pick("fork","spoon","knife")]"
if(prob(25))
new_item = new /obj/item/weapon/kitchen/utensil/fork(src.loc)
else if(prob(50))
new_item = new /obj/item/weapon/kitchen/utensil/knife(src.loc)
else
new_item = new /obj/item/weapon/kitchen/utensil/spoon(src.loc)
additional_desc = "[pick("It's like no [item_type] you've ever seen before",\
"It's a mystery how anyone is supposed to eat with this",\
"You wonder what the creator's mouth was shaped like")]."
if(4)
item_type = "statuette"
icon_state = "statuette"
additional_desc = "It depicts a [pick("small","ferocious","wild","pleasing","hulking")] \
[pick("alien figure","rodent-like creature","reptilian alien","primate","unidentifiable object")] \
[pick("performing unspeakable acts","posing heroically","in a feotal position","cheering","sobbing","making a plaintive gesture","making a rude gesture")]."
if(5)
item_type = "instrument"
icon_state = "instrument"
if(prob(30))
apply_image_decorations = 1
additional_desc = "[pick("You're not sure how anyone could have played this",\
"You wonder how many mouths the creator had",\
"You wonder what it sounds like",\
"You wonder what kind of music was made with it")]."
if(6)
item_type = "[pick("bladed knife","serrated blade","sharp cutting implement")]"
new_item = new /obj/item/weapon/kitchenknife(src.loc)
additional_desc = "[pick("It doesn't look safe.",\
"It looks wickedly jagged",\
"There appear to be [pick("dark red","dark purple","dark green","dark blue")] stains along the edges")]."
if(7)
//assuming there are 10 types of coins
var/chance = 10
for(var/type in typesof(/obj/item/weapon/coin))
if(prob(chance))
new_item = new type(src.loc)
break
chance += 10
item_type = new_item.name
apply_prefix = 0
apply_material_decorations = 0
apply_image_decorations = 1
if(8)
item_type = "handcuffs"
new_item = new /obj/item/weapon/handcuffs(src.loc)
additional_desc = "[pick("They appear to be for securing two things together","Looks kinky","Doesn't seem like a children's toy")]."
if(9)
item_type = "[pick("wicked","evil","byzantine","dangerous")] looking [pick("device","contraption","thing","trap")]"
apply_prefix = 0
new_item = new /obj/item/weapon/legcuffs/beartrap(src.loc)
additional_desc = "[pick("It looks like it could take a limb off",\
"Could be some kind of animal trap",\
"There appear to be [pick("dark red","dark purple","dark green","dark blue")] stains along part of it")]."
if(10)
item_type = "[pick("cylinder","tank","chamber")]"
new_item = new /obj/item/weapon/lighter(src.loc)
additional_desc = "There is a tiny device attached."
if(prob(30))
apply_image_decorations = 1
if(11)
item_type = "box"
new_item = new /obj/item/weapon/storage/box(src.loc)
new_item.icon = 'xenoarchaeology.dmi'
new_item.icon_state = "box"
if(prob(30))
apply_image_decorations = 1
if(12)
item_type = "[pick("cylinder","tank","chamber")]"
if(prob(25))
new_item = new /obj/item/weapon/tank/air(src.loc)
else if(prob(50))
new_item = new /obj/item/weapon/tank/anesthetic(src.loc)
else
new_item = new /obj/item/weapon/tank/plasma(src.loc)
icon_state = pick("oxygen","oxygen_fr","oxygen_f","plasma","anesthetic")
additional_desc = "It [pick("gloops","sloshes")] slightly when you shake it."
if(13)
item_type = "tool"
if(prob(25))
new_item = new /obj/item/weapon/wrench(src.loc)
else if(prob(25))
new_item = new /obj/item/weapon/crowbar(src.loc)
else
new_item = new /obj/item/weapon/screwdriver(src.loc)
additional_desc = "[pick("It doesn't look safe.",\
"You wonder what it was used for",\
"There appear to be [pick("dark red","dark purple","dark green","dark blue")] stains on it")]."
if(14)
apply_material_decorations = 0
var/list/possible_spawns = list()
possible_spawns += /obj/item/stack/sheet/metal
possible_spawns += /obj/item/stack/sheet/plasteel
possible_spawns += /obj/item/stack/sheet/glass
possible_spawns += /obj/item/stack/sheet/rglass
possible_spawns += /obj/item/stack/sheet/mineral/plasma
possible_spawns += /obj/item/stack/sheet/mineral/mythril
possible_spawns += /obj/item/stack/sheet/mineral/gold
possible_spawns += /obj/item/stack/sheet/mineral/silver
possible_spawns += /obj/item/stack/sheet/mineral/enruranium
possible_spawns += /obj/item/stack/sheet/mineral/sandstone
possible_spawns += /obj/item/stack/sheet/mineral/silver
var/new_type = pick(possible_spawns)
new_item = new new_type(src.loc)
new_item:amount = rand(5,45)
if(15)
if(prob(75))
new_item = new /obj/item/weapon/pen(src.loc)
else
new_item = new /obj/item/weapon/pen/sleepypen(src.loc)
if(prob(30))
apply_image_decorations = 1
if(16)
apply_prefix = 0
if(prob(25))
item_type = "smooth green crystal"
icon_state = "Green lump"
else if(prob(33))
item_type = "irregular purple crystal"
icon_state = "Phazon"
else if(prob(50))
item_type = "rough red crystal"
icon_state = "changerock"
else
item_type = "smooth red crystal"
icon_state = "ore"
additional_desc = pick("It shines faintly as it catches the light.","It appears to have a faint inner glow.","It seems to draw you inward as you look it at.","Something twinkles faintly as you look at it.","It's mesmerizing to behold.")
apply_material_decorations = 0
if(prob(10))
apply_image_decorations = 1
if(17)
//cultblade
apply_prefix = 0
new_item = new /obj/item/weapon/melee/cultblade(src.loc)
apply_material_decorations = 0
apply_image_decorations = 0
if(18)
new_item = new /obj/item/device/radio/beacon(src.loc)
talkative = 0
new_item.icon_state = "unknown[rand(1,4)]"
new_item.icon = 'xenoarchaeology.dmi'
new_item.desc = ""
if(19)
apply_prefix = 0
new_item = new /obj/item/weapon/claymore(src.loc)
item_type = new_item.name
if(20)
//arcane clothing
apply_prefix = 0
var/list/possible_spawns = list(/obj/item/clothing/head/culthood,
/obj/item/clothing/head/magus,
/obj/item/clothing/head/culthood/alt,
/obj/item/clothing/head/helmet/space/cult)
var/new_type = pick(possible_spawns)
new_item = new new_type(src.loc)
if(21)
//soulstone
apply_prefix = 0
new_item = new /obj/item/device/soulstone(src.loc)
item_type = new_item.name
apply_material_decorations = 0
if(22)
if(prob(50))
new_item = new /obj/item/weapon/shard(src.loc)
else
new_item = new /obj/item/weapon/shard/plasma(src.loc)
apply_prefix = 0
apply_image_decorations = 0
apply_material_decorations = 0
if(23)
apply_prefix = 0
new_item = new /obj/item/stack/rods(src.loc)
apply_image_decorations = 0
apply_material_decorations = 0
if(24)
var/list/possible_spawns = typesof(/obj/item/weapon/stock_parts)
possible_spawns -= /obj/item/weapon/stock_parts
possible_spawns -= /obj/item/weapon/stock_parts/subspace
var/new_type = pick(possible_spawns)
new_item = new new_type(src.loc)
item_type = new_item.name
apply_material_decorations = 0
if(25)
apply_prefix = 0
new_item = new /obj/item/weapon/katana(src.loc)
item_type = new_item.name
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)]"
//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)
//revolver
var/obj/item/weapon/gun/projectile/new_gun = new /obj/item/weapon/gun/projectile(src.loc)
new_item = new_gun
new_item.icon_state = "gun[rand(1,4)]"
//33% chance to be able to reload the gun with human ammunition
if(prob(66))
new_gun.caliber = "999"
//33% chance to fill it with a random amount of bullets
new_gun.max_shells = rand(1,12)
if(prob(33))
var/num_bullets = rand(1,new_gun.max_shells)
if(num_bullets < new_gun.loaded.len)
for(var/i = num_bullets, i <= new_gun.loaded.len, i++)
new_gun.loaded += new new_gun.ammo_type(src)
else
for(var/obj/item/I in new_gun)
if(new_gun.loaded.len > num_bullets)
if(I in new_gun.loaded)
new_gun.loaded.Remove(I)
I.loc = null
else
break
else
for(var/obj/item/I in new_gun)
if(I in new_gun.loaded)
new_gun.loaded.Remove(I)
I.loc = null
item_type = "gun"
if(28)
//completely unknown alien device
if(prob(50))
apply_image_decorations = 0
if(29)
//fossil bone/skull
//new_item = new /obj/item/weapon/fossil/base(src.loc)
//the replacement item propogation isn't working, and it's messy code anyway so just do it here
var/list/candidates = list("/obj/item/weapon/fossil/bone"=9,"/obj/item/weapon/fossil/skull"=3,
"/obj/item/weapon/fossil/skull/horned"=2)
var/spawn_type = pickweight(candidates)
new_item = new spawn_type(src.loc)
apply_prefix = 0
additional_desc = "A fossilised part of an alien, long dead."
apply_image_decorations = 0
apply_material_decorations = 0
if(30)
//fossil shell
new_item = new /obj/item/weapon/fossil/shell(src.loc)
apply_prefix = 0
additional_desc = "A fossilised, pre-Stygian alien crustacean."
apply_image_decorations = 0
apply_material_decorations = 0
if(prob(10))
apply_image_decorations = 1
if(31)
//fossil plant
new_item = new /obj/item/weapon/fossil/plant(src.loc)
item_type = new_item.name
additional_desc = "A fossilised shred of alien plant matter."
apply_image_decorations = 0
apply_material_decorations = 0
apply_prefix = 0
if(32)
//humanoid remains
apply_prefix = 0
item_type = "humanoid [pick("remains","skeleton")]"
icon = 'blood.dmi'
icon_state = "remains"
additional_desc = pick("They appear almost human.",\
"They are contorted in a most gruesome way.",\
"They look almost peaceful.",\
"The bones are yellowing and old, but remarkably well preserved.",\
"The bones are scored by numerous burns and partially melted.",\
"The are battered and broken, in some cases less than splinters are left.",\
"The mouth is wide open in a death rictus, the victim would appear to have died screaming.")
apply_image_decorations = 0
apply_material_decorations = 0
if(33)
//robot remains
apply_prefix = 0
item_type = "[pick("mechanical","robotic","cyborg")] [pick("remains","chassis","debris")]"
icon = 'blood.dmi'
icon_state = "remainsrobot"
additional_desc = pick("Almost mistakeable for the remains of a modern cyborg.",\
"They are barely recognisable as anything other than a pile of waste metals.",\
"It looks like the battered remains of an ancient robot chassis.",\
"The chassis is rusting and old, but remarkably well preserved.",\
"The chassis is scored by numerous burns and partially melted.",\
"The chassis is battered and broken, in some cases only chunks of metal are left.",\
"A pile of wires and crap metal that looks vaguely robotic.")
apply_image_decorations = 0
apply_material_decorations = 0
if(34)
//xenos remains
apply_prefix = 0
item_type = "alien [pick("remains","skeleton")]"
icon = 'blood.dmi'
icon_state = "remainsxeno"
additional_desc = pick("It looks vaguely reptilian, but with more teeth.",\
"They are faintly unsettling.",\
"There is a faint aura of unease about them.",\
"The bones are yellowing and old, but remarkably well preserved.",\
"The bones are scored by numerous burns and partially melted.",\
"The are battered and broken, in some cases less than splinters are left.",\
"This creature would have been twisted and monstrous when it was alive.",\
"It doesn't look human.")
apply_image_decorations = 0
apply_material_decorations = 0
var/decorations = ""
if(apply_material_decorations)
source_material = pick("cordite","quadrinium","steel","titanium","aluminium","ferritic-alloy","plasteel","duranium")
desc = "A [material_descriptor ? "[material_descriptor] " : ""][item_type] made of [source_material], all craftsmanship is of [pick("the lowest","low","average","high","the highest")] quality."
var/list/descriptors = list()
if(prob(30))
descriptors.Add("is encrusted with [pick("","synthetic ","multi-faceted ","uncut ","sparkling ") + pick("rubies","emeralds","diamonds","opals","lapiz lazuli")]")
if(prob(30))
descriptors.Add("is studded with [pick("gold","silver","aluminium","titanium")]")
if(prob(30))
descriptors.Add("is encircled with bands of [pick("quadrinium","cordite","ferritic-alloy","plasteel","duranium")]")
if(prob(30))
descriptors.Add("menaces with spikes of [pick("solid plasma","uranium","white pearl","black steel")]")
if(descriptors.len > 0)
decorations = "It "
for(var/index=1, index <= descriptors.len, index++)
if(index > 1)
if(index == descriptors.len)
decorations += " and "
else
decorations += ", "
decorations += descriptors[index]
decorations += "."
if(decorations)
desc += " " + decorations
var/engravings = ""
if(apply_image_decorations)
engravings = "[pick("Engraved","Carved","Etched")] on the item is [pick("an image of","a frieze of","a depiction of")] \
[pick("an alien humanoid","an amorphic blob","a short, hairy being","a rodent-like creature","a robot","a primate","a reptilian alien","an unidentifiable object","a statue","a starship","unusual devices","a structure")] \
[pick("surrounded by","being held aloft by","being struck by","being examined by","communicating with")] \
[pick("alien humanoids","amorphic blobs","short, hairy beings","rodent-like creatures","robots","primates","reptilian aliens")]"
if(prob(50))
engravings += ", [pick("they seem to be enjoying themselves","they seem extremely angry","they look pensive","they are making gestures of supplication","the scene is one of subtle horror","the scene conveys a sense of desperation","the scene is completely bizarre")]"
engravings += "."
if(desc)
desc += " "
desc += engravings
if(apply_prefix)
name = "[pick("Strange","Ancient","Alien","")] [item_type]"
else
name = item_type
if(desc)
desc += " "
desc += additional_desc
if(!desc)
desc = "This item is completely [pick("alien","bizarre")]."
//icon and icon_state should have already been set
if(new_item)
new_item.name = name
new_item.desc = src.desc
if(talkative)
new_item.listening_to_players = 1
if(prob(25))
new_item.speaking_to_players = 1
processing_objects.Add(src)
var/turf/T = get_turf(src)
if(istype(T, /turf/simulated/mineral))
T:last_find = new_item
del(src)
else if(talkative)
listening_to_players = 1
if(prob(25))
speaking_to_players = 1
processing_objects.Add(src)

View File

@@ -0,0 +1,249 @@
#define ARCHAEO_BOWL 1
#define ARCHAEO_URN 2
#define ARCHAEO_CUTLERY 3
#define ARCHAEO_STATUETTE 4
#define ARCHAEO_INSTRUMENT 5
#define ARCHAEO_KNIFE 6
#define ARCHAEO_COIN 7
#define ARCHAEO_HANDCUFFS 8
#define ARCHAEO_BEARTRAP 9
#define ARCHAEO_LIGHTER 10
#define ARCHAEO_BOX 11
#define ARCHAEO_GASTANK 12
#define ARCHAEO_TOOL 13
#define ARCHAEO_METAL 14
#define ARCHAEO_PEN 15
#define ARCHAEO_CRYSTAL 16
#define ARCHAEO_CULTBLADE 17
#define ARCHAEO_TELEBEACON 18
#define ARCHAEO_CLAYMORE 19
#define ARCHAEO_CULTROBES 20
#define ARCHAEO_SOULSTONE 21
#define ARCHAEO_SHARD 22
#define ARCHAEO_RODS 23
#define ARCHAEO_STOCKPARTS 24
#define ARCHAEO_KATANA 25
#define ARCHAEO_LASER 26
#define ARCHAEO_GUN 27
#define ARCHAEO_UNKNOWN 28
#define ARCHAEO_FOSSIL 29
#define ARCHAEO_SHELL 30
#define ARCHAEO_PLANT 31
#define ARCHAEO_REMAINS_HUMANOID 32
#define ARCHAEO_REMAINS_ROBOT 33
#define ARCHAEO_REMAINS_XENO 34
#define MAX_ARCHAEO 34
//eggs
//droppings
//footprints
//alien clothing
//DNA sampling from fossils, or a new archaeo type specifically for it?
//descending order of likeliness to spawn
#define DIGSITE_GARDEN 1
#define DIGSITE_ANIMAL 2
#define DIGSITE_HOUSE 3
#define DIGSITE_TECHNICAL 4
#define DIGSITE_TEMPLE 5
#define DIGSITE_WAR 6
/proc/get_responsive_reagent(var/find_type)
switch(find_type)
if(ARCHAEO_BOWL)
return "mercury"
if(ARCHAEO_URN)
return "mercury"
if(ARCHAEO_CUTLERY)
return "mercury"
if(ARCHAEO_STATUETTE)
return "mercury"
if(ARCHAEO_INSTRUMENT)
return "mercury"
if(ARCHAEO_COIN)
return "iron"
if(ARCHAEO_KNIFE)
return "iron"
if(ARCHAEO_HANDCUFFS)
return "mercury"
if(ARCHAEO_BEARTRAP)
return "mercury"
if(ARCHAEO_LIGHTER)
return "mercury"
if(ARCHAEO_BOX)
return "mercury"
if(ARCHAEO_GASTANK)
return "mercury"
if(ARCHAEO_TOOL)
return "iron"
if(ARCHAEO_METAL)
return "iron"
if(ARCHAEO_PEN)
return "mercury"
if(ARCHAEO_CRYSTAL)
return "nitrogen"
if(ARCHAEO_CULTBLADE)
return "potassium"
if(ARCHAEO_TELEBEACON)
return "potassium"
if(ARCHAEO_CLAYMORE)
return "iron"
if(ARCHAEO_CULTROBES)
return "potassium"
if(ARCHAEO_SOULSTONE)
return "nitrogen"
if(ARCHAEO_SHARD)
return "nitrogen"
if(ARCHAEO_RODS)
return "iron"
if(ARCHAEO_STOCKPARTS)
return "potassium"
if(ARCHAEO_KATANA)
return "iron"
if(ARCHAEO_LASER)
return "iron"
if(ARCHAEO_GUN)
return "iron"
if(ARCHAEO_UNKNOWN)
return "mercury"
if(ARCHAEO_FOSSIL)
return "carbon"
if(ARCHAEO_SHELL)
return "carbon"
if(ARCHAEO_PLANT)
return "carbon"
if(ARCHAEO_REMAINS_HUMANOID)
return "carbon"
if(ARCHAEO_REMAINS_ROBOT)
return "carbon"
if(ARCHAEO_REMAINS_XENO)
return "carbon"
return "plasma"
//see /turf/simulated/mineral/New() in code/modules/mining/mine_turfs.dm
/proc/get_random_digsite_type()
return pick(100;DIGSITE_GARDEN,95;DIGSITE_ANIMAL,90;DIGSITE_HOUSE,85;DIGSITE_TECHNICAL,80;DIGSITE_TEMPLE,75;DIGSITE_WAR)
/proc/get_random_find_type(var/digsite)
var/find_type = 0
switch(digsite)
if(DIGSITE_GARDEN)
find_type = pick(\
100;ARCHAEO_PLANT,\
25;ARCHAEO_SHELL,\
25;ARCHAEO_FOSSIL,\
5;ARCHAEO_BEARTRAP\
)
if(DIGSITE_ANIMAL)
find_type = pick(\
100;ARCHAEO_FOSSIL,\
50;ARCHAEO_SHELL,\
50;ARCHAEO_PLANT,\
25;ARCHAEO_BEARTRAP\
)
if(DIGSITE_HOUSE)
find_type = pick(\
100;ARCHAEO_BOWL,\
100;ARCHAEO_URN,\
100;ARCHAEO_CUTLERY,\
100;ARCHAEO_STATUETTE,\
100;ARCHAEO_INSTRUMENT,\
100;ARCHAEO_PEN,\
100;ARCHAEO_LIGHTER,\
100;ARCHAEO_BOX,\
75;ARCHAEO_COIN,\
75;ARCHAEO_UNKNOWN,\
50;ARCHAEO_SHARD,\
50;ARCHAEO_RODS,\
25;ARCHAEO_METAL\
)
if(DIGSITE_TECHNICAL)
find_type = pick(\
100;ARCHAEO_METAL,\
100;ARCHAEO_GASTANK,\
100;ARCHAEO_TELEBEACON,\
100;ARCHAEO_TOOL,\
100;ARCHAEO_STOCKPARTS,\
75;ARCHAEO_SHARD,\
75;ARCHAEO_RODS,\
75;ARCHAEO_UNKNOWN,\
50;ARCHAEO_HANDCUFFS,\
50;ARCHAEO_BEARTRAP,\
)
if(DIGSITE_TEMPLE)
find_type = pick(\
200;ARCHAEO_CULTROBES,\
100;ARCHAEO_URN,\
100;ARCHAEO_BOWL,\
100;ARCHAEO_KNIFE,\
100;ARCHAEO_CRYSTAL,\
75;ARCHAEO_CULTBLADE,\
50;ARCHAEO_SOULSTONE,\
50;ARCHAEO_UNKNOWN,\
25;ARCHAEO_HANDCUFFS,\
25;ARCHAEO_BEARTRAP,\
10;ARCHAEO_KATANA,\
10;ARCHAEO_CLAYMORE,\
10;ARCHAEO_SHARD,\
10;ARCHAEO_RODS,\
10;ARCHAEO_METAL\
)
if(DIGSITE_WAR)
find_type = pick(\
100;ARCHAEO_GUN,\
100;ARCHAEO_KNIFE,\
75;ARCHAEO_LASER,\
75;ARCHAEO_KATANA,\
75;ARCHAEO_CLAYMORE,\
50;ARCHAEO_UNKNOWN,\
50;ARCHAEO_CULTROBES,\
50;ARCHAEO_CULTBLADE,\
25;ARCHAEO_HANDCUFFS,\
25;ARCHAEO_BEARTRAP,\
25;ARCHAEO_TOOL\
)
return find_type
#undef ARCHAEO_BOWL
#undef ARCHAEO_URN
#undef ARCHAEO_CUTLERY
#undef ARCHAEO_STATUETTE
#undef ARCHAEO_INSTRUMENT
#undef ARCHAEO_KNIFE
#undef ARCHAEO_COIN
#undef ARCHAEO_HANDCUFFS
#undef ARCHAEO_BEARTRAP
#undef ARCHAEO_LIGHTER
#undef ARCHAEO_BOX
#undef ARCHAEO_GASTANK
#undef ARCHAEO_TOOL
#undef ARCHAEO_METAL
#undef ARCHAEO_PEN
#undef ARCHAEO_CRYSTAL
#undef ARCHAEO_CULTBLADE
#undef ARCHAEO_TELEBEACON
#undef ARCHAEO_CLAYMORE
#undef ARCHAEO_CULTROBES
#undef ARCHAEO_SOULSTONE
#undef ARCHAEO_SHARD
#undef ARCHAEO_RODS
#undef ARCHAEO_STOCKPARTS
#undef ARCHAEO_KATANA
#undef ARCHAEO_LASER
#undef ARCHAEO_GUN
#undef ARCHAEO_UNKNOWN
#undef ARCHAEO_FOSSIL
#undef ARCHAEO_SHELL
#undef ARCHAEO_PLANT
#undef ARCHAEO_REMAINS_HUMANOID
#undef ARCHAEO_REMAINS_ROBOT
#undef ARCHAEO_REMAINS_XENO
#undef DIGSITE_GARDEN
#undef DIGSITE_ANIMAL
#undef DIGSITE_HOUSE
#undef DIGSITE_TECHNICAL
#undef DIGSITE_TEMPLE
#undef DIGSITE_WAR

View File

@@ -0,0 +1,102 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// fossils
/obj/item/weapon/fossil
name = "Fossil"
icon = 'xenoarchaeology.dmi'
icon_state = "bone"
desc = "It's a fossil."
/obj/item/weapon/fossil/base/New()
var/list/l = list("/obj/item/weapon/fossil/bone"=9,"/obj/item/weapon/fossil/skull"=3,
"/obj/item/weapon/fossil/skull/horned"=2)
var/t = pickweight(l)
var/obj/item/weapon/W = new t(src.loc)
var/turf/T = get_turf(src)
if(istype(T, /turf/simulated/mineral))
T:last_find = W
del src
/obj/item/weapon/fossil/bone
name = "Fossilised bone"
icon_state = "bone"
desc = "It's a fossilised bone."
/obj/item/weapon/fossil/skull
name = "Fossilised skull"
icon_state = "skull"
desc = "It's a fossilised skull."
/obj/item/weapon/fossil/skull/horned
icon_state = "hskull"
desc = "It's a fossilised, horned skull."
/obj/item/weapon/fossil/skull/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/fossil/bone))
var/obj/o = new /obj/skeleton(get_turf(src))
var/a = new /obj/item/weapon/fossil/bone
var/b = new src.type
o.contents.Add(a)
o.contents.Add(b)
del W
del src
/obj/skeleton
name = "Incomplete skeleton"
icon = 'xenoarchaeology.dmi'
icon_state = "uskel"
desc = "Incomplete skeleton."
var/bnum = 1
var/breq
var/bstate = 0
var/plaque_contents = "Unnamed alien creature"
/obj/skeleton/New()
src.breq = rand(6)+3
src.desc = "An incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
/obj/skeleton/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/fossil/bone))
if(!bstate)
bnum++
src.contents.Add(new/obj/item/weapon/fossil/bone)
del W
if(bnum==breq)
usr = user
icon_state = "skel"
src.bstate = 1
src.density = 1
src.name = "alien skeleton display"
if(src.contents.Find(/obj/item/weapon/fossil/skull/horned))
src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull. The plaque reads \'[plaque_contents]\'."
else
src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull. The plaque reads \'[plaque_contents]\'."
else
src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones."
user << "Looks like it could use [src.breq-src.bnum] more bones."
else
..()
else if(istype(W,/obj/item/weapon/pen))
plaque_contents = input("What would you like to write on the plaque:","Skeleton plaque","")
user.visible_message("[user] writes something on the base of [src].","You relabel the plaque on the base of \icon[src] [src].")
if(src.contents.Find(/obj/item/weapon/fossil/skull/horned))
src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull. The plaque reads \'[plaque_contents]\'."
else
src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull. The plaque reads \'[plaque_contents]\'."
else
..()
//shells and plants do not make skeletons
/obj/item/weapon/fossil/shell
name = "Fossilised shell"
icon_state = "shell"
desc = "It's a fossilised shell."
/obj/item/weapon/fossil/plant
name = "Fossilised plant"
icon_state = "plant1"
desc = "It's fossilised plant remains."
/obj/item/weapon/fossil/plant/New()
icon_state = "plant[rand(1,4)]"

View File

@@ -0,0 +1,69 @@
/obj/item/weapon/shard/plasma
name = "plasma shard"
icon_state = "plasmalarge"
/obj/item/weapon/shard/plasma/New()
src.icon_state = pick("plasmalarge", "plasmamedium", "plasmasmall")
switch(src.icon_state)
if("plasmasmall")
src.pixel_x = rand(-12, 12)
src.pixel_y = rand(-12, 12)
if("plasmamedium")
src.pixel_x = rand(-8, 8)
src.pixel_y = rand(-8, 8)
if("plasmalarge")
src.pixel_x = rand(-5, 5)
src.pixel_y = rand(-5, 5)
else
return
/obj/item/weapon/shard/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if ( istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0, user))
var/obj/item/stack/sheet/mineral/plasma/NG = new (user.loc)
for (var/obj/item/stack/sheet/mineral/plasma/G in user.loc)
if(G==NG)
continue
if(G.amount>=G.max_amount)
continue
G.attackby(NG, user)
usr << "You add the newly-formed plasma to the stack. It now contains [NG.amount] sheets."
//SN src = null
del(src)
return
return ..()
//legacy crystal
/obj/machinery/crystal
name = "Crystal"
icon = 'mining.dmi'
icon_state = "crystal"
/obj/machinery/crystal/New()
if(prob(50))
icon_state = "crystal2"
//large finds
/*
/obj/machinery/syndicate_beacon
/obj/machinery/wish_granter
if(18)
item_type = "jagged green crystal"
additional_desc = pick("It shines faintly as it catches the light.","It appears to have a faint inner glow.","It seems to draw you inward as you look it at.","Something twinkles faintly as you look at it.","It's mesmerizing to behold.")
icon_state = "crystal"
apply_material_decorations = 0
if(prob(10))
apply_image_decorations = 1
if(19)
item_type = "jagged pink crystal"
additional_desc = pick("It shines faintly as it catches the light.","It appears to have a faint inner glow.","It seems to draw you inward as you look it at.","Something twinkles faintly as you look at it.","It's mesmerizing to behold.")
icon_state = "crystal2"
apply_material_decorations = 0
if(prob(10))
apply_image_decorations = 1
*/
//machinery type artifacts?

View File

@@ -0,0 +1,109 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Formerly talking crystals - these procs are now modular so that you can make any /obj/item/weapon 'parrot' player speech back to them
// This could be extended to atoms, but it's bad enough as is
// I genuinely tried to Add and Remove them from var and proc lists, but just couldn't get it working
/obj/item/weapon
var/list/heard_words = list()
var/lastsaid
var/listening_to_players = 0
var/speaking_to_players = 0
/obj/item/weapon/process()
if(!speaking_to_players)
processing_objects.Remove(src)
return
if(prob(10) && world.timeofday >= lastsaid && heard_words.len >= 1)
SaySomething()
/obj/item/weapon/proc/catchMessage(var/msg, var/mob/source)
if(speaking_to_players)
var/list/seperate = list()
if(findtext(msg,"(("))
return
else if(findtext(msg,"))"))
return
else if(findtext(msg," ")==0)
return
else
/*var/l = lentext(msg)
if(findtext(msg," ",l,l+1)==0)
msg+=" "*/
seperate = stringsplit(msg, " ")
for(var/Xa = 1,Xa<seperate.len,Xa++)
var/next = Xa + 1
if(heard_words.len > 20 + rand(10,20))
heard_words.Remove(heard_words[1])
if(!heard_words["[lowertext(seperate[Xa])]"])
heard_words["[lowertext(seperate[Xa])]"] = list()
var/list/w = heard_words["[lowertext(seperate[Xa])]"]
if(w)
w.Add("[lowertext(seperate[next])]")
//world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]"
if(!rand(0, 5))
spawn(2) SaySomething(pick(seperate))
if(prob(30))
for(var/mob/O in viewers(src))
O.show_message("\blue [src] hums for bit then stops...", 1)
/*/obj/item/weapon/talkingcrystal/proc/debug()
//set src in view()
for(var/v in heard_words)
world << "[uppertext(v)]"
var/list/d = heard_words["[v]"]
for(var/X in d)
world << "[X]"*/
/obj/item/weapon/proc/SaySomething(var/word = null)
var/msg
var/limit = rand(max(5,heard_words.len/2))+3
var/text
if(!word)
text = "[pick(heard_words)]"
else
text = pick(stringsplit(word, " "))
if(lentext(text)==1)
text=uppertext(text)
else
var/cap = copytext(text,1,2)
cap = uppertext(cap)
cap += copytext(text,2,lentext(text)+1)
text=cap
var/q = 0
msg+=text
if(msg=="What" | msg == "Who" | msg == "How" | msg == "Why" | msg == "Are")
q=1
text=lowertext(text)
for(var/ya,ya <= limit,ya++)
if(heard_words.Find("[text]"))
var/list/w = heard_words["[text]"]
text=pick(w)
else
text = "[pick(heard_words)]"
msg+=" [text]"
if(q)
msg+="?"
else
if(rand(0,10))
msg+="."
else
msg+="!"
var/list/listening = viewers(src)
for(var/mob/M in world)
if (!M.client)
continue //skip monkeys and leavers
if (istype(M, /mob/new_player))
continue
if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
listening|=M
for(var/mob/M in listening)
M << "<b>[src]</b> reverberates, \blue\"[msg]\""
lastsaid = world.timeofday + rand(300,800)

View File

@@ -1,42 +1,167 @@
/*
#define FIND_PLANT 1
#define FIND_BIO 2
#define FIND_METEORIC 3
#define FIND_ICE 4
#define FIND_CRYSTALLINE 5
#define FIND_METALLIC 6
#define FIND_IGNEOUS 7
#define FIND_METAMORPHIC 8
#define FIND_SEDIMENTARY 9
#define FIND_NOTHING 10
*/
datum/geosample
var/scrambled = 0 //if this sample has been mixed with other samples
//
var/age_thousand = 1 //age can correspond to different artifacts
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rock sliver
/obj/item/weapon/rocksliver
name = "rock sliver"
desc = "It looks extremely delicate."
icon = 'xenoarchaeology.dmi'
icon_state = "sliver1" //0-4
w_class = 1
//item_state = "electronic"
var/source_rock = "/turf/simulated/mineral/"
var/datum/geosample/geological_data
/obj/item/weapon/rocksliver/New()
icon_state = "sliver[rand(1,3)]"
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
/datum/geosample
var/age = 0 //age can correspond to different archaeological finds
var/age_thousand = 0
var/age_million = 0
var/age_billion = 0
var/artifact_id = "" //id of a nearby artifact, if there is one
var/artifact_strength = 0 //proportional to distance
var/responsive_reagent = "" ///each reagent corresponds to a different type of find
var/reagent_response = "" //likelihood of there being finds there
var/artifact_distance = -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
var/list/find_presence = list()
/datum/geosample/New(var/turf/simulated/mineral/container)
datum/geosample/New(var/turf/simulated/mineral/container)
UpdateTurf(container)
//this function should only be called once. it's here just in case
datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container)
src = null
//this should only need to be called once
/datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container)
if(!container || !istype(container))
return
age = rand(1,999)
total_spread = 0
switch(container.mineralName)
if("Uranium")
age_million = rand(1, 704)
age_thousand = rand(1,999)
find_presence["potassium"] = rand(1,1000) / 100
source_mineral = "potassium"
if("Iron")
age_thousand = rand(1, 999)
age_million = rand(1, 999)
find_presence["iron"] = rand(1,1000) / 100
source_mineral = "iron"
if("Diamond")
age_thousand = rand(1,999)
age_million = rand(1,999)
find_presence["nitrogen"] = rand(1,1000) / 100
source_mineral = "nitrogen"
if("Gold")
age_thousand = rand(1,999)
age_million = rand(1,999)
age_billion = rand(3,4)
find_presence["iron"] = rand(1,1000) / 100
source_mineral = "iron"
if("Silver")
age_thousand = rand(1,999)
age_million = rand(1,999)
find_presence["iron"] = rand(1,1000) / 100
source_mineral = "iron"
if("Plasma")
age_thousand = rand(1,999)
age_million = rand(1,999)
age_billion = rand(10, 13)
if("Archaeo")
//snowflake
age_thousand = rand(1,999)
find_presence["plasma"] = rand(1,1000) / 100
source_mineral = "plasma"
if("Clown")
age = rand(-1,-999) //thats the joke
age_thousand = rand(-1,-999)
find_presence["plasma"] = rand(1,1000) / 100
source_mineral = "plasma"
if(prob(75))
find_presence["phosphorus"] = rand(1,500) / 100
if(prob(25))
find_presence["mercury"] = rand(1,500) / 100
find_presence["chlorine"] = rand(500,2500) / 100
//loop over finds, grab any relevant stuff
for(var/datum/find/F in container.finds)
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]
//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)
if(!container || !istype(container))
return
if(container.artifact_find)
artifact_distance = rand()
artifact_id = container.artifact_find.artifact_id
else
for(var/turf/simulated/mineral/holder in artifact_spawning_turfs)
if(holder.artifact_find)
var/dist = get_dist(container, holder)
if(dist < holder.artifact_find.artifact_detect_range && dist < src.artifact_distance)
src.artifact_distance = dist
src.artifact_id = holder.artifact_find.artifact_id
else
artifact_spawning_turfs.Remove(holder)
/*
#undef FIND_PLANT
#undef FIND_BIO
#undef FIND_METEORIC
#undef FIND_ICE
#undef FIND_CRYSTALLINE
#undef FIND_METALLIC
#undef FIND_IGNEOUS
#undef FIND_METAMORPHIC
#undef FIND_SEDIMENTARY
#undef FIND_NOTHING
*/

View File

@@ -0,0 +1,45 @@
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/accuracy = GetResultSpecifity(scanned_sample, carrier_name)
accuracy += 0.5 * (1 - accuracy) / scanned_sample.total_spread
if(!accuracy)
accuracy = rand(0.01, 0.5)
results = "Kinetic acceleration of carrier ([carrier_name]) indicates age ([100 * accuracy]% accuracy): <br><br>"
if(scanned_sample.age_billion)
var/displayed_age_millions = scanned_sample.age_million + max(scanned_sample.age_million * ((1 - accuracy) * (2 * rand() - 1)), 0)
var/displayed_age_billions = scanned_sample.age_billion + max(scanned_sample.age_billion * ((1 - accuracy) * (2 * rand() - 1)), 0)
results += "[displayed_age_billions + displayed_age_millions / 1000] billion years.<br>"
else if(scanned_sample.age_million)
var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age_thousand * ((1 - accuracy) * (4 * rand() - 2)), 0)
var/displayed_age_millions = scanned_sample.age_million + max(scanned_sample.age_million * ((1 - accuracy) * (2 * rand() - 1)), 0)
results += "[displayed_age_millions + displayed_age_thousands / 1000] million years.<br>"
else if(scanned_sample.age_thousand)
var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - accuracy) * (8 * rand() - 4)), 0)
var/displayed_age_thousands = scanned_sample.age_thousand + max(scanned_sample.age * ((1 - accuracy) * (4 * rand() - 2)), 0)
results += "[displayed_age_thousands + displayed_age / 1000] thousand years.<br>"
else
var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - accuracy) * (8 * rand() - 4)), 0)
results += "[displayed_age] years.<br>"
results += "<br>Warning, results only valid for ages on the scale of billions of years."
return results

View File

@@ -0,0 +1,171 @@
/obj/machinery/anomaly
name = "Analysis machine"
desc = "A specialised, complex analysis machine."
anchored = 1
density = 1
icon = 'icons/obj/virology.dmi'
icon_state = "analyser"
//
var/obj/item/weapon/reagent_containers/glass/held_container
var/obj/item/weapon/tank/fuel_container
var/target_scan_ticks = 60
var/report_num = 0
var/scan_process = 0
var/heat_accumulation_rate = 1
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
/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()
//heat up as we go, but if the air is freezing then heat up much slower
var/new_heat = heat_accumulation_rate + heat_accumulation_rate * rand(-5,5) / 10
temperature += new_heat
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)
else if(temperature > environmental_temp)
//cool down to match the air
temperature -= heat_accumulation_rate + heat_accumulation_rate * rand(-5,5) / 10
if(temperature < environmental_temp)
temperature = environmental_temp
if(prob(5))
src.visible_message("\blue \icon[src] hisses softly.", 2)
else if(temperature < environmental_temp)
//heat up to match the air
temperature += heat_accumulation_rate + rand(-5,5) / 10
if(temperature > environmental_temp)
temperature = environmental_temp
else
if(prob(5))
src.visible_message("\blue \icon[src] plinks quietly.", 2)
//warm up the lab slightly
if(env.temperature < temperature)
env.temperature += (temperature - env.temperature) * 0.1
//this proc should be overriden by each individual machine
/obj/machinery/anomaly/attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.machine = src
var/dat = "<B>[src.name]</B><BR>"
dat += "Module heat level: [temperature] kelvin<br>"
dat += "Safeties set at 300k, shielding failure at 400k. Failure to maintain safe heat levels may result in equipment damage.<br>"
dat += "<hr>"
if(scan_process)
dat += "Scan in progress<br><br><br>"
else
dat += "[held_container ? "<A href='?src=\ref[src];eject_beaker=1'>Eject beaker</a>" : "No beaker inserted."]<br>"
dat += "[fuel_container ? "<A href='?src=\ref[src];eject_fuel=1'>Eject fuel tank</a>" : "No fuel tank inserted."]<br>"
dat += "[held_container ? "<A href='?src=\ref[src];begin=1'>Begin scanning</a>" : ""]"
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</a><BR>"
dat += "<A href='?src=\ref[src];close=1'>Close</a><BR>"
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 = "<b>[src] analysis report #[report_num]</b><br><br>" + 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 >= 300)
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

View File

@@ -0,0 +1,37 @@
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/accuracy = GetResultSpecifity(scanned_sample, carrier)
var/distance = scanned_sample.artifact_distance
if(distance > 0)
if(prob(accuracy))
distance += (2 * rand() - 1) * distance * 0.05
accuracy = 0.95 + 0.05 * (2 * rand() - 1)
else
var/offset = 1 - accuracy
distance += (2 * rand() - 1) * distance * offset
results = "Fourier transform analysis on anomalous energy absorption through carrier ([carrier]) indicates source located inside emission radius ([100 * accuracy]% accuracy): [distance]."
else
results = "Energy dispersion detected throughout sample consistent with background readings.<br>"
if(carrier == scanned_sample.source_mineral)
results += "Warning, analysis may be contaminated by high quantities of molecular carrier present throughout sample."
return results

View File

@@ -0,0 +1,40 @@
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 = 0.15
if(carrier)
specifity = GetResultSpecifity(scanned_sample, carrier)
results = "Chromatography partitioning analysis over carrier ([carrier]) indicates the following elements present ([110 * (specifity / (specifity + 0.1))]% accuracy):<br><br>"
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( 110 * (specifity / (specifity + 0.1)) ))
results += " - " + finds_as_strings[index] + "<br>"
num_found++
if(!num_found)
results = "Chromatography partitioning results over carrier ([carrier]) to determine elemental makeup were inconclusive.<br>"
if(!carrier)
results += "<br>No carrier detected, scan accuracy affected.<br>"
return results

View File

@@ -0,0 +1,51 @@
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]):<br>"
if(specifity <= 0.25)
results += "<img src=\"http://i.imgur.com/TAQHn.jpg\"></img><br>"
else if(specifity <= 0.5)
results += "<img src=\"http://i.imgur.com/EwOZ7.jpg\"></img><br>"
else if(specifity <= 0.75)
results += "<img src=\"http://i.imgur.com/1qCae.jpg\"></img><br>"
else
results += "<img src=\"http://i.imgur.com/9T9nc.jpg\"></img><br>"
results += "<br>"
if(scanned_sample.artifact_id)
results += "Detected energy signatures [100 * (1 - specifity)]% consistent with standard background readings.<br>"
if(prob( (specifity + 0.5 * (1 - specifity)) * 100))
results += "Anomalous exotic energy signature isolated: <font color='red'><b>[scanned_sample.artifact_id].</b></font>"
else
results += "Detected energy signatures [95 + 5 * (2 * rand() - 1) * (1 - specifity)]% consistent with standard background readings."
return results

View File

@@ -0,0 +1,45 @@
obj/machinery/anomaly/ion_mobility
name = "Ion Mobility Spectrometer"
desc = "A specialised, complex analysis machine."
icon = '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:<br><br>"
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]<br>"
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]%<br>"
found++
*/
if(!found)
results = "Kinetic analysis on sample's ionic residue in carrier ([carrier]) to determine composition were inconclusive.<br>"
if(carrier == scanned_sample.source_mineral)
results += "Warning, analysis may be contaminated by high quantities of molecular carrier present throughout sample."
return results

View File

@@ -0,0 +1,49 @@
obj/machinery/anomaly/isotope_ratio
name = "Isotope ratio spectrometer"
desc = "A specialised, complex analysis machine."
icon = '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): <br><br>"
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.<br>"
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.<br>"
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.<br>"
else
var/displayed_age = scanned_sample.age + max(scanned_sample.age * ((1 - accuracy) * (2 * rand() - 1)), 0)
results += "[displayed_age] years.<br>"
results += "<br>Warning, results only valid up to ages of one billion years."
return results

View File

@@ -0,0 +1,251 @@
/obj/machinery/artifact_analyser
name = "Anomaly Analyser"
desc = "Studies the emissions of anomalous materials to discover their uses."
icon = 'icons/obj/virology.dmi'
icon_state = "isolator"
anchored = 1
density = 1
var/scan_in_progress = 0
var/scan_num = 0
var/obj/scanned_obj
var/obj/machinery/artifact_scanpad/owned_scanner = null
var/scan_completion_time = 0
var/scan_duration = 120
var/obj/scanned_object
var/report_num = 0
/obj/machinery/artifact_analyser/New()
..()
reconnect_scanner()
/obj/machinery/artifact_analyser/proc/reconnect_scanner()
//connect to a nearby scanner pad
owned_scanner = locate(/obj/machinery/artifact_scanpad) in get_step(src, dir)
if(!owned_scanner)
owned_scanner = locate(/obj/machinery/artifact_scanpad) in orange(1, src)
/obj/machinery/artifact_analyser/attack_hand(var/mob/user as mob)
src.add_fingerprint(user)
interact(user)
/obj/machinery/artifact_analyser/interact(mob/user)
if(stat & (NOPOWER|BROKEN) || get_dist(src, user) > 1)
user.unset_machine(src)
return
var/dat = "<B>Anomalous material analyser</B><BR>"
dat += "<HR>"
if(!owned_scanner)
owned_scanner = locate() in orange(1, src)
if(!owned_scanner)
dat += "<b><font color=red>Unable to locate analysis pad.</font></b><br>"
else if(scan_in_progress)
dat += "Please wait. Analysis in progress.<br>"
dat += "<a href='?src=\ref[src];halt_scan=1'>Halt scanning.</a><br>"
else
dat += "Scanner is ready.<br>"
dat += "<a href='?src=\ref[src];begin_scan=1'>Begin scanning.</a><br>"
dat += "<br>"
dat += "<hr>"
dat += "<a href='?src=\ref[src]'>Refresh</a> <a href='?src=\ref[src];close=1'>Close</a>"
user << browse(dat, "window=artanalyser;size=450x500")
user.set_machine(src)
onclose(user, "artanalyser")
/obj/machinery/artifact_analyser/process()
if(scan_in_progress && world.time > scan_completion_time)
//finish scanning
scan_in_progress = 0
updateDialog()
//print results
var/results = ""
if(!owned_scanner)
reconnect_scanner()
if(!owned_scanner)
results = "Error communicating with scanner."
else if(!scanned_object || scanned_object.loc != owned_scanner.loc)
results = "Unable to locate scanned object. Ensure it was not moved in the process."
else
results = get_scan_info(scanned_object)
src.visible_message("<b>[name]</b> states, \"Scanning complete.\"")
var/obj/item/weapon/paper/P = new(src.loc)
P.name = "[src] report #[++report_num]"
P.info = "<b>[src] analysis report #[report_num]</b><br>"
P.info += "<br>"
P.info += "\icon[scanned_object] [results]"
P.stamped = list(/obj/item/weapon/stamp)
P.overlays = list("paper_stamped")
if(scanned_object && istype(scanned_object, /obj/machinery/artifact))
var/obj/machinery/artifact/A = scanned_object
A.anchored = 0
A.being_used = 0
/obj/machinery/artifact_analyser/Topic(href, href_list)
if(href_list["begin_scan"])
if(!owned_scanner)
reconnect_scanner()
if(owned_scanner)
var/artifact_in_use = 0
for(var/obj/O in owned_scanner.loc)
if(O == owned_scanner)
continue
if(O.invisibility)
continue
if(istype(scanned_object, /obj/machinery/artifact))
var/obj/machinery/artifact/A = scanned_object
if(A.being_used)
artifact_in_use = 1
else
A.anchored = 1
A.being_used = 1
if(artifact_in_use)
src.visible_message("<b>[name]</b> states, \"Cannot harvest. Too much interference.\"")
else
scanned_object = O
scan_in_progress = 1
scan_completion_time = world.time + scan_duration
src.visible_message("<b>[name]</b> states, \"Scanning begun.\"")
break
if(!scanned_object)
src.visible_message("<b>[name]</b> states, \"Unable to isolate scan target.\"")
if(href_list["halt_scan"])
scan_in_progress = 0
src.visible_message("<b>[name]</b> states, \"Scanning halted.\"")
if(href_list["close"])
usr.unset_machine(src)
usr << browse(null, "window=artanalyser")
..()
updateDialog()
//hardcoded responses, oh well
/obj/machinery/artifact_analyser/proc/get_scan_info(var/obj/scanned_obj)
switch(scanned_obj.type)
if(/obj/machinery/auto_cloner)
return "Automated cloning pod - appears to rely on organic nanomachines with a self perpetuating \
ecosystem involving self cannibalism and a symbiotic relationship with the contained liquid.<br><br>\
Structure is composed of a carbo-titanium alloy with interlaced reinforcing energy fields, and the contained liquid \
resembles proto-plasmic residue supportive of single cellular developmental conditions."
if(/obj/machinery/power/supermatter)
return "Super dense plasma clump - Appears to have been shaped or hewn, structure is composed of matter 2000% denser than ordinary carbon matter residue.\
Potential application as unrefined plasma source."
if(/obj/machinery/power/supermatter)
return "Super dense plasma clump - Appears to have been shaped or hewn, structure is composed of matter 2000% denser than ordinary carbon matter residue.\
Potential application as unrefined plasma source."
if(/obj/structure/constructshell)
return "Tribal idol - Item resembles statues/emblems built by superstitious pre-warp civilisations to honour their gods. Material appears to be a \
rock/plastcrete composite."
if(/obj/machinery/giga_drill)
return "Automated mining drill - structure composed of titanium-carbide alloy, with tip and drill lines edged in an alloy of diamond and plasma."
if(/obj/structure/cult/pylon)
return "Tribal pylon - Item resembles statues/emblems built by cargo cult civilisations to honour energy systems from post-warp civilisations."
if(/obj/mecha/working/hoverpod)
return "Vacuum capable repair pod - Item is a remarkably intact single man repair craft capable of flight in a vacuum. Outer shell composed of primarily \
post-warp hull alloys, with internal wiring and circuitry consistent with modern electronics and engineering."
if(/obj/machinery/replicator)
return "Automated construction unit - Item appears to be able to synthesize synthetic items, some with simple internal circuitry. Method unknown, \
phasing suggested?"
if(/obj/structure/crystal)
return "Crystal formation - Pseudo organic crystalline matrix, unlikely to have formed naturally. No known technology exists to synthesize this exact composition."
if(/obj/machinery/artifact)
//the fun one
var/obj/machinery/artifact/A = scanned_obj
var/out = "Anomalous alien device - Composed of an unknown alloy, "
//primary effect
if(A.my_effect)
//what kind of effect the artifact has
switch(A.my_effect.effect_type)
if(1)
out += "concentrated energy emissions"
if(2)
out += "intermittent psionic wavefront"
if(3)
out += "electromagnetic energy"
if(4)
out += "high frequency particles"
if(5)
out += "organically reactive exotic particles"
if(6)
out += "interdimensional/bluespace? phasing"
if(7)
out += "atomic synthesis"
else
out += "low level energy emissions"
out += " have been detected "
//how the artifact does it's effect
switch(A.my_effect.effect_type)
if(1)
out += " emitting in an ambient energy field."
if(2)
out += " emitting in periodic bursts."
else
out += " interspersed throughout substructure and shell."
if(A.my_effect.trigger >= 0 && A.my_effect.trigger <= 4)
out += " Activation index involves physical interaction with artifact surface."
else if(A.my_effect.trigger >= 5 && A.my_effect.trigger <= 8)
out += " Activation index involves energetic interaction with artifact surface."
else if(A.my_effect.trigger >= 9 && A.my_effect.trigger <= 12)
out += " Activation index involves precise local atmospheric conditions."
else
out += " Unable to determine any data about activation trigger."
//secondary:
if(A.secondary_effect && A.secondary_effect.activated)
//sciencey words go!
out += "<br><br>Warning, internal scans indicate ongoing [pick("subluminous","subcutaneous","superstructural")] activity operating \
independantly from primary systems. Auxiliary activity involves "
//what kind of effect the artifact has
switch(A.secondary_effect.effect_type)
if(1)
out += "concentrated energy emissions"
if(2)
out += "intermittent psionic wavefront"
if(3)
out += "electromagnetic energy"
if(4)
out += "high frequency particles"
if(5)
out += "organically reactive exotic particles"
if(6)
out += "interdimensional/bluespace? phasing"
if(7)
out += "atomic synthesis"
else
out += "low level radiation"
//how the artifact does it's effect
switch(A.secondary_effect.effect_type)
if(1)
out += " emitting in an ambient energy field."
if(2)
out += " emitting in periodic bursts."
else
out += " interspersed throughout substructure and shell."
if(A.secondary_effect.trigger >= 0 && A.secondary_effect.trigger <= 4)
out += " Activation index involves physical interaction with artifact surface, but subsystems indicate \
anomalous interference with standard attempts at triggering."
else if(A.secondary_effect.trigger >= 5 && A.secondary_effect.trigger <= 8)
out += " Activation index involves energetic interaction with artifact surface, but subsystems indicate \
anomalous interference with standard attempts at triggering."
else if(A.secondary_effect.trigger >= 9 && A.secondary_effect.trigger <= 12)
out += " Activation index involves precise local atmospheric conditions, but subsystems indicate \
anomalous interference with standard attempts at triggering."
else
out += " Unable to determine any data about activation trigger."
return out
else
//it was an ordinary item
return "[scanned_obj.name] - Mundane application, composed of carbo-ferritic alloy composite."

View File

@@ -1,318 +1,318 @@
//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 = '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 = "<B>Artifact Analyser</B><BR>"
dat += "<HR><BR>"
if(!owned_pad)
dat += "<B><font color=red>Unable to locate analysis pad.</font><BR></b>"
dat += "<HR><BR>"
else if (!src.working)
dat += "<B>Artifact ID:</B> [cur_id]<BR>"
dat += "<B>Artifact Origin:</B> [aorigin] ([accuO]%)<BR>"
dat += "<B>Activation Trigger:</B> [atrigger] ([accuT]%)<BR>"
dat += "<B>Artifact Function:</B> [aeffect1] ([accuE1]%)<BR>"
dat += "<B>Artifact Range:</B> [aeffect2] ([accuE2]%)<BR><BR>"
dat += "<HR><BR>"
dat += "Artifact ID is determined from unique energy emission signatures.<br>"
dat += "<A href='?src=\ref[src];analyse=1'>Analyse Artifact (Scan number #[scan_num+1])</a><BR>"
dat += "<A href='?src=\ref[src];upload=1'>Upload/update artifact scan</a><BR>"
dat += "<A href='?src=\ref[src];print=1'>Print Page</a><BR>"
else
dat += "<B>Please wait. Analysis in progress.</B><BR>"
dat += "<HR><BR>"
//
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
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 = "<b>[src]</b> 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 = "<b>[src]</b> 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 = "<b>[src]</b> states, \"Analysis complete.\""
src.visible_message(message, message)
use_power(500)
else if (findarti > 1)
var/message = "<b>[src]</b> states, \"Cannot analyse. Error isolating energy signature.\""
src.visible_message(message, message)
else
var/message = "<b>[src]</b> 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])<hr>"
r += "<B>Artifact ID:</B> [cur_id] (determined from unique energy emission signatures)<BR>"
r += "<B>Artifact Origin:</B> [aorigin] ([accuO]%)<BR>"
r += "<B>Activation Trigger:</B> [atrigger] ([accuT]%)<BR>"
r += "<B>Artifact Function:</B> [aeffect1] ([accuE1]%)<BR>"
r += "<B>Artifact Range:</B> [aeffect2] ([accuE2]%)<BR><BR>"
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 = '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*/
//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 = '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 = "<B>Artifact Analyser</B><BR>"
dat += "<HR><BR>"
if(!owned_pad)
dat += "<B><font color=red>Unable to locate analysis pad.</font><BR></b>"
dat += "<HR><BR>"
else if (!src.working)
dat += "<B>Artifact ID:</B> [cur_id]<BR>"
dat += "<B>Artifact Origin:</B> [aorigin] ([accuO]%)<BR>"
dat += "<B>Activation Trigger:</B> [atrigger] ([accuT]%)<BR>"
dat += "<B>Artifact Function:</B> [aeffect1] ([accuE1]%)<BR>"
dat += "<B>Artifact Range:</B> [aeffect2] ([accuE2]%)<BR><BR>"
dat += "<HR><BR>"
dat += "Artifact ID is determined from unique energy emission signatures.<br>"
dat += "<A href='?src=\ref[src];analyse=1'>Analyse Artifact (Scan number #[scan_num+1])</a><BR>"
dat += "<A href='?src=\ref[src];upload=1'>Upload/update artifact scan</a><BR>"
dat += "<A href='?src=\ref[src];print=1'>Print Page</a><BR>"
else
dat += "<B>Please wait. Analysis in progress.</B><BR>"
dat += "<HR><BR>"
//
dat += "<A href='?src=\ref[src];close=1'>Close<BR>"
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 = "<b>[src]</b> 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 = "<b>[src]</b> 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 = "<b>[src]</b> states, \"Analysis complete.\""
src.visible_message(message, message)
use_power(500)
else if (findarti > 1)
var/message = "<b>[src]</b> states, \"Cannot analyse. Error isolating energy signature.\""
src.visible_message(message, message)
else
var/message = "<b>[src]</b> 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])<hr>"
r += "<B>Artifact ID:</B> [cur_id] (determined from unique energy emission signatures)<BR>"
r += "<B>Artifact Origin:</B> [aorigin] ([accuO]%)<BR>"
r += "<B>Activation Trigger:</B> [atrigger] ([accuT]%)<BR>"
r += "<B>Artifact Function:</B> [aeffect1] ([accuE1]%)<BR>"
r += "<B>Artifact Range:</B> [aeffect2] ([accuE2]%)<BR><BR>"
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 = '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*/

View File

@@ -1,58 +1,58 @@
/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 = "<B>Artifact Database</B><BR>"
t += "<hr>"
for(var/datum/catalogued_artifact/CA in catalogued_artifacts)
t += "<B>Artifact ID:</B> [CA.display_id] (determined from unique energy emission signatures)<BR>"
t += "<B>Artifact Origin:</B> [CA.origin]<BR>"
t += "<B>Activation Trigger:</B> [CA.trigger]<BR>"
t += "<B>Artifact Function:</B> [CA.effecttype]<BR>"
t += "<B>Artifact Range:</B> [CA.effectmode]<BR><BR>"
t += "<hr>"
t += "<A href='?src=\ref[src];refresh=1'>Refresh</A> <A href='?src=\ref[src];close=1'>Close</A><BR>"
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
/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 = "<B>Artifact Database</B><BR>"
t += "<hr>"
for(var/datum/catalogued_artifact/CA in catalogued_artifacts)
t += "<B>Artifact ID:</B> [CA.display_id] (determined from unique energy emission signatures)<BR>"
t += "<B>Artifact Origin:</B> [CA.origin]<BR>"
t += "<B>Activation Trigger:</B> [CA.trigger]<BR>"
t += "<B>Artifact Function:</B> [CA.effecttype]<BR>"
t += "<B>Artifact Range:</B> [CA.effectmode]<BR><BR>"
t += "<hr>"
t += "<A href='?src=\ref[src];refresh=1'>Refresh</A> <A href='?src=\ref[src];close=1'>Close</A><BR>"
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
*/

View File

@@ -0,0 +1,227 @@
/obj/machinery/artifact_harvester
name = "Exotic Particle Harvester"
icon = 'virology.dmi'
icon_state = "incubator" //incubator_on
anchored = 1
density = 1
idle_power_usage = 50
active_power_usage = 750
use_power = 1
var/harvesting = 0
var/obj/item/weapon/anobattery/inserted_battery
var/obj/machinery/artifact/cur_artifact
var/obj/machinery/artifact_scanpad/owned_scanner = null
/obj/machinery/artifact_harvester/New()
..()
//connect to a nearby scanner pad
owned_scanner = locate(/obj/machinery/artifact_scanpad) in get_step(src, dir)
if(!owned_scanner)
owned_scanner = locate(/obj/machinery/artifact_scanpad) in orange(1, src)
/obj/machinery/artifact_harvester/attackby(var/obj/I as obj, var/mob/user as mob)
if(istype(I,/obj/item/weapon/anobattery))
if(!inserted_battery)
user << "\blue You insert [I] into [src]."
user.drop_item()
I.loc = src
src.inserted_battery = I
updateDialog()
else
user << "\red There is already a battery in [src]."
else
return..()
/obj/machinery/artifact_harvester/attack_hand(var/mob/user as mob)
src.add_fingerprint(user)
interact(user)
/obj/machinery/artifact_harvester/interact(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return
user.set_machine(src)
var/dat = "<B>Artifact Power Harvester</B><BR>"
dat += "<HR><BR>"
//
if(owned_scanner)
if(harvesting)
if(harvesting > 0)
dat += "Please wait. Harvesting in progress ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%).<br>"
else
dat += "Please wait. Energy dump in progress ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%).<br>"
dat += "<A href='?src=\ref[src];stopharvest=1'>Halt early</A><BR>"
else
if(inserted_battery)
dat += "<b>[inserted_battery.name]</b> inserted, charge level: [inserted_battery.stored_charge]/[inserted_battery.capacity] ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%)<BR>"
dat += "<b>Energy signature ID:</b>[inserted_battery.battery_effect.artifact_id == "" ? "???" : "[inserted_battery.battery_effect.artifact_id]"]<BR>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
dat += "<A href='?src=\ref[src];drainbattery=1'>Drain battery of all charge</a><BR>"
dat += "<A href='?src=\ref[src];harvest=1'>Begin harvesting</a><BR>"
else
dat += "No battery inserted.<BR>"
else
dat += "<B><font color=red>Unable to locate analysis pad.</font><BR></b>"
//
dat += "<HR>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</A> <A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artharvester;size=450x500")
onclose(user, "artharvester")
/obj/machinery/artifact_harvester/process()
if(stat & (NOPOWER|BROKEN))
return
if(harvesting > 0)
//gain a bit of charge
inserted_battery.stored_charge += 0.5
//check if we've finished
if(inserted_battery.stored_charge >= inserted_battery.capacity)
use_power = 1
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
src.visible_message("<b>[name]</b> states, \"Battery is full.\"")
icon_state = "incubator"
else if(harvesting < 0)
//dump some charge
inserted_battery.stored_charge -= 2
//do the effect
if(inserted_battery.battery_effect)
inserted_battery.battery_effect.process()
//if the effect works by touch, activate it on anyone viewing the console
if(inserted_battery.battery_effect.effect == 0)
var/list/nearby = viewers(1, src)
for(var/mob/M in nearby)
if(M.machine == src)
inserted_battery.battery_effect.DoEffectTouch(M)
//if there's no charge left, finish
if(inserted_battery.stored_charge <= 0)
use_power = 1
inserted_battery.stored_charge = 0
harvesting = 0
if(inserted_battery.battery_effect && inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate()
src.visible_message("<b>[name]</b> states, \"Battery dump completed.\"")
icon_state = "incubator"
/obj/machinery/artifact_harvester/Topic(href, href_list)
if (href_list["harvest"])
//locate artifact on analysis pad
cur_artifact = null
var/articount = 0
var/obj/machinery/artifact/analysed
for(var/obj/machinery/artifact/A in get_turf(owned_scanner))
analysed = A
articount++
var/mundane = 0
for(var/obj/O in get_turf(owned_scanner))
if(O.invisibility)
continue
if(!istype(O, /obj/machinery/artifact) && !istype(O, /obj/machinery/artifact_scanpad))
mundane++
break
for(var/mob/O in get_turf(owned_scanner))
if(O.invisibility)
continue
mundane++
break
if(analysed.being_used)
var/message = "<b>[src]</b> states, \"Cannot harvest. Too much interference.\""
src.visible_message(message)
else if(articount == 1 && !mundane)
cur_artifact = analysed
//there should already be a battery inserted, but this is just in case
if(inserted_battery)
//see if we can clear out an old effect
//delete it when the ids match to account for duplicate ids having different effects
if(inserted_battery.battery_effect && inserted_battery.stored_charge <= 0)
del(inserted_battery.battery_effect)
//only charge up
var/matching_id = 0
if(inserted_battery.battery_effect)
matching_id = (inserted_battery.battery_effect.artifact_id == cur_artifact.my_effect.artifact_id)
var/matching_effecttype = 0
if(inserted_battery.battery_effect)
matching_effecttype = (inserted_battery.battery_effect.type == cur_artifact.my_effect.type)
if(!inserted_battery.battery_effect || (matching_id && matching_effecttype))
harvesting = 1
use_power = 2
cur_artifact.anchored = 1
cur_artifact.being_used = 1
icon_state = "incubator_on"
var/message = "<b>[src]</b> states, \"Beginning artifact energy harvesting.\""
src.visible_message(message)
//duplicate the artifact's effect datum
if(!inserted_battery.battery_effect)
var/effecttype = cur_artifact.my_effect.type
var/datum/artifact_effect/E = new effecttype(inserted_battery)
//duplicate it's unique settings
for(var/varname in list("chargelevelmax","artifact_id","effect","effectrange","trigger"))
E.vars[varname] = cur_artifact.my_effect.vars[varname]
//copy the new datum into the battery
inserted_battery.battery_effect = E
inserted_battery.stored_charge = 0
else
var/message = "<b>[src]</b> states, \"Cannot harvest. Incompatible energy signatures detected.\""
src.visible_message(message)
else if(cur_artifact)
var/message = "<b>[src]</b> states, \"Cannot harvest. No battery inserted.\""
src.visible_message(message)
else if(articount > 1 || mundane)
var/message = "<b>[src]</b> states, \"Cannot harvest. Error isolating energy signature.\""
src.visible_message(message)
else if(!articount)
var/message = "<b>[src]</b> states, \"Cannot harvest. No noteworthy energy signature isolated.\""
src.visible_message(message)
if (href_list["stopharvest"])
if(harvesting)
if(harvesting < 0 && inserted_battery.battery_effect && inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate()
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
src.visible_message("<b>[name]</b> states, \"Activity interrupted.\"")
icon_state = "incubator"
if (href_list["ejectbattery"])
src.inserted_battery.loc = src.loc
src.inserted_battery = null
if (href_list["drainbattery"])
if(inserted_battery)
if(inserted_battery.battery_effect && inserted_battery.stored_charge > 0)
if(alert("This action will dump all charge, safety gear is recommended before proceeding","Warning","Continue","Cancel"))
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(0)
harvesting = -1
use_power = 2
icon_state = "incubator_on"
var/message = "<b>[src]</b> states, \"Warning, battery charge dump commencing.\""
src.visible_message(message)
else
var/message = "<b>[src]</b> states, \"Cannot dump energy. Battery is drained of charge already.\""
src.visible_message(message)
else
var/message = "<b>[src]</b> states, \"Cannot dump energy. No battery inserted.\""
src.visible_message(message)
if(href_list["close"])
usr << browse(null, "window=artharvester")
usr.unset_machine(src)
updateDialog()

View File

@@ -0,0 +1,8 @@
/obj/machinery/artifact_scanpad
name = "Anomaly Scanner Pad"
desc = "Place things here for scanning."
icon = 'stationobjs.dmi'
icon_state = "tele0"
anchored = 1
density = 0

View File

@@ -0,0 +1,413 @@
/obj/item/weapon/book/manual/excavation
name = "Out on the dig"
icon_state = "excavation"
author = "Professor Patrick Mason, Curator of the Antiquities Museum on Ichar VII"
title = "Out on the dig"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h1 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Prep">Prepping the expedition</a></li>
<li><a href="#Tools">Knowing your tools</a></li>
<li><a href="#Find">Finding the dig</a></li>
<li><a href="#Analyse">Analysing deposits</a></li>
<li><a href="#Excavate">Extracting your first find</a></li>
</ol>
<br>
<h1><a name="Prep">Prepping the expedition</a></h1>
Every digsite I've been to, someone has forgotten something and I've never yet been to a dig that hasn't had me hiking to get to it - so gather your gear
and get it to the site the first time. You learn quick that time is money, when you've got a shipful of bandits searching for you the next valley over,
but don't be afraid to clear some space if there are any inconvenient boulders in the way.<br>
<list>
<li>Floodlights (if it's dark)</li>
<li>Wooden trestle tables (for holding tools and finds)</li>
<li>Suspension field generator</li>
<li>Load bearing servitors (such as a mulebot, or hover-tray)</li>
<li>Spare energy packs</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Tools">Knowing your tools</a></h1>
Every archaeologist has a plethora of tools at their disposal, but here's the important ones:<br>
<list>
<li><b>Picks, pickaxes and brushes</b> - don't underestimate the the smallest or largest in your arsenal, each one clears a different amount
of the rockface so each one has a use.</li>
<li><b>Measuring tape</b> - don't leave home without it, you can use it to measure the depth a rock face has been excavated to.</li>
<li><b>GPS locater</b> - knowing where you are is the first step to not be lost.</li>
<li><b>Core sampler</b> - use this to take core samples from rock faces, which you can then run to the lab for analysis.</li>
<li><b>Depth scanner</b> - 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.</li>
<li><b>Radio beacon locater</b> - leave a beacon at an item of interest, then track it down later with this handy gadget. Watch for interference from other
devices though.</li>
<li><b>Flashlight or portable light source</b> - Self explanatory, I hope.</li>
<li><b>Environmental safety gear</b> - This one's dependant on the environment you're working in, but enclosed footwear and pack of internals
could save your life.</li>
<li><b>Anomaly safety gear</b> - A biosealed and catalysis-resistant suit along with eye shielding, tinted hood and non-reactive disposable gloves are
the best kind of protection you can hope for from the errors our forbears may have unleashed.</li>
<li><b>Personal defence weapon</b> - Never know what you'll find on the dig: pirates, natives, ancient guardians, carnivorous wildlife...
it pays in blood to be prepared.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Find">Finding the dig</a></h1>
Wouldn't be an archaeologist without their dig, but everyone has to start somewhere. Here's a basic procedure I go through when cataloguing a new planet:<br>
<list>
<li><b>Get in touch with the locals</b> (in particular geologists, miners and farmers) - Never know what's been turned up by accident, then left to
gather dust on a shelf.</li>
<li><b>Check the obvious areas first</b> - even if you're pressed for time, these ones are the generally easiest to search, and the most likely targets
of your rivals.</li>
<li><b>Do some prospecting</b> - the earth mother isn't in the habit of displaying her secrets to the world (although sometimes you get lucky).
Drop a shaft and clear away a bit of surface rock here and there, you never know what might be lurking below the surface.</li>
<li><b>Tips on unearthing a deposit</b> - How do you know when you're golden? Look for telltale white strata that looks strange or out of place, or if
something has broken under your pick while you're digging. Your depth scanner is your best friend, but even it can't distinguish between
ordinary minerals and ancient leavings, if in doubt then err on the side of caution.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Analyse">Analysing the contents of a dig</a></h1>
You've found some unusual strata, but it's not all peaches from here. No archaeologist ever managed to pull a bone from the earth without doing thorough
chemical analysis on every two meters of rock face nearby.<br>
<list>
<li><b>Take core samples</b> - Grab a rock core for every 4m^2.</li>
<li><b>Clear around any potential finds</b> - Clear away ordinary rock, leaving your prizes reachable in a clearly marked area.</li>
<li><b>Haul off excess rock</b> - It's easy for a dig to get cluttered, and a neat archaeologist is a successful archaeologist.</li>
<li><b>Don't be afraid to be cautious</b> - It's slower sometimes, but the extra time will be worth the payoff when you find an Exolitic relic.</li>
<li><b>Chemical analysis</b> - I won't go into detail here, but the labwork is essential to any successful extraction. Marshal your core samples, and
send them off to the labcoated geniuses</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Excavate">Extracting your first find</a></h1>
<list>
<li><b>Scan the rock</b> - Use a depth scanner to determine the find's depth and clearance. DON'T FORGET THESE.</li>
<li><b>Choose stasis field</b> - Chemical analysis on a core sample from the rock face will tell you which field is necessary to extract the find safely</li>
<li><b>Setup field gen</b> - Bolt it down, choose the field, check the charge and activate it. If you forget it, you'll wish you hadn't when that priceless
Uryom vase crumbles as it sees the light of day.</li>
<li><b>FUNCTIONAL AND SAFE digging</b> - Dig into the rock until you've cleared away a depth equal to (the anomaly depth MINUS the clearance range). The find
should come loose on it's own, but it will be in the midst of a chunk of rock. Use a welder or miniature excavation tool to clear away the excess.</li>
<li><b>FANCY AND SPEEDY digging</b> - Dig into the rock until you've cleared away a depth equal to the anomaly depth, but without any of your strokes
entering the clearance range.</li>
<li><b>The Big Find</b> - Sometimes, you'll chance upon something big, both literally and figuratively. Giant statues and functioning remnants of Precursor
technology are just as exciting, to the right buyers. If your digging leaves a large boulder behind, dig into it normally and see if anything's hidden
inside.</li>
</list><br>
<a href="#Contents">Contents</a>
</body>
</html>
"}
/obj/item/weapon/book/manual/mass_spectrometry
name = "High power mass spectrometry, a comprehensive guide"
icon_state = "analysis"
author = "Winton Rice, Chief Mass Spectrometry Technician at the Institute of Applied Sciences on Arcadia"
title = "High powered mass spectrometry, a comprehensive guide"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h1 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Terms">A note on terms</a></li>
<li><a href="#Isotope">Isotope ratio spectrometer</a></li>
<li><a href="#Accelerator">Accelerator spectrometer</a></li>
<li><a href="#Gas">Gas chromatography spectrometer</a></li>
<li><a href="#Ion">Ion mobility spectrometer</a></li>
</ol>
<br>
<h1><a name="Terms">A note on terms</a></h1>
<list>
<li><b>Dissonance ratio</b> - 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.</li>
<li><b>Mass spectrometry</b> - MS is the procedure used used to measure and quantify the components of matter. The most prized tool in the field of
'Materials analysis'</li>
<li><b>Radiometric dating</b> - MS applied using the right carrier reagents can be used to accurately determine the age of a sample.</li>
<li><b>Sample specifity</b> - 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.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Isotope">Isotope ratio spectrometer</a></h1>
Isotope ratio mass spectrometers work by coating a small surface with a semiliquid <i>stationary phase</i> consisting of the sample to be
analysed, and recording it's interactions with a gaseous <i>mobile phase</i> comprised of an inert or nonreactive gas such as helium or nitrogen.<br>
<br>
IRMS are employed as radiometric daters, extremely accurate but only so up to ages of one billion years.<br>
<a href="#Contents">Contents</a>
<h1><a name="Accelerator">Accelerator spectrometer</a></h1>
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.<br>
<br>
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.<br>
<a href="#Contents">Contents</a>
<h1><a name="Gas">Gas chromatography spectrometer</a></h1>
Gas-liquid chromatography mass spectrometers work by coating a small surface with a semiliquid <i>stationary phase</i> consisting of the sample to be
analysed, and recording it's interactions with a gaseous <i>mobile phase</i> comprised of an inert or nonreactive gas such as helium or nitrogen.<br>
<br>
GLCS are employed in forensic and geological analysis to determine what elements are present in a sample.<br>
<a href="#Contents">Contents</a>
<h1><a name="Ion">Ion mobility spectrometer</a></h1>
Ion mobility mass spectrometers work by examining the mobility of ionized molecules in an inert carrier gas<br>
<br>
IMS returns a dissonance ratio over the scanned sample and carrier reagent, indicating the average total presence of the sample.<br>
<a href="#Contents">Contents</a>
</body>
</html>
"}
/obj/item/weapon/book/manual/anomaly_spectroscopy
name = "Spectroscopy: Analysing the anomalies of the cosmos"
icon_state = "anomaly"
author = "Doctor Martin Boyle, Director Research at the Lower Hydrolian Sector Listening Array"
title = "Spectroscopy: Analysing the anomalies of the cosmos"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h1 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Terms">Some useful phrases for you</a></li>
<li><a href="#Sample">Sample preparation and analysis</a></li>
<li><a href="#Fourier">Fourier transform spectroscope</a></li>
<li><a href="#Hyperspectral">Hyperspectral Imager</a></li>
</ol>
<br>
<h1><a name="Terms">Some useful phrases for you</a></h1>
<list>
<li><b>Spectroscopy</b> - Spectroscopy is the study of the behaviour of light, commonly used in the 26th century for analysis of anomalous
behaviour of energy or light.</li>
<li><b>Sample specifity</b> - 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.</li>
<li><b>Anomalies</b> - 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.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Sample">Sample preparation and analysis</a></h1>
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.
<list>
<li><b>Obtain material sample</b> - This should be an ordinary chunk of matter the size of your finger, a good example is a 6mm rock core.</li>
<li><b>Run density separation treatment</b> - Perform the DST procedure on your sample, following generic specifications.</li>
<li><b>Ensure sample purity</b> - DST can sometimes leave behind chemical waste or chunks of matter, make sure there aren't any before proceeding.</li>
<li><b>Prepare analysis tray</b> - A sample tray holds a miniscule amount of liquid (2u), but that's all that our spectrometers require for a good reading.</li>
<li><b>Choose carrier reagent</b> - Standard spectrometers require 1u of the material sample, and 1u of a 'carrier' reagent to provide control comparison
and to enable refraction inferencing.</li>
<li><b>Insert sample tray into machine</b> - And press the 'Go' button. Now go make a cup of coffee.</li>
<li><b>Monitor machine heat levels</b> - 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.</li>
<li><b>Examine analysis report</b> - 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!</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Fourier">Fourier transform spectroscope</a></h1>
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 <i>Fourier Transform Procedure,</i> with the mathematical algorithms dating back to the 19th century on Earth.<br>
<br>
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.<br>
<a href="#Contents">Contents</a>
<h1><a name="Hyperspectral">Hyperspectral Imager</a></h1>
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.<br>
<br>
As well as visualising background energy readings, a hyperspectral imager will isolate and identify any anomalous energy signatures in the sample.<br>
<a href="#Contents">Contents</a>
</body>
</html>
"}
/obj/item/weapon/book/manual/materials_chemistry_analysis
name = "Chemical preparation for materials analysis"
icon_state = "chemistry"
author = "Jasper Pascal, Senior Lecturer in Materials Analysis at the University of Jol'Nar"
title = "Chemical preparation for materials analysis"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h1 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Terms">Relevant words and their meanings</a></li>
<li><a href="#Sample">Sample preparation for spectrometry/spectroscopy</a></li>
<li><a href="#DST">Density Separation Treatment</a></li>
<li><a href="#Carrier">Choosing a carrier reagent</a></li>
</ol>
<br>
<h1><a name="Terms">Relevant words and their meanings</a></h1>
<list>
<li><b>Dissonance ratio</b> - 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.</li>
<li><b>Density separation treatment</b> - The DST procedure purifies a sample, removing any unwanted matter to ensure the finest scan resolution possible.</li>
<li><b>Mass spectrometry</b> - MS is the procedure used used to measure and quantify the components of matter. The most prized tool in the field of
'Materials analysis'</li>
<li><b>Spectroscopy</b> - Spectroscopy is the study of the behaviour of light, commonly used in the 26th century for analysis of anomalous
behaviour of energy or light.</li>
<li><b>Sample specifity</b> - 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.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Sample">Sample preparation for spectrometry/spectroscopy</a></h1>
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.
<list>
<li><b>Obtain material sample</b> - This should be an ordinary chunk of matter the size of your finger, a good example is a 6mm rock core.</li>
<li><b>Run density separation treatment</b> - Perform the DST procedure on your sample, following generic specifications.</li>
<li><b>Ensure sample purity</b> - DST can sometimes leave behind chemical waste or chunks of matter, make sure there aren't any before proceeding.</li>
<li><b>Prepare analysis tray</b> - A sample tray holds a miniscule amount of liquid (2u), but that's all that our spectrometers require for a good reading.</li>
<li><b>Choose carrier reagent</b> - Standard spectrometers require 1u of the material sample, and 1u of a 'carrier' reagent to provide control comparison
and to enable refraction inferencing.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="DST">Density Separation Treatment</a></h1>
<list>
<li><b>Obtain material sample</b> - This should be an ordinary chunk of matter the size of your finger, a good example is a 6mm rock core.</li>
<li><b>Grind material to powder</b> - In order to treat the material, we have to have the sample in it's basest form.</li>
<li><b>Prepare separator solution</b> - A chemical solution called LiNa2WO4, or <i>Lithium Sodium Tungstate</i> must be prepared to separate
the the denser clumps of matter out of the refined sample. This is done by mixing 1 part lithium, 2 parts sodium, 1 part tungsten, 4 parts oxygen.</li>
<li><b>Mix separator with sample</b> - The resulting mixture is very close to the final product, but make sure to extract any leftover reagents and
the chemical waste byproduct.</li>
<li><b>Bring sample to boil</b> - Using a standard bunsen burner, bring the mixture to a boil to vaporise the remaining unwanted matter. Remember
to again clear out any waste byproducts.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Carrier">Choosing a carrier reagent</a></h1>
Below is a list of the most commonly used scan carrier reagents, and the particular molecules they resonate most strongly with:
<list>
<li><b>Carbon</b> - Trace organic cells, typically used for carbon dating of organic remains.</li>
<li><b>Potassium</b> - Long exposure particles floating in the depths of space, such as meteorites.</li>
<li><b>Hydrogen</b> - Trace water particles.</li>
<li><b>Nitrogen</b> - Crystalline structures.</li>
<li><b>Mercury</b> - Metallic derivatives such as ferritic elements and pure metallic substances.</li>
<li><b>Iron</b> - Metallic composites such as alloys and atomic structures that are metallic in nature.</li>
<li><b>Chlorine</b> - Metamorphic/igneous rock composite.</li>
<li><b>Phosphorus</b> - Metamorphic/sedimentary rock composite.</li>
<li><b>Plasma</b> - Anomalous materials such as bluespace phased composites that are not fully understood by modern science.</li>
</list><br>
<a href="#Contents">Contents</a>
</body>
</html>
"}
/obj/item/weapon/book/manual/anomaly_testing
name = "Anomalous materials and energies"
icon_state = "triangulate"
author = "Norman York, formerly of the Tyrolion Institute on Titan"
title = "Anomalous materials and energies"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h1 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Anomalies">Forward: Modern attitude towards anomalies</a></li>
<li><a href="#Tri">Triangulating anomalous energy readings</a></li>
<li><a href="#Synthetic">Harvesting and utilising anomalous energy signatures</a></li>
</ol>
<br>
<h1><a name="Anomalies">Modern attitude towards anomalies</a></h1>
It's only when confronted with things we don't know, that we may push back our knowledge of the world around us. Nowhere is this more obvious than the
vast and inscrutable mysterious of the cosmos that scholars from such august institutions as the Elysian Institute of the Sciences present
formulas and hypotheses for every few decades.<br>
<br>
Using our vast telescopic array installations and deep space satellite networks, we are able to detect anomalous energy fields and formations in deep space,
but are limited to those that are large enough to output energy that will stretch across light years worth of distance between stars.<br>
<br>
While some sectors (such as the Hydrolian Rift and Keppel's Run) are replete with inexplicable energetic activity and unique phenomena found nowhere else in
the galaxy, the majority of space is dry, barren and cold - and if past experience has told us anything, it is that there are always more things we are
unable to explain.<br>
<br>
Indeed, a great source of knowledge and technology has always been those who come before us, in the form of the multitudinous ancient alien precursors that
have left scattered remnants of their great past all over settled (and unexplored) space.<br>
<br>
It is from xenoarchaeologists, high energy materials researchers and technology reconstruction authorities that we are able to theorise on the gifts these
species have left behind, and in some cases even reverse engineer or rebuild the technology in question. My colleague Doctor Raymond Ward of the
Tyrolian Institute on Titan has made great breakthroughs in a related field through his pioneering development of universally reflective materials capable
of harvesting and 'bottling' up virtually any energy emissions yet encountered by spacefaring civilisations.<br>
<br>
And yet, there are some amongst us who do not see the benefits of those who have come before us - indeed, some among them profess the opinion that there
is no species that could possibly match humanity in it's achievements and knowledge, or simply that employing non-human technology is dangerous and unethical.
Folly, say I. If it is their desire to throw onto the wayside the greatest achievements <i>in the history of the galaxy</i>, simply for preferment of the
greatest achievements <i>in the history of mankind</i>, then they have no business in the establishment of science.<br>
<a href="#Contents">Contents</a>
<h1><a name="Tri">Triangulating anomalous energy readings</a></h1>
Strong energy emissions, when remaining constant from any one fixed location for millenia, can leave an 'imprint' or distinctive energy signature on other
matter composites that are spatially fixed relative to the source.<br>
<br>
By taking samples of such 'fixed' matter, we can apply complex analytics such as the modified Fourier Transform Procedure to reverse engineer the path of the
energy, and determine the approximate distance and direction that the energy source is, relative to the sample's point in space.<br>
<br>
A canny researcher can thusly analyse material samples from pre-chosen points strategically scattered around an area, and if there are any anomalous energy
emissions in range of those points, combined they can direct the researcher to the source.<br>
<a href="#Contents">Contents</a>
<h1><a name="Synthetic">Harvesting and utilising anomalous energy signatures</a></h1>
As mentioned in the forward, my colleague from the Tyrolian Institute on Saturn's moon of Titan, in the Sol System, Doctor Raymond Ward has made great strides
in the area of harvesting and application of the energy emitted by anomalous phenomena from around the galaxy (although I profess I have not yet seen him
venture further from his birthplace on Earth than the comfortable distance of the Sol Cis-Oort Satellite Sphere).<br>
<br>
By employing a patented semi-phased alloy with unique and fascinating bluespace interaction properties, Ward's contraption is able to 'harvest' energy, store
it and redirect it later at will (with appropriate electronic mechanisms, of course). Although he professes to see or desire no commercial or material gain
for the application and use of said energy once it is harvested, there are no doubt myriad ways we can come to benefit from such things beyond mere research,
such as the reconstruction of torn cartiligenous tissue that a peculiar radiation from an amphibious species on Brachis IV was found to emit.<br>
<a href="#Contents">Contents</a>
</body>
</html>
"}

View File

@@ -0,0 +1,105 @@
//---- Noticeboard
/obj/structure/noticeboard/anomaly/New()
notices = 5
icon_state = "nboard05"
//add some memos
var/obj/item/weapon/paper/P = new()
P.name = "Memo RE: proper analysis procedure"
P.info = "Rose,<br>activate <i>then</i> analyse the artifacts, the machine will have a much easier time determining their function/s. Remember to employ basic quasi-elemental forces such as heat, energy, force and various chemical mixes - who knows why those ancient aliens made such obscure activation indices.<br><br>And don't forget your suit this time, I can't afford to have any researchers out of commision for as long as that again!.<br>Ward"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Memo RE: materials gathering"
P.info = "Corasang,<br>the hands-on approach to gathering our samples may very well be slow at times, but it's safer than allowing the blundering miners to roll willy-nilly over our dig sites in their mechs, destroying everything in the process. And don't forget the escavation tools on your way out there!<br>- R.W"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Memo RE: ethical quandaries"
P.info = "Darion-<br><br>I don't care what his rank is, our business is that of science and knowledge - questions of moral application do not come into this. Sure, so there are those who would employ the energy-wave particles my modified device has managed to abscond for their own personal gain, but I can hardly see the practical benefits of some of these artifacts our benefactors left behind. Ward--"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "READ ME! Before you people destroy any more samples"
P.info = "how many times do i have to tell you people, these xeno-arch samples are del-i-cate, and should be handled so! careful application of a focussed, ceoncentrated heat or some corrosive liquids should clear away the extraneous carbon matter, while application of an energy beam will most decidedly destroy it entirely! W, <b>the one who signs your paychecks</b>"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
P = new()
P.name = "Reminder regarding the anomalous material suits"
P.info = "Do you people think the anomaly suits are cheap to come by? I'm about a hair trigger away from instituting a log book for the damn things. Only wear them if you're going out for a dig, and for god's sake don't go tramping around in them unless you're field testing something, R"
P.stamped = list(/obj/item/weapon/stamp/rd)
P.overlays = list("paper_stamped_rd")
src.contents += P
//---- Bookcase
/obj/structure/bookcase/manuals/xenoarchaeology
name = "Xenoarchaeology Manuals bookcase"
New()
..()
new /obj/item/weapon/book/manual/excavation(src)
new /obj/item/weapon/book/manual/mass_spectrometry(src)
new /obj/item/weapon/book/manual/materials_chemistry_analysis(src)
new /obj/item/weapon/book/manual/anomaly_testing(src)
new /obj/item/weapon/book/manual/anomaly_spectroscopy(src)
update_icon()
//---- Lockers and closets
/obj/structure/closet/secure_closet/xenoarchaeologist
name = "Xenoarchaeologist Locker"
req_access = list(access_tox_storage)
icon_state = "secureres1"
icon_closed = "secureres"
icon_locked = "secureres1"
icon_opened = "secureresopen"
icon_broken = "secureresbroken"
icon_off = "secureresoff"
New()
..()
sleep(2)
new /obj/item/clothing/under/rank/scientist(src)
new /obj/item/clothing/suit/storage/labcoat(src)
new /obj/item/clothing/shoes/white(src)
new /obj/item/clothing/glasses/science(src)
new /obj/item/device/radio/headset/headset_sci(src)
new /obj/item/weapon/storage/belt/archaeology(src)
new /obj/item/weapon/storage/box/excavation(src)
return
/obj/structure/closet/excavation
name = "Excavation tools"
icon_state = "toolcloset"
New()
..()
sleep(2)
new /obj/item/weapon/storage/belt/archaeology(src)
new /obj/item/weapon/storage/box/excavation(src)
new /obj/item/device/flashlight/lantern(src)
new /obj/item/device/depth_scanner(src)
new /obj/item/device/core_sampler(src)
new /obj/item/device/gps(src)
new /obj/item/device/beacon_locator(src)
new /obj/item/device/radio/beacon(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/weapon/pickaxe(src)
return
//---- Isolation room air alarms
/obj/machinery/alarm/isolation
name = "Isolation room air control"
req_access = list(access_research)

View File

@@ -1,36 +0,0 @@
/obj/item/device/depth_scanner
name = "depth analysis scanner"
desc = "Used to check mass spatial depth and density."
icon = 'pda.dmi'
icon_state = "crap"
item_state = "analyzer"
w_class = 1.0
flags = FPRINT | TABLEPASS
//slot_flags = SLOT_BELT
/obj/item/weapon/pickaxe/hand_pick
name = "hand pick"
icon_state = "excavation"
item_state = "minipick"
digspeed = 50
desc = "A smaller, more precise version of the pickaxe."
flags = FPRINT | TABLEPASS
w_class = 2.0
/obj/item/weapon/pickaxe/mini_pick
name = "mini pick"
icon_state = "excavation"
item_state = "minipick"
digspeed = 60
desc = "A miniature excavation tool for precise digging around delicate finds."
flags = FPRINT | TABLEPASS
w_class = 1.0
//todo: this
/obj/item/device/beacon_locator
name = "locater device"
desc = "Used to triangulate position signal emitters."
icon = 'device.dmi'
icon_state = "pinoff" //pinonfar, pinonmedium, pinonclose, pinondirect, pinonnull
item_state = "electronic"
w_class = 1.0

View File

@@ -0,0 +1,196 @@
/obj/item/weapon/anobattery
name = "Anomaly power battery"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "anobattery0"
var/datum/artifact_effect/battery_effect
var/capacity = 200
var/stored_charge = 0
var/effect_id = ""
/obj/item/weapon/anobattery/New()
battery_effect = new()
/obj/item/weapon/anobattery/proc/UpdateSprite()
var/p = (stored_charge/capacity)*100
p = min(p, 100)
icon_state = "anobattery[round(p,25)]"
/obj/item/weapon/anodevice
name = "Anomaly power utilizer"
icon = 'xenoarchaeology.dmi'
icon_state = "anodev"
var/cooldown = 0
var/activated = 0
var/timing = 0
var/time = 50
var/archived_time = 50
var/obj/item/weapon/anobattery/inserted_battery
var/turf/archived_loc
/obj/item/weapon/anodevice/New()
..()
processing_objects.Add(src)
/obj/item/weapon/anodevice/attackby(var/obj/I as obj, var/mob/user as mob)
if(istype(I, /obj/item/weapon/anobattery))
if(!inserted_battery)
user << "\blue You insert the battery."
user.drop_item()
I.loc = src
inserted_battery = I
UpdateSprite()
else
return ..()
/obj/item/weapon/anodevice/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/weapon/anodevice/interact(var/mob/user)
user.set_machine(src)
var/dat = "<b>Anomalous Materials Energy Utiliser</b><br>"
if(inserted_battery)
if(cooldown)
dat += "Cooldown in progress, please wait.<br>"
else if(activated)
if(timing)
dat += "Device active.<br>"
else
dat += "Device active in timed mode.<br>"
dat += "[inserted_battery] inserted, anomaly ID: [inserted_battery.battery_effect.artifact_id ? inserted_battery.battery_effect.artifact_id : "NA"]<BR>"
dat += "<b>Total Power:</b> [inserted_battery.stored_charge]/[inserted_battery.capacity]<BR><BR>"
dat += "<b>Timed activation:</b> <A href='?src=\ref[src];neg_changetime_max=-100'>--</a> <A href='?src=\ref[src];neg_changetime=-10'>-</a> [time >= 1000 ? "[time/10]" : time >= 100 ? " [time/10]" : " [time/10]" ] <A href='?src=\ref[src];changetime=10'>+</a> <A href='?src=\ref[src];changetime_max=100'>++</a><BR>"
if(cooldown)
dat += "<font color=red>Cooldown in progress.</font><BR>"
dat += "<br>"
else if(!activated)
dat += "<A href='?src=\ref[src];startup=1'>Start</a><BR>"
dat += "<A href='?src=\ref[src];startup=1;starttimer=1'>Start in timed mode</a><BR>"
else
dat += "<a href='?src=\ref[src];shutdown=1'>Shutdown emission</a><br>"
dat += "<br>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
else
dat += "Please insert battery<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<hr>"
dat += "<a href='?src=\ref[src]'>Refresh</a> <a href='?src=\ref[src];close=1'>Close</a>"
user << browse(dat, "window=anodevice;size=400x500")
onclose(user, "anodevice")
/obj/item/weapon/anodevice/process()
if(cooldown > 0)
cooldown -= 1
if(cooldown <= 0)
cooldown = 0
src.visible_message("\blue \icon[src] [src] chimes.", "\blue \icon[src] You hear something chime.")
else if(activated)
if(inserted_battery && inserted_battery.battery_effect)
//make sure the effect is active
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
//update the effect loc
var/turf/T = get_turf(src)
if(T != archived_loc)
archived_loc = T
inserted_battery.battery_effect.UpdateMove()
//process the effect
inserted_battery.battery_effect.process()
//if someone is holding the device, do the effect on them
if(inserted_battery.battery_effect.effect == 0 && ismob(src.loc))
inserted_battery.battery_effect.DoEffectTouch(src.loc)
//handle charge
inserted_battery.stored_charge -= 1
if(inserted_battery.stored_charge <= 0)
shutdown_emission()
//handle timed mode
if(timing)
time -= 1
if(time <= 0)
shutdown_emission()
else
shutdown()
/obj/item/weapon/anodevice/proc/shutdown_emission()
if(activated)
activated = 0
timing = 0
src.visible_message("\blue \icon[src] [src] buzzes.", "\icon[src]\blue You hear something buzz.")
cooldown = archived_time / 2
if(inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
/obj/item/weapon/anodevice/Topic(href, href_list)
if(href_list["neg_changetime_max"])
time += -100
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["neg_changetime"])
time += -10
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["changetime"])
time += 10
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["changetime_max"])
time += 100
if(time > inserted_battery.capacity)
time = inserted_battery.capacity
else if (time < 0)
time = 0
if(href_list["startup"])
activated = 1
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
if(href_list["shutdown"])
activated = 0
if(href_list["starttimer"])
timing = 1
archived_time = time
if(href_list["ejectbattery"])
shutdown_emission()
inserted_battery.loc = get_turf(src)
inserted_battery = null
UpdateSprite()
if(href_list["close"])
usr << browse(null, "window=anodevice")
usr.unset_machine(src)
..()
updateDialog()
/obj/item/weapon/anodevice/proc/UpdateSprite()
if(!inserted_battery)
icon_state = "anodev"
return
var/p = (inserted_battery.stored_charge/inserted_battery.capacity)*100
p = min(p, 100)
icon_state = "anodev[round(p,25)]"
/obj/item/weapon/anodevice/Del()
processing_objects.Remove(src)
..()

Some files were not shown because too many files have changed in this diff Show More