Initial Commit

This commit is contained in:
skull132
2014-03-11 09:03:52 +02:00
commit a8d9450c7e
3486 changed files with 415920 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
/*///////////////Circuit Imprinter (By Darem)////////////////////////
Used to print new circuit boards (for computers and similar systems) and AI modules. Each circuit board pattern are stored in
a /datum/desgin on the linked R&D console. You can then print them out in a fasion similar to a regular lathe. However, instead of
using metal and glass, it uses glass and reagents (usually sulfuric acis).
*/
/obj/machinery/r_n_d/circuit_imprinter
name = "Circuit Imprinter"
icon_state = "circuit_imprinter"
flags = OPENCONTAINER
var/g_amount = 0
var/gold_amount = 0
var/diamond_amount = 0
var/uranium_amount = 0
var/max_material_amount = 75000.0
New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/circuit_imprinter(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
RefreshParts()
RefreshParts()
var/T = 0
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
T += G.reagents.maximum_volume
var/datum/reagents/R = new/datum/reagents(T) //Holder for the reagents used as materials.
reagents = R
R.my_atom = src
T = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
T += M.rating
max_material_amount = T * 75000.0
blob_act()
if (prob(50))
del(src)
meteorhit()
del(src)
return
proc/TotalMaterials()
return g_amount + gold_amount + diamond_amount + uranium_amount
attackby(var/obj/item/O as obj, var/mob/user as mob)
if (shocked)
shock(user,50)
if (istype(O, /obj/item/weapon/screwdriver))
if (!opened)
opened = 1
if(linked_console)
linked_console.linked_imprinter = null
linked_console = null
icon_state = "circuit_imprinter_t"
user << "You open the maintenance hatch of [src]."
else
opened = 0
icon_state = "circuit_imprinter"
user << "You close the maintenance hatch of [src]."
return
if (opened)
if(istype(O, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker))
reagents.trans_to(I, reagents.total_volume)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
if(g_amount >= 3750)
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
G.amount = round(g_amount / 3750)
if(gold_amount >= 2000)
var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
G.amount = round(gold_amount / 2000)
if(diamond_amount >= 2000)
var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
G.amount = round(diamond_amount / 2000)
if(uranium_amount >= 2000)
var/obj/item/stack/sheet/mineral/uranium/G = new /obj/item/stack/sheet/mineral/uranium(src.loc)
G.amount = round(uranium_amount / 2000)
del(src)
return 1
else
user << "\red You can't load the [src.name] while it's opened."
return 1
if (disabled)
user << "\The [name] appears to not be working!"
return
if (!linked_console)
user << "\The [name] must be linked to an R&D console first!"
return 1
if (O.is_open_container())
return 0
if (!istype(O, /obj/item/stack/sheet/glass) && !istype(O, /obj/item/stack/sheet/mineral/gold) && !istype(O, /obj/item/stack/sheet/mineral/diamond) && !istype(O, /obj/item/stack/sheet/mineral/uranium))
user << "\red You cannot insert this item into the [name]!"
return 1
if (stat)
return 1
if (busy)
user << "\red The [name] is busy. Please wait for completion of previous operation."
return 1
var/obj/item/stack/sheet/stack = O
if ((TotalMaterials() + stack.perunit) > max_material_amount)
user << "\red The [name] is full. Please remove glass from the protolathe in order to insert more."
return 1
var/amount = round(input("How many sheets do you want to add?") as num)
if(amount < 0)
amount = 0
if(amount == 0)
return
if(amount > stack.amount)
amount = min(stack.amount, round((max_material_amount-TotalMaterials())/stack.perunit))
busy = 1
use_power(max(1000, (3750*amount/10)))
var/stacktype = stack.type
stack.use(amount)
if(do_after(usr,16))
user << "\blue You add [amount] sheets to the [src.name]."
switch(stacktype)
if(/obj/item/stack/sheet/glass)
g_amount += amount * 3750
if(/obj/item/stack/sheet/mineral/gold)
gold_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/diamond)
diamond_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/uranium)
uranium_amount += amount * 2000
else
new stacktype(src.loc, amount)
busy = 0
src.updateUsrDialog()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,113 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
Destructive Analyzer
It is used to destroy hand-held objects and advance technological research. Controls are in the linked R&D console.
Note: Must be placed within 3 tiles of the R&D Console
*/
/obj/machinery/r_n_d/destructive_analyzer
name = "Destructive Analyzer"
icon_state = "d_analyzer"
var/obj/item/weapon/loaded_item = null
var/decon_mod = 1
/obj/machinery/r_n_d/destructive_analyzer/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/destructive_analyzer(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
RefreshParts()
/obj/machinery/r_n_d/destructive_analyzer/RefreshParts()
var/T = 0
for(var/obj/item/weapon/stock_parts/S in src)
T += S.rating * 0.1
T = between (0, T, 1)
decon_mod = T
/obj/machinery/r_n_d/destructive_analyzer/meteorhit()
del(src)
return
/obj/machinery/r_n_d/destructive_analyzer/proc/ConvertReqString2List(var/list/source_list)
var/list/temp_list = params2list(source_list)
for(var/O in temp_list)
temp_list[O] = text2num(temp_list[O])
return temp_list
/obj/machinery/r_n_d/destructive_analyzer/attackby(var/obj/O as obj, var/mob/user as mob)
if (shocked)
shock(user,50)
if (istype(O, /obj/item/weapon/screwdriver))
if (!opened)
opened = 1
if(linked_console)
linked_console.linked_destroy = null
linked_console = null
icon_state = "d_analyzer_t"
user << "You open the maintenance hatch of [src]."
else
opened = 0
icon_state = "d_analyzer"
user << "You close the maintenance hatch of [src]."
return
if (opened)
if(istype(O, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
I.loc = src.loc
del(src)
return 1
else
user << "\red You can't load the [src.name] while it's opened."
return 1
if (disabled)
return
if (!linked_console)
user << "\red The destructive analyzer must be linked to an R&D console first!"
return
if (busy)
user << "\red The destructive analyzer is busy right now."
return
if (istype(O, /obj/item) && !loaded_item)
if(isrobot(user)) //Don't put your module items in there!
return
if(!O.origin_tech)
user << "\red This doesn't seem to have a tech origin!"
return
var/list/temp_tech = ConvertReqString2List(O.origin_tech)
if (temp_tech.len == 0)
user << "\red You cannot deconstruct this item!"
return
if(O.reliability < 90 && O.crit_fail == 0)
usr << "\red Item is neither reliable enough nor broken enough to learn from."
return
busy = 1
loaded_item = O
user.drop_item()
O.loc = src
user << "\blue You add the [O.name] to the machine!"
flick("d_analyzer_la", src)
spawn(10)
icon_state = "d_analyzer_l"
busy = 0
return 1
return
//For testing purposes only.
/*/obj/item/weapon/deconstruction_test
name = "Test Item"
desc = "WTF?"
icon = 'icons/obj/weapons.dmi'
icon_state = "d20"
g_amt = 5000
m_amt = 5000
origin_tech = "materials=5;plasmatech=5;syndicate=5;programming=9"*/
+355
View File
@@ -0,0 +1,355 @@
var/global/list/obj/machinery/message_server/message_servers = list()
/datum/data_pda_msg
var/recipient = "Unspecified" //name of the person
var/sender = "Unspecified" //name of the sender
var/message = "Blank" //transferred message
/datum/data_pda_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "")
if(param_rec)
recipient = param_rec
if(param_sender)
sender = param_sender
if(param_message)
message = param_message
/datum/data_rc_msg
var/rec_dpt = "Unspecified" //name of the person
var/send_dpt = "Unspecified" //name of the sender
var/message = "Blank" //transferred message
var/stamp = "Unstamped"
var/id_auth = "Unauthenticated"
var/priority = "Normal"
/datum/data_rc_msg/New(var/param_rec = "",var/param_sender = "",var/param_message = "",var/param_stamp = "",var/param_id_auth = "",var/param_priority)
if(param_rec)
rec_dpt = param_rec
if(param_sender)
send_dpt = param_sender
if(param_message)
message = param_message
if(param_stamp)
stamp = param_stamp
if(param_id_auth)
id_auth = param_id_auth
if(param_priority)
switch(param_priority)
if(1)
priority = "Normal"
if(2)
priority = "High"
if(3)
priority = "Extreme"
else
priority = "Undetermined"
/obj/machinery/message_server
icon = 'icons/obj/machines/research.dmi'
icon_state = "server"
name = "Messaging Server"
density = 1
anchored = 1.0
use_power = 1
idle_power_usage = 10
active_power_usage = 100
var/list/datum/data_pda_msg/pda_msgs = list()
var/list/datum/data_rc_msg/rc_msgs = list()
var/active = 1
var/decryptkey = "password"
/obj/machinery/message_server/New()
message_servers += src
decryptkey = GenerateKey()
send_pda_message("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.")
..()
return
/obj/machinery/message_server/Del()
message_servers -= src
..()
return
/obj/machinery/message_server/proc/GenerateKey()
//Feel free to move to Helpers.
var/newKey
newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le")
newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai")
newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
return newKey
/obj/machinery/message_server/process()
//if(decryptkey == "password")
// decryptkey = generateKey()
if(active && (stat & (BROKEN|NOPOWER)))
active = 0
return
update_icon()
return
/obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "")
pda_msgs += new/datum/data_pda_msg(recipient,sender,message)
/obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1)
rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth)
/obj/machinery/message_server/attack_hand(user as mob)
// user << "\blue There seem to be some parts missing from this server. They should arrive on the station in a few days, give or take a few CentCom delays."
user << "You toggle PDA message passing from [active ? "On" : "Off"] to [active ? "Off" : "On"]"
active = !active
update_icon()
return
/obj/machinery/message_server/update_icon()
if((stat & (BROKEN|NOPOWER)))
icon_state = "server-nopower"
else if (!active)
icon_state = "server-off"
else
icon_state = "server-on"
return
/datum/feedback_variable
var/variable
var/value
var/details
/datum/feedback_variable/New(var/param_variable,var/param_value = 0)
variable = param_variable
value = param_value
/datum/feedback_variable/proc/inc(var/num = 1)
if(isnum(value))
value += num
else
value = text2num(value)
if(isnum(value))
value += num
else
value = num
/datum/feedback_variable/proc/dec(var/num = 1)
if(isnum(value))
value -= num
else
value = text2num(value)
if(isnum(value))
value -= num
else
value = -num
/datum/feedback_variable/proc/set_value(var/num)
if(isnum(num))
value = num
/datum/feedback_variable/proc/get_value()
return value
/datum/feedback_variable/proc/get_variable()
return variable
/datum/feedback_variable/proc/set_details(var/text)
if(istext(text))
details = text
/datum/feedback_variable/proc/add_details(var/text)
if(istext(text))
if(!details)
details = text
else
details += " [text]"
/datum/feedback_variable/proc/get_details()
return details
/datum/feedback_variable/proc/get_parsed()
return list(variable,value,details)
var/obj/machinery/blackbox_recorder/blackbox
/obj/machinery/blackbox_recorder
icon = 'icons/obj/stationobjs.dmi'
icon_state = "blackbox"
name = "Blackbox Recorder"
density = 1
anchored = 1.0
use_power = 1
idle_power_usage = 10
active_power_usage = 100
var/list/messages = list() //Stores messages of non-standard frequencies
var/list/messages_admin = list()
var/list/msg_common = list()
var/list/msg_science = list()
var/list/msg_command = list()
var/list/msg_medical = list()
var/list/msg_engineering = list()
var/list/msg_security = list()
var/list/msg_deathsquad = list()
var/list/msg_syndicate = list()
var/list/msg_mining = list()
var/list/msg_cargo = list()
var/list/datum/feedback_variable/feedback = new()
//Only one can exsist in the world!
/obj/machinery/blackbox_recorder/New()
if(blackbox)
if(istype(blackbox,/obj/machinery/blackbox_recorder))
del(src)
blackbox = src
/obj/machinery/blackbox_recorder/Del()
var/turf/T = locate(1,1,2)
if(T)
blackbox = null
var/obj/machinery/blackbox_recorder/BR = new/obj/machinery/blackbox_recorder(T)
BR.msg_common = msg_common
BR.msg_science = msg_science
BR.msg_command = msg_command
BR.msg_medical = msg_medical
BR.msg_engineering = msg_engineering
BR.msg_security = msg_security
BR.msg_deathsquad = msg_deathsquad
BR.msg_syndicate = msg_syndicate
BR.msg_mining = msg_mining
BR.msg_cargo = msg_cargo
BR.feedback = feedback
BR.messages = messages
BR.messages_admin = messages_admin
if(blackbox != BR)
blackbox = BR
..()
/obj/machinery/blackbox_recorder/proc/find_feedback_datum(var/variable)
for(var/datum/feedback_variable/FV in feedback)
if(FV.get_variable() == variable)
return FV
var/datum/feedback_variable/FV = new(variable)
feedback += FV
return FV
/obj/machinery/blackbox_recorder/proc/get_round_feedback()
return feedback
/obj/machinery/blackbox_recorder/proc/round_end_data_gathering()
var/pda_msg_amt = 0
var/rc_msg_amt = 0
for(var/obj/machinery/message_server/MS in machines)
if(MS.pda_msgs.len > pda_msg_amt)
pda_msg_amt = MS.pda_msgs.len
if(MS.rc_msgs.len > rc_msg_amt)
rc_msg_amt = MS.rc_msgs.len
feedback_set_details("radio_usage","")
feedback_add_details("radio_usage","COM-[msg_common.len]")
feedback_add_details("radio_usage","SCI-[msg_science.len]")
feedback_add_details("radio_usage","HEA-[msg_command.len]")
feedback_add_details("radio_usage","MED-[msg_medical.len]")
feedback_add_details("radio_usage","ENG-[msg_engineering.len]")
feedback_add_details("radio_usage","SEC-[msg_security.len]")
feedback_add_details("radio_usage","DTH-[msg_deathsquad.len]")
feedback_add_details("radio_usage","SYN-[msg_syndicate.len]")
feedback_add_details("radio_usage","MIN-[msg_mining.len]")
feedback_add_details("radio_usage","CAR-[msg_cargo.len]")
feedback_add_details("radio_usage","OTH-[messages.len]")
feedback_add_details("radio_usage","PDA-[pda_msg_amt]")
feedback_add_details("radio_usage","RC-[rc_msg_amt]")
feedback_set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set.
//This proc is only to be called at round end.
/obj/machinery/blackbox_recorder/proc/save_all_data_to_sql()
if(!feedback) return
round_end_data_gathering() //round_end time logging and some other data processing
establish_db_connection()
if(!dbcon.IsConnected()) return
var/round_id
var/DBQuery/query = dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM erro_feedback")
query.Execute()
while(query.NextRow())
round_id = query.item[1]
if(!isnum(round_id))
round_id = text2num(round_id)
round_id++
for(var/datum/feedback_variable/FV in feedback)
var/sql = "INSERT INTO erro_feedback VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")"
var/DBQuery/query_insert = dbcon.NewQuery(sql)
query_insert.Execute()
// Sanitize inputs to avoid SQL injection attacks
proc/sql_sanitize_text(var/text)
text = replacetext(text, "'", "''")
text = replacetext(text, ";", "")
text = replacetext(text, "&", "")
return text
proc/feedback_set(var/variable,var/value)
if(!blackbox) return
variable = sql_sanitize_text(variable)
var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable)
if(!FV) return
FV.set_value(value)
proc/feedback_inc(var/variable,var/value)
if(!blackbox) return
variable = sql_sanitize_text(variable)
var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable)
if(!FV) return
FV.inc(value)
proc/feedback_dec(var/variable,var/value)
if(!blackbox) return
variable = sql_sanitize_text(variable)
var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable)
if(!FV) return
FV.dec(value)
proc/feedback_set_details(var/variable,var/details)
if(!blackbox) return
variable = sql_sanitize_text(variable)
details = sql_sanitize_text(details)
var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable)
if(!FV) return
FV.set_details(details)
proc/feedback_add_details(var/variable,var/details)
if(!blackbox) return
variable = sql_sanitize_text(variable)
details = sql_sanitize_text(details)
var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable)
if(!FV) return
FV.add_details(details)
+183
View File
@@ -0,0 +1,183 @@
/*
Protolathe
Similar to an autolathe, you load glass and metal sheets (but not other objects) into it to be used as raw materials for the stuff
it creates. All the menus and other manipulation commands are in the R&D console.
Note: Must be placed west/left of and R&D console to function.
*/
/obj/machinery/r_n_d/protolathe
name = "Protolathe"
icon_state = "protolathe"
flags = OPENCONTAINER
var/max_material_storage = 100000 //All this could probably be done better with a list but meh.
var/m_amount = 0.0
var/g_amount = 0.0
var/gold_amount = 0.0
var/silver_amount = 0.0
var/plasma_amount = 0.0
var/uranium_amount = 0.0
var/diamond_amount = 0.0
var/clown_amount = 0.0
var/adamantine_amount = 0.0
/obj/machinery/r_n_d/protolathe/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/protolathe(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
RefreshParts()
/obj/machinery/r_n_d/protolathe/proc/TotalMaterials() //returns the total of all the stored materials. Makes code neater.
return m_amount + g_amount + gold_amount + silver_amount + plasma_amount + uranium_amount + diamond_amount + clown_amount
/obj/machinery/r_n_d/protolathe/RefreshParts()
var/T = 0
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
T += G.reagents.maximum_volume
var/datum/reagents/R = new/datum/reagents(T) //Holder for the reagents used as materials.
reagents = R
R.my_atom = src
T = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
T += M.rating
max_material_storage = T * 75000
/obj/machinery/r_n_d/protolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if (shocked)
shock(user,50)
if (O.is_open_container())
return 1
if (istype(O, /obj/item/weapon/screwdriver))
if (!opened)
opened = 1
if(linked_console)
linked_console.linked_lathe = null
linked_console = null
icon_state = "protolathe_t"
user << "You open the maintenance hatch of [src]."
else
opened = 0
icon_state = "protolathe"
user << "You close the maintenance hatch of [src]."
return
if (opened)
if(istype(O, /obj/item/weapon/crowbar))
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker))
reagents.trans_to(I, reagents.total_volume)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
if(m_amount >= 3750)
var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src.loc)
G.amount = round(m_amount / G.perunit)
if(g_amount >= 3750)
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
G.amount = round(g_amount / G.perunit)
if(plasma_amount >= 2000)
var/obj/item/stack/sheet/mineral/plasma/G = new /obj/item/stack/sheet/mineral/plasma(src.loc)
G.amount = round(plasma_amount / G.perunit)
if(silver_amount >= 2000)
var/obj/item/stack/sheet/mineral/silver/G = new /obj/item/stack/sheet/mineral/silver(src.loc)
G.amount = round(silver_amount / G.perunit)
if(gold_amount >= 2000)
var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
G.amount = round(gold_amount / G.perunit)
if(uranium_amount >= 2000)
var/obj/item/stack/sheet/mineral/uranium/G = new /obj/item/stack/sheet/mineral/uranium(src.loc)
G.amount = round(uranium_amount / G.perunit)
if(diamond_amount >= 2000)
var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
G.amount = round(diamond_amount / G.perunit)
if(clown_amount >= 2000)
var/obj/item/stack/sheet/mineral/clown/G = new /obj/item/stack/sheet/mineral/clown(src.loc)
G.amount = round(clown_amount / G.perunit)
if(adamantine_amount >= 2000)
var/obj/item/stack/sheet/mineral/adamantine/G = new /obj/item/stack/sheet/mineral/adamantine(src.loc)
G.amount = round(adamantine_amount / G.perunit)
del(src)
return 1
else
user << "\red You can't load the [src.name] while it's opened."
return 1
if (disabled)
return
if (!linked_console)
user << "\The protolathe must be linked to an R&D console first!"
return 1
if (busy)
user << "\red The protolathe is busy. Please wait for completion of previous operation."
return 1
if (!istype(O, /obj/item/stack/sheet))
user << "\red You cannot insert this item into the protolathe!"
return 1
if (stat)
return 1
if(istype(O,/obj/item/stack/sheet))
var/obj/item/stack/sheet/S = O
if (TotalMaterials() + S.perunit > max_material_storage)
user << "\red The protolathe's material bin is full. Please remove material before adding more."
return 1
var/obj/item/stack/sheet/stack = O
var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
if(!O)
return
if(amount < 0)//No negative numbers
amount = 0
if(amount == 0)
return
if(amount > stack.amount)
amount = stack.amount
if(max_material_storage - TotalMaterials() < (amount*stack.perunit))//Can't overfill
amount = min(stack.amount, round((max_material_storage-TotalMaterials())/stack.perunit))
src.overlays += "protolathe_[stack.name]"
sleep(10)
src.overlays -= "protolathe_[stack.name]"
icon_state = "protolathe"
busy = 1
use_power(max(1000, (3750*amount/10)))
var/stacktype = stack.type
stack.use(amount)
if (do_after(user, 16))
user << "\blue You add [amount] sheets to the [src.name]."
icon_state = "protolathe"
switch(stacktype)
if(/obj/item/stack/sheet/metal)
m_amount += amount * 3750
if(/obj/item/stack/sheet/glass)
g_amount += amount * 3750
if(/obj/item/stack/sheet/mineral/gold)
gold_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/silver)
silver_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/plasma)
plasma_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/uranium)
uranium_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/diamond)
diamond_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/clown)
clown_amount += amount * 2000
if(/obj/item/stack/sheet/mineral/adamantine)
adamantine_amount += amount * 2000
else
new stacktype(src.loc, amount)
busy = 0
src.updateUsrDialog()
return
+239
View File
@@ -0,0 +1,239 @@
/*
Research and Development System. (Designed specifically for the /tg/station 13 (Space Station 13) open source project)
///////////////Overview///////////////////
This system is a "tech tree" research and development system designed for SS13. It allows a "researcher" job (this document assumes
the "scientist" job is given this role) the tools necessiary to research new and better technologies. In general, the system works
by breaking existing technology and using what you learn from to advance your knowledge of SCIENCE! As your knowledge progresses,
you can build newer (and better?) devices (which you can also, eventually, deconstruct to advance your knowledge).
A brief overview is below. For more details, see the related files.
////////////Game Use/////////////
The major research and development is performed using a combination of four machines:
- R&D Console: A computer console that allows you to manipulate the other devices that are linked to it and view/manipulate the
technologies you have researched so far.
- Protolathe: Used to make new hand-held devices and parts for larger devices. All metals and reagents as raw materials.
- Destructive Analyzer: You can put hand-held objects into it and it'll analyze them for technological advancements but it destroys
them in the process. Destroyed items will send their raw materials to a linked Protolathe (if any)
- Circuit Imprinter: Similar to the Protolathe, it allows for the construction of circuit boards. Uses glass and acid as the raw
materials.
While researching you are dealing with two different types of information: Technology Paths and Device Designs. Technology Paths
are the "Tech Trees" of the game. You start out with a number of them at the game start and they are improved by using the
Destructive Analyzer. By themselves, they don't do a whole lot. However, they unlock Device Designs. This is the information used
by the circuit imprinter and the protolathe to produce objects. It also tracks the current reliability of that particular design.
//EXISTING TECH
Each tech path should have at LEAST one item at every level (levels 1 - 20). This is to allow for a more fluid progression of the
researching. Existing tech (ie, anything you can find on the station or get from the quartermaster) shouldn't go higher then
level 5 or 7. Everything past that should be stuff you research.
Below is a checklist to make sure every tree is filled. As new items get added to R&D, add them here if there is an empty slot.
When thinking about new stuff, check here to see if there are any slots unfilled.
//MATERIALS
1 | Metal
2 | Solid Plasma
3 | Silver
4 | Gold, Super Capacitor
5 | Uranium, Nuclear Gun, SUPERPACMAN
6 | Diamond, MRSPACMAN
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//PLASMA TECH
1 |
2 | Solid Plasma
3 | Pacman Generator
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//POWER TECH
1 | Basic Capacitor, Basic Cell
2 | High-Capacity Cell (10,000)
3 | Super-Capacity Cell (20,000), Powersink, PACMAN
4 | SUPERPACMAN
5 | MRSPACMAN, Super Capacitor
6 | Hyper-Capacity Cell (30,000)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//BLUE SPACE
1 |
2 | Teleporter Console Board
3 | Teleport Gun, Hand Tele
4 | Teleportation Scroll
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//BIOTECH
1 | Bruise Pack, Scalple
2 | PANDEMIC Board, Mass Spectrometer
3 | AI Core, Brains (MMI)
4 | MMI+Radio
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//MAGNETS
1 | Basic Sensor
2 | Comm Console Board
3 | Adv Sensor
4 | Adv Mass Spectrometer, Chameleon Projector
5 | Phasic Sensor
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//PROGRAMMING
1 | Arcade Board
2 | Sec Camera
3 | Cloning Machine Console Board
4 | AI Core, Intellicard
5 | Pico-Manipulator, Ultra-Micro-Laser
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//SYNDICATE
1 | Sleepypen
2 | TYRANT Module, Emag
3 | Cloaking Device, Power Sink
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
//COMBAT
1 | Flashbang, Mousetrap, Nettle
2 | Stun Baton
3 | Power Axe, Death Nettle, Nuclear Gun
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
*/
+915
View File
@@ -0,0 +1,915 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
/*
Research and Development (R&D) Console
This is the main work horse of the R&D system. It contains the menus/controls for the Destructive Analyzer, Protolathe, and Circuit
imprinter. It also contains the /datum/research holder with all the known/possible technology paths and device designs.
Basic use: When it first is created, it will attempt to link up to related devices within 3 squares. It'll only link up if they
aren't already linked to another console. Any consoles it cannot link up with (either because all of a certain type are already
linked or there aren't any in range), you'll just not have access to that menu. In the settings menu, there are menu options that
allow a player to attempt to re-sync with nearby consoles. You can also force it to disconnect from a specific console.
The imprinting and construction menus do NOT require toxins access to access but all the other menus do. However, if you leave it
on a menu, nothing is to stop the person from using the options on that menu (although they won't be able to change to a different
one). You can also lock the console on the settings menu if you're feeling paranoid and you don't want anyone messing with it who
doesn't have toxins access.
When a R&D console is destroyed or even partially disassembled, you lose all research data on it. However, there are two ways around
this dire fate:
- The easiest way is to go to the settings menu and select "Sync Database with Network." That causes it to upload (but not download)
it's data to every other device in the game. Each console has a "disconnect from network" option that'll will cause data base sync
operations to skip that console. This is useful if you want to make a "public" R&D console or, for example, give the engineers
a circuit imprinter with certain designs on it and don't want it accidentally updating. The downside of this method is that you have
to have physical access to the other console to send data back. Note: An R&D console is on CentCom so if a random griffan happens to
cause a ton of data to be lost, an admin can go send it back.
- The second method is with Technology Disks and Design Disks. Each of these disks can hold a single technology or design datum in
it's entirety. You can then take the disk to any R&D console and upload it's data to it. This method is a lot more secure (since it
won't update every console in existence) but it's more of a hassle to do. Also, the disks can be stolen.
*/
/obj/machinery/computer/rdconsole
name = "R&D Console"
icon_state = "rdcomp"
var/datum/research/files //Stores all the collected research data.
var/obj/item/weapon/disk/tech_disk/t_disk = null //Stores the technology disk.
var/obj/item/weapon/disk/design_disk/d_disk = null //Stores the design disk.
var/obj/machinery/r_n_d/destructive_analyzer/linked_destroy = null //Linked Destructive Analyzer
var/obj/machinery/r_n_d/protolathe/linked_lathe = null //Linked Protolathe
var/obj/machinery/r_n_d/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter
var/screen = 1.0 //Which screen is currently showing.
var/id = 0 //ID of the computer (for server restrictions).
var/sync = 1 //If sync = 0, it doesn't show up on Server Control Console
req_access = list(access_tox) //Data and setting manipulation requires scientist access.
/obj/machinery/computer/rdconsole/proc/CallTechName(var/ID) //A simple helper proc to find the name of a tech with a given ID.
var/datum/tech/check_tech
var/return_name = null
for(var/T in typesof(/datum/tech) - /datum/tech)
check_tech = null
check_tech = new T()
if(check_tech.id == ID)
return_name = check_tech.name
del(check_tech)
check_tech = null
break
return return_name
/obj/machinery/computer/rdconsole/proc/CallMaterialName(var/ID)
var/datum/reagent/temp_reagent
var/return_name = null
if (copytext(ID, 1, 2) == "$")
return_name = copytext(ID, 2)
switch(return_name)
if("metal")
return_name = "Metal"
if("glass")
return_name = "Glass"
if("gold")
return_name = "Gold"
if("silver")
return_name = "Silver"
if("plasma")
return_name = "Solid Plasma"
if("uranium")
return_name = "Uranium"
if("diamond")
return_name = "Diamond"
if("clown")
return_name = "Bananium"
else
for(var/R in typesof(/datum/reagent) - /datum/reagent)
temp_reagent = null
temp_reagent = new R()
if(temp_reagent.id == ID)
return_name = temp_reagent.name
del(temp_reagent)
temp_reagent = null
break
return return_name
/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any).
for(var/obj/machinery/r_n_d/D in oview(3,src))
if(D.linked_console != null || D.disabled || D.opened)
continue
if(istype(D, /obj/machinery/r_n_d/destructive_analyzer))
if(linked_destroy == null)
linked_destroy = D
D.linked_console = src
else if(istype(D, /obj/machinery/r_n_d/protolathe))
if(linked_lathe == null)
linked_lathe = D
D.linked_console = src
else if(istype(D, /obj/machinery/r_n_d/circuit_imprinter))
if(linked_imprinter == null)
linked_imprinter = D
D.linked_console = src
return
//Have it automatically push research to the centcomm server so wild griffins can't fuck up R&D's work --NEO
/obj/machinery/computer/rdconsole/proc/griefProtection()
for(var/obj/machinery/r_n_d/server/centcom/C in machines)
for(var/datum/tech/T in files.known_tech)
C.files.AddTech2Known(T)
for(var/datum/design/D in files.known_designs)
C.files.AddDesign2Known(D)
C.files.RefreshResearch()
/obj/machinery/computer/rdconsole/New()
..()
files = new /datum/research(src) //Setup the research data holder.
if(!id)
for(var/obj/machinery/r_n_d/server/centcom/S in machines)
S.initialize()
break
/obj/machinery/computer/rdconsole/initialize()
SyncRDevices()
/* Instead of calling this every tick, it is only being called when needed
/obj/machinery/computer/rdconsole/process()
griefProtection()
*/
/obj/machinery/computer/rdconsole/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob)
//The construction/deconstruction of the console code.
if(istype(D, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
new /obj/item/weapon/shard( src.loc )
var/obj/item/weapon/circuitboard/rdconsole/M = new /obj/item/weapon/circuitboard/rdconsole( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.state = 3
A.icon_state = "3"
A.anchored = 1
del(src)
else
user << "\blue You disconnect the monitor."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/item/weapon/circuitboard/rdconsole/M = new /obj/item/weapon/circuitboard/rdconsole( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.state = 4
A.icon_state = "4"
A.anchored = 1
del(src)
//Loading a disk into it.
else if(istype(D, /obj/item/weapon/disk))
if(t_disk || d_disk)
user << "A disk is already loaded into the machine."
return
if(istype(D, /obj/item/weapon/disk/tech_disk)) t_disk = D
else if (istype(D, /obj/item/weapon/disk/design_disk)) d_disk = D
else
user << "\red Machine cannot accept disks in that format."
return
user.drop_item()
D.loc = src
user << "\blue You add the disk to the machine!"
else if(istype(D, /obj/item/weapon/card/emag) && !emagged)
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
user << "\blue You you disable the security protocols"
src.updateUsrDialog()
return
/obj/machinery/computer/rdconsole/Topic(href, href_list)
if(..())
return
add_fingerprint(usr)
usr.set_machine(src)
if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code.
var/temp_screen = text2num(href_list["menu"])
if(temp_screen <= 1.1 || (3 <= temp_screen && 4.9 >= temp_screen) || src.allowed(usr) || emagged) //Unless you are making something, you need access.
screen = temp_screen
else
usr << "Unauthorized Access."
else if(href_list["updt_tech"]) //Update the research holder with information from the technology disk.
screen = 0.0
spawn(50)
screen = 1.2
files.AddTech2Known(t_disk.stored)
updateUsrDialog()
griefProtection() //Update centcomm too
else if(href_list["clear_tech"]) //Erase data on the technology disk.
t_disk.stored = null
else if(href_list["eject_tech"]) //Eject the technology disk.
t_disk:loc = src.loc
t_disk = null
screen = 1.0
else if(href_list["copy_tech"]) //Copys some technology data from the research holder to the disk.
for(var/datum/tech/T in files.known_tech)
if(href_list["copy_tech_ID"] == T.id)
t_disk.stored = T
break
screen = 1.2
else if(href_list["updt_design"]) //Updates the research holder with design data from the design disk.
screen = 0.0
spawn(50)
screen = 1.4
files.AddDesign2Known(d_disk.blueprint)
updateUsrDialog()
griefProtection() //Update centcomm too
else if(href_list["clear_design"]) //Erases data on the design disk.
d_disk.blueprint = null
else if(href_list["eject_design"]) //Eject the design disk.
d_disk:loc = src.loc
d_disk = null
screen = 1.0
else if(href_list["copy_design"]) //Copy design data from the research holder to the design disk.
for(var/datum/design/D in files.known_designs)
if(href_list["copy_design_ID"] == D.id)
d_disk.blueprint = D
break
screen = 1.4
else if(href_list["eject_item"]) //Eject the item inside the destructive analyzer.
if(linked_destroy)
if(linked_destroy.busy)
usr << "\red The destructive analyzer is busy at the moment."
else if(linked_destroy.loaded_item)
linked_destroy.loaded_item.loc = linked_destroy.loc
linked_destroy.loaded_item = null
linked_destroy.icon_state = "d_analyzer"
screen = 2.1
else if(href_list["deconstruct"]) //Deconstruct the item in the destructive analyzer and update the research holder.
if(linked_destroy)
if(linked_destroy.busy)
usr << "\red The destructive analyzer is busy at the moment."
else
var/choice = input("Proceeding will destroy loaded item.") in list("Proceed", "Cancel")
if(choice == "Cancel" || !linked_destroy) return
linked_destroy.busy = 1
screen = 0.1
updateUsrDialog()
flick("d_analyzer_process", linked_destroy)
spawn(24)
if(linked_destroy)
linked_destroy.busy = 0
if(!linked_destroy.hacked)
if(!linked_destroy.loaded_item)
usr <<"\red The destructive analyzer appears to be empty."
screen = 1.0
return
if(linked_destroy.loaded_item.reliability >= 90)
var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
for(var/T in temp_tech)
files.UpdateTech(T, temp_tech[T])
if(linked_destroy.loaded_item.reliability < 100 && linked_destroy.loaded_item.crit_fail)
files.UpdateDesign(linked_destroy.loaded_item.type)
if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any.
linked_lathe.m_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.m_amt*linked_destroy.decon_mod))
linked_lathe.g_amount += min((linked_lathe.max_material_storage - linked_lathe.TotalMaterials()), (linked_destroy.loaded_item.g_amt*linked_destroy.decon_mod))
linked_destroy.loaded_item = null
for(var/obj/I in linked_destroy.contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/sheet))//Only deconsturcts one sheet at a time instead of the entire stack
var/obj/item/stack/sheet/S = I
if(S.amount > 1)
S.amount--
linked_destroy.loaded_item = S
else
del(S)
linked_destroy.icon_state = "d_analyzer"
else
if(!(I in linked_destroy.component_parts))
del(I)
linked_destroy.icon_state = "d_analyzer"
use_power(250)
screen = 1.0
updateUsrDialog()
else if(href_list["lock"]) //Lock the console from use by anyone without tox access.
if(src.allowed(usr))
screen = text2num(href_list["lock"])
else
usr << "Unauthorized Access."
else if(href_list["sync"]) //Sync the research holder with all the R&D consoles in the game that aren't sync protected.
screen = 0.0
if(!sync)
usr << "\red You must connect to the network first!"
else
griefProtection() //Putting this here because I dont trust the sync process
spawn(30)
if(src)
for(var/obj/machinery/r_n_d/server/S in machines)
var/server_processed = 0
if(S.disabled)
continue
if((id in S.id_with_upload) || istype(S, /obj/machinery/r_n_d/server/centcom))
for(var/datum/tech/T in files.known_tech)
S.files.AddTech2Known(T)
for(var/datum/design/D in files.known_designs)
S.files.AddDesign2Known(D)
S.files.RefreshResearch()
server_processed = 1
if(((id in S.id_with_download) && !istype(S, /obj/machinery/r_n_d/server/centcom)) || S.hacked)
for(var/datum/tech/T in S.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in S.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
server_processed = 1
if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed)
S.produce_heat(100)
screen = 1.6
updateUsrDialog()
else if(href_list["togglesync"]) //Prevents the console from being synced by other consoles. Can still send data.
sync = !sync
else if(href_list["build"]) //Causes the Protolathe to build something.
if(linked_lathe)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == href_list["build"])
being_built = D
break
if(being_built)
var/power = 2000
for(var/M in being_built.materials)
power += round(being_built.materials[M] / 5)
power = max(2000, power)
screen = 0.3
linked_lathe.busy = 1
flick("protolathe_n",linked_lathe)
var/key = usr.key //so we don't lose the info during the spawn delay
spawn(16)
use_power(power)
spawn(16)
for(var/M in being_built.materials)
switch(M)
if("$metal")
linked_lathe.m_amount = max(0, (linked_lathe.m_amount-being_built.materials[M]))
if("$glass")
linked_lathe.g_amount = max(0, (linked_lathe.g_amount-being_built.materials[M]))
if("$gold")
linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-being_built.materials[M]))
if("$silver")
linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-being_built.materials[M]))
if("$plasma")
linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-being_built.materials[M]))
if("$uranium")
linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-being_built.materials[M]))
if("$diamond")
linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-being_built.materials[M]))
if("$clown")
linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-being_built.materials[M]))
else
linked_lathe.reagents.remove_reagent(M, being_built.materials[M])
if(being_built.build_path)
var/obj/new_item = new being_built.build_path(src)
if( new_item.type == /obj/item/weapon/storage/backpack/holding )
new_item.investigate_log("built by [key]","singulo")
new_item.reliability = being_built.reliability
if(linked_lathe.hacked) being_built.reliability = max((reliability / 2), 0)
/*if(being_built.locked)
var/obj/item/weapon/storage/lockbox/L = new/obj/item/weapon/storage/lockbox(linked_lathe.loc)
new_item.loc = L
L.name += " ([new_item.name])"*/
else
new_item.loc = linked_lathe.loc
linked_lathe.busy = 0
screen = 3.1
updateUsrDialog()
else if(href_list["imprint"]) //Causes the Circuit Imprinter to build something.
if(linked_imprinter)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == href_list["imprint"])
being_built = D
break
if(being_built)
var/power = 2000
for(var/M in being_built.materials)
power += round(being_built.materials[M] / 5)
power = max(2000, power)
screen = 0.4
linked_imprinter.busy = 1
flick("circuit_imprinter_ani",linked_imprinter)
spawn(16)
use_power(power)
for(var/M in being_built.materials)
switch(M)
if("$glass")
linked_imprinter.g_amount = max(0, (linked_imprinter.g_amount-being_built.materials[M]))
if("$gold")
linked_imprinter.gold_amount = max(0, (linked_imprinter.gold_amount-being_built.materials[M]))
if("$diamond")
linked_imprinter.diamond_amount = max(0, (linked_imprinter.diamond_amount-being_built.materials[M]))
if("$uranium")
linked_imprinter.uranium_amount = max(0, (linked_imprinter.uranium_amount-being_built.materials[M]))
else
linked_imprinter.reagents.remove_reagent(M, being_built.materials[M])
var/obj/new_item = new being_built.build_path(src)
new_item.reliability = being_built.reliability
if(linked_imprinter.hacked) being_built.reliability = max((reliability / 2), 0)
new_item.loc = linked_imprinter.loc
linked_imprinter.busy = 0
screen = 4.1
updateUsrDialog()
else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it)
linked_imprinter.reagents.del_reagent(href_list["dispose"])
else if(href_list["disposeallI"] && linked_imprinter) //Causes the circuit imprinter to dispose of all it's reagents.
linked_imprinter.reagents.clear_reagents()
else if(href_list["disposeP"] && linked_lathe) //Causes the protolathe to dispose of a single reagent (all of it)
linked_lathe.reagents.del_reagent(href_list["dispose"])
else if(href_list["disposeallP"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents.
linked_lathe.reagents.clear_reagents()
else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material
var/desired_num_sheets = text2num(href_list["lathe_ejectsheet_amt"])
var/res_amount, type
switch(href_list["lathe_ejectsheet"])
if("metal")
type = /obj/item/stack/sheet/metal
res_amount = "m_amount"
if("glass")
type = /obj/item/stack/sheet/glass
res_amount = "g_amount"
if("gold")
type = /obj/item/stack/sheet/mineral/gold
res_amount = "gold_amount"
if("silver")
type = /obj/item/stack/sheet/mineral/silver
res_amount = "silver_amount"
if("plasma")
type = /obj/item/stack/sheet/mineral/plasma
res_amount = "plasma_amount"
if("uranium")
type = /obj/item/stack/sheet/mineral/uranium
res_amount = "uranium_amount"
if("diamond")
type = /obj/item/stack/sheet/mineral/diamond
res_amount = "diamond_amount"
if("clown")
type = /obj/item/stack/sheet/mineral/clown
res_amount = "clown_amount"
if(ispath(type) && hasvar(linked_lathe, res_amount))
var/obj/item/stack/sheet/sheet = new type(linked_lathe.loc)
var/available_num_sheets = round(linked_lathe.vars[res_amount]/sheet.perunit)
if(available_num_sheets>0)
sheet.amount = min(available_num_sheets, desired_num_sheets)
linked_lathe.vars[res_amount] = max(0, (linked_lathe.vars[res_amount]-sheet.amount * sheet.perunit))
else
del sheet
else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the protolathe to eject a sheet of material
var/desired_num_sheets = text2num(href_list["imprinter_ejectsheet_amt"])
var/res_amount, type
switch(href_list["imprinter_ejectsheet"])
if("glass")
type = /obj/item/stack/sheet/glass
res_amount = "g_amount"
if("gold")
type = /obj/item/stack/sheet/mineral/gold
res_amount = "gold_amount"
if("diamond")
type = /obj/item/stack/sheet/mineral/diamond
res_amount = "diamond_amount"
if("uranium")
type = /obj/item/stack/sheet/mineral/uranium
res_amount = "uranium_amount"
if(ispath(type) && hasvar(linked_imprinter, res_amount))
var/obj/item/stack/sheet/sheet = new type(linked_imprinter.loc)
var/available_num_sheets = round(linked_imprinter.vars[res_amount]/sheet.perunit)
if(available_num_sheets>0)
sheet.amount = min(available_num_sheets, desired_num_sheets)
linked_imprinter.vars[res_amount] = max(0, (linked_imprinter.vars[res_amount]-sheet.amount * sheet.perunit))
else
del sheet
else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with.
screen = 0.0
spawn(20)
SyncRDevices()
screen = 1.7
updateUsrDialog()
else if(href_list["disconnect"]) //The R&D console disconnects with a specific device.
switch(href_list["disconnect"])
if("destroy")
linked_destroy.linked_console = null
linked_destroy = null
if("lathe")
linked_lathe.linked_console = null
linked_lathe = null
if("imprinter")
linked_imprinter.linked_console = null
linked_imprinter = null
else if(href_list["reset"]) //Reset the R&D console's database.
griefProtection()
var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
screen = 0.0
del(files)
files = new /datum/research(src)
spawn(20)
screen = 1.6
updateUsrDialog()
updateUsrDialog()
return
/obj/machinery/computer/rdconsole/attack_hand(mob/user as mob)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
var/dat = ""
files.RefreshResearch()
switch(screen) //A quick check to make sure you get the right screen when a device is disconnected.
if(2 to 2.9)
if(linked_destroy == null)
screen = 2.0
else if(linked_destroy.loaded_item == null)
screen = 2.1
else
screen = 2.2
if(3 to 3.9)
if(linked_lathe == null)
screen = 3.0
if(4 to 4.9)
if(linked_imprinter == null)
screen = 4.0
switch(screen)
//////////////////////R&D CONSOLE SCREENS//////////////////
if(0.0) dat += "Updating Database...."
if(0.1) dat += "Processing and Updating Database..."
if(0.2)
dat += "SYSTEM LOCKED<BR><BR>"
dat += "<A href='?src=\ref[src];lock=1.6'>Unlock</A>"
if(0.3)
dat += "Constructing Prototype. Please Wait..."
if(0.4)
dat += "Imprinting Circuit. Please Wait..."
if(1.0) //Main Menu
dat += "Main Menu:<BR><BR>"
dat += "<A href='?src=\ref[src];menu=1.1'>Current Research Levels</A><BR>"
if(t_disk) dat += "<A href='?src=\ref[src];menu=1.2'>Disk Operations</A><BR>"
else if(d_disk) dat += "<A href='?src=\ref[src];menu=1.4'>Disk Operations</A><BR>"
else dat += "(Please Insert Disk)<BR>"
if(linked_destroy != null) dat += "<A href='?src=\ref[src];menu=2.2'>Destructive Analyzer Menu</A><BR>"
if(linked_lathe != null) dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Construction Menu</A><BR>"
if(linked_imprinter != null) dat += "<A href='?src=\ref[src];menu=4.1'>Circuit Construction Menu</A><BR>"
dat += "<A href='?src=\ref[src];menu=1.6'>Settings</A>"
if(1.1) //Research viewer
dat += "Current Research Levels:<BR><BR>"
for(var/datum/tech/T in files.known_tech)
dat += "[T.name]<BR>"
dat += "* Level: [T.level]<BR>"
dat += "* Summary: [T.desc]<HR>"
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A>"
if(1.2) //Technology Disk Menu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "Disk Contents: (Technology Data Disk)<BR><BR>"
if(t_disk.stored == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];menu=1.3'>Load Tech to Disk</A> || "
else
dat += "Name: [t_disk.stored.name]<BR>"
dat += "Level: [t_disk.stored.level]<BR>"
dat += "Description: [t_disk.stored.desc]<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];updt_tech=1'>Upload to Database</A> || "
dat += "<A href='?src=\ref[src];clear_tech=1'>Clear Disk</A> || "
dat += "<A href='?src=\ref[src];eject_tech=1'>Eject Disk</A>"
if(1.3) //Technology Disk submenu
dat += "<BR><A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.2'>Return to Disk Operations</A><HR>"
dat += "Load Technology to Disk:<BR><BR>"
for(var/datum/tech/T in files.known_tech)
dat += "[T.name] "
dat += "<A href='?src=\ref[src];copy_tech=1;copy_tech_ID=[T.id]'>(Copy to Disk)</A><BR>"
if(1.4) //Design Disk menu.
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
if(d_disk.blueprint == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];menu=1.5'>Load Design to Disk</A> || "
else
dat += "Name: [d_disk.blueprint.name]<BR>"
dat += "Level: [between(0, (d_disk.blueprint.reliability + rand(-15,15)), 100)]<BR>"
switch(d_disk.blueprint.build_type)
if(IMPRINTER) dat += "Lathe Type: Circuit Imprinter<BR>"
if(PROTOLATHE) dat += "Lathe Type: Proto-lathe<BR>"
if(AUTOLATHE) dat += "Lathe Type: Auto-lathe<BR>"
dat += "Required Materials:<BR>"
for(var/M in d_disk.blueprint.materials)
if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]<BR>"
else dat += "* [M] x [d_disk.blueprint.materials[M]]<BR>"
dat += "<HR>Operations: "
dat += "<A href='?src=\ref[src];updt_design=1'>Upload to Database</A> || "
dat += "<A href='?src=\ref[src];clear_design=1'>Clear Disk</A> || "
dat += "<A href='?src=\ref[src];eject_design=1'>Eject Disk</A>"
if(1.5) //Technology disk submenu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.4'>Return to Disk Operations</A><HR>"
dat += "Load Design to Disk:<BR><BR>"
for(var/datum/design/D in files.known_designs)
dat += "[D.name] "
dat += "<A href='?src=\ref[src];copy_design=1;copy_design_ID=[D.id]'>(Copy to Disk)</A><BR>"
if(1.6) //R&D console settings
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "R&D Console Setting:<BR><BR>"
if(sync)
dat += "<A href='?src=\ref[src];sync=1'>Sync Database with Network</A><BR>"
dat += "<A href='?src=\ref[src];togglesync=1'>Disconnect from Research Network</A><BR>"
else
dat += "<A href='?src=\ref[src];togglesync=1'>Connect to Research Network</A><BR>"
dat += "<A href='?src=\ref[src];menu=1.7'>Device Linkage Menu</A><BR>"
dat += "<A href='?src=\ref[src];lock=0.2'>Lock Console</A><BR>"
dat += "<A href='?src=\ref[src];reset=1'>Reset R&D Database.</A><BR>"
if(1.7) //R&D device linkage
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.6'>Settings Menu</A><HR> "
dat += "R&D Console Device Linkage Menu:<BR><BR>"
dat += "<A href='?src=\ref[src];find_device=1'>Re-sync with Nearby Devices</A><BR>"
dat += "Linked Devices:<BR>"
if(linked_destroy)
dat += "* Destructive Analyzer <A href='?src=\ref[src];disconnect=destroy'>(Disconnect)</A><BR>"
else
dat += "* (No Destructive Analyzer Linked)<BR>"
if(linked_lathe)
dat += "* Protolathe <A href='?src=\ref[src];disconnect=lathe'>(Disconnect)</A><BR>"
else
dat += "* (No Protolathe Linked)<BR>"
if(linked_imprinter)
dat += "* Circuit Imprinter <A href='?src=\ref[src];disconnect=imprinter'>(Disconnect)</A><BR>"
else
dat += "* (No Circuit Imprinter Linked)<BR>"
////////////////////DESTRUCTIVE ANALYZER SCREENS////////////////////////////
if(2.0)
dat += "NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE<BR><BR>"
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A>"
if(2.1)
dat += "No Item Loaded. Standing-by...<BR><HR>"
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A>"
if(2.2)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "Deconstruction Menu<HR>"
dat += "Name: [linked_destroy.loaded_item.name]<BR>"
dat += "Origin Tech:<BR>"
var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
for(var/T in temp_tech)
dat += "* [CallTechName(T)] [temp_tech[T]]<BR>"
dat += "<HR><A href='?src=\ref[src];deconstruct=1'>Deconstruct Item</A> || "
dat += "<A href='?src=\ref[src];eject_item=1'>Eject Item</A> || "
/////////////////////PROTOLATHE SCREENS/////////////////////////
if(3.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "NO PROTOLATHE LINKED TO CONSOLE<BR><BR>"
if(3.1)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.2'>Material Storage</A> || "
dat += "<A href='?src=\ref[src];menu=3.3'>Chemical Storage</A><HR>"
dat += "Protolathe Menu:<BR><BR>"
dat += "<B>Material Amount:</B> [linked_lathe.TotalMaterials()] cm<sup>3</sup> (MAX: [linked_lathe.max_material_storage])<BR>"
dat += "<B>Chemical Volume:</B> [linked_lathe.reagents.total_volume] (MAX: [linked_lathe.reagents.maximum_volume])<HR>"
for(var/datum/design/D in files.known_designs)
if(!(D.build_type & PROTOLATHE))
continue
var/temp_dat = "[D.name]"
var/check_materials = 1
for(var/M in D.materials)
temp_dat += " [D.materials[M]] [CallMaterialName(M)]"
if(copytext(M, 1, 2) == "$")
switch(M)
if("$glass")
if(D.materials[M] > linked_lathe.g_amount) check_materials = 0
if("$metal")
if(D.materials[M] > linked_lathe.m_amount) check_materials = 0
if("$gold")
if(D.materials[M] > linked_lathe.gold_amount) check_materials = 0
if("$silver")
if(D.materials[M] > linked_lathe.silver_amount) check_materials = 0
if("$plasma")
if(D.materials[M] > linked_lathe.plasma_amount) check_materials = 0
if("$uranium")
if(D.materials[M] > linked_lathe.uranium_amount) check_materials = 0
if("$diamond")
if(D.materials[M] > linked_lathe.diamond_amount) check_materials = 0
if("$clown")
if(D.materials[M] > linked_lathe.clown_amount) check_materials = 0
else if (!linked_lathe.reagents.has_reagent(M, D.materials[M]))
check_materials = 0
if (check_materials)
dat += "* <A href='?src=\ref[src];build=[D.id]'>[temp_dat]</A><BR>"
else
dat += "* [temp_dat]<BR>"
if(3.2) //Protolathe Material Storage Sub-menu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Menu</A><HR>"
dat += "Material Storage<BR><HR>"
//Metal
dat += "* [linked_lathe.m_amount] cm<sup>3</sup> of Metal || "
dat += "Eject: "
if(linked_lathe.m_amount >= 3750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=metal;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.m_amount >= 18750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=metal;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.m_amount >= 3750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=metal;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Glass
dat += "* [linked_lathe.g_amount] cm<sup>3</sup> of Glass || "
dat += "Eject: "
if(linked_lathe.g_amount >= 3750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=glass;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.g_amount >= 18750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=glass;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.g_amount >= 3750) dat += "<A href='?src=\ref[src];lathe_ejectsheet=glass;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Gold
dat += "* [linked_lathe.gold_amount] cm<sup>3</sup> of Gold || "
dat += "Eject: "
if(linked_lathe.gold_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=gold;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.gold_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=gold;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.gold_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=gold;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Silver
dat += "* [linked_lathe.silver_amount] cm<sup>3</sup> of Silver || "
dat += "Eject: "
if(linked_lathe.silver_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=silver;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.silver_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=silver;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.silver_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=silver;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Plasma
dat += "* [linked_lathe.plasma_amount] cm<sup>3</sup> of Solid Plasma || "
dat += "Eject: "
if(linked_lathe.plasma_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=plasma;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.plasma_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=plasma;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.plasma_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=plasmalathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Uranium
dat += "* [linked_lathe.uranium_amount] cm<sup>3</sup> of Uranium || "
dat += "Eject: "
if(linked_lathe.uranium_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=uranium;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.uranium_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=uranium;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.uranium_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=uranium;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Diamond
dat += "* [linked_lathe.diamond_amount] cm<sup>3</sup> of Diamond || "
dat += "Eject: "
if(linked_lathe.diamond_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=diamond;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.diamond_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=diamond;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.diamond_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=diamond;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Bananium
dat += "* [linked_lathe.clown_amount] cm<sup>3</sup> of Bananium || "
dat += "Eject: "
if(linked_lathe.clown_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=clown;lathe_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_lathe.clown_amount >= 10000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=clown;lathe_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_lathe.clown_amount >= 2000) dat += "<A href='?src=\ref[src];lathe_ejectsheet=clown;lathe_ejectsheet_amt=50'>(Max Sheets)</A>"
if(3.3) //Protolathe Chemical Storage Submenu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Menu</A><HR>"
dat += "Chemical Storage<BR><HR>"
for(var/datum/reagent/R in linked_lathe.reagents.reagent_list)
dat += "Name: [R.name] | Units: [R.volume] "
dat += "<A href='?src=\ref[src];disposeP=[R.id]'>(Purge)</A><BR>"
dat += "<A href='?src=\ref[src];disposeallP=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
///////////////////CIRCUIT IMPRINTER SCREENS////////////////////
if(4.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "NO CIRCUIT IMPRINTER LINKED TO CONSOLE<BR><BR>"
if(4.1)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.3'>Material Storage</A> || "
dat += "<A href='?src=\ref[src];menu=4.2'>Chemical Storage</A><HR>"
dat += "Circuit Imprinter Menu:<BR><BR>"
dat += "Material Amount: [linked_imprinter.TotalMaterials()] cm<sup>3</sup><BR>"
dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]<HR>"
for(var/datum/design/D in files.known_designs)
if(!(D.build_type & IMPRINTER))
continue
var/temp_dat = "[D.name]"
var/check_materials = 1
for(var/M in D.materials)
temp_dat += " [D.materials[M]] [CallMaterialName(M)]"
if(copytext(M, 1, 2) == "$")
switch(M)
if("$glass")
if(D.materials[M] > linked_imprinter.g_amount) check_materials = 0
if("$gold")
if(D.materials[M] > linked_imprinter.gold_amount) check_materials = 0
if("$diamond")
if(D.materials[M] > linked_imprinter.diamond_amount) check_materials = 0
if("$uranium")
if(D.materials[M] > linked_imprinter.uranium_amount) check_materials = 0
else if (!linked_imprinter.reagents.has_reagent(M, D.materials[M]))
check_materials = 0
if (check_materials)
dat += "* <A href='?src=\ref[src];imprint=[D.id]'>[temp_dat]</A><BR>"
else
dat += "* [temp_dat]<BR>"
if(4.2)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.1'>Imprinter Menu</A><HR>"
dat += "Chemical Storage<BR><HR>"
for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list)
dat += "Name: [R.name] | Units: [R.volume] "
dat += "<A href='?src=\ref[src];disposeI=[R.id]'>(Purge)</A><BR>"
dat += "<A href='?src=\ref[src];disposeallI=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
if(4.3)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "Material Storage<BR><HR>"
//Glass
dat += "* [linked_imprinter.g_amount] cm<sup>3</sup> of Glass || "
dat += "Eject: "
if(linked_imprinter.g_amount >= 3750) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=glass;imprinter_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_imprinter.g_amount >= 18750) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=glass;imprinter_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_imprinter.g_amount >= 3750) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=glass;imprinter_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Gold
dat += "* [linked_imprinter.gold_amount] cm<sup>3</sup> of Gold || "
dat += "Eject: "
if(linked_imprinter.gold_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=gold;imprinter_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_imprinter.gold_amount >= 10000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=gold;imprinter_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_imprinter.gold_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=gold;imprinter_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Diamond
dat += "* [linked_imprinter.diamond_amount] cm<sup>3</sup> of Diamond || "
dat += "Eject: "
if(linked_imprinter.diamond_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=diamond;imprinter_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_imprinter.diamond_amount >= 10000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=diamond;imprinter_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_imprinter.diamond_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=diamond;imprinter_ejectsheet_amt=50'>(Max Sheets)</A>"
dat += "<BR>"
//Uranium
dat += "* [linked_imprinter.uranium_amount] cm<sup>3</sup> of Uranium || "
dat += "Eject: "
if(linked_imprinter.uranium_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=uranium;imprinter_ejectsheet_amt=1'>(1 Sheet)</A> "
if(linked_imprinter.uranium_amount >= 10000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=uranium;imprinter_ejectsheet_amt=5'>(5 Sheets)</A> "
if(linked_imprinter.uranium_amount >= 2000) dat += "<A href='?src=\ref[src];imprinter_ejectsheet=uranium;imprinter_ejectsheet_amt=50'>(Max Sheets)</A>"
user << browse("<TITLE>Research and Development Console</TITLE><HR>[dat]", "window=rdconsole;size=575x400")
onclose(user, "rdconsole")
/obj/machinery/computer/rdconsole/robotics
name = "Robotics R&D Console"
id = 2
req_access = null
req_access_txt = "29"
/obj/machinery/computer/rdconsole/core
name = "Core R&D Console"
id = 1
+107
View File
@@ -0,0 +1,107 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
//All devices that link into the R&D console fall into thise type for easy identification and some shared procs.
/obj/machinery/r_n_d
name = "R&D Device"
icon = 'icons/obj/machines/research.dmi'
density = 1
anchored = 1
use_power = 1
var/busy = 0
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/list/wires = list()
var/hack_wire
var/disable_wire
var/shock_wire
var/opened = 0
var/obj/machinery/computer/rdconsole/linked_console
/obj/machinery/r_n_d/New()
..()
wires["Red"] = 0
wires["Blue"] = 0
wires["Green"] = 0
wires["Yellow"] = 0
wires["Black"] = 0
wires["White"] = 0
var/list/w = list("Red","Blue","Green","Yellow","Black","White")
src.hack_wire = pick(w)
w -= src.hack_wire
src.shock_wire = pick(w)
w -= src.shock_wire
src.disable_wire = pick(w)
w -= src.disable_wire
/obj/machinery/r_n_d/proc/
shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
return 0
if(!prob(prb))
return 0
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
if (electrocute_mob(user, get_area(src), src, 0.7))
return 1
else
return 0
/obj/machinery/r_n_d/attack_hand(mob/user as mob)
if (shocked)
shock(user,50)
if(opened)
var/dat as text
dat += "[src.name] Wires:<BR>"
for(var/wire in src.wires)
dat += text("[wire] Wire: <A href='?src=\ref[src];wire=[wire];cut=1'>[src.wires[wire] ? "Mend" : "Cut"]</A> <A href='?src=\ref[src];wire=[wire];pulse=1'>Pulse</A><BR>")
dat += text("The red light is [src.disabled ? "off" : "on"].<BR>")
dat += text("The green light is [src.shocked ? "off" : "on"].<BR>")
dat += text("The blue light is [src.hacked ? "off" : "on"].<BR>")
user << browse("<HTML><HEAD><TITLE>[src.name] Hacking</TITLE></HEAD><BODY>[dat]</BODY></HTML>","window=hack_win")
return
/obj/machinery/r_n_d/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["pulse"])
var/temp_wire = href_list["wire"]
if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
usr << "You need a multitool!"
else
if(src.wires[temp_wire])
usr << "You can't pulse a cut wire."
else
if(src.hack_wire == href_list["wire"])
src.hacked = !src.hacked
spawn(100) src.hacked = !src.hacked
if(src.disable_wire == href_list["wire"])
src.disabled = !src.disabled
src.shock(usr,50)
spawn(100) src.disabled = !src.disabled
if(src.shock_wire == href_list["wire"])
src.shocked = !src.shocked
src.shock(usr,50)
spawn(100) src.shocked = !src.shocked
if(href_list["cut"])
if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters))
usr << "You need wirecutters!"
else
var/temp_wire = href_list["wire"]
wires[temp_wire] = !wires[temp_wire]
if(src.hack_wire == temp_wire)
src.hacked = !src.hacked
if(src.disable_wire == temp_wire)
src.disabled = !src.disabled
src.shock(usr,50)
if(src.shock_wire == temp_wire)
src.shocked = !src.shocked
src.shock(usr,50)
src.updateUsrDialog()
+272
View File
@@ -0,0 +1,272 @@
/*
General Explination:
The research datum is the "folder" where all the research information is stored in a R&D console. It's also a holder for all the
various procs used to manipulate it. It has four variables and seven procs:
Variables:
- possible_tech is a list of all the /datum/tech that can potentially be researched by the player. The RefreshResearch() proc
(explained later) only goes through those when refreshing what you know. Generally, possible_tech contains ALL of the existing tech
but it is possible to add tech to the game that DON'T start in it (example: Xeno tech). Generally speaking, you don't want to mess
with these since they should be the default version of the datums. They're actually stored in a list rather then using typesof to
refer to them since it makes it a bit easier to search through them for specific information.
- know_tech is the companion list to possible_tech. It's the tech you can actually research and improve. Until it's added to this
list, it can't be improved. All the tech in this list are visible to the player.
- possible_designs is functionally identical to possbile_tech except it's for /datum/design.
- known_designs is functionally identical to known_tech except it's for /datum/design
Procs:
- TechHasReqs: Used by other procs (specifically RefreshResearch) to see whether all of a tech's requirements are currently in
known_tech and at a high enough level.
- DesignHasReqs: Same as TechHasReqs but for /datum/design and known_design.
- AddTech2Known: Adds a /datum/tech to known_tech. It checks to see whether it already has that tech (if so, it just replaces it). If
it doesn't have it, it adds it. Note: It does NOT check possible_tech at all. So if you want to add something strange to it (like
a player made tech?) you can.
- AddDesign2Known: Same as AddTech2Known except for /datum/design and known_designs.
- RefreshResearch: This is the workhorse of the R&D system. It updates the /datum/research holder and adds any unlocked tech paths
and designs you have reached the requirements for. It only checks through possible_tech and possible_designs, however, so it won't
accidentally add "secret" tech to it.
- UpdateTech is used as part of the actual researching process. It takes an ID and finds techs with that same ID in known_tech. When
it finds it, it checks to see whether it can improve it at all. If the known_tech's level is less then or equal to
the inputted level, it increases the known tech's level to the inputted level -1 or know tech's level +1 (whichever is higher).
The tech datums are the actual "tech trees" that you improve through researching. Each one has five variables:
- Name: Pretty obvious. This is often viewable to the players.
- Desc: Pretty obvious. Also player viewable.
- ID: This is the unique ID of the tech that is used by the various procs to find and/or maniuplate it.
- Level: This is the current level of the tech. All techs start at 1 and have a max of 20. Devices and some techs require a certain
level in specific techs before you can produce them.
- Req_tech: This is a list of the techs required to unlock this tech path. If left blank, it'll automatically be loaded into the
research holder datum.
*/
/***************************************************************
** Master Types **
** Includes all the helper procs and basic tech processing. **
***************************************************************/
/datum/research //Holder for all the existing, archived, and known tech. Individual to console.
//Datum/tech go here.
var/list/possible_tech = list() //List of all tech in the game that players have access to (barring special events).
var/list/known_tech = list() //List of locally known tech.
var/list/possible_designs = list() //List of all designs (at base reliability).
var/list/known_designs = list() //List of available designs (at base reliability).
/datum/research/New() //Insert techs into possible_tech here. Known_tech automatically updated.
for(var/T in typesof(/datum/tech) - /datum/tech)
possible_tech += new T(src)
for(var/D in typesof(/datum/design) - /datum/design)
possible_designs += new D(src)
RefreshResearch()
//Checks to see if tech has all the required pre-reqs.
//Input: datum/tech; Output: 0/1 (false/true)
/datum/research/proc/TechHasReqs(var/datum/tech/T)
if(T.req_tech.len == 0)
return 1
var/matches = 0
for(var/req in T.req_tech)
for(var/datum/tech/known in known_tech)
if((req == known.id) && (known.level >= T.req_tech[req]))
matches++
break
if(matches == T.req_tech.len)
return 1
else
return 0
//Checks to see if design has all the required pre-reqs.
//Input: datum/design; Output: 0/1 (false/true)
/datum/research/proc/DesignHasReqs(var/datum/design/D)
if(D.req_tech.len == 0)
return 1
var/matches = 0
var/list/k_tech = list()
for(var/datum/tech/known in known_tech)
k_tech[known.id] = known.level
for(var/req in D.req_tech)
if(!isnull(k_tech[req]) && k_tech[req] >= D.req_tech[req])
matches++
if(matches == D.req_tech.len)
return 1
else
return 0
/*
//Checks to see if design has all the required pre-reqs.
//Input: datum/design; Output: 0/1 (false/true)
/datum/research/proc/DesignHasReqs(var/datum/design/D)
if(D.req_tech.len == 0)
return 1
var/matches = 0
for(var/req in D.req_tech)
for(var/datum/tech/known in known_tech)
if((req == known.id) && (known.level >= D.req_tech[req]))
matches++
break
if(matches == D.req_tech.len)
return 1
else
return 0
*/
//Adds a tech to known_tech list. Checks to make sure there aren't duplicates and updates existing tech's levels if needed.
//Input: datum/tech; Output: Null
/datum/research/proc/AddTech2Known(var/datum/tech/T)
for(var/datum/tech/known in known_tech)
if(T.id == known.id)
if(T.level > known.level)
known.level = T.level
return
known_tech += T
return
/datum/research/proc/AddDesign2Known(var/datum/design/D)
for(var/datum/design/known in known_designs)
if(D.id == known.id)
if(D.reliability_mod > known.reliability_mod)
known.reliability_mod = D.reliability_mod
return
known_designs += D
return
//Refreshes known_tech and known_designs list. Then updates the reliability vars of the designs in the known_designs list.
//Input/Output: n/a
/datum/research/proc/RefreshResearch()
for(var/datum/tech/PT in possible_tech)
if(TechHasReqs(PT))
AddTech2Known(PT)
for(var/datum/design/PD in possible_designs)
if(DesignHasReqs(PD))
AddDesign2Known(PD)
for(var/datum/tech/T in known_tech)
T = between(1,T.level,20)
for(var/datum/design/D in known_designs)
D.CalcReliability(known_tech)
return
//Refreshes the levels of a given tech.
//Input: Tech's ID and Level; Output: null
/datum/research/proc/UpdateTech(var/ID, var/level)
for(var/datum/tech/KT in known_tech)
if(KT.id == ID)
if(KT.level <= level) KT.level = max((KT.level + 1), (level - 1))
return
/datum/research/proc/UpdateDesign(var/path)
for(var/datum/design/KD in known_designs)
if(KD.build_path == path)
KD.reliability_mod += rand(1,2)
break
return
/***************************************************************
** Technology Datums **
** Includes all the various technoliges and what they make. **
***************************************************************/
datum/tech //Datum of individual technologies.
var/name = "name" //Name of the technology.
var/desc = "description" //General description of what it does and what it makes.
var/id = "id" //An easily referenced ID. Must be alphanumeric, lower-case, and no symbols.
var/level = 1 //A simple number scale of the research level. Level 0 = Secret tech.
var/list/req_tech = list() //List of ids associated values of techs required to research this tech. "id" = #
//Trunk Technologies (don't require any other techs and you start knowning them).
datum/tech/materials
name = "Materials Research"
desc = "Development of new and improved materials."
id = "materials"
datum/tech/engineering
name = "Engineering Research"
desc = "Development of new and improved engineering parts and."
id = "engineering"
datum/tech/plasmatech
name = "Plasma Research"
desc = "Research into the mysterious substance colloqually known as 'plasma'."
id = "plasmatech"
datum/tech/powerstorage
name = "Power Manipulation Technology"
desc = "The various technologies behind the storage and generation of electicity."
id = "powerstorage"
datum/tech/bluespace
name = "'Blue-space' Research"
desc = "Research into the sub-reality known as 'blue-space'"
id = "bluespace"
datum/tech/biotech
name = "Biological Technology"
desc = "Research into the deeper mysteries of life and organic substances."
id = "biotech"
datum/tech/combat
name = "Combat Systems Research"
desc = "The development of offensive and defensive systems."
id = "combat"
datum/tech/magnets
name = "Electromagnetic Spectrum Research"
desc = "Research into the electromagnetic spectrum. No clue how they actually work, though."
id = "magnets"
datum/tech/programming
name = "Data Theory Research"
desc = "The development of new computer and artificial intelligence and data storage systems."
id = "programming"
datum/tech/syndicate
name = "Illegal Technologies Research"
desc = "The study of technologies that violate standard Nanotrasen regulations."
id = "syndicate"
/*
datum/tech/arcane
name = "Arcane Research"
desc = "Research into the occult and arcane field for use in practical science"
id = "arcane"
level = 0 //It didn't become "secret" as advertised.
//Branch Techs
datum/tech/explosives
name = "Explosives Research"
desc = "The creation and application of explosive materials."
id = "explosives"
req_tech = list("materials" = 3)
datum/tech/generators
name = "Power Generation Technology"
desc = "Research into more powerful and more reliable sources."
id = "generators"
req_tech = list("powerstorage" = 2)
datum/tech/robotics
name = "Robotics Technology"
desc = "The development of advanced automated, autonomous machines."
id = "robotics"
req_tech = list("materials" = 3, "programming" = 3)
*/
/obj/item/weapon/disk/tech_disk
name = "Technology Disk"
desc = "A disk for storing technology data for further research."
icon = 'icons/obj/cloning.dmi'
icon_state = "datadisk2"
item_state = "card-id"
w_class = 1.0
m_amt = 30
g_amt = 10
var/datum/tech/stored
/obj/item/weapon/disk/tech_disk/New()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
+127
View File
@@ -0,0 +1,127 @@
/**********************Shuttle Computer**************************/
//copy paste from the mining shuttle
var/research_shuttle_tickstomove = 10
var/research_shuttle_moving = 0
var/research_shuttle_location = 0 // 0 = station 13, 1 = research station
proc/move_research_shuttle()
if(research_shuttle_moving) return
research_shuttle_moving = 1
spawn(research_shuttle_tickstomove*10)
var/area/fromArea
var/area/toArea
if (research_shuttle_location == 1)
fromArea = locate(/area/shuttle/research/outpost)
toArea = locate(/area/shuttle/research/station)
else
fromArea = locate(/area/shuttle/research/station)
toArea = locate(/area/shuttle/research/outpost)
var/list/dstturfs = list()
var/throwy = world.maxy
for(var/turf/T in toArea)
dstturfs += T
if(T.y < throwy)
throwy = T.y
// hey you, get out of the way!
for(var/turf/T in dstturfs)
// find the turf to move things to
var/turf/D = locate(T.x, throwy - 1, 1)
//var/turf/E = get_step(D, SOUTH)
for(var/atom/movable/AM as mob|obj in T)
AM.Move(D)
// NOTE: Commenting this out to avoid recreating mass driver glitch
/*
spawn(0)
AM.throw_at(E, 1, 1)
return
*/
if(istype(T, /turf/simulated))
del(T)
for(var/mob/living/carbon/bug in toArea) // If someone somehow is still in the shuttle's docking area...
bug.gib()
for(var/mob/living/simple_animal/pest in toArea) // And for the other kind of bug...
pest.gib()
fromArea.move_contents_to(toArea)
if (research_shuttle_location)
research_shuttle_location = 0
else
research_shuttle_location = 1
research_shuttle_moving = 0
return
/obj/machinery/computer/research_shuttle
name = "Research Shuttle Console"
icon = 'icons/obj/computer.dmi'
icon_state = "shuttle"
req_access = list(access_research)
circuit = "/obj/item/weapon/circuitboard/research_shuttle"
var/hacked = 0
var/location = 0 //0 = station, 1 = research base
/obj/machinery/computer/research_shuttle/attack_hand(user as mob)
src.add_fingerprint(usr)
var/dat = "<center>Research shuttle: <b><A href='?src=\ref[src];move=1'>Send</A></b></center><br>"
user << browse("[dat]", "window=researchshuttle;size=200x100")
/obj/machinery/computer/research_shuttle/Topic(href, href_list)
if(..())
return
usr.machine = src
src.add_fingerprint(usr)
if(href_list["move"])
//if(ticker.mode.name == "blob")
// if(ticker.mode:declared)
// usr << "Under directive 7-10, [station_name()] is quarantined until further notice."
// return
if (!research_shuttle_moving)
usr << "\blue Shuttle recieved message and will be sent shortly."
move_research_shuttle()
else
usr << "\blue Shuttle is already moving."
/obj/machinery/computer/research_shuttle/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/card/emag))
var/obj/item/weapon/card/emag/E = W
if(E.uses)
E.uses--
else
return
src.req_access = list()
hacked = 1
usr << "You fried the consoles ID checking system. It's now available to everyone!"
else if(istype(W, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/item/weapon/circuitboard/research_shuttle/M = new /obj/item/weapon/circuitboard/research_shuttle( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.anchored = 1
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
new /obj/item/weapon/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
user << "\blue You disconnect the monitor."
A.state = 4
A.icon_state = "4"
del(src)
+380
View File
@@ -0,0 +1,380 @@
/obj/machinery/r_n_d/server
name = "R&D Server"
icon = 'icons/obj/machines/research.dmi'
icon_state = "server"
var/datum/research/files
var/health = 100
var/list/id_with_upload = list() //List of R&D consoles with upload to server access.
var/list/id_with_download = list() //List of R&D consoles with download from server access.
var/id_with_upload_string = "" //String versions for easy editing in map editor.
var/id_with_download_string = ""
var/server_id = 0
var/heat_gen = 100
var/heating_power = 40000
var/delay = 10
req_access = list(access_rd) //Only the R&D can change server settings.
/obj/machinery/r_n_d/server/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/rdserver(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/cable_coil(src)
component_parts += new /obj/item/weapon/cable_coil(src)
RefreshParts()
src.initialize(); //Agouri
/obj/machinery/r_n_d/server/Del()
griefProtection()
..()
/obj/machinery/r_n_d/server/RefreshParts()
var/tot_rating = 0
for(var/obj/item/weapon/stock_parts/SP in src)
tot_rating += SP.rating
heat_gen /= max(1, tot_rating)
/obj/machinery/r_n_d/server/initialize()
if(!files) files = new /datum/research(src)
var/list/temp_list
if(!id_with_upload.len)
temp_list = list()
temp_list = text2list(id_with_upload_string, ";")
for(var/N in temp_list)
id_with_upload += text2num(N)
if(!id_with_download.len)
temp_list = list()
temp_list = text2list(id_with_download_string, ";")
for(var/N in temp_list)
id_with_download += text2num(N)
/obj/machinery/r_n_d/server/process()
var/datum/gas_mixture/environment = loc.return_air()
switch(environment.temperature)
if(0 to T0C)
health = min(100, health + 1)
if(T0C to (T20C + 20))
health = between(0, health, 100)
if((T20C + 20) to (T0C + 70))
health = max(0, health - 1)
if(health <= 0)
griefProtection() //I dont like putting this in process() but it's the best I can do without re-writing a chunk of rd servers.
files.known_designs = list()
for(var/datum/tech/T in files.known_tech)
if(prob(1))
T.level--
files.RefreshResearch()
if(delay)
delay--
else
produce_heat(heat_gen)
delay = initial(delay)
/obj/machinery/r_n_d/server/meteorhit(var/obj/O as obj)
griefProtection()
..()
/obj/machinery/r_n_d/server/emp_act(severity)
griefProtection()
..()
/obj/machinery/r_n_d/server/ex_act(severity)
griefProtection()
..()
/obj/machinery/r_n_d/server/blob_act()
griefProtection()
..()
//Backup files to centcomm to help admins recover data after greifer attacks
/obj/machinery/r_n_d/server/proc/griefProtection()
for(var/obj/machinery/r_n_d/server/centcom/C in machines)
for(var/datum/tech/T in files.known_tech)
C.files.AddTech2Known(T)
for(var/datum/design/D in files.known_designs)
C.files.AddDesign2Known(D)
C.files.RefreshResearch()
/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt)
if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater.
var/turf/simulated/L = loc
if(istype(L))
var/datum/gas_mixture/env = L.return_air()
if(env.temperature < (heat_amt+T0C))
var/transfer_moles = 0.25 * env.total_moles()
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
var/heat_capacity = removed.heat_capacity()
if(heat_capacity == 0 || heat_capacity == null)
heat_capacity = 1
removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
env.merge(removed)
/obj/machinery/r_n_d/server/attackby(var/obj/item/O as obj, var/mob/user as mob)
if (disabled)
return
if (shocked)
shock(user,50)
if (istype(O, /obj/item/weapon/screwdriver))
if (!opened)
opened = 1
icon_state = "server_o"
user << "You open the maintenance hatch of [src]."
else
opened = 0
icon_state = "server"
user << "You close the maintenance hatch of [src]."
return
if (opened)
if(istype(O, /obj/item/weapon/crowbar))
griefProtection()
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc)
M.state = 2
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
del(src)
return 1
/obj/machinery/r_n_d/server/attack_hand(mob/user as mob)
if (disabled)
return
if (shocked)
shock(user,50)
return
/obj/machinery/r_n_d/server/centcom
name = "Centcom Central R&D Database"
server_id = -1
/obj/machinery/r_n_d/server/centcom/initialize()
..()
var/list/no_id_servers = list()
var/list/server_ids = list()
for(var/obj/machinery/r_n_d/server/S in machines)
switch(S.server_id)
if(-1)
continue
if(0)
no_id_servers += S
else
server_ids += S.server_id
for(var/obj/machinery/r_n_d/server/S in no_id_servers)
var/num = 1
while(!S.server_id)
if(num in server_ids)
num++
else
S.server_id = num
server_ids += num
no_id_servers -= S
/obj/machinery/r_n_d/server/centcom/process()
return PROCESS_KILL //don't need process()
/obj/machinery/computer/rdservercontrol
name = "R&D Server Controller"
icon_state = "rdcomp"
var/screen = 0
var/obj/machinery/r_n_d/server/temp_server
var/list/servers = list()
var/list/consoles = list()
var/badmin = 0
/obj/machinery/computer/rdservercontrol/Topic(href, href_list)
if(..())
return
add_fingerprint(usr)
usr.set_machine(src)
if(!src.allowed(usr) && !emagged)
usr << "\red You do not have the required access level"
return
if(href_list["main"])
screen = 0
else if(href_list["access"] || href_list["data"] || href_list["transfer"])
temp_server = null
consoles = list()
servers = list()
for(var/obj/machinery/r_n_d/server/S in machines)
if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"]))
temp_server = S
break
if(href_list["access"])
screen = 1
for(var/obj/machinery/computer/rdconsole/C in machines)
if(C.sync)
consoles += C
else if(href_list["data"])
screen = 2
else if(href_list["transfer"])
screen = 3
for(var/obj/machinery/r_n_d/server/S in machines)
if(S == src)
continue
servers += S
else if(href_list["upload_toggle"])
var/num = text2num(href_list["upload_toggle"])
if(num in temp_server.id_with_upload)
temp_server.id_with_upload -= num
else
temp_server.id_with_upload += num
else if(href_list["download_toggle"])
var/num = text2num(href_list["download_toggle"])
if(num in temp_server.id_with_download)
temp_server.id_with_download -= num
else
temp_server.id_with_download += num
else if(href_list["reset_tech"])
var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/tech/T in temp_server.files.known_tech)
if(T.id == href_list["reset_tech"])
T.level = 1
break
temp_server.files.RefreshResearch()
else if(href_list["reset_design"])
var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/design/D in temp_server.files.known_designs)
if(D.id == href_list["reset_design"])
D.reliability_mod = 0
temp_server.files.known_designs -= D
break
temp_server.files.RefreshResearch()
updateUsrDialog()
return
/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
var/dat = ""
switch(screen)
if(0) //Main Menu
dat += "Connected Servers:<BR><BR>"
for(var/obj/machinery/r_n_d/server/S in machines)
if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
continue
dat += "[S.name] || "
dat += "<A href='?src=\ref[src];access=[S.server_id]'> Access Rights</A> | "
dat += "<A href='?src=\ref[src];data=[S.server_id]'>Data Management</A>"
if(badmin) dat += " | <A href='?src=\ref[src];transfer=[S.server_id]'>Server-to-Server Transfer</A>"
dat += "<BR>"
if(1) //Access rights menu
dat += "[temp_server.name] Access Rights<BR><BR>"
dat += "Consoles with Upload Access<BR>"
for(var/obj/machinery/computer/rdconsole/C in consoles)
var/turf/console_turf = get_turf(C)
dat += "* <A href='?src=\ref[src];upload_toggle=[C.id]'>[console_turf.loc]" //FYI, these are all numeric ids, eventually.
if(C.id in temp_server.id_with_upload)
dat += " (Remove)</A><BR>"
else
dat += " (Add)</A><BR>"
dat += "Consoles with Download Access<BR>"
for(var/obj/machinery/computer/rdconsole/C in consoles)
var/turf/console_turf = get_turf(C)
dat += "* <A href='?src=\ref[src];download_toggle=[C.id]'>[console_turf.loc]"
if(C.id in temp_server.id_with_download)
dat += " (Remove)</A><BR>"
else
dat += " (Add)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
if(2) //Data Management menu
dat += "[temp_server.name] Data ManagementP<BR><BR>"
dat += "Known Technologies<BR>"
for(var/datum/tech/T in temp_server.files.known_tech)
dat += "* [T.name] "
dat += "<A href='?src=\ref[src];reset_tech=[T.id]'>(Reset)</A><BR>" //FYI, these are all strings.
dat += "Known Designs<BR>"
for(var/datum/design/D in temp_server.files.known_designs)
dat += "* [D.name] "
dat += "<A href='?src=\ref[src];reset_design=[D.id]'>(Delete)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
if(3) //Server Data Transfer
dat += "[temp_server.name] Server to Server Transfer<BR><BR>"
dat += "Send Data to what server?<BR>"
for(var/obj/machinery/r_n_d/server/S in servers)
dat += "[S.name] <A href='?src=\ref[src];send_to=[S.server_id]'> (Transfer)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
user << browse("<TITLE>R&D Server Control</TITLE><HR>[dat]", "window=server_control;size=575x400")
onclose(user, "server_control")
return
/obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob)
if(istype(D, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
new /obj/item/weapon/shard( src.loc )
var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.state = 3
A.icon_state = "3"
A.anchored = 1
del(src)
else
user << "\blue You disconnect the monitor."
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/item/weapon/circuitboard/rdservercontrol/M = new /obj/item/weapon/circuitboard/rdservercontrol( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.state = 4
A.icon_state = "4"
A.anchored = 1
del(src)
else if(istype(D, /obj/item/weapon/card/emag) && !emagged)
playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
user << "\blue You you disable the security protocols"
src.updateUsrDialog()
return
/obj/machinery/r_n_d/server/robotics
name = "Robotics R&D Server"
id_with_upload_string = "1;2"
id_with_download_string = "1;2"
server_id = 2
/obj/machinery/r_n_d/server/core
name = "Core R&D Server"
id_with_upload_string = "1"
id_with_download_string = "1"
server_id = 1
@@ -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"
@@ -0,0 +1,99 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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
anchored = 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
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 are long gone.")
del(src)
return
if(prob(excavation_level))
//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)
@@ -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--
@@ -0,0 +1,36 @@
/obj/structure/crystal
name = "large crystal"
icon = 'icons/obj/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
@@ -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.GetDrilled()
src.loc = M
drilling_turf = null
anchored = 0
@@ -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/working/hoverpod/mechturn(direction)
dir = direction
//playsound(src,'sound/machines/hiss.ogg',40,1)
return 1
/obj/mecha/working/hoverpod/mechstep(direction)
var/result = step(src,direction)
if(result)
playsound(src,'sound/machines/hiss.ogg',40,1)
return result
/obj/mecha/working/hoverpod/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*/
@@ -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 = 'icons/obj/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)"
@@ -0,0 +1,367 @@
#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 = 'icons/obj/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()
var/turf/L = loc
if(isnull(L) || !istype(L)) // We're inside a container or on null turf, either way stop processing effects
return
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()
@@ -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
@@ -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)
@@ -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
@@ -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 mob_list)
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 mob_list)
for (var/obj/item/weapon/cell/D in M.contents)
D.charge += rand() * 100
M << "\blue SYSTEM ALERT: Energy boost detected!"
return 1
@@ -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 mob_list)
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 mob_list)
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
@@ -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)
@@ -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
@@ -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)
@@ -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())
@@ -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())
@@ -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())
@@ -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())
@@ -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()
@@ -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
@@ -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()
@@ -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)
@@ -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()
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
@@ -0,0 +1,160 @@
//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 = "#DCDCDC" // rgb: 220, 220, 220, silver
lithiumsodiumtungstate
name = "Lithium Sodium Tungstate"
id = "lithiumsodiumtungstate"
description = "A reducing agent for geological compounds."
reagent_state = LIQUID
color = "#C0C0C0" // rgb: 192, 192, 192, darker silver
ground_rock
name = "Ground Rock"
id = "ground_rock"
description = "A fine dust made of ground up rock."
reagent_state = SOLID
color = "#A0522D" //rgb: 160, 82, 45, 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 = "#DEB887" //rgb: 222, 184, 135, light brown
analysis_sample
name = "Analysis liquid"
id = "analysis_sample"
description = "A watery paste used in chemical analysis."
reagent_state = LIQUID
color = "#F5FFFA" //rgb: 245, 255, 250, almost white
chemical_waste
name = "Chemical Waste"
id = "chemical_waste"
description = "A viscous, toxic liquid left over from many chemical processes."
reagent_state = LIQUID
color = "#ADFF2F" //rgb: 173, 255, 47, toxic 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()
@@ -0,0 +1,538 @@
//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 = 90 //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 = 'icons/obj/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 = get_turf(src)
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 = 'icons/obj/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 = 'icons/obj/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 = 'icons/obj/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 fetal 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 = 'icons/obj/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 = 'icons/obj/xenoarchaeology.dmi'
new_item.desc = ""
if(19)
apply_prefix = 0
new_item = new /obj/item/weapon/claymore(src.loc)
new_item.force = 10
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)
new_item.force = 10
item_type = new_item.name
if(26)
//energy gun
var/spawn_type = pick(\
/obj/item/weapon/gun/energy/laser/practice,\
/obj/item/weapon/gun/energy/laser,\
/obj/item/weapon/gun/energy/xray,\
/obj/item/weapon/gun/energy/laser/captain)
if(spawn_type)
var/obj/item/weapon/gun/energy/new_gun = new spawn_type(src.loc)
new_item = new_gun
new_item.icon_state = "egun[rand(1,6)]"
new_gun.desc = "This is an antique energy weapon, you're not sure if it will fire or not."
//5% chance to explode when first fired
//10% chance to have an unchargeable cell
//15% chance to gain a random amount of starting energy, otherwise start with an empty cell
if(prob(5))
new_gun.power_supply.rigged = 1
if(prob(10))
new_gun.power_supply.maxcharge = 0
if(prob(15))
new_gun.power_supply.charge = rand(0, new_gun.power_supply.maxcharge)
else
new_gun.power_supply.charge = 0
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)]"
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
//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)
new_gun.loaded.Cut()
for(var/i = 1, i <= num_bullets, i++)
var/A = text2path(new_gun.ammo_type)
new_gun.loaded += new A(new_gun)
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 = 'icons/effects/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 = 'icons/effects/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 = 'icons/effects/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 && istype(new_item,/obj/item/weapon))
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)
@@ -0,0 +1,271 @@
#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
var/list/responsive_carriers = list( \
"carbon", \
"potassium", \
"hydrogen", \
"nitrogen", \
"mercury", \
"iron", \
"chlorine", \
"phosphorus", \
"plasma")
var/list/finds_as_strings = list( \
"Trace organic cells", \
"Long exposure particles", \
"Trace water particles", \
"Crystalline structures", \
"Metallic derivative", \
"Metallic composite", \
"Metamorphic/igneous rock composite", \
"Metamorphic/sedimentary rock composite", \
"Anomalous material" )
#undef ARCHAEO_BOWL
#undef ARCHAEO_URN
#undef ARCHAEO_CUTLERY
#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
@@ -0,0 +1,102 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// fossils
/obj/item/weapon/fossil
name = "Fossil"
icon = 'icons/obj/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 = 'icons/obj/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)]"
@@ -0,0 +1,71 @@
/obj/item/weapon/shard/plasma
name = "plasma shard"
desc = "A shard of plasma glass. Considerably tougher then normal glass shards. Apparently not tough enough to be a window."
force = 8.0
throwforce = 15.0
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/glass/plasmaglass/NG = new (user.loc)
for (var/obj/item/stack/sheet/glass/plasmaglass/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 glass to the stack. It now contains [NG.amount] sheets."
//SN src = null
del(src)
return
return ..()
//legacy crystal
/obj/machinery/crystal
name = "Crystal"
icon = 'icons/obj/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?
@@ -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 = text2list(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(text2list(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 mob_list)
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)
@@ -0,0 +1,151 @@
/*
#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
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rock sliver
/obj/item/weapon/rocksliver
name = "rock sliver"
desc = "It looks extremely delicate."
icon = 'icons/obj/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
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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_distance = -1 //proportional to distance
var/source_mineral = "chlorine" //machines will pop up a warning telling players that the sample may be confused
//
//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)
UpdateTurf(container)
//this should only need to be called once
/datum/geosample/proc/UpdateTurf(var/turf/simulated/mineral/container)
set background = 1
if(!container || !istype(container))
return
age = rand(1,999)
if(container.mineral)
switch(container.mineral.name)
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)
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
//loop over again to reset values to percentages
var/total_presence = 0
for(var/carrier in find_presence)
total_presence += find_presence[carrier]
for(var/carrier in find_presence)
find_presence[carrier] = find_presence[carrier] / total_presence
/*for(var/entry in find_presence)
total_spread += find_presence[entry]*/
//have this separate from UpdateTurf() so that we dont have a billion turfs being updated (redundantly) every time an artifact spawns
/datum/geosample/proc/UpdateNearbyArtifactInfo(var/turf/simulated/mineral/container)
if(!container || !istype(container))
return
if(container.artifact_find)
artifact_distance = rand()
artifact_id = container.artifact_find.artifact_id
else
if(master_controller) //Sanity check due to runtimes ~Z
for(var/turf/simulated/mineral/T in master_controller.artifact_spawning_turfs)
if(T.artifact_find)
var/cur_dist = get_dist(container, T) * 2
if( (artifact_distance < 0 || cur_dist < artifact_distance) && cur_dist <= T.artifact_find.artifact_detect_range )
artifact_distance = cur_dist + rand() * 2 - 1
artifact_id = T.artifact_find.artifact_id
else
master_controller.artifact_spawning_turfs.Remove(T)
/*
#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
*/
@@ -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."
@@ -0,0 +1,227 @@
/obj/machinery/artifact_harvester
name = "Exotic Particle Harvester"
icon = 'icons/obj/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()
@@ -0,0 +1,8 @@
/obj/machinery/artifact_scanpad
name = "Anomaly Scanner Pad"
desc = "Place things here for scanning."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "tele0"
anchored = 1
density = 0
@@ -0,0 +1,59 @@
datum/reagent/coolant
name = "Coolant"
id = "coolant"
description = "Industrial cooling substance."
reagent_state = LIQUID
color = "#C8A5DC" // rgb: 200, 165, 220
datum/chemical_reaction/coolant
name = "Coolant"
id = "coolant"
result = "coolant"
required_reagents = list("tungsten" = 1, "oxygen" = 1, "water" = 1)
result_amount = 3
/obj/structure/reagent_dispensers/coolanttank
name = "coolant tank"
desc = "A tank of industrial coolant"
icon = 'icons/obj/objects.dmi'
icon_state = "coolanttank"
amount_per_transfer_from_this = 10
New()
..()
reagents.add_reagent("coolant",1000)
/obj/structure/reagent_dispensers/coolanttank/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
explode()
/obj/structure/reagent_dispensers/coolanttank/blob_act()
explode()
/obj/structure/reagent_dispensers/coolanttank/ex_act()
explode()
/obj/structure/reagent_dispensers/coolanttank/proc/explode()
var/datum/effect/effect/system/smoke_spread/S = new /datum/effect/effect/system/smoke_spread
//S.attach(src)
S.set_up(5, 0, src.loc)
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
spawn(0)
S.start()
var/datum/gas_mixture/env = src.loc.return_air()
if(env)
if (reagents.total_volume > 750)
env.temperature = 0
else if (reagents.total_volume > 500)
env.temperature -= 100
else
env.temperature -= 50
sleep(10)
if(src)
del(src)
@@ -0,0 +1,362 @@
/obj/machinery/radiocarbon_spectrometer
name = "Radiocarbon spectrometer"
desc = "A specialised, complex scanner for gleaning information on all manner of small things."
anchored = 1
density = 1
icon = 'icons/obj/virology.dmi'
icon_state = "analyser"
use_power = 1 //1 = idle, 2 = active
idle_power_usage = 20
active_power_usage = 300
//var/obj/item/weapon/reagent_containers/glass/coolant_container
var/scanning = 0
var/report_num = 0
//
var/obj/item/scanned_item
var/last_scan_data = "No scans on record."
//
var/last_process_worldtime = 0
//
var/scanner_progress = 0
var/scanner_rate = 1.25 //80 seconds per scan
var/scanner_rpm = 0
var/scanner_rpm_dir = 1
var/scanner_temperature = 0
var/scanner_seal_integrity = 100
//
var/coolant_usage_rate = 0 //measured in u/microsec
var/fresh_coolant = 0
var/coolant_purity = 0
var/datum/reagents/coolant_reagents
var/used_coolant = 0
var/list/coolant_reagents_purity = list()
//
var/maser_wavelength = 0
var/optimal_wavelength = 0
var/optimal_wavelength_target = 0
var/tleft_retarget_optimal_wavelength = 0
var/maser_efficiency = 0
//
var/radiation = 0 //0-100 mSv
var/t_left_radspike = 0
var/rad_shield = 0
/obj/machinery/radiocarbon_spectrometer/New()
..()
create_reagents(500)
coolant_reagents_purity["water"] = 0.5
coolant_reagents_purity["icecoffee"] = 0.6
coolant_reagents_purity["icetea"] = 0.6
coolant_reagents_purity["milkshake"] = 0.6
coolant_reagents_purity["leporazine"] = 0.7
coolant_reagents_purity["kelotane"] = 0.7
coolant_reagents_purity["sterilizine"] = 0.7
coolant_reagents_purity["dermaline"] = 0.7
coolant_reagents_purity["hyperzine"] = 0.8
coolant_reagents_purity["cryoxadone"] = 0.9
coolant_reagents_purity["coolant"] = 1
coolant_reagents_purity["adminordrazine"] = 2
/obj/machinery/radiocarbon_spectrometer/attack_hand(var/mob/user as mob)
ui_interact(user)
/obj/machinery/radiocarbon_spectrometer/attackby(var/obj/I as obj, var/mob/user as mob)
if(scanning)
user << "<span class='warning'>You can't do that while [src] is scanning!</span>"
else
if(istype(I, /obj/item/stack/nanopaste))
var/choice = alert("What do you want to do with the nanopaste?","Radiometric Scanner","Scan nanopaste","Fix seal integrity")
if(choice == "Fix seal integrity")
var/obj/item/stack/nanopaste/N = I
var/amount_used = min(N.amount, 10 - scanner_seal_integrity / 10)
N.use(amount_used)
scanner_seal_integrity = round(scanner_seal_integrity + amount_used * 10)
return
if(istype(I, /obj/item/weapon/reagent_containers/glass))
var/choice = alert("What do you want to do with the container?","Radiometric Scanner","Add coolant","Empty coolant","Scan container")
if(choice == "Add coolant")
var/obj/item/weapon/reagent_containers/glass/G = I
var/amount_transferred = min(src.reagents.maximum_volume - src.reagents.total_volume, G.reagents.total_volume)
G.reagents.trans_to(src, amount_transferred)
user << "<span class='info'>You empty [amount_transferred]u of coolant into [src].</span>"
update_coolant()
return
else if(choice == "Empty coolant")
var/obj/item/weapon/reagent_containers/glass/G = I
var/amount_transferred = min(G.reagents.maximum_volume - G.reagents.total_volume, src.reagents.total_volume)
src.reagents.trans_to(G, amount_transferred)
user << "<span class='info'>You remove [amount_transferred]u of coolant from [src].</span>"
update_coolant()
return
user.drop_item()
I.loc = src
scanned_item = I
/obj/machinery/radiocarbon_spectrometer/proc/update_coolant()
var/total_purity = 0
fresh_coolant = 0
coolant_purity = 0
var/num_reagent_types = 0
for (var/datum/reagent/current_reagent in src.reagents.reagent_list)
if (!current_reagent)
continue
var/cur_purity = coolant_reagents_purity[current_reagent.id]
if(!cur_purity)
cur_purity = 0.1
else if(cur_purity > 1)
cur_purity = 1
total_purity += cur_purity * current_reagent.volume
fresh_coolant += current_reagent.volume
num_reagent_types += 1
if(total_purity && fresh_coolant)
coolant_purity = total_purity / fresh_coolant
/obj/machinery/radiocarbon_spectrometer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(user.stat)
return
// this is the data which will be sent to the ui
var/data[0]
data["scanned_item"] = (scanned_item ? scanned_item.name : "")
data["scanned_item_desc"] = (scanned_item ? (scanned_item.desc ? scanned_item.desc : "No information on record.") : "")
data["last_scan_data"] = last_scan_data
//
data["scan_progress"] = round(scanner_progress)
data["scanning"] = scanning
//
data["scanner_seal_integrity"] = round(scanner_seal_integrity)
data["scanner_rpm"] = round(scanner_rpm)
data["scanner_temperature"] = round(scanner_temperature)
//
data["coolant_usage_rate"] = "[coolant_usage_rate]"
data["unused_coolant_abs"] = round(fresh_coolant)
data["unused_coolant_per"] = round(fresh_coolant / reagents.maximum_volume * 100)
data["coolant_purity"] = "[coolant_purity * 100]"
//
data["optimal_wavelength"] = round(optimal_wavelength)
data["maser_wavelength"] = round(maser_wavelength)
data["maser_efficiency"] = round(maser_efficiency * 100)
//
data["radiation"] = round(radiation)
data["t_left_radspike"] = round(t_left_radspike)
data["rad_shield_on"] = rad_shield
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "geoscanner.tmpl", "High Res Radiocarbon Spectrometer", 900, 825)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
/obj/machinery/radiocarbon_spectrometer/process()
if(scanning)
if(!scanned_item || scanned_item.loc != src)
scanned_item = null
stop_scanning()
else if(scanner_progress >= 100)
complete_scan()
else
//calculate time difference
var/deltaT = (world.time - last_process_worldtime) * 0.1
//modify the RPM over time
//i want 1u to last for 10 sec at 500 RPM, scaling linearly
scanner_rpm += scanner_rpm_dir * 50 * deltaT
if(scanner_rpm > 1000)
scanner_rpm = 1000
scanner_rpm_dir = -1 * pick(0.5, 2.5, 5.5)
else if(scanner_rpm < 1)
scanner_rpm = 1
scanner_rpm_dir = 1 * pick(0.5, 2.5, 5.5)
//heat up according to RPM
//each unit of coolant
scanner_temperature += scanner_rpm * deltaT * 0.05
//radiation
t_left_radspike -= deltaT
if(t_left_radspike > 0)
//ordinary radiation
radiation = rand() * 15
else
//radspike
if(t_left_radspike > -5)
radiation = rand() * 15 + 85
if(!rad_shield)
//irradiate nearby mobs
for(var/mob/living/M in view(7,src))
M.apply_effect(radiation / 25, IRRADIATE, 0)
else
t_left_radspike = pick(10,15,25)
//use some coolant to cool down
if(coolant_usage_rate > 0)
var/coolant_used = min(fresh_coolant, coolant_usage_rate * deltaT)
if(coolant_used > 0)
fresh_coolant -= coolant_used
used_coolant += coolant_used
scanner_temperature = max(scanner_temperature - coolant_used * coolant_purity * 20, 0)
//modify the optimal wavelength
tleft_retarget_optimal_wavelength -= deltaT
if(tleft_retarget_optimal_wavelength <= 0)
tleft_retarget_optimal_wavelength = pick(4,8,15)
optimal_wavelength_target = rand() * 9900 + 100
//
if(optimal_wavelength < optimal_wavelength_target)
optimal_wavelength = min(optimal_wavelength + 700 * deltaT, optimal_wavelength_target)
else if(optimal_wavelength > optimal_wavelength_target)
optimal_wavelength = max(optimal_wavelength - 700 * deltaT, optimal_wavelength_target)
//
maser_efficiency = 1 - max(min(10000, abs(optimal_wavelength - maser_wavelength) * 3), 1) / 10000
//make some scan progress
if(!rad_shield)
scanner_progress = min(100, scanner_progress + scanner_rate * maser_efficiency * deltaT)
//degrade the seal over time according to temperature
//i want temperature of 50K to degrade at 1%/sec
scanner_seal_integrity -= (max(scanner_temperature, 1) / 1000) * deltaT
//emergency stop if seal integrity reaches 0
if(scanner_seal_integrity <= 0 || (scanner_temperature >= 1273 && !rad_shield))
stop_scanning()
src.visible_message("\blue \icon[src] buzzes unhappily. It has failed mid-scan!", 2)
if(prob(5))
src.visible_message("\blue \icon[src] [pick("whirrs","chuffs","clicks")][pick(" excitedly"," energetically"," busily")].", 2)
else
//gradually cool down over time
if(scanner_temperature > 0)
scanner_temperature = max(scanner_temperature - 5 - 10 * rand(), 0)
if(prob(0.75))
src.visible_message("\blue \icon[src] [pick("plinks","hisses")][pick(" quietly"," softly"," sadly"," plaintively")].", 2)
last_process_worldtime = world.time
/obj/machinery/radiocarbon_spectrometer/proc/stop_scanning()
scanning = 0
scanner_rpm_dir = 1
scanner_rpm = 0
optimal_wavelength = 0
maser_efficiency = 0
maser_wavelength = 0
coolant_usage_rate = 0
radiation = 0
t_left_radspike = 0
if(used_coolant)
src.reagents.remove_any(used_coolant)
used_coolant = 0
/obj/machinery/radiocarbon_spectrometer/proc/complete_scan()
src.visible_message("\blue \icon[src] makes an insistent chime.", 2)
if(scanned_item)
//create report
var/obj/item/weapon/paper/P = new(src)
P.name = "[src] report #[++report_num]: [scanned_item.name]"
P.stamped = list(/obj/item/weapon/stamp)
P.overlays = list("paper_stamped")
//work out data
var/data = " - Mundane object: [scanned_item.desc ? scanned_item.desc : "No information on record."]<br>"
var/datum/geosample/G
switch(scanned_item.type)
if(/obj/item/weapon/ore)
var/obj/item/weapon/ore/O = scanned_item
if(O.geologic_data)
G = O.geologic_data
if(/obj/item/weapon/rocksliver)
var/obj/item/weapon/rocksliver/O = scanned_item
if(O.geological_data)
G = O.geological_data
if(/obj/item/weapon/archaeological_find)
data = " - Mundane object (archaic xenos origins)<br>"
var/obj/item/weapon/archaeological_find/A = scanned_item
if(A.speaking_to_players)
data = " - Exhibits properties consistent with sonic reproduction.<br>"
if(A.listening_to_players)
data = " - Exhibits properties similar to audio capture technology.<br>"
var/anom_found = 0
if(G)
data = " - Spectometric analysis on mineral sample has determined type [finds_as_strings[responsive_carriers.Find(G.source_mineral)]]<br>"
if(G.age_billion > 0)
data += " - Radiometric dating shows age of [G.age_billion].[G.age_million] billion years<br>"
else if(G.age_million > 0)
data += " - Radiometric dating shows age of [G.age_million].[G.age_thousand] million years<br>"
else
data += " - Radiometric dating shows age of [G.age_thousand * 1000 + G.age] years<br>"
data += " - Chromatographic analysis shows the following materials present:<br>"
for(var/carrier in G.find_presence)
if(G.find_presence[carrier])
var/index = responsive_carriers.Find(carrier)
if(index > 0 && index <= finds_as_strings.len)
data += " > [100 * G.find_presence[carrier]]% [finds_as_strings[index]]<br>"
if(G.artifact_id && G.artifact_distance >= 0)
anom_found = 1
data += " - Hyperspectral imaging reveals exotic energy wavelength detected with ID: [G.artifact_id]<br>"
data += " - Fourier transform analysis on anomalous energy absorption indicates energy source located inside emission radius of [G.artifact_distance]m<br>"
if(!anom_found)
data += " - No anomalous data<br>"
P.info = "<b>[src] analysis report #[report_num]</b><br>"
P.info += "<b>Scanned item:</b> [scanned_item.name]<br><br>" + data
last_scan_data = P.info
P.loc = src.loc
scanned_item.loc = src.loc
scanned_item = null
/obj/machinery/radiocarbon_spectrometer/Topic(href, href_list)
if(stat & (NOPOWER|BROKEN))
return 0 // don't update UIs attached to this object
if(href_list["scanItem"])
if(scanning)
stop_scanning()
else
if(scanned_item)
if(scanner_seal_integrity > 0)
scanner_progress = 0
scanning = 1
t_left_radspike = pick(5,10,15)
usr << "<span class='notice'>Scan initiated.</span>"
else
usr << "<span class='warning'>Could not initiate scan, seal requires replacing.</span>"
else
usr << "<span class='warning'>Insert an item to scan.</span>"
if(href_list["maserWavelength"])
maser_wavelength = max(min(maser_wavelength + 1000 * text2num(href_list["maserWavelength"]), 10000), 1)
if(href_list["coolantRate"])
coolant_usage_rate = max(min(coolant_usage_rate + text2num(href_list["coolantRate"]), 10000), 0)
if(href_list["toggle_rad_shield"])
if(rad_shield)
rad_shield = 0
else
rad_shield = 1
if(href_list["ejectItem"])
if(scanned_item)
scanned_item.loc = src.loc
scanned_item = null
add_fingerprint(usr)
return 1 // update UIs attached to this object
@@ -0,0 +1,370 @@
/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>Alden-Saraspova counter</b> - uses a patented application of Fourier Transform analysis to determine the difference between background and
exotic radiation. Use it to determine how far you are from anomalous energy sources.</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="#Analysis">Analysis progression</a></li>
<li><a href="#Heat">Heat management</a></li>
<li><a href="#Radiation">Ambient radiation</a></li>
</ol>
<br>
<h1><a name="Terms">A note on terms</a></h1>
<list>
<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>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>Vacuum seal integrity</b> - A reference to how close an airtight seal is to failure.</li>
</list><br>
<a href="#Contents">Contents</a>
<h1><a name="Analysis">Analysis progression</a></h1>
Modern mass spectrometry requires constant attention from the diligant researcher in order to be successul. There are many different elements to juggle,
and later chapters will delve into them. For the spectrometry assistant, the first thing you need to know is that the scanner wavelength is automatically
calculated for you. Just tweak the settings and try to match it with the actual wavelength as closely as possible.<br>
<br>
<a href="#Contents">Contents</a>
<h1><a name="Seal">Seal integrity</a></h1>
In order to maintain sterile and environmentally static procedures, a special chamber is setup inside the spectrometer. It's protected by a proprietary vacuum seal
produced by top tier industrial science. It will only last for a certain number of scans before failing outright, but it can be resealed through use of nanite paste.
Unfortunately, it's susceptible to malforming under heat stress so exposing it to higher temperatures will cause it's operation life to drop significantly.<br>
<br>
<a href="#Contents">Contents</a>
<h1><a name="Heat">Heat management</a></h1>
The scanner relies on a gyro-rotational system that varies in speed and intensity. Over the course of an ordinary scan, the RPMs can change dramatically. Higher RPMs
means greater heat generation, but is necessary for the ongoing continuation of the scan. To offset heat production, spectrometers have an inbuilt cooling system.
Researchers can modify the flow rate of coolant to aid in dropping temperature as necessary, but are advised that frequent coolant replacements may be necessary
depending on coolant purity. Water and substances such as cryoxadone are viable substitutes, but nowhere near as effective as pure coolant itself.<br>
<br>
<a href="#Contents">Contents</a>
<h1><a name="Radiation">Ambient radiation</a></h1>
Researchers are warned that while operational, mass spectrometers emit period bursts of radiation and are thus advised to wear protective gear. In the event of
radiation spikes, there is also a special shield that can be lowered to block emissions. Lowering this, however, will have the effect of blocking the scanner
so use it sparingly.<br>
<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>
It's perhaps one of the most exciting times to be alive, with the recent breakthroughs in understanding and categorisation of things we may one day no longer call
'anomalies,' but rather 'infrequent or rare occurrences of certain celestial weather or phenomena.' Perhaps a little more long winded, but no less eloquent all the
same! Why, look at the strides we're making in piercing the walls of bluespace or our steadily improving ability to clarify and stabilise subspace emissions; it's
certainly an exciting time to be alive. For the moment the Hydrolian hasn't seen two spatial anomalies alike but the day will come and it is soon, I can feel it.
"}
/obj/item/weapon/book/manual/materials_chemistry_analysis
name = "Materials analysis and the chemical implications"
icon_state = "chemistry"
author = "Jasper Pascal, Senior Lecturer in Materials Analysis at the University of Jol'Nar"
title = "Materials analysis and the chemical implications"
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>
In today's high tech research fields, leaps and bounds are being made every day. Whether it's great strides forward in our understanding of the physical universe
or the operation of some fancy new piece of equipment, it seems like all the cool fields are producing new toys to play with leaving doddery old fields such as
materials analysis and chemistry relegated to the previous few centuries, when we were still learning the makeup and structure of the elements.<br>
<br>
Well, when you're out there building the next gryo-whatsitron or isotope mobility thingummy, remember how the field of archaeology experienced a massive new rebirth
following the excavations at Paranol IV and consider how all of the scientific greats will come crawling back to basic paradigms of natural philosophy when they discover
a new element that defies classification. I defy you to classify it without reviving this once great field!
"}
/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. Modern portable devices can do
all this purely by taking readings of local radiation.<br>
<br>
A canny researcher can thusly analyse radiationat pre-chosen points strategically scattered around an area, and if there are any anomalous energy
emissions in range of those points, combined the researcher can triangulate 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>
"}
/obj/item/weapon/book/manual/stasis
name = "Cellular suspension, the new Cryogenics?"
icon_state = "stasis"
author = "Elvin Schmidt"
title = "Cellular suspension, the new Cryogenics?"
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="#Forward">Forward: A replacement for cryosleep?</a></li>
<li><a href="#Development">The breakthrough</a></li>
<li><a href="#Application">Applying this new principle</a></li>
</ol>
<br>
<h1><a name="Forward">Forward: A replacement for cryosleep?</a></h1>
The development of rudimentary cryofreezing in the 20th and 21st centuries was hailed as a crank science by some, but many early visionaries recognised the
potential it had to change the way we approach so many fields, such as medicine, therapeutics and space travel. It was breakthroughs in the field in the 22nd and
later centures that turned the procedure from science fiction to science fact, however. Since then, cryogenics has become a hallmark of modern science, and
regarded as one of the great achievements of our era. As with all sciences however, they have their time and are superseded by newer technological miracles when
it is over.<br>
<a href="#Contents">Contents</a>
<h1><a name="Development">The breakthrough</a></h1>
It was in examining the effects of decellerated, blue-space high energy particles when transphased through bluespace that the effects where primarily noticed.
Due to exigent properties of that dimension, transphasing those particles capable of existing in bluespace with high stability levels has the effect of bringing
some of those effects into realspace. Examining the Hoffman emissions in particular, it was discovered that they exhibited a-entropic behaviour, and in what is
now termed the 'Effete Hoffman Principle,' it was found that metastabilising the Hoffman radiation resulted in the effect being applied across other physical
interactions, in particular forces and reactions.<br>
<a href="#Contents">Contents</a>
<h1><a name="Application">Applying this new principle</a></h1>
When combined with an appropriate energy-effect replicate for cryogenics (slowing down biological activity, thus stabilising the organics), the effect is
effectively identical to cryogenics, and while it consumes vastly more power and requires extremely complex equipment, it's (for all intents and purposes) superior
to cryogenics, all that remains is to 'commercialise' the process by enabling cheaper development and mass production.<br>
The Effete Hoffman Principle can be tweak-combined with other effects however, for different purposes. A division of PMC Research initially developed the application
in prisons as a literal 'suspension field' where convincts are held immobile in the air, and the use quickly spread to numerous other areas.<br>
<br>
By examining the material resonance properties of certain strong waveforms when combined with Hoffman radiation, an effect was produced able to reverse energy
transferral through matter, and to slow the effects of gravity. When combined with energy repulse technology, the triple effects compound themselves into a much
stronger field, although all three componenets do slightly different things. High energy researchers assure me of the following key points:<br>
<ol>
<li>The energy repulsion factor provides a 'shell' capable of weak suspension.</li>
<li>The Hoffman emissions nullify energy transferral and other kinetic activity, maintaining stability inside the field.</li>
<li>The resonant waveform combines the effects of the above two points, and applies it magnified onto it's synched 'resonance' materials.</li>
</ol>
As an interesting aside, a carbon waveform was chosen for the field in prison suspension fields, due to it's resonance with organic matter.<br>
<a href="#Contents">Contents</a>
</body>
</html>
"}
@@ -0,0 +1,160 @@
#define XENOARCH_SPAWN_CHANCE 0.5
#define XENOARCH_SPREAD_CHANCE 15
#define ARTIFACT_SPAWN_CHANCE 20
proc/SetupXenoarch()
for(var/turf/simulated/mineral/M in block(locate(1,1,1), locate(world.maxx, world.maxy, world.maxz)))
if(!M.geologic_data)
M.geologic_data = new/datum/geosample(M)
if(!prob(XENOARCH_SPAWN_CHANCE))
continue
var/digsite = get_random_digsite_type()
var/list/processed_turfs = list()
var/list/turfs_to_process = list(M)
for(var/turf/simulated/mineral/archeo_turf in turfs_to_process)
for(var/turf/simulated/mineral/T in orange(1, archeo_turf))
if(T.finds)
continue
if(T in processed_turfs)
continue
if(prob(XENOARCH_SPREAD_CHANCE))
turfs_to_process.Add(T)
processed_turfs.Add(archeo_turf)
if(!archeo_turf.finds)
archeo_turf.finds = list()
if(prob(50))
archeo_turf.finds.Add(new /datum/find(digsite, rand(5,95)))
else if(prob(75))
archeo_turf.finds.Add(new /datum/find(digsite, rand(5,45)))
archeo_turf.finds.Add(new /datum/find(digsite, rand(55,95)))
else
archeo_turf.finds.Add(new /datum/find(digsite, rand(5,30)))
archeo_turf.finds.Add(new /datum/find(digsite, rand(35,75)))
archeo_turf.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 = archeo_turf.finds[1]
if(F.excavation_required <= F.view_range)
archeo_turf.archaeo_overlay = "overlay_archaeo[rand(1,3)]"
archeo_turf.overlays += archeo_turf.archaeo_overlay
//dont create artifact machinery in animal or plant digsites, or if we already have one
if(!M.artifact_find && digsite != 1 && digsite != 2 && prob(ARTIFACT_SPAWN_CHANCE))
M.artifact_find = new()
artifact_spawn.Add(src)
//---- Noticeboard
/obj/structure/noticeboard/anomaly
notices = 5
icon_state = "nboard05"
/obj/structure/noticeboard/anomaly/New()
//add some memos
var/obj/item/weapon/paper/P = new()
P.name = "Memo RE: proper analysis procedure"
P.info = "<br>We keep test dummies in pens here for a reason, so standard procedure should be to activate newfound alien artifacts and place the two in close proximity. Promising items I might even approve monkey testing on."
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, concentrated heat or some corrosive liquids should clear away the extraneous carbon matter, while application of an energy beam will most decidedly destroy it entirely - like someone did to the chemical dispenser! 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)
new /obj/item/weapon/book/manual/stasis(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"
icon_closed = "toolcloset"
icon_opened = "toolclosetopen"
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)
new /obj/item/device/measuring_tape(src)
new /obj/item/weapon/pickaxe/hand(src)
return
//---- Isolation room air alarms
/obj/machinery/alarm/isolation
name = "Isolation room air control"
req_access = list(access_research)
@@ -0,0 +1,5 @@
//coming soon
//there'll probably be some stuff on the wiki at some point
//original code from alfie275 / lunacode, artifacts are from isaidno
@@ -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 = 'icons/obj/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)
..()
@@ -0,0 +1,30 @@
//changes: rad protection up to 100 from 20/50 respectively
/obj/item/clothing/suit/bio_suit/anomaly
name = "Anomaly suit"
desc = "A sealed bio suit capable of insulating against exotic alien energies"
icon_state = "engspace_suit"
item_state = "engspace_suit"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
/obj/item/clothing/head/bio_hood/anomaly
name = "Anomaly hood"
desc = "A sealed bio hood capable of insulating against exotic alien energies."
icon_state = "engspace_helmet"
item_state = "engspace_helmet"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
/obj/item/clothing/suit/space/anomaly
name = "Excavation suit"
desc = "A pressure resistant excavation suit partially capable of insulating against exotic alien energies."
icon_state = "cespace_suit"
item_state = "cespace_suit"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank)
/obj/item/clothing/head/helmet/space/anomaly
name = "Excavation hood"
desc = "A pressure resistant excavation hood partially capable of insulating against exotic alien energies."
icon_state = "cespace_helmet"
item_state = "cespace_helmet"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100)
@@ -0,0 +1,57 @@
/obj/machinery/bunsen_burner
name = "bunsen burner"
desc = "A flat, self-heating device designed for bringing chemical mixtures to boil."
icon = 'icons/obj/device.dmi'
icon_state = "bunsen0"
var/heating = 0 //whether the bunsen is turned on
var/heated = 0 //whether the bunsen has been on long enough to let stuff react
var/obj/item/weapon/reagent_containers/held_container
var/heat_time = 50
/obj/machinery/bunsen_burner/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/reagent_containers))
if(held_container)
user << "\red You must remove the [held_container] first."
else
user.drop_item(src)
held_container = W
held_container.loc = src
user << "\blue You put the [held_container] onto the [src]."
var/image/I = image("icon"=W, "layer"=FLOAT_LAYER)
underlays += I
if(heating)
spawn(heat_time)
try_heating()
else
user << "\red You can't put the [W] onto the [src]."
/obj/machinery/bunsen_burner/attack_hand(mob/user as mob)
if(held_container)
underlays = null
user << "\blue You remove the [held_container] from the [src]."
held_container.loc = src.loc
held_container.attack_hand(user)
held_container = null
else
user << "\red There is nothing on the [src]."
/obj/machinery/bunsen_burner/proc/try_heating()
src.visible_message("\blue \icon[src] [src] hisses.")
if(held_container && heating)
heated = 1
held_container.reagents.handle_reactions()
heated = 0
spawn(heat_time)
try_heating()
/obj/machinery/bunsen_burner/verb/toggle()
set src in view(1)
set name = "Toggle bunsen burner"
set category = "IC"
heating = !heating
icon_state = "bunsen[heating]"
if(heating)
spawn(heat_time)
try_heating()
@@ -0,0 +1,28 @@
/obj/item/weapon/storage/belt/archaeology
name = "excavation gear-belt"
desc = "Can hold various excavation gear."
icon_state = "gearbelt"
item_state = "utility"
can_hold = list(
"/obj/item/weapon/storage/box/samplebags",
"/obj/item/device/core_sampler",
"/obj/item/device/beacon_locator",
"/obj/item/device/radio/beacon",
"/obj/item/device/gps",
"/obj/item/device/measuring_tape",
"/obj/item/device/flashlight",
"/obj/item/weapon/pickaxe",
"/obj/item/device/depth_scanner",
"/obj/item/device/camera",
"/obj/item/weapon/paper",
"/obj/item/weapon/photo",
"/obj/item/weapon/folder",
"/obj/item/weapon/pen",
"/obj/item/weapon/folder",
"/obj/item/weapon/clipboard",
"/obj/item/weapon/anodevice",
"/obj/item/clothing/glasses",
"/obj/item/weapon/wrench",
"/obj/item/weapon/storage/box/excavation",
"/obj/item/weapon/anobattery")
@@ -0,0 +1,337 @@
/obj/machinery/suspension_gen
name = "suspension field generator"
desc = "It has stubby legs bolted up against it's body for stabilising."
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "suspension2"
density = 1
req_access = list(access_research)
var/obj/item/weapon/cell/cell
var/obj/item/weapon/card/id/auth_card
var/locked = 1
var/open = 0
var/screwed = 1
var/field_type = ""
var/power_use = 25
var/obj/effect/suspension_field/suspension_field
var/list/secured_mobs = list()
/obj/machinery/suspension_gen/New()
src.cell = new/obj/item/weapon/cell/high(src)
..()
/obj/machinery/suspension_gen/process()
set background = 1
if (suspension_field)
cell.charge -= power_use
var/turf/T = get_turf(suspension_field)
if(field_type == "carbon")
for(var/mob/living/carbon/M in T)
M.weakened = max(M.weakened, 3)
cell.charge -= power_use
if(prob(5))
M << "\blue [pick("You feel tingly.","You feel like floating.","It is hard to speak.","You can barely move.")]"
if(field_type == "iron")
for(var/mob/living/silicon/M in T)
M.weakened = max(M.weakened, 3)
cell.charge -= power_use
if(prob(5))
M << "\blue [pick("You feel tingly.","You feel like floating.","It is hard to speak.","You can barely move.")]"
for(var/obj/item/I in T)
if(!suspension_field.contents.len)
suspension_field.icon_state = "energynet"
suspension_field.overlays += "shield2"
I.loc = suspension_field
for(var/mob/living/simple_animal/M in T)
M.weakened = max(M.weakened, 3)
cell.charge -= power_use
if(prob(5))
M << "\blue [pick("You feel tingly.","You feel like floating.","It is hard to speak.","You can barely move.")]"
if(cell.charge <= 0)
deactivate()
/obj/machinery/suspension_gen/interact(mob/user as mob)
var/dat = "<b>Multi-phase mobile suspension field generator MK II \"Steadfast\"</b><br>"
if(cell)
var/colour = "red"
if(cell.charge / cell.maxcharge > 0.66)
colour = "green"
else if(cell.charge / cell.maxcharge > 0.33)
colour = "orange"
dat += "<b>Energy cell</b>: <font color='[colour]'>[100 * cell.charge / cell.maxcharge]%</font><br>"
else
dat += "<b>Energy cell</b>: None<br>"
if(auth_card)
dat += "<A href='?src=\ref[src];ejectcard=1'>\[[auth_card]\]<a><br>"
if(!locked)
dat += "<b><A href='?src=\ref[src];toggle_field=1'>[suspension_field ? "Disable" : "Enable"] field</a></b><br>"
else
dat += "<br>"
else
dat += "<A href='?src=\ref[src];insertcard=1'>\[------\]<a><br>"
if(!locked)
dat += "<b><A href='?src=\ref[src];toggle_field=1'>[suspension_field ? "Disable" : "Enable"] field</a></b><br>"
else
dat += "Enter your ID to begin.<br>"
dat += "<hr>"
if(!locked)
dat += "<b>Select field mode</b><br>"
dat += "[field_type=="carbon"?"<b>":"" ]<A href='?src=\ref[src];select_field=carbon'>Diffracted carbon dioxide laser</A></b><br>"
dat += "[field_type=="nitrogen"?"<b>":"" ]<A href='?src=\ref[src];select_field=nitrogen'>Nitrogen tracer field</A></b><br>"
dat += "[field_type=="potassium"?"<b>":"" ]<A href='?src=\ref[src];select_field=potassium'>Potassium refrigerant cloud</A></b><br>"
dat += "[field_type=="mercury"?"<b>":"" ]<A href='?src=\ref[src];select_field=mercury'>Mercury dispersion wave</A></b><br>"
dat += "[field_type=="iron"?"<b>":"" ]<A href='?src=\ref[src];select_field=iron'>Iron wafer conduction field</A></b><br>"
dat += "[field_type=="calcium"?"<b>":"" ]<A href='?src=\ref[src];select_field=calcium'>Calcium binary deoxidiser</A></b><br>"
dat += "[field_type=="plasma"?"<b>":"" ]<A href='?src=\ref[src];select_field=chlorine'>Chlorine diffusion emissions</A></b><br>"
dat += "[field_type=="plasma"?"<b>":"" ]<A href='?src=\ref[src];select_field=plasma'>Plasma saturated field</A></b><br>"
else
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<hr>"
dat += "<font color='blue'><b>Always wear safety gear and consult a field manual before operation.</b></font><br>"
if(!locked)
dat += "<A href='?src=\ref[src];lock=1'>Lock console</A><br>"
else
dat += "<br>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh console</A><br>"
dat += "<A href='?src=\ref[src];close=1'>Close console</A>"
user << browse(dat, "window=suspension;size=500x400")
onclose(user, "suspension")
/obj/machinery/suspension_gen/Topic(href, href_list)
..()
usr.set_machine(src)
if(href_list["toggle_field"])
if(!suspension_field)
if(cell.charge > 0)
if(anchored)
activate()
else
usr << "<span class='warning'>You are unable to activate [src] until it is properly secured on the ground.</span>"
else
deactivate()
if(href_list["select_field"])
field_type = href_list["select_field"]
else if(href_list["insertcard"])
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/card))
usr.drop_item()
I.loc = src
auth_card = I
if(attempt_unlock(I))
usr << "<span class='info'>You insert [I], the console flashes \'<i>Access granted.</a>\'</span>"
else
usr << "<span class='warning'>You insert [I], the console flashes \'<i>Access denied.</a>\'</span>"
else if(href_list["ejectcard"])
if(auth_card)
if(ishuman(usr))
auth_card.loc = usr.loc
if(!usr.get_active_hand())
usr.put_in_hands(auth_card)
auth_card = null
else
auth_card.loc = loc
auth_card = null
else if(href_list["lock"])
locked = 1
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=suspension")
updateUsrDialog()
/obj/machinery/suspension_gen/attack_hand(mob/user as mob)
if(!open)
interact(user)
else if(cell)
cell.loc = loc
cell.add_fingerprint(user)
cell.updateicon()
icon_state = "suspension0"
cell = null
user << "<span class='info'>You remove the power cell</span>"
/obj/machinery/suspension_gen/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/screwdriver))
if(!open)
if(screwed)
screwed = 0
else
screwed = 1
user << "<span class='info'>You [screwed ? "screw" : "unscrew"] the battery panel.</span>"
else if (istype(W, /obj/item/weapon/crowbar))
if(!locked)
if(!screwed)
if(!suspension_field)
if(open)
open = 0
else
open = 1
user << "<span class='info'>You crowbar the battery panel [open ? "open" : "in place"].</span>"
icon_state = "suspension[open ? (cell ? "1" : "0") : "2"]"
else
user << "<span class='warning'>[src]'s safety locks are engaged, shut it down first.</span>"
else
user << "<span class='warning'>Unscrew [src]'s battery panel first.</span>"
else
user << "<span class='warning'>[src]'s security locks are engaged.</span>"
else if (istype(W, /obj/item/weapon/wrench))
if(!suspension_field)
if(anchored)
anchored = 0
else
anchored = 1
user << "<span class='info'>You wrench the stabilising legs [anchored ? "into place" : "up against the body"].</span>"
if(anchored)
desc = "It is resting securely on four stubby legs."
else
desc = "It has stubby legs bolted up against it's body for stabilising."
else
user << "<span class='warning'>You are unable to secure [src] while it is active!</span>"
else if (istype(W, /obj/item/weapon/cell))
if(open)
if(cell)
user << "<span class='warning'>There is a power cell already installed.</span>"
else
user.drop_item()
W.loc = src
cell = W
user << "<span class='info'>You insert the power cell.</span>"
icon_state = "suspension1"
else if(istype(W, /obj/item/weapon/card))
var/obj/item/weapon/card/I = W
if(!auth_card)
if(attempt_unlock(I))
user << "<span class='info'>You swipe [I], the console flashes \'<i>Access granted.</i>\'</span>"
else
user << "<span class='warning'>You swipe [I], console flashes \'<i>Access denied.</i>\'</span>"
else
user << "<span class='warning'>Remove [auth_card] first.</span>"
/obj/machinery/suspension_gen/proc/attempt_unlock(var/obj/item/weapon/card/C)
if(!open)
if(istype(C, /obj/item/weapon/card/emag) && cell.charge > 0)
//put sparks here
if(prob(95))
locked = 0
else if(istype(C, /obj/item/weapon/card/id) && check_access(C))
locked = 0
if(!locked)
return 1
//checks for whether the machine can be activated or not should already have occurred by this point
/obj/machinery/suspension_gen/proc/activate()
//depending on the field type, we might pickup certain items
var/turf/T = get_turf(get_step(src,dir))
var/success = 0
var/collected = 0
switch(field_type)
if("carbon")
success = 1
for(var/mob/living/carbon/C in T)
C.weakened += 5
C.visible_message("\blue \icon[C] [C] begins to float in the air!","You feel tingly and light, but it is difficult to move.")
if("nitrogen")
success = 1
//
if("mercury")
success = 1
//
if("chlorine")
success = 1
//
if("potassium")
success = 1
//
if("plasma")
success = 1
//
if("calcium")
success = 1
//
if("iron")
success = 1
for(var/mob/living/silicon/R in T)
R.weakened += 5
R.visible_message("\blue \icon[R] [R] begins to float in the air!","You feel tingly and light, but it is difficult to move.")
//
//in case we have a bad field type
if(!success)
return
for(var/mob/living/simple_animal/C in T)
C.visible_message("\blue \icon[C] [C] begins to float in the air!","You feel tingly and light, but it is difficult to move.")
C.weakened += 5
suspension_field = new(T)
suspension_field.field_type = field_type
src.visible_message("\blue \icon[src] [src] activates with a low hum.")
icon_state = "suspension3"
for(var/obj/item/I in T)
I.loc = suspension_field
collected++
if(collected)
suspension_field.icon_state = "energynet"
suspension_field.overlays += "shield2"
src.visible_message("\blue \icon[suspension_field] [suspension_field] gently absconds [collected > 1 ? "something" : "several things"].")
else
if(istype(T,/turf/simulated/mineral) || istype(T,/turf/simulated/wall))
suspension_field.icon_state = "shieldsparkles"
else
suspension_field.icon_state = "shield2"
/obj/machinery/suspension_gen/proc/deactivate()
//drop anything we picked up
var/turf/T = get_turf(suspension_field)
for(var/mob/M in T)
M << "<span class='info'>You no longer feel like floating.</span>"
M.weakened = min(M.weakened, 3)
src.visible_message("\blue \icon[src] [src] deactivates with a gentle shudder.")
del(suspension_field)
icon_state = "suspension2"
/obj/machinery/suspension_gen/Del()
//safety checks: clear the field and drop anything it's holding
deactivate()
..()
/obj/machinery/suspension_gen/verb/toggle()
set src in view(1)
set name = "Rotate suspension gen (clockwise)"
set category = "IC"
if(anchored)
usr << "\red You cannot rotate [src], it has been firmly fixed to the floor."
else
dir = turn(dir, 90)
/obj/effect/suspension_field
name = "energy field"
icon = 'icons/effects/effects.dmi'
anchored = 1
density = 1
var/field_type = "chlorine"
/obj/effect/suspension_field/Del()
for(var/obj/I in src)
I.loc = src.loc
..()
@@ -0,0 +1,24 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Miscellaneous xenoarchaeology tools
/obj/item/device/gps
name = "relay positioning device"
desc = "Triangulates the approximate co-ordinates using a nearby satellite network."
icon = 'icons/obj/device.dmi'
icon_state = "locator"
item_state = "locator"
w_class = 2
/obj/item/device/gps/attack_self(var/mob/user as mob)
var/turf/T = get_turf(src)
user << "\blue \icon[src] [src] flashes <i>[T.x].[rand(0,9)]:[T.y].[rand(0,9)]:[T.z].[rand(0,9)]</i>."
/obj/item/device/measuring_tape
name = "measuring tape"
desc = "A coiled metallic tape used to check dimensions and lengths."
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "measuring"
w_class = 2
//todo: dig site tape
@@ -0,0 +1,49 @@
/obj/item/device/ano_scanner
name = "Alden-Saraspova counter"
desc = "Aids in triangulation of exotic particles."
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "flashgun"
item_state = "lampgreen"
w_class = 1.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
var/nearest_artifact_id = "unknown"
var/nearest_artifact_distance = -1
var/last_scan_time = 0
var/scan_delay = 25
/obj/item/device/ano_scanner/New()
..()
spawn(0)
scan()
/obj/item/device/ano_scanner/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/device/ano_scanner/interact(var/mob/user as mob)
var/message = "Background radiation levels detected."
if(nearest_artifact_distance >= 0)
message = "Exotic energy detected on wavelength '[nearest_artifact_id]' in a radius of [nearest_artifact_distance]m"
user << "<span class='info'>[message]</span>"
if(world.time - last_scan_time >= scan_delay)
spawn(0)
scan()
/obj/item/device/ano_scanner/proc/scan()
set background = 1
last_scan_time = world.time
nearest_artifact_distance = -1
var/turf/cur_turf = get_turf(src)
if(master_controller) //Sanity check due to runtimes ~Z
for(var/turf/simulated/mineral/T in master_controller.artifact_spawning_turfs)
if(T.artifact_find)
if(T.z == cur_turf.z)
var/cur_dist = get_dist(cur_turf, T) * 2
if( (nearest_artifact_distance < 0 || cur_dist < nearest_artifact_distance) && cur_dist <= T.artifact_find.artifact_detect_range )
nearest_artifact_distance = cur_dist + rand() * 2 - 1
nearest_artifact_id = T.artifact_find.artifact_id
else
master_controller.artifact_spawning_turfs.Remove(T)
cur_turf.visible_message("<span class='info'>[src] clicks.</span>")
@@ -0,0 +1,101 @@
//device to take core samples from mineral turfs - used for various types of analysis
/obj/item/weapon/storage/box/samplebags
name = "sample bag box"
desc = "A box claiming to contain sample bags."
New()
for(var/i=0, i<7, i++)
var/obj/item/weapon/evidencebag/S = new(src)
S.name = "sample bag"
S.desc = "a bag for holding research samples."
..()
return
//////////////////////////////////////////////////////////////////
/obj/item/device/core_sampler
name = "core sampler"
desc = "Used to extract geological core samples."
icon = 'icons/obj/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/evidencebag/filled_bag
/obj/item/device/core_sampler/examine()
set src in orange(1)
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] bag[num_stored_bags != 1 ? "s" : ""] remaining."
else
return ..()
/obj/item/device/core_sampler/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/evidencebag))
if(num_stored_bags < 10)
del(W)
num_stored_bags += 1
user << "\blue You insert the [W] into the core sampler."
else
user << "\red The core sampler can not fit any more bags!"
else
return ..()
/obj/item/device/core_sampler/proc/sample_item(var/item_to_sample, var/mob/user as mob)
var/datum/geosample/geo_data
if(istype(item_to_sample, /turf/simulated/mineral))
var/turf/simulated/mineral/T = item_to_sample
T.geologic_data.UpdateNearbyArtifactInfo(T)
geo_data = T.geologic_data
else if(istype(item_to_sample, /obj/item/weapon/ore))
var/obj/item/weapon/ore/O = item_to_sample
geo_data = O.geologic_data
if(geo_data)
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
//create a new sample bag which we'll fill with rock samples
filled_bag = new /obj/item/weapon/evidencebag(src)
filled_bag.name = "sample bag"
filled_bag.desc = "a bag for holding research samples."
icon_state = "sampler1"
num_stored_bags--
//put in a rock sliver
var/obj/item/weapon/rocksliver/R = new()
R.geological_data = geo_data
R.loc = filled_bag
//update the sample bag
filled_bag.icon_state = "evidence"
var/image/I = image("icon"=R, "layer"=FLOAT_LAYER)
filled_bag.underlays += I
filled_bag.w_class = 1
user << "\blue You take a core sample of the [item_to_sample]."
else
user << "\red You are unable to take a sample of [item_to_sample]."
/obj/item/device/core_sampler/attack_self()
if(filled_bag)
usr << "\blue You eject the full sample bag."
var/success = 0
if(istype(src.loc, /mob))
var/mob/M = src.loc
success = M.put_in_inactive_hand(filled_bag)
if(!success)
filled_bag.loc = get_turf(src)
filled_bag = null
icon_state = "sampler0"
else
usr << "\red The core sampler is empty."
@@ -0,0 +1,131 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Depth scanner - scans rock turfs / boulders and tells players if there is anything interesting inside, logs all finds + coordinates + times
//also known as the x-ray diffractor
/obj/item/device/depth_scanner
name = "depth analysis scanner"
desc = "Used to check spatial depth and density of rock outcroppings."
icon = 'icons/obj/pda.dmi'
icon_state = "crap"
item_state = "analyzer"
w_class = 1.0
flags = FPRINT | TABLEPASS
slot_flags = SLOT_BELT
var/list/positive_locations = list()
var/datum/depth_scan/current
/datum/depth_scan
var/time = ""
var/coords = ""
var/depth = 0
var/clearance = 0
var/record_index = 1
var/dissonance_spread = 1
var/material = "unknown"
/obj/item/device/depth_scanner/proc/scan_atom(var/mob/user, var/atom/A)
user.visible_message("\blue [user] scans [A], the air around them humming gently.")
if(istype(A,/turf/simulated/mineral))
var/turf/simulated/mineral/M = A
if(M.finds.len || M.artifact_find)
//create a new scanlog entry
var/datum/depth_scan/D = new()
D.coords = "[M.x].[rand(0,9)]:[M.y].[rand(0,9)]:[10 * M.z].[rand(0,9)]"
D.time = worldtime2text()
D.record_index = positive_locations.len + 1
D.material = M.mineral ? M.mineral.display_name : "Rock"
//find the first artifact and store it
if(M.finds.len)
var/datum/find/F = M.finds[1]
D.depth = F.excavation_required * 2 //0-100% and 0-200cm
D.clearance = F.clearance_range * 2
D.material = get_responsive_reagent(F.find_type)
positive_locations.Add(D)
for(var/mob/L in range(src, 1))
L << "\blue \icon[src] [src] pings."
else if(istype(A,/obj/structure/boulder))
var/obj/structure/boulder/B = A
if(B.artifact_find)
//create a new scanlog entry
var/datum/depth_scan/D = new()
D.coords = "[10 * B.x].[rand(0,9)]:[10 * B.y].[rand(0,9)]:[10 * B.z].[rand(0,9)]"
D.time = worldtime2text()
D.record_index = positive_locations.len + 1
//these values are arbitrary
D.depth = rand(75,100)
D.clearance = rand(5,25)
D.dissonance_spread = rand(750,2500) / 100
positive_locations.Add(D)
for(var/mob/L in range(src, 1))
L << "\blue \icon[src] [src] pings [pick("madly","wildly","excitedly","crazily")]!."
/obj/item/device/depth_scanner/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/device/depth_scanner/interact(var/mob/user as mob)
var/dat = "<b>Co-ordinates with positive matches</b><br>"
dat += "<A href='?src=\ref[src];clear=0'>== Clear all ==</a><br>"
if(current)
dat += "Time: [current.time]<br>"
dat += "Coords: [current.coords]<br>"
dat += "Anomaly depth: [current.depth] cm<br>"
dat += "Clearance above anomaly depth: [current.clearance] cm<br>"
dat += "Dissonance spread: [current.dissonance_spread]<br>"
var/index = responsive_carriers.Find(current.material)
if(index > 0 && index <= finds_as_strings.len)
dat += "Anomaly material: [finds_as_strings[index]]<br>"
else
dat += "Anomaly material: Unknown<br>"
dat += "<A href='?src=\ref[src];clear=[current.record_index]'>clear entry</a><br>"
else
dat += "Select an entry from the list<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<br>"
dat += "<hr>"
if(positive_locations.len)
for(var/index=1, index<=positive_locations.len, index++)
var/datum/depth_scan/D = positive_locations[index]
dat += "<A href='?src=\ref[src];select=[index]'>[D.time], coords: [D.coords]</a><br>"
else
dat += "No entries recorded."
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=depth_scanner;size=300x500")
onclose(user, "depth_scanner")
/obj/item/device/depth_scanner/Topic(href, href_list)
..()
usr.set_machine(src)
if(href_list["select"])
var/index = text2num(href_list["select"])
if(index && index <= positive_locations.len)
current = positive_locations[index]
else if(href_list["clear"])
var/index = text2num(href_list["clear"])
if(index)
if(index <= positive_locations.len)
var/datum/depth_scan/D = positive_locations[index]
positive_locations.Remove(D)
del(D)
else
//GC will hopefully pick them up before too long
positive_locations = list()
del(current)
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=depth_scanner")
updateSelfDialog()
@@ -0,0 +1,97 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GPS Locater - locks into a radio frequency and tracks it
/obj/item/device/beacon_locator
name = "locater device"
desc = "Used to scan and locate signals on a particular frequency according ."
icon = 'icons/obj/device.dmi'
icon_state = "pinoff" //pinonfar, pinonmedium, pinonclose, pinondirect, pinonnull
item_state = "electronic"
var/frequency = 1459
var/scan_ticks = 0
var/obj/item/device/radio/target_radio
/obj/item/device/beacon_locator/New()
..()
processing_objects.Add(src)
/obj/item/device/beacon_locator/Del()
processing_objects.Remove(src)
..()
/obj/item/device/beacon_locator/process()
if(target_radio)
dir = get_dir(src,target_radio)
switch(get_dist(src,target_radio))
if(0 to 3)
icon_state = "pinondirect"
if(4 to 10)
icon_state = "pinonclose"
if(11 to 30)
icon_state = "pinonmedium"
if(31 to INFINITY)
icon_state = "pinonfar"
else
if(scan_ticks)
icon_state = "pinonnull"
scan_ticks++
if(prob(scan_ticks * 10))
spawn(0)
set background = 1
if(processing_objects.Find(src))
//scan radios in the world to try and find one
var/cur_dist = 999
for(var/obj/item/device/radio/beacon/R in world)
if(R.z == src.z && R.frequency == src.frequency)
var/check_dist = get_dist(src,R)
if(check_dist < cur_dist)
cur_dist = check_dist
target_radio = R
scan_ticks = 0
var/turf/T = get_turf(src)
if(target_radio)
T.visible_message("\icon[src] [src] [pick("chirps","chirrups","cheeps")] happily.")
else
T.visible_message("\icon[src] [src] [pick("chirps","chirrups","cheeps")] sadly.")
else
icon_state = "pinoff"
/obj/item/device/beacon_locator/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/device/beacon_locator/interact(var/mob/user as mob)
var/dat = "<b>Radio frequency tracker</b><br>"
dat += {"
<A href='byond://?src=\ref[src];reset_tracking=1'>Reset tracker</A><BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
"}
dat += "<A href='?src=\ref[src];close=1'>Close</a><br>"
user << browse(dat,"window=locater;size=300x150")
onclose(user, "locater")
/obj/item/device/beacon_locator/Topic(href, href_list)
..()
usr.set_machine(src)
if(href_list["reset_tracking"])
scan_ticks = 1
target_radio = null
else if(href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if (frequency < 1200 || frequency > 1600)
new_frequency = sanitize_frequency(new_frequency, 1499)
frequency = new_frequency
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=locater")
updateSelfDialog()
@@ -0,0 +1,132 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Excavation pickaxes - sorted in order of delicacy. Players will have to choose the right one for each part of excavation.
/obj/item/weapon/pickaxe/brush
name = "brush"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick_brush"
item_state = "syringe_0"
digspeed = 20
desc = "Thick metallic wires for clearing away dust and loose scree (1 centimetre excavation depth)."
excavation_amount = 0.5
drill_sound = 'sound/weapons/thudswoosh.ogg'
drill_verb = "brushing"
w_class = 2
/obj/item/weapon/pickaxe/one_pick
name = "1/6 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick1"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (2 centimetre excavation depth)."
excavation_amount = 1
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/two_pick
name = "1/3 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick2"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (4 centimetre excavation depth)."
excavation_amount = 2
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/three_pick
name = "1/2 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick3"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (6 centimetre excavation depth)."
excavation_amount = 3
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/four_pick
name = "2/3 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick4"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (8 centimetre excavation depth)."
excavation_amount = 4
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/five_pick
name = "5/6 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick5"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (10 centimetre excavation depth)."
excavation_amount = 5
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/six_pick
name = "1/1 pick"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick6"
item_state = "syringe_0"
digspeed = 20
desc = "A miniature excavation tool for precise digging (12 centimetre excavation depth)."
excavation_amount = 6
drill_sound = 'sound/items/Screwdriver.ogg'
drill_verb = "delicately picking"
w_class = 2
/obj/item/weapon/pickaxe/hand
name = "hand pickaxe"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pick_hand"
item_state = "syringe_0"
digspeed = 30
desc = "A smaller, more precise version of the pickaxe (30 centimetre excavation depth)."
excavation_amount = 15
drill_sound = 'sound/items/Crowbar.ogg'
drill_verb = "clearing"
w_class = 3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pack for holding pickaxes
/obj/item/weapon/storage/box/excavation
name = "excavation pick set"
icon = 'icons/obj/storage.dmi'
icon_state = "excavation"
desc = "A set of picks for excavation."
item_state = "syringe_kit"
foldable = /obj/item/stack/sheet/cardboard //BubbleWrap
storage_slots = 7
w_class = 2
can_hold = list("/obj/item/weapon/pickaxe/brush",\
"/obj/item/weapon/pickaxe/one_pick",\
"/obj/item/weapon/pickaxe/two_pick",\
"/obj/item/weapon/pickaxe/three_pick",\
"/obj/item/weapon/pickaxe/four_pick",\
"/obj/item/weapon/pickaxe/five_pick",\
"/obj/item/weapon/pickaxe/six_pick")
max_combined_w_class = 17
max_w_class = 4
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
/obj/item/weapon/storage/box/excavation/New()
..()
new /obj/item/weapon/pickaxe/brush(src)
new /obj/item/weapon/pickaxe/one_pick(src)
new /obj/item/weapon/pickaxe/two_pick(src)
new /obj/item/weapon/pickaxe/three_pick(src)
new /obj/item/weapon/pickaxe/four_pick(src)
new /obj/item/weapon/pickaxe/five_pick(src)
new /obj/item/weapon/pickaxe/six_pick(src)