Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into crewobjectivesandmiscreants

This commit is contained in:
deathride58
2017-09-27 23:44:22 -04:00
619 changed files with 12516 additions and 11883 deletions
+2
View File
@@ -354,6 +354,7 @@
output += "<form method='GET' action='?src=\ref[src]'><b>Add custom ban:</b> (ONLY use this if you can't ban through any other method)"
output += "<input type='hidden' name='src' value='\ref[src]'>"
output += HrefTokenFormField()
output += "<table width='100%'><tr>"
output += "<td><b>Ban type:</b><select name='dbbanaddtype'>"
output += "<option value=''>--</option>"
@@ -387,6 +388,7 @@
output += "<form method='GET' action='?src=\ref[src]'><b>Search:</b> "
output += "<input type='hidden' name='src' value='\ref[src]'>"
output += HrefTokenFormField()
output += "<b>Ckey:</b> <input type='text' name='dbsearchckey' value='[playerckey]'>"
output += "<b>Admin ckey:</b> <input type='text' name='dbsearchadmin' value='[adminckey]'>"
output += "<input type='submit' value='search'>"
+2 -4
View File
@@ -380,8 +380,6 @@
else
dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
//to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]")
//to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]")
usr << browse(dat, "window=admincaster_main;size=400x600")
onclose(usr, "admincaster_main")
@@ -433,7 +431,7 @@
else
rebootconfirm = TRUE
if(rebootconfirm)
var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
if(result)
SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
switch(result)
@@ -513,7 +511,7 @@
set category = "Server"
set desc="Toggle dis bitch"
set name="Toggle Dead OOC"
GLOB.dooc_allowed = !( GLOB.dooc_allowed )
toggle_dooc()
log_admin("[key_name(usr)] toggled OOC.")
message_admins("[key_name_admin(usr)] toggled Dead OOC.")
+2 -1
View File
@@ -27,7 +27,8 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
return list(
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags_1*/
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
/datum/verbs/menu/Admin/verb/playerpanel,
/client/proc/game_panel, /*game panel, allows to change game-mode etc*/
/client/proc/check_ai_laws, /*shows AI and borg laws*/
/datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
-10
View File
@@ -1,10 +0,0 @@
diff a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm (rejected hunks)
@@ -663,7 +664,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, AVerbsHideable())
if(!holder)
return
-
+
if(has_antag_hud())
toggle_antag_hud()
+1 -1
View File
@@ -6,7 +6,7 @@
create_mob_html = file2text('html/create_object.html')
create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"")
user << browse(replacetext(create_mob_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_mob;size=425x475")
user << browse(create_panel_helper(create_mob_html), "window=create_mob;size=425x475")
/proc/randomize_human(mob/living/carbon/human/H)
H.gender = pick(MALE, FEMALE)
+7 -2
View File
@@ -1,3 +1,8 @@
/datum/admins/proc/create_panel_helper(template)
var/final_html = replacetext(template, "/* ref src */", "\ref[src];[HrefToken()]")
final_html = replacetext(final_html,"/* hreftokenfield */","[HrefTokenFormField()]")
return final_html
/datum/admins/proc/create_object(mob/user)
var/static/create_object_html = null
if (!create_object_html)
@@ -6,7 +11,7 @@
create_object_html = file2text('html/create_object.html')
create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"")
user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_object;size=425x475")
user << browse(create_panel_helper(create_object_html), "window=create_object;size=425x475")
/datum/admins/proc/quick_create_object(mob/user)
var/static/list/create_object_forms = list(
@@ -23,4 +28,4 @@
html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"")
create_object_forms[path] = html_form
user << browse(replacetext(html_form, "/* ref src */", "\ref[src];[HrefToken()]"), "window=qco[path];size=425x475")
user << browse(create_panel_helper(html_form), "window=qco[path];size=425x475")
+1 -1
View File
@@ -6,4 +6,4 @@
create_turf_html = file2text('html/create_object.html')
create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"")
user << browse(replacetext(create_turf_html, "/* ref src */", "\ref[src];[HrefToken()]"), "window=create_turf;size=425x475")
user << browse(create_panel_helper(create_turf_html), "window=create_turf;size=425x475")
+8 -2
View File
@@ -40,7 +40,7 @@ GLOBAL_PROTECT(href_token)
for(var/I in 1 to 32)
. += "[rand(10)]"
/proc/HrefToken(forceGlobal = FALSE)
/proc/RawHrefToken(forceGlobal = FALSE)
var/tok = GLOB.href_token
if(!forceGlobal && usr)
var/client/C = usr.client
@@ -49,7 +49,13 @@ GLOBAL_PROTECT(href_token)
var/datum/admins/holder = C.holder
if(holder)
tok = holder.href_token
return "admin_token=[tok]"
return tok
/proc/HrefToken(forceGlobal = FALSE)
return "admin_token=[RawHrefToken(forceGlobal)]"
/proc/HrefTokenFormField(forceGlobal = FALSE)
return "<input type='hidden' name='admin_token' value='[RawHrefToken(forceGlobal)]'>"
/datum/admins/proc/associate(client/C)
if(IsAdminAdvancedProcCall())
@@ -86,7 +86,7 @@
admin_id = text2num(query_get_admin.item[1])
if(new_admin)
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin")]` (`id`, `ckey`, `rank`, `level`, `flags_1`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin")]` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
if(!query_add_admin.warn_execute())
return
var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
@@ -119,7 +119,7 @@
if(!adm_ckey || !istext(adm_ckey) || !isnum(new_permission))
return
var/datum/DBQuery/query_get_perms = SSdbcore.NewQuery("SELECT id, flags_1 FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
var/datum/DBQuery/query_get_perms = SSdbcore.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
if(!query_get_perms.warn_execute())
return
@@ -130,7 +130,7 @@
if(!admin_id)
return
var/datum/DBQuery/query_change_perms = SSdbcore.NewQuery("UPDATE `[format_table_name("admin")]` SET flags_1 = [new_permission] WHERE id = [admin_id]")
var/datum/DBQuery/query_change_perms = SSdbcore.NewQuery("UPDATE `[format_table_name("admin")]` SET flags = [new_permission] WHERE id = [admin_id]")
if(!query_change_perms.warn_execute())
return
var/datum/DBQuery/query_change_perms_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edit permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
+16 -1
View File
@@ -317,7 +317,7 @@
dat += "Replacement Game Mode: <B>[SSticker.mode.replacementmode.name]</B><BR>"
else
dat += "Current Game Mode: <B>[SSticker.mode.name]</B><BR>"
dat += "Round Duration: <B>[round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]</B><BR>"
dat += "Round Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B><BR>"
dat += "<B>Emergency shuttle</B><BR>"
if(EMERGENCY_IDLE_OR_RECALLED)
dat += "<a href='?_src_=holder;[HrefToken()];call_shuttle=1'>Call Shuttle</a><br>"
@@ -517,6 +517,21 @@
dat += "<td><A href='?priv_msg=[traitor.key]'>PM</A></td></tr>"
dat += "</table>"
if(SSticker.mode.brother_teams.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Brothers</B></td><td></td><td></td></tr>"
for(var/datum/objective_team/brother_team/team in SSticker.mode.brother_teams)
for(var/datum/mind/brother in team.members)
var/mob/M = brother.current
if(M)
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[M]'>FLW</a></td>"
dat += "<td><A HREF='?_src_=holder;[HrefToken()];traitor=\ref[M]'>Show Objective</A></td></tr>"
else
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[brother]'>[brother.name]([brother.key])</a><i>Brother body destroyed!</i></td>"
dat += "<td><A href='?priv_msg=[brother.key]'>PM</A></td></tr>"
dat += "</table>"
if(SSticker.mode.abductors.len)
dat += "<br><table cellspacing=5><tr><td><B>Abductors</B></td><td></td><td></td></tr>"
for(var/datum/mind/abductor in SSticker.mode.abductors)
+3 -2
View File
@@ -147,12 +147,13 @@
return
var/output
var/ruler = "<hr style='background:#000000; border:0; height:3px'>"
var/navbar = "<a href='?_src_=holder;[HrefToken()];nonalpha=1'>\[All\]</a>|<a href='?_src_=holder;nonalpha=2'>\[#\]</a>"
var/navbar = "<a href='?_src_=holder;[HrefToken()];nonalpha=1'>\[All\]</a>|<a href='?_src_=holder;[HrefToken()];nonalpha=2'>\[#\]</a>"
for(var/letter in GLOB.alphabet)
navbar += "|<a href='?_src_=holder;[HrefToken()];showmessages=[letter]'>\[[letter]\]</a>"
navbar += "|<a href='?_src_=holder;[HrefToken()];showmemo=1'>\[Memos\]</a>|<a href='?_src_=holder;showwatch=1'>\[Watchlist\]</a>"
navbar += "|<a href='?_src_=holder;[HrefToken()];showmemo=1'>\[Memos\]</a>|<a href='?_src_=holder;[HrefToken()];showwatch=1'>\[Watchlist\]</a>"
navbar += "<br><form method='GET' name='search' action='?'>\
<input type='hidden' name='_src_' value='holder'>\
[HrefTokenFormField()]\
<input type='text' name='searchmessages' value='[index]'>\
<input type='submit' value='Search'></form>"
if(!linkless)
+1 -2
View File
@@ -37,7 +37,6 @@
if(!query_text || length(query_text) < 1)
return
//to_chat(world, query_text)
var/list/query_list = SDQL2_tokenize(query_text)
@@ -115,7 +114,7 @@
end_time -= start_time
to_chat(usr, "<span class='admin'>SDQL query results: [query_text]</span>")
to_chat(usr, "<span class='admin'>SDQL query completed: [objs_all] objects selected by path, and [objs_eligible] objects executed on after WHERE filtering if applicable.</span>")
to_chat(usr, "<span class='admin'>SDQL query took [end_time/10] seconds to complete.</span>")
to_chat(usr, "<span class='admin'>SDQL query took [DisplayTimeText(end_time)] to complete.</span>")
/proc/SDQL_qdel_datum(datum/d)
qdel(d)
+9 -4
View File
@@ -106,8 +106,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help_tickets/proc/ClientLogin(client/C)
C.current_ticket = CKey2ActiveTicket(C.ckey)
if(C.current_ticket)
C.current_ticket.AddInteraction("Client reconnected.")
C.current_ticket.initiator = C
C.current_ticket.AddInteraction("Client reconnected.")
//Dissasociate ticket
/datum/admin_help_tickets/proc/ClientLogout(client/C)
@@ -152,6 +152,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
var/client/initiator //semi-misnomer, it's the person who ahelped/was bwoinked
var/initiator_ckey
var/initiator_key_name
var/heard_by_no_admins = FALSE
var/list/_interactions //use AddInteraction() or, preferably, admin_ticket_log()
@@ -199,6 +200,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
log_admin_private("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
heard_by_no_admins = TRUE
GLOB.ahelp_tickets.active_tickets += src
@@ -209,6 +211,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
return ..()
/datum/admin_help/proc/AddInteraction(formatted_message)
if(heard_by_no_admins && usr && usr.ckey != initiator_ckey)
heard_by_no_admins = FALSE
send2irc(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]")
_interactions += "[gameTimestamp()]: [formatted_message]"
//Removes the ahelp verb and returns it after 2 minutes
@@ -394,9 +399,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)][GLOB.TAB][TicketHref("Re-Title", ref_src, "retitle")]"
if(state != AHELP_ACTIVE)
dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [(world.time - opened_at) / 600] minutes ago)"
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)"
if(closed_at)
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [(world.time - closed_at) / 600] minutes ago)"
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)"
dat += "<br><br>"
if(initiator)
dat += "<b>Actions:</b> [FullMonty(ref_src)]<br>"
@@ -674,7 +679,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(found.mind && found.mind.special_role)
is_antag = 1
founds += "Name: [found.name]([found.real_name]) Ckey: [found.ckey] [is_antag ? "(Antag)" : null] "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;[HrefToken()];adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[found]'>F</A>)</font> "
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;[HrefToken(TRUE)];adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;[HrefToken(TRUE)];adminplayerobservefollow=\ref[found]'>F</A>)</font> "
continue
msg += "[original_word] "
if(irc)
+2 -2
View File
@@ -43,8 +43,8 @@
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] lastDblClick = [M.next_click] world.time = [world.time]")
M.next_move = 1
M.next_click = 0
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!")
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!")
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [DisplayTimeText(largest_move_time)]!")
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!")
message_admins("world.time = [world.time]")
SSblackbox.add_details("admin_verb","Unfreeze Everyone") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+2 -1
View File
@@ -844,8 +844,9 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/dat = {"
<html><head><title>Create Outfit</title></head><body>
<form name="outfit" action="byond://?src=\ref[src]" method="get">
<form name="outfit" action="byond://?src=\ref[src];[HrefToken()]" method="get">
<input type="hidden" name="src" value="\ref[src]">
[HrefTokenFormField()]
<input type="hidden" name="create_outfit" value="1">
<table>
<tr>
@@ -1,25 +0,0 @@
diff a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm (rejected hunks)
@@ -1246,7 +1246,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return
- C.set_db_player_flags()
+ if(!C.set_db_player_flags())
+ to_chat(usr, "<span class='danger'>ERROR: Unable read player flags from database. Please check logs.</span>")
var/dbflags = C.prefs.db_flags
var/newstate = FALSE
if(dbflags & DB_FLAG_EXEMPT)
@@ -1254,6 +1255,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
else
newstate = TRUE
- message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
- log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
- C.update_flag_db(DB_FLAG_EXEMPT, newstate)
\ No newline at end of file
+ if(C.update_flag_db(DB_FLAG_EXEMPT, newstate))
+ to_chat(usr, "<span class='danger'>ERROR: Unable to update player flags. Please check logs.</span>")
+ else
+ message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
+ log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
\ No newline at end of file
@@ -106,7 +106,7 @@
T.air_update_turf(1)
air_update_turf(1)
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make a easy proc to spawn your plasma fires
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires
var/turf/open/T = get_turf(src)
if(!istype(T))
return
@@ -1,482 +1,482 @@
/*
What are the archived variables for?
Calculations are done using the archived variables with the results merged into the regular variables.
This prevents race conditions that arise based on the order of tile processing.
*/
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/proc/init_gaslist_cache()
. = list()
for(var/id in GLOB.meta_gas_info)
var/list/cached_gas = new(3)
.[id] = cached_gas
cached_gas[MOLES] = 0
cached_gas[ARCHIVE] = 0
cached_gas[GAS_META] = GLOB.meta_gas_info[id]
#define GASLIST(id, out_list)\
var/list/tmp_gaslist = GLOB.gaslist_cache[id];\
out_list = tmp_gaslist.Copy();
/datum/gas_mixture
var/list/gases
var/temperature //kelvins
var/tmp/temperature_archived
var/volume //liters
var/last_share
var/list/reaction_results
/datum/gas_mixture/New(volume = CELL_VOLUME)
gases = new
temperature = 0
temperature_archived = 0
src.volume = volume
last_share = 0
reaction_results = new
//listmos procs
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
var/cached_gases = gases
if(cached_gases[gas_id])
return
GASLIST(gas_id, cached_gases[gas_id])
//assert_gases(args) - shorthand for calling assert_gas() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
assert_gas(id)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id. This can clobber existing gases.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
GASLIST(gas_id, gases[gas_id])
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
var/cached_gases = gases
for(var/id in args)
GASLIST(id, cached_gases[id])
//garbage_collect() - removes any gas list which is empty.
//If called with a list as an argument, only removes gas lists with IDs from that list.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
/datum/gas_mixture/proc/garbage_collect(list/tocheck)
var/list/cached_gases = gases
for(var/id in (tocheck || cached_gases))
if(cached_gases[id][MOLES] <= 0 && cached_gases[id][ARCHIVE] <= 0)
cached_gases -= id
//PV = nRT
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[MOLES] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/proc/heat_capacity_archived() //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[ARCHIVE] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
//prefer this in performance critical areas
#define TOTAL_MOLES(cached_gases, out_var)\
out_var = 0;\
for(var/total_moles_id in cached_gases){\
out_var += cached_gases[total_moles_id][MOLES];\
}
/datum/gas_mixture/proc/total_moles()
var/cached_gases = gases
TOTAL_MOLES(cached_gases, .)
/datum/gas_mixture/proc/return_pressure() //kilopascals
if(volume > 0) // to prevent division by zero
var/cached_gases = gases
TOTAL_MOLES(cached_gases, .)
. *= R_IDEAL_GAS_EQUATION * temperature / volume
return
return 0
/datum/gas_mixture/proc/return_temperature() //kelvins
return temperature
/datum/gas_mixture/proc/return_volume() //liters
return max(0, volume)
/datum/gas_mixture/proc/thermal_energy() //joules
return temperature * heat_capacity()
/datum/gas_mixture/proc/archive()
//Update archived versions of variables
//Returns: 1 in all cases
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
//Merges all air from giver into self. Deletes giver.
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/remove(amount)
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/datum/gas_mixture/proc/remove_ratio(ratio)
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/datum/gas_mixture/proc/copy()
//Creates new, identical gas mixture
//Returns: duplicate gas mixture
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
//Copies variables from sample
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with temperature
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/parse_gas_string(gas_string)
//Copies variables from a particularly formatted string.
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Returns: amount of gas exchanged (+ if sharer received)
/datum/gas_mixture/proc/after_share(datum/gas_mixture/sharer)
//called on share's sharer to let it know it just got some gases
/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
//Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length
//Returns: new temperature of the sharer
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
//Returns: a string indicating what check failed, or "" if check passes
/datum/gas_mixture/proc/react(turf/open/dump_location)
//Performs various reactions such as combustion or fusion (LOL)
//Returns: 1 if any reaction took place; 0 otherwise
/datum/gas_mixture/archive()
var/list/cached_gases = gases
temperature_archived = temperature
for(var/id in cached_gases)
cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
return 1
/datum/gas_mixture/merge(datum/gas_mixture/giver)
if(!giver)
return 0
//heat transfer
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity)
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/giver_gases = giver.gases
//gas transfer
for(var/giver_id in giver_gases)
assert_gas(giver_id)
cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
return 1
/datum/gas_mixture/remove(amount)
var/sum
var/list/cached_gases = gases
TOTAL_MOLES(cached_gases, sum)
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES] / sum) * amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
return removed
/datum/gas_mixture/remove_ratio(ratio)
if(ratio <= 0)
return null
ratio = min(ratio, 1)
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
return removed
/datum/gas_mixture/copy()
var/list/cached_gases = gases
var/datum/gas_mixture/copy = new
var/list/copy_gases = copy.gases
copy.temperature = temperature
for(var/id in cached_gases)
copy.add_gas(id)
copy_gases[id][MOLES] = cached_gases[id][MOLES]
return copy
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/sample_gases = sample.gases
temperature = sample.temperature
for(var/id in sample_gases)
assert_gas(id)
cached_gases[id][MOLES] = sample_gases[id][MOLES]
//remove all gases not in the sample
cached_gases &= sample_gases
return 1
/datum/gas_mixture/copy_from_turf(turf/model)
parse_gas_string(model.initial_gas_mix)
//acounts for changes in temperature
var/turf/model_parent = model.parent_type
if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
temperature = model.temperature
return 1
/datum/gas_mixture/parse_gas_string(gas_string)
var/list/gases = src.gases
var/list/gas = params2list(gas_string)
if(gas["TEMP"])
temperature = text2num(gas["TEMP"])
gas -= "TEMP"
gases.Cut()
for(var/id in gas)
add_gas(id)
gases[id][MOLES] = text2num(gas[id])
return 1
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
if(!sharer)
return 0
var/list/cached_gases = gases
var/list/sharer_gases = sharer.gases
var/temperature_delta = temperature_archived - sharer.temperature_archived
var/abs_temperature_delta = abs(temperature_delta)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
var/moved_moles = 0
var/abs_moved_moles = 0
//GAS TRANSFER
for(var/id in sharer_gases - cached_gases) // create gases not in our cache
add_gas(id)
for(var/id in cached_gases) // transfer gases
if(!sharer_gases[id]) //checking here prevents an uneeded proc call if the check fails.
sharer.add_gas(id)
var/gas = cached_gases[id]
var/sharergas = sharer_gases[id]
var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT]
if(delta > 0)
heat_capacity_self_to_sharer += gas_heat_capacity
else
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. saves a proc call.
gas[MOLES] -= delta
sharergas[MOLES] += delta
moved_moles += delta
abs_moved_moles += abs(delta)
last_share = abs_moved_moles
//THERMAL ENERGY TRANSFER
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
//transfer of thermal energy (via changed heat capacity) between self and sharer
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
//thermal energy of the system (self and sharer) is unchanged
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
var/list/unique_gases = cached_gases ^ sharer_gases
if(unique_gases.len) //if all gases were present in both mixtures, we know that no gases are 0
garbage_collect(cached_gases - sharer_gases) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
sharer.garbage_collect(sharer_gases - cached_gases) //the reverse is equally true
sharer.after_share(src, atmos_adjacent_turfs)
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/our_moles
TOTAL_MOLES(cached_gases,our_moles)
var/their_moles
TOTAL_MOLES(sharer_gases,their_moles)
var/delta_pressure = temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)
return delta_pressure * R_IDEAL_GAS_EQUATION / volume
/datum/gas_mixture/after_share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
return
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
//transfer of thermal energy (via conduction) between self and sharer
if(sharer)
sharer_temperature = sharer.temperature_archived
var/temperature_delta = temperature_archived - sharer_temperature
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*temperature_delta* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature = max(temperature - heat/self_heat_capacity, TCMB)
sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB)
if(sharer)
sharer.temperature = sharer_temperature
return sharer_temperature
//thermal energy of the system (self and sharer) is unchanged
/datum/gas_mixture/compare(datum/gas_mixture/sample)
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
var/gas_moles = cached_gases[id]
gas_moles = gas_moles ? gas_moles[MOLES] : 0
var/sample_moles = sample_gases[id]
sample_moles = sample_moles ? sample_moles[MOLES] : 0
var/delta = abs(gas_moles - sample_moles)
if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
return id
var/our_moles
TOTAL_MOLES(cached_gases, our_moles)
if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE)
var/temp = temperature
var/sample_temp = sample.temperature
var/temperature_delta = abs(temp - sample_temp)
if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return "temp"
return ""
/datum/gas_mixture/react(turf/open/dump_location)
. = 0
if(temperature < TCMB) //just for safety
temperature = TCMB
reaction_results = new
var/list/cached_gases = gases
var/temp = temperature
var/ener = thermal_energy()
reaction_loop:
for(var/r in SSair.gas_reactions)
var/datum/gas_reaction/reaction = r
var/list/min_reqs = reaction.min_requirements.Copy()
if((min_reqs["TEMP"] && temp < min_reqs["TEMP"]) \
|| (min_reqs["ENER"] && ener < min_reqs["ENER"]))
continue
min_reqs -= "TEMP"
min_reqs -= "ENER"
for(var/id in min_reqs)
if(!cached_gases[id] || cached_gases[id][MOLES] < min_reqs[id])
continue reaction_loop
//at this point, all minimum requirements for the reaction are satisfied.
/* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost
var/list/max_reqs = reaction.max_requirements.Copy()
if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \
|| (max_reqs["ENER"] && ener > max_reqs["ENER"]))
continue
max_reqs -= "TEMP"
max_reqs -= "ENER"
for(var/id in max_reqs)
if(cached_gases[id] && cached_gases[id][MOLES] > max_reqs[id])
continue reaction_loop
//at this point, all requirements for the reaction are satisfied. we can now react()
*/
. |= reaction.react(src, dump_location)
if(.)
garbage_collect()
//Takes the amount of the gas you want to PP as an argument
//So I don't have to do some hacky switches/defines/magic strings
//eg:
//Tox_PP = get_partial_pressure(gas_mixture.toxins)
//O2_PP = get_partial_pressure(gas_mixture.oxygen)
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
//inverse
/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
//Mathematical proofs:
/*
get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp
get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
10/20*5 = 2.5
10 = 2.5/5*20
*/
/*
What are the archived variables for?
Calculations are done using the archived variables with the results merged into the regular variables.
This prevents race conditions that arise based on the order of tile processing.
*/
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/proc/init_gaslist_cache()
. = list()
for(var/id in GLOB.meta_gas_info)
var/list/cached_gas = new(3)
.[id] = cached_gas
cached_gas[MOLES] = 0
cached_gas[ARCHIVE] = 0
cached_gas[GAS_META] = GLOB.meta_gas_info[id]
#define GASLIST(id, out_list)\
var/list/tmp_gaslist = GLOB.gaslist_cache[id];\
out_list = tmp_gaslist.Copy();
/datum/gas_mixture
var/list/gases
var/temperature //kelvins
var/tmp/temperature_archived
var/volume //liters
var/last_share
var/list/reaction_results
/datum/gas_mixture/New(volume = CELL_VOLUME)
gases = new
temperature = 0
temperature_archived = 0
src.volume = volume
last_share = 0
reaction_results = new
//listmos procs
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
var/cached_gases = gases
if(cached_gases[gas_id])
return
GASLIST(gas_id, cached_gases[gas_id])
//assert_gases(args) - shorthand for calling assert_gas() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
assert_gas(id)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id. This can clobber existing gases.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
GASLIST(gas_id, gases[gas_id])
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
var/cached_gases = gases
for(var/id in args)
GASLIST(id, cached_gases[id])
//garbage_collect() - removes any gas list which is empty.
//If called with a list as an argument, only removes gas lists with IDs from that list.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
/datum/gas_mixture/proc/garbage_collect(list/tocheck)
var/list/cached_gases = gases
for(var/id in (tocheck || cached_gases))
if(cached_gases[id][MOLES] <= 0 && cached_gases[id][ARCHIVE] <= 0)
cached_gases -= id
//PV = nRT
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[MOLES] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/proc/heat_capacity_archived() //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[ARCHIVE] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
//prefer this in performance critical areas
#define TOTAL_MOLES(cached_gases, out_var)\
out_var = 0;\
for(var/total_moles_id in cached_gases){\
out_var += cached_gases[total_moles_id][MOLES];\
}
/datum/gas_mixture/proc/total_moles()
var/cached_gases = gases
TOTAL_MOLES(cached_gases, .)
/datum/gas_mixture/proc/return_pressure() //kilopascals
if(volume > 0) // to prevent division by zero
var/cached_gases = gases
TOTAL_MOLES(cached_gases, .)
. *= R_IDEAL_GAS_EQUATION * temperature / volume
return
return 0
/datum/gas_mixture/proc/return_temperature() //kelvins
return temperature
/datum/gas_mixture/proc/return_volume() //liters
return max(0, volume)
/datum/gas_mixture/proc/thermal_energy() //joules
return temperature * heat_capacity()
/datum/gas_mixture/proc/archive()
//Update archived versions of variables
//Returns: 1 in all cases
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
//Merges all air from giver into self. Deletes giver.
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/remove(amount)
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/datum/gas_mixture/proc/remove_ratio(ratio)
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/datum/gas_mixture/proc/copy()
//Creates new, identical gas mixture
//Returns: duplicate gas mixture
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
//Copies variables from sample
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with temperature
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/parse_gas_string(gas_string)
//Copies variables from a particularly formatted string.
//Returns: 1 if we are mutable, 0 otherwise
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Returns: amount of gas exchanged (+ if sharer received)
/datum/gas_mixture/proc/after_share(datum/gas_mixture/sharer)
//called on share's sharer to let it know it just got some gases
/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
//Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length
//Returns: new temperature of the sharer
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
//Returns: a string indicating what check failed, or "" if check passes
/datum/gas_mixture/proc/react(turf/open/dump_location)
//Performs various reactions such as combustion or fusion (LOL)
//Returns: 1 if any reaction took place; 0 otherwise
/datum/gas_mixture/archive()
var/list/cached_gases = gases
temperature_archived = temperature
for(var/id in cached_gases)
cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
return 1
/datum/gas_mixture/merge(datum/gas_mixture/giver)
if(!giver)
return 0
//heat transfer
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity)
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/giver_gases = giver.gases
//gas transfer
for(var/giver_id in giver_gases)
assert_gas(giver_id)
cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
return 1
/datum/gas_mixture/remove(amount)
var/sum
var/list/cached_gases = gases
TOTAL_MOLES(cached_gases, sum)
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES] / sum) * amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
return removed
/datum/gas_mixture/remove_ratio(ratio)
if(ratio <= 0)
return null
ratio = min(ratio, 1)
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
return removed
/datum/gas_mixture/copy()
var/list/cached_gases = gases
var/datum/gas_mixture/copy = new
var/list/copy_gases = copy.gases
copy.temperature = temperature
for(var/id in cached_gases)
copy.add_gas(id)
copy_gases[id][MOLES] = cached_gases[id][MOLES]
return copy
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/sample_gases = sample.gases
temperature = sample.temperature
for(var/id in sample_gases)
assert_gas(id)
cached_gases[id][MOLES] = sample_gases[id][MOLES]
//remove all gases not in the sample
cached_gases &= sample_gases
return 1
/datum/gas_mixture/copy_from_turf(turf/model)
parse_gas_string(model.initial_gas_mix)
//acounts for changes in temperature
var/turf/model_parent = model.parent_type
if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature))
temperature = model.temperature
return 1
/datum/gas_mixture/parse_gas_string(gas_string)
var/list/gases = src.gases
var/list/gas = params2list(gas_string)
if(gas["TEMP"])
temperature = text2num(gas["TEMP"])
gas -= "TEMP"
gases.Cut()
for(var/id in gas)
add_gas(id)
gases[id][MOLES] = text2num(gas[id])
return 1
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
if(!sharer)
return 0
var/list/cached_gases = gases
var/list/sharer_gases = sharer.gases
var/temperature_delta = temperature_archived - sharer.temperature_archived
var/abs_temperature_delta = abs(temperature_delta)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
var/moved_moles = 0
var/abs_moved_moles = 0
//GAS TRANSFER
for(var/id in sharer_gases - cached_gases) // create gases not in our cache
add_gas(id)
for(var/id in cached_gases) // transfer gases
if(!sharer_gases[id]) //checking here prevents an uneeded proc call if the check fails.
sharer.add_gas(id)
var/gas = cached_gases[id]
var/sharergas = sharer_gases[id]
var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT]
if(delta > 0)
heat_capacity_self_to_sharer += gas_heat_capacity
else
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. saves a proc call.
gas[MOLES] -= delta
sharergas[MOLES] += delta
moved_moles += delta
abs_moved_moles += abs(delta)
last_share = abs_moved_moles
//THERMAL ENERGY TRANSFER
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
//transfer of thermal energy (via changed heat capacity) between self and sharer
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
//thermal energy of the system (self and sharer) is unchanged
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
var/list/unique_gases = cached_gases ^ sharer_gases
if(unique_gases.len) //if all gases were present in both mixtures, we know that no gases are 0
garbage_collect(cached_gases - sharer_gases) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
sharer.garbage_collect(sharer_gases - cached_gases) //the reverse is equally true
sharer.after_share(src, atmos_adjacent_turfs)
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/our_moles
TOTAL_MOLES(cached_gases,our_moles)
var/their_moles
TOTAL_MOLES(sharer_gases,their_moles)
var/delta_pressure = temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)
return delta_pressure * R_IDEAL_GAS_EQUATION / volume
/datum/gas_mixture/after_share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
return
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
//transfer of thermal energy (via conduction) between self and sharer
if(sharer)
sharer_temperature = sharer.temperature_archived
var/temperature_delta = temperature_archived - sharer_temperature
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*temperature_delta* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature = max(temperature - heat/self_heat_capacity, TCMB)
sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB)
if(sharer)
sharer.temperature = sharer_temperature
return sharer_temperature
//thermal energy of the system (self and sharer) is unchanged
/datum/gas_mixture/compare(datum/gas_mixture/sample)
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
var/gas_moles = cached_gases[id]
gas_moles = gas_moles ? gas_moles[MOLES] : 0
var/sample_moles = sample_gases[id]
sample_moles = sample_moles ? sample_moles[MOLES] : 0
var/delta = abs(gas_moles - sample_moles)
if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
return id
var/our_moles
TOTAL_MOLES(cached_gases, our_moles)
if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE)
var/temp = temperature
var/sample_temp = sample.temperature
var/temperature_delta = abs(temp - sample_temp)
if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return "temp"
return ""
/datum/gas_mixture/react(turf/open/dump_location)
. = 0
if(temperature < TCMB) //just for safety
temperature = TCMB
reaction_results = new
var/list/cached_gases = gases
var/temp = temperature
var/ener = thermal_energy()
reaction_loop:
for(var/r in SSair.gas_reactions)
var/datum/gas_reaction/reaction = r
var/list/min_reqs = reaction.min_requirements.Copy()
if((min_reqs["TEMP"] && temp < min_reqs["TEMP"]) \
|| (min_reqs["ENER"] && ener < min_reqs["ENER"]))
continue
min_reqs -= "TEMP"
min_reqs -= "ENER"
for(var/id in min_reqs)
if(!cached_gases[id] || cached_gases[id][MOLES] < min_reqs[id])
continue reaction_loop
//at this point, all minimum requirements for the reaction are satisfied.
/* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost
var/list/max_reqs = reaction.max_requirements.Copy()
if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \
|| (max_reqs["ENER"] && ener > max_reqs["ENER"]))
continue
max_reqs -= "TEMP"
max_reqs -= "ENER"
for(var/id in max_reqs)
if(cached_gases[id] && cached_gases[id][MOLES] > max_reqs[id])
continue reaction_loop
//at this point, all requirements for the reaction are satisfied. we can now react()
*/
. |= reaction.react(src, dump_location)
if(.)
garbage_collect()
//Takes the amount of the gas you want to PP as an argument
//So I don't have to do some hacky switches/defines/magic strings
//eg:
//Tox_PP = get_partial_pressure(gas_mixture.toxins)
//O2_PP = get_partial_pressure(gas_mixture.oxygen)
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
//inverse
/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
//Mathematical proofs:
/*
get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp
get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
10/20*5 = 2.5
10 = 2.5/5*20
*/
@@ -108,8 +108,6 @@
var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
var/temperature = air.temperature
var/list/cached_results = air.reaction_results
//to_chat(world, "pre [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]")
cached_results[id] = 0
//General volatile gas burn
@@ -165,8 +163,6 @@
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
//to_chat(world, "post [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]")
//let the floor know a fire is happening
if(istype(location))
temperature = air.temperature
@@ -201,7 +197,6 @@
//Fusion wont occur if the level of impurities is too high.
return NO_REACTION
//to_chat(world, "pre [temperature, [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]])
var/old_heat_capacity = air.heat_capacity()
var/carbon_efficency = min(cached_gases["plasma"][MOLES]/cached_gases["co2"][MOLES],MAX_CARBON_EFFICENCY)
var/reaction_energy = air.thermal_energy()
@@ -226,7 +221,6 @@
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB)
//Prevents whatever mechanism is causing it to hit negative temperatures.
//to_chat(world, "post [temperature], [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]])
return REACTING
#undef REACTING
@@ -73,7 +73,7 @@
var/datum/radio_frequency/radio_connection
var/list/TLV = list( // Breathable air.
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.80, ONE_ATMOSPHERE* 0.90, ONE_ATMOSPHERE * 1.10, ONE_ATMOSPHERE * 1.20), // kPa
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
"o2" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
"n2" = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
@@ -101,7 +101,7 @@
/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
TLV = list(
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.80, ONE_ATMOSPHERE* 0.90, ONE_ATMOSPHERE * 1.10, ONE_ATMOSPHERE * 1.20), // kPa
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(200,210,273.15,283.15), // K
"o2" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
"n2" = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
@@ -415,7 +415,6 @@
signal.data["sigtype"] = "command"
radio_connection.post_signal(src, signal, GLOB.RADIO_FROM_AIRALARM)
// to_chat(world, text("Signal [] Broadcasted to []", command, target))
return 1
@@ -709,6 +708,16 @@
qdel(W)
return
if(istype(W, /obj/item/device/electroadaptive_pseudocircuit))
var/obj/item/device/electroadaptive_pseudocircuit/P = W
if(!P.adapt_circuit(user, 25))
return
user.visible_message("<span class='notice'>[user] fabricates a circuit and places it into [src].</span>", \
"<span class='notice'>You adapt an air alarm circuit and slot it into the assembly.</span>")
buildstage = 1
update_icon()
return
if(istype(W, /obj/item/wrench))
to_chat(user, "<span class='notice'>You detach \the [src] from the wall.</span>")
playsound(src.loc, W.usesound, 50, 1)
@@ -91,7 +91,7 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/can_be_node(obj/machinery/atmospherics/target)
if(target.initialize_directions & get_dir(target,src))
return 1
return TRUE
/obj/machinery/atmospherics/proc/pipeline_expansion()
return nodes
@@ -208,6 +208,17 @@ Pipelines + Other Objects -> Pipe network
pipe_overlay = . = pipeimages[identifier] = image(iconset, iconstate, dir = direction)
pipe_overlay.color = col
/obj/machinery/atmospherics/proc/icon_addintact(var/obj/machinery/atmospherics/node)
var/image/img = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_intact", get_dir(src,node), node.pipe_color)
underlays += img
return img.dir
/obj/machinery/atmospherics/proc/icon_addbroken(var/connected = FALSE)
var/unconnected = (~connected) & initialize_directions
for(var/direction in GLOB.cardinals)
if(unconnected & direction)
underlays += getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_exposed", direction)
/obj/machinery/atmospherics/on_construction(pipe_type, obj_color)
if(can_unwrench)
add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY)
@@ -275,7 +286,7 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/can_crawl_through()
return 1
return TRUE
/obj/machinery/atmospherics/proc/returnPipenets()
return list()
@@ -288,4 +299,5 @@ Pipelines + Other Objects -> Pipe network
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
/obj/machinery/atmospherics/proc/can_see_pipes()
return 1
return TRUE
@@ -1,70 +1,63 @@
//node2, air2, network2 correspond to input
//node1, air1, network1 correspond to output
/obj/machinery/atmospherics/components/binary/circulator
name = "circulator/heat exchanger"
desc = "A gas circulator pump and heat exchanger."
icon_state = "circ1-off"
var/side = CIRC_LEFT
var/status = 0
var/last_pressure_delta = 0
//node2, air2, network2 correspond to input
//node1, air1, network1 correspond to output
/obj/machinery/atmospherics/components/binary/circulator
name = "circulator/heat exchanger"
desc = "A gas circulator pump and heat exchanger."
icon_state = "circ1-off"
var/side = CIRC_LEFT
var/status = 0
var/last_pressure_delta = 0
anchored = TRUE
density = TRUE
var/global/const/CIRC_LEFT = 1
var/global/const/CIRC_RIGHT = 2
/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air()
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
var/output_starting_pressure = air1.return_pressure()
var/input_starting_pressure = air2.return_pressure()
if(output_starting_pressure >= input_starting_pressure-10)
//Need at least 10 KPa difference to overcome friction in the mechanism
last_pressure_delta = 0
return null
//Calculate necessary moles to transfer using PV = nRT
if(air2.temperature>0)
var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2
var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
last_pressure_delta = pressure_delta
//to_chat(world, "pressure_delta = [pressure_delta]; transfer_moles = [transfer_moles];")
//Actually transfer the gas
var/datum/gas_mixture/removed = air2.remove(transfer_moles)
update_parents()
return removed
else
last_pressure_delta = 0
/obj/machinery/atmospherics/components/binary/circulator/process_atmos()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/circulator/update_icon()
if(stat & (BROKEN|NOPOWER))
icon_state = "circ[side]-p"
else if(last_pressure_delta > 0)
if(last_pressure_delta > ONE_ATMOSPHERE)
icon_state = "circ[side]-run"
else
icon_state = "circ[side]-slow"
else
icon_state = "circ[side]-off"
return 1
var/global/const/CIRC_LEFT = 1
var/global/const/CIRC_RIGHT = 2
/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air()
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
var/output_starting_pressure = air1.return_pressure()
var/input_starting_pressure = air2.return_pressure()
if(output_starting_pressure >= input_starting_pressure-10)
//Need at least 10 KPa difference to overcome friction in the mechanism
last_pressure_delta = 0
return null
//Calculate necessary moles to transfer using PV = nRT
if(air2.temperature>0)
var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2
var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
last_pressure_delta = pressure_delta
var/datum/gas_mixture/removed = air2.remove(transfer_moles)
update_parents()
return removed
else
last_pressure_delta = 0
/obj/machinery/atmospherics/components/binary/circulator/process_atmos()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/circulator/update_icon()
if(!is_operational())
icon_state = "circ[side]-p"
else if(last_pressure_delta > 0)
if(last_pressure_delta > ONE_ATMOSPHERE)
icon_state = "circ[side]-run"
else
icon_state = "circ[side]-slow"
else
icon_state = "circ[side]-off"
@@ -1,211 +1,207 @@
/*
Acts like a normal vent, but has an input AND output.
*/
#define EXT_BOUND 1
#define INPUT_MIN 2
#define OUTPUT_MAX 4
/obj/machinery/atmospherics/components/binary/dp_vent_pump
icon = 'icons/obj/atmospherics/components/unary_devices.dmi' //We reuse the normal vent icons!
icon_state = "dpvent_map"
//node2 is output port
//node1 is input port
name = "dual-port air vent"
desc = "Has a valve and pump attached to it. There are two ports."
level = 1
var/frequency = 0
var/id = null
var/datum/radio_frequency/radio_connection
/*
Acts like a normal vent, but has an input AND output.
*/
#define EXT_BOUND 1
#define INPUT_MIN 2
#define OUTPUT_MAX 4
/obj/machinery/atmospherics/components/binary/dp_vent_pump
icon = 'icons/obj/atmospherics/components/unary_devices.dmi' //We reuse the normal vent icons!
icon_state = "dpvent_map"
//node2 is output port
//node1 is input port
name = "dual-port air vent"
desc = "Has a valve and pump attached to it. There are two ports."
level = 1
var/frequency = 0
var/id = null
var/datum/radio_frequency/radio_connection
var/on = FALSE
var/pump_direction = 1 //0 = siphoning, 1 = releasing
var/external_pressure_bound = ONE_ATMOSPHERE
var/input_pressure_min = 0
var/output_pressure_max = 0
var/pressure_checks = EXT_BOUND
//EXT_BOUND: Do not pass external_pressure_bound
//INPUT_MIN: Do not pass input_pressure_min
//OUTPUT_MAX: Do not pass output_pressure_max
/obj/machinery/atmospherics/components/binary/dp_vent_pump/on
on = TRUE
icon_state = "dpvent_map_on"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/Destroy()
var/pump_direction = 1 //0 = siphoning, 1 = releasing
var/external_pressure_bound = ONE_ATMOSPHERE
var/input_pressure_min = 0
var/output_pressure_max = 0
var/pressure_checks = EXT_BOUND
//EXT_BOUND: Do not pass external_pressure_bound
//INPUT_MIN: Do not pass input_pressure_min
//OUTPUT_MAX: Do not pass output_pressure_max
/obj/machinery/atmospherics/components/binary/dp_vent_pump/on
on = TRUE
icon_state = "dpvent_map_on"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/Destroy()
SSradio.remove_object(src, frequency)
return ..()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume
name = "large dual-port air vent"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/on
on = TRUE
icon_state = "dpvent_map_on"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/New()
..()
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
air1.volume = 1000
air2.volume = 1000
/obj/machinery/atmospherics/components/binary/dp_vent_pump/update_icon_nopipes()
cut_overlays()
if(showpipe)
add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "dpvent_cap"))
if(!on || stat & (NOPOWER|BROKEN))
icon_state = "vent_off"
return
if(pump_direction)
icon_state = "vent_out"
else
icon_state = "vent_in"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/process_atmos()
..()
if(!on)
return FALSE
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
var/datum/gas_mixture/environment = loc.return_air()
var/environment_pressure = environment.return_pressure()
if(pump_direction) //input -> external
var/pressure_delta = 10000
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
if(pressure_checks&INPUT_MIN)
pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
if(pressure_delta > 0)
if(air1.temperature > 0)
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
//Removed can be null if there is no atmosphere in air1
if(!removed)
return FALSE
loc.assume_air(removed)
air_update_turf()
var/datum/pipeline/parent1 = PARENT1
parent1.update = 1
else //external -> output
var/pressure_delta = 10000
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
if(pressure_checks&INPUT_MIN)
pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
if(pressure_delta > 0)
if(environment.temperature > 0)
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
//removed can be null if there is no air in the location
if(!removed)
return FALSE
air2.merge(removed)
air_update_turf()
var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
return TRUE
//Radio remote control
/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/broadcast_status()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.source = src
signal.data = list(
"tag" = id,
"device" = "ADVP",
"power" = on,
"direction" = pump_direction?("release"):("siphon"),
"checks" = pressure_checks,
"input" = input_pressure_min,
"output" = output_pressure_max,
"external" = external_pressure_bound,
"sigtype" = "status"
)
radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
return 1
/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit()
..()
if(frequency)
set_frequency(frequency)
broadcast_status()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
if("power" in signal.data)
on = text2num(signal.data["power"])
if("power_toggle" in signal.data)
on = !on
if("set_direction" in signal.data)
pump_direction = text2num(signal.data["set_direction"])
if("checks" in signal.data)
pressure_checks = text2num(signal.data["checks"])
if("purge" in signal.data)
pressure_checks &= ~1
pump_direction = 0
if("stabalize" in signal.data)
pressure_checks |= 1
pump_direction = 1
if("set_input_pressure" in signal.data)
input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_output_pressure" in signal.data)
output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_external_pressure" in signal.data)
external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("status" in signal.data)
spawn(2)
broadcast_status()
return //do not update_icon
//if(signal.data["tag"])
spawn(2)
broadcast_status()
update_icon()
#undef EXT_BOUND
#undef INPUT_MIN
#undef OUTPUT_MAX
return ..()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume
name = "large dual-port air vent"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/on
on = TRUE
icon_state = "dpvent_map_on"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/New()
..()
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
air1.volume = 1000
air2.volume = 1000
/obj/machinery/atmospherics/components/binary/dp_vent_pump/update_icon_nopipes()
cut_overlays()
if(showpipe)
add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "dpvent_cap"))
if(!on || !is_operational())
icon_state = "vent_off"
return
if(pump_direction)
icon_state = "vent_out"
else
icon_state = "vent_in"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/process_atmos()
..()
if(!on)
return
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
var/datum/gas_mixture/environment = loc.return_air()
var/environment_pressure = environment.return_pressure()
if(pump_direction) //input -> external
var/pressure_delta = 10000
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
if(pressure_checks&INPUT_MIN)
pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
if(pressure_delta > 0)
if(air1.temperature > 0)
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
//Removed can be null if there is no atmosphere in air1
if(!removed)
return
loc.assume_air(removed)
air_update_turf()
var/datum/pipeline/parent1 = PARENT1
parent1.update = 1
else //external -> output
var/pressure_delta = 10000
if(pressure_checks&EXT_BOUND)
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
if(pressure_checks&INPUT_MIN)
pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
if(pressure_delta > 0)
if(environment.temperature > 0)
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
//removed can be null if there is no air in the location
if(!removed)
return
air2.merge(removed)
air_update_turf()
var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
//Radio remote control
/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/broadcast_status()
if(!radio_connection)
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.source = src
signal.data = list(
"tag" = id,
"device" = "ADVP",
"power" = on,
"direction" = pump_direction?("release"):("siphon"),
"checks" = pressure_checks,
"input" = input_pressure_min,
"output" = output_pressure_max,
"external" = external_pressure_bound,
"sigtype" = "status"
)
radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit()
..()
if(frequency)
set_frequency(frequency)
broadcast_status()
/obj/machinery/atmospherics/components/binary/dp_vent_pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return
if("power" in signal.data)
on = text2num(signal.data["power"])
if("power_toggle" in signal.data)
on = !on
if("set_direction" in signal.data)
pump_direction = text2num(signal.data["set_direction"])
if("checks" in signal.data)
pressure_checks = text2num(signal.data["checks"])
if("purge" in signal.data)
pressure_checks &= ~1
pump_direction = 0
if("stabalize" in signal.data)
pressure_checks |= 1
pump_direction = 1
if("set_input_pressure" in signal.data)
input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_output_pressure" in signal.data)
output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]),0,ONE_ATMOSPHERE*50)
if("set_external_pressure" in signal.data)
external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("status" in signal.data)
spawn(2)
broadcast_status()
return //do not update_icon
//if(signal.data["tag"])
spawn(2)
broadcast_status()
update_icon()
#undef EXT_BOUND
#undef INPUT_MIN
#undef OUTPUT_MAX
@@ -12,7 +12,7 @@ Passive gate is similar to the regular pump except:
name = "passive gate"
desc = "A one-way air valve that does not require power."
can_unwrench = 1
can_unwrench = TRUE
var/on = FALSE
var/target_pressure = ONE_ATMOSPHERE
@@ -36,7 +36,7 @@ Passive gate is similar to the regular pump except:
/obj/machinery/atmospherics/components/binary/passive_gate/process_atmos()
..()
if(!on)
return 0
return
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -47,7 +47,7 @@ Passive gate is similar to the regular pump except:
if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10))
//No need to pump gas if target is already reached or input pressure is too low
//Need at least 10 KPa difference to overcome friction in the mechanism
return 1
return
//Calculate necessary moles to transfer using PV = nRT
if((air1.total_moles() > 0) && (air1.temperature>0))
@@ -73,7 +73,7 @@ Passive gate is similar to the regular pump except:
/obj/machinery/atmospherics/components/binary/passive_gate/proc/broadcast_status()
if(!radio_connection)
return 0
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -89,8 +89,6 @@ Passive gate is similar to the regular pump except:
radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
return 1
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -137,7 +135,7 @@ Passive gate is similar to the regular pump except:
/obj/machinery/atmospherics/components/binary/passive_gate/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
return
var/old_on = on //for logging
@@ -159,16 +157,14 @@ Passive gate is similar to the regular pump except:
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/binary/passive_gate/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/passive_gate/can_unwrench(mob/user)
if(..())
if(on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
return 1
. = ..()
if(. && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -17,7 +17,7 @@ Thus, the two variables affect pump operation are set in New():
name = "gas pump"
desc = "A pump that moves gas by pressure."
can_unwrench = 1
can_unwrench = TRUE
var/on = FALSE
var/target_pressure = ONE_ATMOSPHERE
@@ -36,7 +36,7 @@ Thus, the two variables affect pump operation are set in New():
return ..()
/obj/machinery/atmospherics/components/binary/pump/update_icon_nopipes()
if(stat & NOPOWER)
if(!is_operational())
icon_state = "pump_off"
return
@@ -44,10 +44,8 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/pump/process_atmos()
// ..()
if(stat & (NOPOWER|BROKEN))
return 0
if(!on)
return 0
if(!on || !is_operational())
return
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -56,7 +54,7 @@ Thus, the two variables affect pump operation are set in New():
if((target_pressure - output_starting_pressure) < 0.01)
//No need to pump gas if target is already reached!
return 1
return
//Calculate necessary moles to transfer using PV=nRT
if((air1.total_moles() > 0) && (air1.temperature>0))
@@ -69,8 +67,6 @@ Thus, the two variables affect pump operation are set in New():
update_parents()
return 1
//Radio remote control
/obj/machinery/atmospherics/components/binary/pump/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
@@ -80,7 +76,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/pump/proc/broadcast_status()
if(!radio_connection)
return 0
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -96,8 +92,6 @@ Thus, the two variables affect pump operation are set in New():
radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
return 1
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -121,8 +115,7 @@ Thus, the two variables affect pump operation are set in New():
if("power")
on = !on
investigate_log("Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] manipulated a pump at [x], [y], [z]")
message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
. = TRUE
if("pressure")
var/pressure = params["pressure"]
@@ -139,8 +132,7 @@ Thus, the two variables affect pump operation are set in New():
if(.)
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("Pump, [src.name], was set to [target_pressure] kPa by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was set to [target_pressure] kPa by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] manipulated a pump at [x], [y], [z]")
message_admins("Pump, [src.name], was set to [target_pressure] kPa by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
update_icon()
/obj/machinery/atmospherics/components/binary/pump/atmosinit()
@@ -150,7 +142,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
return
var/old_on = on //for logging
@@ -172,21 +164,18 @@ Thus, the two variables affect pump operation are set in New():
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/binary/pump/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/pump/can_unwrench(mob/user)
if(..())
var/turf/T = get_turf(src)
var/area/A = get_area(src)
if(!(stat & NOPOWER) && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
investigate_log("Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] unwrenched a pump at [x], [y], [z]")
return 1
. = ..()
var/area/A = get_area(src)
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
else
investigate_log("Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(user)] at [A]")
return TRUE
@@ -7,7 +7,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
name = "manual valve"
desc = "A pipe valve"
can_unwrench = 1
can_unwrench = TRUE
var/frequency = 0
var/id = null
@@ -57,8 +57,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
var/turf/T = get_turf(src)
var/area/A = get_area(src)
investigate_log("Valve, [src.name], was manipiulated by [key_name(usr)] at [x], [y], [z], [A]", "atmos")
message_admins("Valve, [src.name], was manipulated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] manipulated a manual valve at [x], [y], [z]")
message_admins("Valve, [src.name], was manipulated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)], [A]")
/obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI
@@ -71,7 +70,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
return src.attack_hand(user)
/obj/machinery/atmospherics/components/binary/valve/digital/update_icon_nopipes(animation)
if(stat & NOPOWER)
if(!is_operational())
normalize_dir()
icon_state = "dvalve_nopower"
return
@@ -17,7 +17,7 @@ Thus, the two variables affect pump operation are set in New():
name = "volumetric gas pump"
desc = "A pump that moves gas by volume."
can_unwrench = 1
can_unwrench = TRUE
var/on = FALSE
var/transfer_rate = MAX_TRANSFER_RATE
@@ -34,7 +34,7 @@ Thus, the two variables affect pump operation are set in New():
on = TRUE
/obj/machinery/atmospherics/components/binary/volume_pump/update_icon_nopipes()
if(stat & NOPOWER)
if(!is_operational())
icon_state = "volpump_off"
return
@@ -42,10 +42,8 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/volume_pump/process_atmos()
// ..()
if(stat & (NOPOWER|BROKEN))
if(!on || !is_operational())
return
if(!on)
return 0
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -56,7 +54,7 @@ Thus, the two variables affect pump operation are set in New():
var/output_starting_pressure = air2.return_pressure()
if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
return 1
return
var/transfer_ratio = min(1, transfer_rate/air1.volume)
@@ -66,8 +64,6 @@ Thus, the two variables affect pump operation are set in New():
update_parents()
return 1
/obj/machinery/atmospherics/components/binary/volume_pump/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
@@ -76,7 +72,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/volume_pump/proc/broadcast_status()
if(!radio_connection)
return 0
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -91,8 +87,6 @@ Thus, the two variables affect pump operation are set in New():
)
radio_connection.post_signal(src, signal)
return 1
/obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -116,14 +110,12 @@ Thus, the two variables affect pump operation are set in New():
if(..())
return
var/turf/T = get_turf(src)
//var/area/A = get_area(src)
var/area/A = get_area(src)
switch(action)
if("power")
on = !on
investigate_log("Volume Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]")
investigate_log("Volume Pump, [src.name], was turned [on ? "on" : "off"] by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
. = TRUE
if("rate")
var/rate = params["rate"]
@@ -139,14 +131,13 @@ Thus, the two variables affect pump operation are set in New():
. = TRUE
if(.)
transfer_rate = Clamp(rate, 0, MAX_TRANSFER_RATE)
investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] manipulated a volume pump at [x], [y], [z]")
investigate_log("Volume Pump, [src.name], was set to [transfer_rate] L/s by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], was set to [transfer_rate] L/s by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
return
var/old_on = on //for logging
@@ -169,22 +160,18 @@ Thus, the two variables affect pump operation are set in New():
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/binary/volume_pump/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/can_unwrench(mob/user)
if(..())
var/turf/T = get_turf(src)
//var/area/A = get_area(src)
if(!(stat & NOPOWER) && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
investigate_log("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [loc.loc]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)]")
log_admin("[key_name(usr)] unwrenched a volume pump at [x], [y], [z]")
return 1
. = ..()
var/area/A = get_area(src)
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
else
investigate_log("Volume Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(usr)] at [A]")
return
@@ -23,18 +23,6 @@ On top of that, now people can add component-speciic procs/vars if they want!
Iconnery
*/
/obj/machinery/atmospherics/components/proc/icon_addintact(var/obj/machinery/atmospherics/node)
var/image/img = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_intact", get_dir(src,node), node.pipe_color)
underlays += img
return img.dir
/obj/machinery/atmospherics/components/proc/icon_addbroken(var/connected = FALSE)
var/unconnected = (~connected) & initialize_directions
for(var/direction in GLOB.cardinals)
if(unconnected & direction)
underlays += getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_exposed", direction)
/obj/machinery/atmospherics/components/proc/update_icon_nopipes()
return
@@ -52,7 +40,7 @@ Iconnery
if(!showpipe)
return //no need to update the pipes if they aren't showing
var/connected = FALSE
var/connected = 0 //Direction bitset
for(DEVICE_TYPE_LOOP) //adds intact pieces
if(NODE_I)
@@ -2,7 +2,7 @@
name = "gas filter"
icon_state = "filter_off"
density = FALSE
can_unwrench = 1
can_unwrench = TRUE
var/on = FALSE
var/target_pressure = ONE_ATMOSPHERE
var/filter_type = ""
@@ -11,7 +11,7 @@
/obj/machinery/atmospherics/components/trinary/filter/flipped
icon_state = "filter_off_f"
flipped = 1
flipped = TRUE
// These two filter types have critical_machine flagged to on and thus causes the area they are in to be exempt from the Grid Check event.
@@ -43,27 +43,21 @@
..()
/obj/machinery/atmospherics/components/trinary/filter/update_icon_nopipes()
if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3)
if(on && NODE1 && NODE2 && NODE3 && is_operational())
icon_state = "filter_on[flipped?"_f":""]"
return
icon_state = "filter_off[flipped?"_f":""]"
/obj/machinery/atmospherics/components/trinary/filter/power_change()
var/old_stat = stat
..()
if(stat & NOPOWER)
on = FALSE
if(old_stat != stat)
if(stat != old_stat)
update_icon()
/obj/machinery/atmospherics/components/trinary/filter/process_atmos()
..()
if(!on)
return 0
if(!(NODE1 && NODE2 && NODE3))
return 0
if(!on || !(NODE1 && NODE2 && NODE3) || !is_operational())
return
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -73,7 +67,7 @@
if(output_starting_pressure >= target_pressure)
//No need to mix if target is already full!
return 1
return
//Calculate necessary moles to transfer using PV=nRT
@@ -113,8 +107,6 @@
update_parents()
return 1
/obj/machinery/atmospherics/components/trinary/filter/atmosinit()
set_frequency(frequency)
return ..()
@@ -167,3 +159,10 @@
investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
update_icon()
/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user)
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -3,7 +3,7 @@
density = FALSE
name = "gas mixer"
can_unwrench = 1
can_unwrench = TRUE
var/on = FALSE
@@ -15,7 +15,7 @@
/obj/machinery/atmospherics/components/trinary/mixer/flipped
icon_state = "mixer_off_f"
flipped = 1
flipped = TRUE
/obj/machinery/atmospherics/components/trinary/mixer/update_icon()
cut_overlays()
@@ -29,18 +29,15 @@
return ..()
/obj/machinery/atmospherics/components/trinary/mixer/update_icon_nopipes()
if(!(stat & NOPOWER) && on && NODE1 && NODE2 && NODE3)
if(on && NODE1 && NODE2 && NODE3 && is_operational())
icon_state = "mixer_on[flipped?"_f":""]"
return
icon_state = "mixer_off[flipped?"_f":""]"
/obj/machinery/atmospherics/components/trinary/mixer/power_change()
var/old_stat = stat
..()
if(stat & NOPOWER)
on = FALSE
if(old_stat != stat)
if(stat != old_stat)
update_icon()
/obj/machinery/atmospherics/components/trinary/mixer/New()
@@ -51,10 +48,8 @@
/obj/machinery/atmospherics/components/trinary/mixer/process_atmos()
..()
if(!on)
return 0
if(!(NODE1 && NODE2 && NODE3))
return 0
if(!on || !(NODE1 && NODE2 && NODE3) && !is_operational())
return
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -64,7 +59,7 @@
if(output_starting_pressure >= target_pressure)
//No need to mix if target is already full!
return 1
return
//Calculate necessary moles to transfer using PV=nRT
@@ -114,7 +109,7 @@
var/datum/pipeline/parent3 = PARENT3
parent3.update = TRUE
return TRUE
return
/obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
@@ -167,4 +162,12 @@
node1_concentration = max(0, min(1, node1_concentration - value))
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
update_icon()
update_icon()
/obj/machinery/atmospherics/components/trinary/filter/can_unwrench(mob/user)
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -6,7 +6,7 @@
device_type = TRINARY
layer = GAS_FILTER_LAYER
var/flipped = 0
var/flipped = FALSE
/obj/machinery/atmospherics/components/trinary/SetInitDirections()
switch(dir)
@@ -44,4 +44,4 @@ Housekeeping and pipe network stuff
node1_connect = turn(node1_connect, 180)
node3_connect = turn(node3_connect, 180)
return list(node1_connect, node2_connect, node3_connect)
return list(node1_connect, node2_connect, node3_connect)
@@ -33,7 +33,7 @@
var/escape_in_progress = FALSE
var/message_cooldown
var/breakout_time = 0.5
var/breakout_time = 300
/obj/machinery/atmospherics/components/unary/cryo_cell/Initialize()
. = ..()
@@ -115,7 +115,7 @@
occupant_overlay.dir = SOUTH
occupant_overlay.pixel_y = 22
if(on && is_operational() && !running_bob_anim)
if(on && !running_bob_anim && is_operational())
icon_state = "pod-on"
running_bob_anim = TRUE
run_bob_anim(TRUE, occupant_overlay)
@@ -246,9 +246,9 @@
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("<span class='notice'>You see [user] kicking against the glass of [src]!</span>", \
"<span class='notice'>You struggle inside [src], kicking the release with your foot... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
"<span class='notice'>You struggle inside [src], kicking the release with your foot... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a thump from [src].</span>")
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
if(do_after(user,(breakout_time), target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
@@ -349,7 +349,7 @@
data["cellTemperature"] = round(air1.temperature, 1)
data["isBeakerLoaded"] = beaker ? TRUE : FALSE
var beakerContents = list()
var/beakerContents = list()
if(beaker && beaker.reagents && beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents += list(list("name" = R.name, "volume" = R.volume))
@@ -378,6 +378,8 @@
if("ejectbeaker")
if(beaker)
beaker.forceMove(loc)
if(Adjacent(usr) && !issilicon(usr))
usr.put_in_hands(beaker)
beaker = null
. = TRUE
update_icon()
@@ -394,4 +396,11 @@
/obj/machinery/atmospherics/components/unary/cryo_cell/can_see_pipes()
return 0 //you can't see the pipe network when inside a cryo cell.
/obj/machinery/atmospherics/components/unary/cryo_cell/return_temperature()
var/datum/gas_mixture/G = AIR1
if(G.total_moles() > 10)
return G.temperature
return ..()
#undef CRYOMOBS
@@ -10,12 +10,7 @@
var/update_cycle
/obj/machinery/atmospherics/components/unary/generator_input/update_icon()
if(NODE1)
icon_state = "intact"
else
icon_state = "exposed"
return
icon_state = NODE1 ? "intact" : "exposed"
/obj/machinery/atmospherics/components/unary/generator_input/proc/return_exchange_air()
return AIR1
@@ -5,7 +5,7 @@
name = "heat exchanger"
desc = "Exchanges heat between two input gases. Setup for fast heat transfer"
can_unwrench = 1
can_unwrench = TRUE
layer = LOW_OBJ_LAYER
@@ -20,8 +20,6 @@
else
icon_state = "he_exposed"
return
/obj/machinery/atmospherics/components/unary/heat_exchanger/atmosinit()
if(!partner)
var/partner_connect = turn(dir,180)
@@ -36,11 +34,8 @@
/obj/machinery/atmospherics/components/unary/heat_exchanger/process_atmos()
..()
if(!partner)
return 0
if(SSair.times_fired <= update_cycle)
return 0
if(!partner || SSair.times_fired <= update_cycle)
return
update_cycle = SSair.times_fired
partner.update_cycle = SSair.times_fired
@@ -67,5 +62,3 @@
if(abs(other_old_temperature-partner_air_contents.temperature) > 1)
partner.update_parents()
return 1
@@ -30,7 +30,7 @@
if(showpipe)
add_overlay(getpipeimage(icon, "inje_cap", initialize_directions))
if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
if(!NODE1 || !on || !is_operational())
icon_state = "inje_off"
return
@@ -47,8 +47,8 @@
..()
injecting = 0
if(!on || stat & (NOPOWER|BROKEN))
return 0
if(!on || !is_operational())
return
var/datum/gas_mixture/air_contents = AIR1
@@ -62,11 +62,9 @@
update_parents()
return 1
/obj/machinery/atmospherics/components/unary/outlet_injector/proc/inject()
if(on || injecting || stat & (NOPOWER|BROKEN))
return 0
if(on || injecting || !is_operational())
return
var/datum/gas_mixture/air_contents = AIR1
@@ -91,7 +89,7 @@
/obj/machinery/atmospherics/components/unary/outlet_injector/proc/broadcast_status()
if(!radio_connection)
return 0
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -108,8 +106,6 @@
radio_connection.post_signal(src, signal)
return 1
/obj/machinery/atmospherics/components/unary/outlet_injector/atmosinit()
set_frequency(frequency)
broadcast_status()
@@ -117,7 +113,7 @@
/obj/machinery/atmospherics/components/unary/outlet_injector/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
return
if("power" in signal.data)
on = text2num(signal.data["power"])
@@ -139,8 +135,6 @@
broadcast_status()
return //do not update_icon
//log_admin("DEBUG \[[world.timeofday]\]: outlet_injector/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
//return
spawn(2)
broadcast_status()
update_icon()
@@ -188,9 +182,8 @@
broadcast_status()
/obj/machinery/atmospherics/components/unary/outlet_injector/can_unwrench(mob/user)
if(..())
if (!(stat & NOPOWER|BROKEN) && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
return 1
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -19,7 +19,7 @@
if(showpipe)
add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions)) //it works for now
if(!NODE1 || !on || stat & BROKEN)
if(!NODE1 || !on || !is_operational())
icon_state = "o2gen_off"
return
@@ -3,7 +3,7 @@
desc = "For connecting portables devices related to atmospherics control."
icon = 'icons/obj/atmospherics/components/unary_devices.dmi'
icon_state = "connector_map" //Only for mapping purposes, so mappers can see direction
can_unwrench = 1
can_unwrench = TRUE
var/obj/machinery/portable_atmospherics/connected_device
use_power = NO_POWER_USE
level = 0
@@ -29,11 +29,10 @@
return ..()
/obj/machinery/atmospherics/components/unary/portables_connector/can_unwrench(mob/user)
if(..())
if(connected_device)
to_chat(user, "<span class='warning'>You cannot unwrench [src], detach [connected_device] first!</span>")
else
return 1
. = ..()
if(. && connected_device)
to_chat(user, "<span class='warning'>You cannot unwrench [src], detach [connected_device] first!</span>")
return FALSE
/obj/machinery/atmospherics/components/unary/portables_connector/portableConnectorReturnAir()
return connected_device.portableConnectorReturnAir()
@@ -39,7 +39,6 @@
icon_state = icon_state_on
else
icon_state = initial(icon_state)
return
/obj/machinery/atmospherics/components/unary/thermomachine/update_icon_nopipes()
cut_overlays()
@@ -10,7 +10,7 @@
desc = "Has a valve and pump attached to it."
icon_state = "vent_map"
use_power = IDLE_POWER_USE
can_unwrench = 1
can_unwrench = TRUE
welded = FALSE
level = 1
layer = GAS_SCRUBBER_LAYER
@@ -92,7 +92,7 @@
icon_state = "vent_welded"
return
if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
if(!NODE1 || !on || !is_operational())
icon_state = "vent_off"
return
@@ -103,12 +103,12 @@
/obj/machinery/atmospherics/components/unary/vent_pump/process_atmos()
..()
if(stat & (NOPOWER|BROKEN))
if(!is_operational())
return
if (!NODE1)
if(!NODE1)
on = FALSE
if(!on || welded)
return 0
return
var/datum/gas_mixture/air_contents = AIR1
var/datum/gas_mixture/environment = loc.return_air()
@@ -150,8 +150,6 @@
air_update_turf()
update_parents()
return 1
//Radio remote control
/obj/machinery/atmospherics/components/unary/vent_pump/proc/set_frequency(new_frequency)
@@ -162,7 +160,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/proc/broadcast_status()
if(!radio_connection)
return 0
return
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -189,8 +187,6 @@
radio_connection.post_signal(src, signal, radio_filter_out)
return 1
/obj/machinery/atmospherics/components/unary/vent_pump/atmosinit()
//some vents work his own spesial way
@@ -202,11 +198,11 @@
..()
/obj/machinery/atmospherics/components/unary/vent_pump/receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN))
if(!is_operational())
return
//log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/components/unary/vent_pump/receive_signal([signal.debug_print()])")
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return 0
return
if("purge" in signal.data)
pressure_checks &= ~EXT_BOUND
@@ -257,7 +253,6 @@
//log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/unary/vent_pump/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool))
@@ -266,7 +261,8 @@
playsound(loc, WT.usesound, 40, 1)
to_chat(user, "<span class='notice'>You begin welding the vent...</span>")
if(do_after(user, 20*W.toolspeed, target = src))
if(!src || !WT.isOn()) return
if(!src || !WT.isOn())
return
playsound(src.loc, 'sound/items/welder2.ogg', 50, 1)
if(!welded)
user.visible_message("[user] welds the vent shut.", "<span class='notice'>You weld the vent shut.</span>", "<span class='italics'>You hear welding.</span>")
@@ -282,11 +278,10 @@
return ..()
/obj/machinery/atmospherics/components/unary/vent_pump/can_unwrench(mob/user)
if(..())
if(!(stat & NOPOWER) && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
return 1
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
/obj/machinery/atmospherics/components/unary/vent_pump/examine(mob/user)
..()
@@ -8,7 +8,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 60
can_unwrench = 1
can_unwrench = TRUE
welded = FALSE
level = 1
layer = GAS_SCRUBBER_LAYER
@@ -17,12 +17,12 @@
var/on = FALSE
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
var/scrub_CO2 = 1
var/scrub_Toxins = 0
var/scrub_N2O = 0
var/scrub_BZ = 0
var/scrub_Freon = 0
var/scrub_WaterVapor = 0
var/scrub_CO2 = TRUE
var/scrub_Toxins = FALSE
var/scrub_N2O = FALSE
var/scrub_BZ = FALSE
var/scrub_Freon = FALSE
var/scrub_WaterVapor = FALSE
var/volume_rate = 200
@@ -58,12 +58,8 @@
return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
if(!powered(power_channel))
return 0
if(!on || welded)
return 0
if(stat & (NOPOWER|BROKEN))
return 0
if(!on || welded || !is_operational() || !powered(power_channel))
return FALSE
var/amount = idle_power_usage
@@ -86,7 +82,7 @@
if(widenet)
amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2))
use_power(amount, power_channel)
return 1
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
cut_overlays()
@@ -97,7 +93,7 @@
icon_state = "scrub_welded"
return
if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
if(!NODE1 || !on || !is_operational())
icon_state = "scrub_off"
return
@@ -113,7 +109,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status()
if(!radio_connection)
return 0
return FALSE
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
@@ -143,7 +139,7 @@
radio_connection.post_signal(src, signal, radio_filter_out)
return 1
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
radio_filter_in = frequency==initial(frequency)?(GLOB.RADIO_FROM_AIRALARM):null
@@ -156,20 +152,21 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
..()
if(stat & (NOPOWER|BROKEN))
return
if (!NODE1)
if(!is_operational())
return FALSE
if(!NODE1)
on = FALSE
if(!on || welded)
return 0
return FALSE
scrub(loc)
if(widenet)
for (var/turf/tile in adjacent_turfs)
for(var/turf/tile in adjacent_turfs)
scrub(tile)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile)
if (!istype(tile))
return 0
if(!istype(tile))
return FALSE
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = AIR1
@@ -189,8 +186,8 @@
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
//Nothing left to remove from the tile
if (isnull(removed))
return
if(isnull(removed))
return FALSE
var/list/removed_gases = removed.gases
//Filter it
@@ -199,39 +196,39 @@
filtered_out.temperature = removed.temperature
if(scrub_Toxins && removed_gases["plasma"])
filtered_out.assert_gas("plasma")
filtered_out.add_gas("plasma")
filtered_gases["plasma"][MOLES] = removed_gases["plasma"][MOLES]
removed.gases["plasma"][MOLES] = 0
if(scrub_CO2 && removed_gases["co2"])
filtered_out.assert_gas("co2")
filtered_out.gases["co2"][MOLES] = removed_gases["co2"][MOLES]
removed.gases["co2"][MOLES] = 0
filtered_out.add_gas("co2")
filtered_gases["co2"][MOLES] = removed_gases["co2"][MOLES]
removed_gases["co2"][MOLES] = 0
if(removed_gases["agent_b"])
filtered_out.assert_gas("agent_b")
filtered_out.gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES]
removed.gases["agent_b"][MOLES] = 0
filtered_out.add_gas("agent_b")
filtered_gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES]
removed_gases["agent_b"][MOLES] = 0
if(scrub_N2O && removed_gases["n2o"])
filtered_out.assert_gas("n2o")
filtered_out.gases["n2o"][MOLES] = removed_gases["n2o"][MOLES]
removed.gases["n2o"][MOLES] = 0
filtered_out.add_gas("n2o")
filtered_gases["n2o"][MOLES] = removed_gases["n2o"][MOLES]
removed_gases["n2o"][MOLES] = 0
if(scrub_BZ && removed_gases["bz"])
filtered_out.assert_gas("bz")
filtered_out.gases["bz"][MOLES] = removed_gases["bz"][MOLES]
removed.gases["bz"][MOLES] = 0
filtered_out.add_gas("bz")
filtered_gases["bz"][MOLES] = removed_gases["bz"][MOLES]
removed_gases["bz"][MOLES] = 0
if(scrub_Freon && removed_gases["freon"])
filtered_out.assert_gas("freon")
filtered_out.gases["freon"][MOLES] = removed_gases["freon"][MOLES]
removed.gases["freon"][MOLES] = 0
filtered_out.add_gas("freon")
filtered_gases["freon"][MOLES] = removed_gases["freon"][MOLES]
removed_gases["freon"][MOLES] = 0
if(scrub_WaterVapor && removed_gases["water_vapor"])
filtered_out.assert_gas("water_vapor")
filtered_out.gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES]
removed.gases["water_vapor"][MOLES] = 0
filtered_out.add_gas("water_vapor")
filtered_gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES]
removed_gases["water_vapor"][MOLES] = 0
removed.garbage_collect()
@@ -242,8 +239,8 @@
tile.air_update_turf()
else //Just siphoning all air
if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE)
return
if(air_contents.return_pressure()>=50*ONE_ATMOSPHERE)
return FALSE
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
@@ -254,7 +251,7 @@
update_parents()
return 1
return TRUE
//There is no easy way for an object to be notified of changes to atmos can pass flags_1
@@ -273,7 +270,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN))
if(!is_operational())
return
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return 0
@@ -363,11 +360,10 @@
return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
if(..())
if (!(stat & NOPOWER) && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
else
return 1
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
return !welded
@@ -5,7 +5,7 @@
var/list/obj/machinery/atmospherics/pipe/members
var/list/obj/machinery/atmospherics/components/other_atmosmch
var/update = 1
var/update = TRUE
/datum/pipeline/New()
other_airs = list()
@@ -25,7 +25,7 @@
/datum/pipeline/process()
if(update)
update = 0
update = FALSE
reconcile_air()
update = air.react()
@@ -114,6 +114,7 @@
other_airs.Add(E.other_airs)
E.members.Cut()
E.other_atmosmch.Cut()
update = TRUE
qdel(E)
/obj/machinery/atmospherics/proc/addMember(obj/machinery/atmospherics/A)
@@ -195,7 +196,7 @@
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
air.temperature -= heat/total_heat_capacity
update = 1
update = TRUE
/datum/pipeline/proc/return_air()
. = other_airs + air
@@ -0,0 +1,47 @@
GLOBAL_LIST_EMPTY(bluespace_pipes)
/obj/machinery/atmospherics/pipe/bluespace
name = "bluespace pipe"
desc = "Transmits gas across large distances of space. Developed using bluespace technology."
icon = 'icons/obj/atmospherics/pipes/bluespace.dmi'
icon_state = "map"
dir = SOUTH
initialize_directions = SOUTH
device_type = UNARY
can_buckle = FALSE
/obj/machinery/atmospherics/pipe/bluespace/New()
icon_state = "pipe"
GLOB.bluespace_pipes += src
..()
/obj/machinery/atmospherics/pipe/bluespace/Destroy()
GLOB.bluespace_pipes -= src
for(var/p in GLOB.bluespace_pipes)
var/obj/machinery/atmospherics/pipe/bluespace/P = p
QDEL_NULL(P.parent)
P.build_network()
return ..()
/obj/machinery/atmospherics/pipe/bluespace/SetInitDirections()
initialize_directions = dir
/obj/machinery/atmospherics/pipe/bluespace/pipeline_expansion()
return ..() + GLOB.bluespace_pipes - src
/obj/machinery/atmospherics/components/pipe/bluespace/hide()
update_icon()
/obj/machinery/atmospherics/pipe/bluespace/update_icon(showpipe)
underlays.Cut()
var/turf/T = loc
if(level != 2 && T.intact)
return //no need to update the pipes if they aren't showing
var/connected = 0 //Direction bitset
for(DEVICE_TYPE_LOOP) //adds intact pieces
if(NODE_I)
connected |= icon_addintact(NODE_I)
icon_addbroken(connected) //adds broken pieces
/obj/machinery/atmospherics/pipe/bluespace/paint()
return FALSE
@@ -42,11 +42,6 @@
invisibility = i ? INVISIBILITY_MAXIMUM : 0
update_icon()
/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
//Return 1 if parent should continue checking other pipes
//Return null if parent should stop checking other pipes. Recall: del(src) will by default return null
return 1
/obj/machinery/atmospherics/pipe/proc/releaseAirToTurf()
if(air_temporary)
var/turf/T = loc
@@ -103,3 +98,10 @@
if(damage_flag == "melee" && damage_amount < 12)
return 0
. = ..()
/obj/machinery/atmospherics/pipe/proc/paint(paint_color)
add_atom_colour(paint_color, FIXED_COLOUR_PRIORITY)
pipe_color = paint_color
update_node_icon()
return TRUE
@@ -210,7 +210,7 @@
return
if(user.ckey in team_members)
if(user.ckey in recently_dead_ckeys)
to_chat(user, "It must be more than [respawn_cooldown/10] seconds from your last death to respawn!")
to_chat(user, "It must be more than [DisplayTimeText(respawn_cooldown)] from your last death to respawn!")
return
var/client/new_team_member = user.client
if(user.mind && user.mind.current)
+1 -1
View File
@@ -123,7 +123,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
if(world.time < wait)
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [round(((wait - world.time) / 10) / 60)] minutes.</span>")
to_chat(user, "<span class='notice'>Error: Warpspace triangulation in progress. Estimated time to completion: [DisplayTimeText(wait - world.time)].</span>")
return
for(var/obj/machinery/gateway/G in linked)
@@ -9,10 +9,13 @@
var/times_spoken_to = 0
var/list/shenanigans = list()
/obj/structure/speaking_tile/New()
var/savefile/S = new /savefile("data/npc_saves/Poly.sav")
S["phrases"] >> shenanigans
..()
/obj/structure/speaking_tile/Initialize()
. = ..()
var/json_file = file("data/npc_saves/Poly.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
shenanigans = json["phrases"]
/obj/structure/speaking_tile/interact(mob/user)
if(!isliving(user) || speaking)
@@ -63,7 +66,7 @@
if(204)
SpeakPeace(list("Notice how there was no special message at 200?", "The slow automation of what used to be meaningful milestones?","It's all part of the joke."))
if(250)
SpeakPeace(list("Congratulations.", "By my very loose calculations you've now wasted a decent chunk of the round doing this.", "But you've seen this meme to its conclusion, and that's a experience in itself, right?"))
SpeakPeace(list("Congratulations.", "By my very loose calculations you've now wasted a decent chunk of the round doing this.", "But you've seen this meme to its conclusion, and that's an experience in itself, right?"))
if(251)
SpeakPeace(list("Anyway, here.", "I can't give you anything that would impact the progression of the round.","But you've earned this at least."))
var/obj/item/reagent_containers/food/drinks/trophy/silver_cup/the_ride = new(get_turf(user))
@@ -118,4 +121,4 @@
..()
/obj/effect/landmark/error
name = "error"
name = "error"
+95 -1
View File
@@ -69,4 +69,98 @@
cost = 3
unit_name = "pair"
message = "of handcuffs"
export_types = list(/obj/item/restraints/handcuffs)
export_types = list(/obj/item/restraints/handcuffs)
// relics of lavaland
/datum/export/weapon/hierophant
cost = 40000
unit_name = "Hierophant Club"
export_types = list(/obj/item/hierophant_club)
/datum/export/weapon/lava
cost = 40000
unit_name = "Lava Staff"
export_types = list(/obj/item/lava_staff)
/datum/export/weapon/cleaving_saw
cost = 40000
unit_name = "Cleaving Saw"
export_types = list(/obj/item/melee/transforming/cleaving_saw)
/datum/export/weapon/mayhem
cost = 40000
unit_name = "Mayhem in a bottle"
export_types = list(/obj/item/mayhem)
/datum/export/weapon/blood_contract
cost = 40000
unit_name = "Blood Contract"
export_types = list(/obj/item/blood_contract)
//Artifacts of lavaland
/datum/export/weapon/immortality_talisman
cost = 10000
unit_name = "Immortality Talisman"
export_types = list(/obj/item/device/immortality_talisman)
/datum/export/weapon/babel
cost = 10000
unit_name = "Book of Babel"
export_types = list(/obj/item/book_of_babel)
/datum/export/weapon/hook
cost = 10000
unit_name = "Meat hook"
export_types = list(/obj/item/gun/magic/hook)
/datum/export/weapon/shipbottle //the price for not breaking the bottle.
cost = 20000
unit_name = "Ship in a bottle"
export_types = list(/obj/item/ship_in_a_bottle)
/datum/export/weapon/tarot //price for sacraficing a very profitiable ally
cost = 20000
unit_name = "Tarot cards"
export_types = list(/obj/item/guardiancreator)
/datum/export/weapon/red //second half of telecube
cost = 5000
unit_name = "Red Cube"
export_types = list(/obj/item/device/warp_cube/red)
/datum/export/weapon/blue //first half of telecube
cost = 5000
unit_name = "Blue Cube"
export_types = list(/obj/item/device/warp_cube)
/datum/export/weapon/wisplantern //thermals on lavaland
cost = 10000
unit_name = "Wisp Lantern"
export_types = list(/obj/item/device/wisp_lantern)
/datum/export/weapon/flight //if xenobiology ever reaches the point to get these without shuttle being called they deserve it
cost = 10000
unit_name = "Strange Elixer"
export_types = list(/obj/item/reagent_containers/glass/bottle/potion/flight)
/datum/export/weapon/cheart //is a very powerfull healing artifact in the robust hands
cost = 10000
unit_name = "Cursed Heart"
export_types = list(/obj/item/organ/heart/cursed/wizard)
/datum/export/weapon/ckatana
cost = 10000
unit_name = "Katana"
export_types = list(/obj/item/katana/cursed)
/datum/export/weapon/geye //xray
cost = 10000
unit_name = "God eye"
export_types = list(/obj/item/clothing/glasses/godeye)
/datum/export/weapon/spectral
cost = 10000
unit_name = "Spectral Sword"
export_types = list(/obj/item/melee/ghost_sword)
+5 -1
View File
@@ -1643,7 +1643,11 @@
/obj/item/toy/talking/griffin,
/obj/item/toy/nuke,
/obj/item/toy/minimeteor,
/obj/item/toy/carpplushie,
/obj/item/toy/plush/carpplushie,
/obj/item/toy/plush/lizardplushie,
/obj/item/toy/plush/snakeplushie,
/obj/item/toy/plush/nukeplushie,
/obj/item/toy/plush/slimeplushie,
/obj/item/coin/antagtoken,
/obj/item/stack/tile/fakespace/loaded,
/obj/item/gun/ballistic/shotgun/toy/crossbow,
+1 -1
View File
@@ -150,7 +150,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
//all of our asset datums, used for referring to these later
GLOBAL_LIST_EMPTY(asset_datums)
//get a assetdatum or make a new one
//get an assetdatum or make a new one
/proc/get_asset_datum(var/type)
if (!(type in GLOB.asset_datums))
return new type()
+24 -2
View File
@@ -46,6 +46,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/preferred_map = null
var/uses_glasses_colour = 0
var/screenshake = 100
var/damagescreenshake = 2
//character preferences
var/real_name //our character's name
@@ -170,7 +173,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/parallax
var/uplink_spawn_loc = UPLINK_PDA
var/list/exp
var/list/menuoptions
@@ -363,6 +366,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "High"
dat += "</a><br>"
dat += "<b>Screen Shake:</b> <a href='?_src_=prefs;preference=screenshake'>[(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]</a><br>"
if (!user.client.prefs.screenshake==0)
dat += "<b>Damage Screen Shake:</b> <a href='?_src_=prefs;preference=damagescreenshake'>[(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]</a><br>"
dat += "</td><td width='300px' height='300px' valign='top'>"
dat += "<h2>Special Role Settings</h2>"
@@ -922,7 +930,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("flavor_text")
var/msg = input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(features["flavor_text"])) as message
if(msg != null)
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
msg = html_encode(msg)
features["flavor_text"] = msg
@@ -1486,6 +1494,20 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["exhibitionist"] = TRUE
else
features["exhibitionist"] = FALSE
if ("screenshake")
var/desiredshake = input(user, "Set the amount of screenshake you want. \n(0 = disabled, 100 = full, 200 = maximum.)", "Character Preference", screenshake) as null|num
if (!isnull(desiredshake))
screenshake = desiredshake
if("damagescreenshake")
switch(damagescreenshake)
if(0)
damagescreenshake = 1
if(1)
damagescreenshake = 2
if(2)
damagescreenshake = 0
else
damagescreenshake = 1
if("publicity")
if(unlock_content)
-14
View File
@@ -1,14 +0,0 @@
diff a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm (rejected hunks)
@@ -130,12 +130,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
menuoptions = list()
return
-/datum/preferences/vv_edit_var(var_name, var_value)
- var/static/list/banned_edits = list("exp")
- if(var_name in banned_edits)
- return FALSE
- return ..()
-
/datum/preferences/proc/ShowChoices(mob/user)
if(!user || !user.client)
return
+89 -80
View File
@@ -48,8 +48,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
var/B_monkey = 2048
var/B_gang = 4096
var/B_abductor = 16384
var/B_brother = 32768
var/list/archived = list(B_traitor,B_operative,B_changeling,B_wizard,B_malf,B_rev,B_alien,B_pai,B_cultist,B_blob,B_ninja,B_monkey,B_gang,B_abductor)
var/list/archived = list(B_traitor,B_operative,B_changeling,B_wizard,B_malf,B_rev,B_alien,B_pai,B_cultist,B_blob,B_ninja,B_monkey,B_gang,B_abductor,B_brother)
be_special = list()
@@ -83,6 +84,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
be_special += ROLE_MONKEY
if(16384)
be_special += ROLE_ABDUCTOR
if(32768)
be_special += ROLE_BROTHER
/datum/preferences/proc/update_preferences(current_version, savefile/S)
@@ -188,6 +191,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["menuoptions"] >> menuoptions
//citadel code
S["arousable"] >> arousable
S["screenshake"] >> screenshake
S["damagescreenshake"] >> damagescreenshake
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -212,6 +217,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
menuoptions = SANITIZE_LIST(menuoptions)
be_special = SANITIZE_LIST(be_special)
screenshake = sanitize_integer(screenshake, 0, 200, initial(screenshake))
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
return 1
@@ -253,7 +260,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay)
//citadel code
S["arousable"] << arousable
WRITE_FILE(S["screenshake"], screenshake)
WRITE_FILE(S["damagescreenshake"], damagescreenshake)
WRITE_FILE(S["arousable"], arousable)
return 1
@@ -384,8 +393,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if((S["flavor_text"] != "") && (S["flavor_text"] != null) && S["flavor_text"]) //If old text isn't null and isn't "" but still exists.
S["flavor_text"] >> features["flavor_text"] //Load old flavortext as current dna-based flavortext
S["feature_flavor_text"] << features["flavor_text"] //Save it in our new type of flavor-text
S["flavor_text"] << "" //Remove old flavortext, completing the cut-and-paste into the new format.
WRITE_FILE(S["feature_flavor_text"], features["flavor_text"]) //Save it in our new type of flavor-text
WRITE_FILE(S["flavor_text"] , "") //Remove old flavortext, completing the cut-and-paste into the new format.
else //We have no old flavortext, default to new
S["feature_flavor_text"] >> features["flavor_text"]
@@ -469,95 +478,95 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["version"] << SAVEFILE_VERSION_MAX //load_character will sanitize any bad data, so assume up-to-date.
//Character
WRITE_FILE(S["OOC_Notes"] , metadata)
WRITE_FILE(S["real_name"] , real_name)
WRITE_FILE(S["OOC_Notes"], metadata)
WRITE_FILE(S["real_name"], real_name)
WRITE_FILE(S["name_is_always_random"] , be_random_name)
WRITE_FILE(S["body_is_always_random"] , be_random_body)
WRITE_FILE(S["gender"] , gender)
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
WRITE_FILE(S["eye_color"] , eye_color)
WRITE_FILE(S["skin_tone"] , skin_tone)
WRITE_FILE(S["hair_style_name"] , hair_style)
WRITE_FILE(S["facial_style_name"] , facial_hair_style)
WRITE_FILE(S["underwear"] , underwear)
WRITE_FILE(S["undershirt"] , undershirt)
WRITE_FILE(S["socks"] , socks)
WRITE_FILE(S["backbag"] , backbag)
WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc)
WRITE_FILE(S["species"] , pref_species.id)
WRITE_FILE(S["feature_mcolor"] , features["mcolor"])
WRITE_FILE(S["feature_lizard_tail"] , features["tail_lizard"])
WRITE_FILE(S["feature_human_tail"] , features["tail_human"])
WRITE_FILE(S["feature_lizard_snout"] , features["snout"])
WRITE_FILE(S["feature_lizard_horns"] , features["horns"])
WRITE_FILE(S["feature_human_ears"] , features["ears"])
WRITE_FILE(S["feature_lizard_frills"] , features["frills"])
WRITE_FILE(S["feature_lizard_spines"] , features["spines"])
WRITE_FILE(S["feature_lizard_body_markings"] , features["body_markings"])
WRITE_FILE(S["feature_lizard_legs"] , features["legs"])
WRITE_FILE(S["clown_name"] , custom_names["clown"])
WRITE_FILE(S["mime_name"] , custom_names["mime"])
WRITE_FILE(S["ai_name"] , custom_names["ai"])
WRITE_FILE(S["cyborg_name"] , custom_names["cyborg"])
WRITE_FILE(S["religion_name"] , custom_names["religion"])
WRITE_FILE(S["deity_name"] , custom_names["deity"])
WRITE_FILE(S["prefered_security_department"] , prefered_security_department)
WRITE_FILE(S["gender"], gender)
WRITE_FILE(S["age"], age)
WRITE_FILE(S["hair_color"], hair_color)
WRITE_FILE(S["facial_hair_color"], facial_hair_color)
WRITE_FILE(S["eye_color"], eye_color)
WRITE_FILE(S["skin_tone"], skin_tone)
WRITE_FILE(S["hair_style_name"], hair_style)
WRITE_FILE(S["facial_style_name"], facial_hair_style)
WRITE_FILE(S["underwear"], underwear)
WRITE_FILE(S["undershirt"], undershirt)
WRITE_FILE(S["socks"], socks)
WRITE_FILE(S["backbag"], backbag)
WRITE_FILE(S["uplink_loc"], uplink_spawn_loc)
WRITE_FILE(S["species"], pref_species.id)
WRITE_FILE(S["feature_mcolor"], features["mcolor"])
WRITE_FILE(S["feature_lizard_tail"], features["tail_lizard"])
WRITE_FILE(S["feature_human_tail"], features["tail_human"])
WRITE_FILE(S["feature_lizard_snout"], features["snout"])
WRITE_FILE(S["feature_lizard_horns"], features["horns"])
WRITE_FILE(S["feature_human_ears"], features["ears"])
WRITE_FILE(S["feature_lizard_frills"], features["frills"])
WRITE_FILE(S["feature_lizard_spines"], features["spines"])
WRITE_FILE(S["feature_lizard_body_markings"], features["body_markings"])
WRITE_FILE(S["feature_lizard_legs"] , features["legs"])
WRITE_FILE(S["clown_name"], custom_names["clown"])
WRITE_FILE(S["mime_name"], custom_names["mime"])
WRITE_FILE(S["ai_name"] , custom_names["ai"])
WRITE_FILE(S["cyborg_name"], custom_names["cyborg"])
WRITE_FILE(S["religion_name"], custom_names["religion"])
WRITE_FILE(S["deity_name"], custom_names["deity"])
WRITE_FILE(S["prefered_security_department"], prefered_security_department)
//Jobs
WRITE_FILE(S["joblessrole"] , joblessrole)
WRITE_FILE(S["job_civilian_high"] , job_civilian_high)
WRITE_FILE(S["job_civilian_med"] , job_civilian_med)
WRITE_FILE(S["job_civilian_low"] , job_civilian_low)
WRITE_FILE(S["job_medsci_high"] , job_medsci_high)
WRITE_FILE(S["job_medsci_med"] , job_medsci_med)
WRITE_FILE(S["job_medsci_low"] , job_medsci_low)
WRITE_FILE(S["job_engsec_high"] , job_engsec_high)
WRITE_FILE(S["job_engsec_med"] , job_engsec_med)
WRITE_FILE(S["job_engsec_low"] , job_engsec_low)
WRITE_FILE(S["joblessrole"], joblessrole)
WRITE_FILE(S["job_civilian_high"], job_civilian_high)
WRITE_FILE(S["job_civilian_med"], job_civilian_med)
WRITE_FILE(S["job_civilian_low"], job_civilian_low)
WRITE_FILE(S["job_medsci_high"], job_medsci_high)
WRITE_FILE(S["job_medsci_med"], job_medsci_med)
WRITE_FILE(S["job_medsci_low"], job_medsci_low)
WRITE_FILE(S["job_engsec_high"], job_engsec_high)
WRITE_FILE(S["job_engsec_med"], job_engsec_med)
WRITE_FILE(S["job_engsec_low"], job_engsec_low)
//Citadel
S["feature_genitals_use_skintone"] << features["genitals_use_skintone"]
S["feature_exhibitionist"] << features["exhibitionist"]
S["feature_mcolor2"] << features["mcolor2"]
S["feature_mcolor3"] << features["mcolor3"]
S["feature_mam_body_markings"] << features["mam_body_markings"]
S["feature_mam_tail"] << features["mam_tail"]
S["feature_mam_ears"] << features["mam_ears"]
S["feature_mam_tail_animated"] << features["mam_tail_animated"]
S["feature_taur"] << features["taur"]
WRITE_FILE(S["feature_genitals_use_skintone"], features["genitals_use_skintone"])
WRITE_FILE(S["feature_exhibitionist"], features["exhibitionist"])
WRITE_FILE(S["feature_mcolor2"], features["mcolor2"])
WRITE_FILE(S["feature_mcolor3"], features["mcolor3"])
WRITE_FILE(S["feature_mam_body_markings"], features["mam_body_markings"])
WRITE_FILE(S["feature_mam_tail"], features["mam_tail"])
WRITE_FILE(S["feature_mam_ears"], features["mam_ears"])
WRITE_FILE(S["feature_mam_tail_animated"], features["mam_tail_animated"])
WRITE_FILE(S["feature_taur"], features["taur"])
//Xeno features
S["feature_xeno_tail"] << features["xenotail"]
S["feature_xeno_dors"] << features["xenodorsal"]
S["feature_xeno_head"] << features["xenohead"]
WRITE_FILE(S["feature_xeno_tail"], features["xenotail"])
WRITE_FILE(S["feature_xeno_dors"], features["xenodorsal"])
WRITE_FILE(S["feature_xeno_head"], features["xenohead"])
//cock features
S["feature_has_cock"] << features["has_cock"]
S["feature_cock_shape"] << features["cock_shape"]
S["feature_cock_color"] << features["cock_color"]
S["feature_cock_length"] << features["cock_length"]
S["feature_cock_girth"] << features["cock_girth"]
S["feature_has_sheath"] << features["sheath_color"]
WRITE_FILE(S["feature_has_cock"], features["has_cock"])
WRITE_FILE(S["feature_cock_shape"], features["cock_shape"])
WRITE_FILE(S["feature_cock_color"], features["cock_color"])
WRITE_FILE(S["feature_cock_length"], features["cock_length"])
WRITE_FILE(S["feature_cock_girth"], features["cock_girth"])
WRITE_FILE(S["feature_has_sheath"], features["sheath_color"])
//balls features
S["feature_has_balls"] << features["has_balls"]
S["feature_balls_color"] << features["balls_color"]
S["feature_balls_size"] << features["balls_size"]
S["feature_balls_sack_size"] << features["balls_sack_size"]
S["feature_balls_fluid"] << features["balls_fluid"]
WRITE_FILE(S["feature_has_balls"], features["has_balls"])
WRITE_FILE(S["feature_balls_color"], features["balls_color"])
WRITE_FILE(S["feature_balls_size"], features["balls_size"])
WRITE_FILE(S["feature_balls_sack_size"], features["balls_sack_size"])
WRITE_FILE(S["feature_balls_fluid"], features["balls_fluid"])
//breasts features
S["feature_has_breasts"] << features["has_breasts"]
S["feature_breasts_size"] << features["breasts_size"]
S["feature_breasts_shape"] << features["breasts_shape"]
S["feature_breasts_color"] << features["breasts_color"]
S["feature_breasts_fluid"] << features["breasts_fluid"]
WRITE_FILE(S["feature_has_breasts"], features["has_breasts"])
WRITE_FILE(S["feature_breasts_size"], features["breasts_size"])
WRITE_FILE(S["feature_breasts_shape"], features["breasts_shape"])
WRITE_FILE(S["feature_breasts_color"], features["breasts_color"])
WRITE_FILE(S["feature_breasts_fluid"], features["breasts_fluid"])
//vagina features
S["feature_has_vag"] << features["has_vag"]
S["feature_vag_shape"] << features["vag_shape"]
S["feature_vag_color"] << features["vag_color"]
WRITE_FILE(S["feature_has_vag"], features["has_vag"])
WRITE_FILE(S["feature_vag_shape"], features["vag_shape"])
WRITE_FILE(S["feature_vag_color"], features["vag_color"])
//womb features
S["feature_has_womb"] << features["has_womb"]
WRITE_FILE(S["feature_has_womb"], features["has_womb"])
//flavor text
S["feature_flavor_text"] << features["flavor_text"]
WRITE_FILE(S["feature_flavor_text"], features["flavor_text"])
return 1
#undef SAVEFILE_VERSION_MAX
+9
View File
@@ -80,6 +80,15 @@
GLOB.ooc_allowed = !GLOB.ooc_allowed
to_chat(world, "<B>The OOC channel has been globally [GLOB.ooc_allowed ? "enabled" : "disabled"].</B>")
/proc/toggle_dooc(toggle = null)
if(toggle != null)
if(toggle != GLOB.dooc_allowed)
GLOB.dooc_allowed = toggle
else
return
else
GLOB.dooc_allowed = !GLOB.dooc_allowed
GLOBAL_VAR_INIT(normal_ooc_colour, OOC_COLOR)
/client/proc/set_ooc(newColor as color)
+3 -14
View File
@@ -214,7 +214,7 @@ BLIND // can't see anything
gender = PLURAL //Carn: for grammarically correct text-parsing
w_class = WEIGHT_CLASS_SMALL
icon = 'icons/obj/clothing/gloves.dmi'
siemens_coefficient = 0.50
siemens_coefficient = 0.5
body_parts_covered = HANDS
slot_flags = SLOT_GLOVES
attack_verb = list("challenged")
@@ -273,17 +273,6 @@ BLIND // can't see anything
var/mob/M = loc
M.update_inv_head()
/obj/item/clothing/head/equipped(mob/user, slot)
..()
if(dynamic_hair_suffix)
user.update_hair()
/obj/item/clothing/head/dropped(mob/user)
..()
if(dynamic_hair_suffix)
user.update_hair()
//Neck
/obj/item/clothing/neck
name = "necklace"
@@ -372,7 +361,7 @@ BLIND // can't see anything
body_parts_covered = FEET
slot_flags = SLOT_FEET
permeability_coefficient = 0.50
permeability_coefficient = 0.5
slowdown = SHOES_SLOWDOWN
var/blood_state = BLOOD_STATE_NOT_BLOODY
var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
@@ -514,7 +503,7 @@ BLIND // can't see anything
icon = 'icons/obj/clothing/uniforms.dmi'
name = "under"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
permeability_coefficient = 0.90
permeability_coefficient = 0.9
slot_flags = SLOT_ICLOTHING
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women
+3 -4
View File
@@ -1,11 +1,10 @@
//Ears: currently only used for headsets and earmuffs
/obj/item/clothing/ears
name = "ears"
w_class = WEIGHT_CLASS_TINY
throwforce = 0
slot_flags = SLOT_EARS
resistance_flags = 0
resistance_flags = NONE
/obj/item/clothing/ears/earmuffs
name = "earmuffs"
@@ -15,7 +14,7 @@
strip_delay = 15
equip_delay_other = 25
resistance_flags = FLAMMABLE
flags_2 = BANG_PROTECT_2|HEALS_EARS_2
flags_2 = BANG_PROTECT_2|HEALS_EARS_2
/obj/item/clothing/ears/headphones
name = "headphones"
@@ -43,4 +42,4 @@
H.update_inv_ears()
H.update_inv_neck()
H.update_inv_head()
to_chat(owner, "<span class='notice'>You turn the music [headphones_on? "on. Untz Untz Untz!" : "off."]</span>")
to_chat(owner, "<span class='notice'>You turn the music [headphones_on? "on. Untz Untz Untz!" : "off."]</span>")
+213 -213
View File
@@ -1,213 +1,213 @@
/obj/item/clothing/gloves/color/yellow
desc = "These gloves will protect the wearer from electric shock."
name = "insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 0
permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = 0
/obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap
desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly."
name = "budget insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 1 //Set to a default of 1, gets overridden in New()
permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = 0
/obj/item/clothing/gloves/color/fyellow/New()
..()
siemens_coefficient = pick(0,0.5,0.5,0.5,0.5,0.75,1.5)
/obj/item/clothing/gloves/color/fyellow/old
desc = "Old and worn out insulated gloves, hopefully they still work."
name = "worn out insulated gloves"
/obj/item/clothing/gloves/color/fyellow/old/Initialize()
. = ..()
siemens_coefficient = pick(0,0,0,0.5,0.5,0.5,0.75)
/obj/item/clothing/gloves/color/black
desc = "These gloves are fire-resistant."
name = "black gloves"
icon_state = "black"
item_state = "blackgloves"
item_color="black"
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = 0
var/can_be_cut = 1
/obj/item/clothing/gloves/color/black/hos
item_color = "hosred" //Exists for washing machines. Is not different from black gloves in any way.
/obj/item/clothing/gloves/color/black/ce
item_color = "chief" //Exists for washing machines. Is not different from black gloves in any way.
/obj/item/clothing/gloves/color/black/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/wirecutters))
if(can_be_cut && icon_state == initial(icon_state))//only if not dyed
to_chat(user, "<span class='notice'>You snip the fingertips off of [src].</span>")
playsound(user.loc, W.usesound, rand(10,50), 1)
new /obj/item/clothing/gloves/fingerless(user.loc)
qdel(src)
..()
/obj/item/clothing/gloves/color/orange
name = "orange gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "orange"
item_state = "orangegloves"
item_color="orange"
/obj/item/clothing/gloves/color/red
name = "red gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "red"
item_state = "redgloves"
item_color = "red"
/obj/item/clothing/gloves/color/red/insulated
name = "insulated gloves"
desc = "These gloves will protect the wearer from electric shock."
siemens_coefficient = 0
permeability_coefficient = 0.05
resistance_flags = 0
/obj/item/clothing/gloves/color/rainbow
name = "rainbow gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "rainbow"
item_state = "rainbowgloves"
item_color = "rainbow"
/obj/item/clothing/gloves/color/rainbow/clown
item_color = "clown"
/obj/item/clothing/gloves/color/blue
name = "blue gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "blue"
item_state = "bluegloves"
item_color="blue"
/obj/item/clothing/gloves/color/purple
name = "purple gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "purple"
item_state = "purplegloves"
item_color="purple"
/obj/item/clothing/gloves/color/green
name = "green gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "green"
item_state = "greengloves"
item_color="green"
/obj/item/clothing/gloves/color/grey
name = "grey gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "gray"
item_state = "graygloves"
item_color="grey"
/obj/item/clothing/gloves/color/grey/rd
item_color = "director" //Exists for washing machines. Is not different from gray gloves in any way.
/obj/item/clothing/gloves/color/grey/hop
item_color = "hop" //Exists for washing machines. Is not different from gray gloves in any way.
/obj/item/clothing/gloves/color/light_brown
name = "light brown gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "lightbrown"
item_state = "lightbrowngloves"
item_color="light brown"
/obj/item/clothing/gloves/color/brown
name = "brown gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "brown"
item_state = "browngloves"
item_color="brown"
/obj/item/clothing/gloves/color/brown/cargo
item_color = "cargo" //Exists for washing machines. Is not different from brown gloves in any way.
/obj/item/clothing/gloves/color/captain
desc = "Regal blue gloves, with a nice gold trim. Swanky."
name = "captain's gloves"
icon_state = "captain"
item_state = "egloves"
item_color = "captain"
siemens_coefficient = 0
permeability_coefficient = 0.05
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
strip_delay = 60
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 70, acid = 50)
/obj/item/clothing/gloves/color/latex
name = "latex gloves"
desc = "Cheap sterile gloves made from latex."
icon_state = "latex"
item_state = "lgloves"
siemens_coefficient = 0.30
permeability_coefficient = 0.01
item_color="white"
transfer_prints = TRUE
resistance_flags = 0
/obj/item/clothing/gloves/color/latex/nitrile
name = "nitrile gloves"
desc = "Pricy sterile gloves that are stronger than latex."
icon_state = "nitrile"
item_state = "nitrilegloves"
item_color = "cmo"
transfer_prints = FALSE
/obj/item/clothing/gloves/color/white
name = "white gloves"
desc = "These look pretty fancy."
icon_state = "white"
item_state = "wgloves"
item_color="mime"
/obj/item/clothing/gloves/color/white/redcoat
item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way.
/obj/item/clothing/gloves/color/random
name = "random gloves"
desc = "These gloves are supposed to be a random color..."
icon_state = "white"
item_state = "wgloves"
item_color = "mime"
/obj/item/clothing/gloves/color/random/New()
..()
var/list/gloves = list(
/obj/item/clothing/gloves/color/orange = 1,
/obj/item/clothing/gloves/color/red = 1,
/obj/item/clothing/gloves/color/blue = 1,
/obj/item/clothing/gloves/color/purple = 1,
/obj/item/clothing/gloves/color/green = 1,
/obj/item/clothing/gloves/color/grey = 1,
/obj/item/clothing/gloves/color/light_brown = 1,
/obj/item/clothing/gloves/color/brown = 1)
var/obj/item/clothing/gloves/color/selected = pick(gloves)
name = initial(selected.name)
desc = initial(selected.desc)
icon_state = initial(selected.icon_state)
item_state = initial(selected.item_state)
item_color = initial(selected.item_color)
/obj/item/clothing/gloves/color/yellow
desc = "These gloves will protect the wearer from electric shock."
name = "insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 0
permeability_coefficient = 0.5
item_color="yellow"
resistance_flags = 0
/obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap
desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly."
name = "budget insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 1 //Set to a default of 1, gets overridden in New()
permeability_coefficient = 0.5
item_color="yellow"
resistance_flags = 0
/obj/item/clothing/gloves/color/fyellow/New()
..()
siemens_coefficient = pick(0,0.5,0.5,0.5,0.5,0.75,1.5)
/obj/item/clothing/gloves/color/fyellow/old
desc = "Old and worn out insulated gloves, hopefully they still work."
name = "worn out insulated gloves"
/obj/item/clothing/gloves/color/fyellow/old/Initialize()
. = ..()
siemens_coefficient = pick(0,0,0,0.5,0.5,0.5,0.75)
/obj/item/clothing/gloves/color/black
desc = "These gloves are fire-resistant."
name = "black gloves"
icon_state = "black"
item_state = "blackgloves"
item_color="black"
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = 0
var/can_be_cut = 1
/obj/item/clothing/gloves/color/black/hos
item_color = "hosred" //Exists for washing machines. Is not different from black gloves in any way.
/obj/item/clothing/gloves/color/black/ce
item_color = "chief" //Exists for washing machines. Is not different from black gloves in any way.
/obj/item/clothing/gloves/color/black/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/wirecutters))
if(can_be_cut && icon_state == initial(icon_state))//only if not dyed
to_chat(user, "<span class='notice'>You snip the fingertips off of [src].</span>")
playsound(user.loc, W.usesound, rand(10,50), 1)
new /obj/item/clothing/gloves/fingerless(user.loc)
qdel(src)
..()
/obj/item/clothing/gloves/color/orange
name = "orange gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "orange"
item_state = "orangegloves"
item_color="orange"
/obj/item/clothing/gloves/color/red
name = "red gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "red"
item_state = "redgloves"
item_color = "red"
/obj/item/clothing/gloves/color/red/insulated
name = "insulated gloves"
desc = "These gloves will protect the wearer from electric shock."
siemens_coefficient = 0
permeability_coefficient = 0.5
resistance_flags = 0
/obj/item/clothing/gloves/color/rainbow
name = "rainbow gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "rainbow"
item_state = "rainbowgloves"
item_color = "rainbow"
/obj/item/clothing/gloves/color/rainbow/clown
item_color = "clown"
/obj/item/clothing/gloves/color/blue
name = "blue gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "blue"
item_state = "bluegloves"
item_color="blue"
/obj/item/clothing/gloves/color/purple
name = "purple gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "purple"
item_state = "purplegloves"
item_color="purple"
/obj/item/clothing/gloves/color/green
name = "green gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "green"
item_state = "greengloves"
item_color="green"
/obj/item/clothing/gloves/color/grey
name = "grey gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "gray"
item_state = "graygloves"
item_color="grey"
/obj/item/clothing/gloves/color/grey/rd
item_color = "director" //Exists for washing machines. Is not different from gray gloves in any way.
/obj/item/clothing/gloves/color/grey/hop
item_color = "hop" //Exists for washing machines. Is not different from gray gloves in any way.
/obj/item/clothing/gloves/color/light_brown
name = "light brown gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "lightbrown"
item_state = "lightbrowngloves"
item_color="light brown"
/obj/item/clothing/gloves/color/brown
name = "brown gloves"
desc = "A pair of gloves, they don't look special in any way."
icon_state = "brown"
item_state = "browngloves"
item_color="brown"
/obj/item/clothing/gloves/color/brown/cargo
item_color = "cargo" //Exists for washing machines. Is not different from brown gloves in any way.
/obj/item/clothing/gloves/color/captain
desc = "Regal blue gloves, with a nice gold trim. Swanky."
name = "captain's gloves"
icon_state = "captain"
item_state = "egloves"
item_color = "captain"
siemens_coefficient = 0
permeability_coefficient = 0.5
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
strip_delay = 60
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 70, acid = 50)
/obj/item/clothing/gloves/color/latex
name = "latex gloves"
desc = "Cheap sterile gloves made from latex."
icon_state = "latex"
item_state = "lgloves"
siemens_coefficient = 0.3
permeability_coefficient = 0.1
item_color="white"
transfer_prints = TRUE
resistance_flags = 0
/obj/item/clothing/gloves/color/latex/nitrile
name = "nitrile gloves"
desc = "Pricy sterile gloves that are stronger than latex."
icon_state = "nitrile"
item_state = "nitrilegloves"
item_color = "cmo"
transfer_prints = FALSE
/obj/item/clothing/gloves/color/white
name = "white gloves"
desc = "These look pretty fancy."
icon_state = "white"
item_state = "wgloves"
item_color="mime"
/obj/item/clothing/gloves/color/white/redcoat
item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way.
/obj/item/clothing/gloves/color/random
name = "random gloves"
desc = "These gloves are supposed to be a random color..."
icon_state = "white"
item_state = "wgloves"
item_color = "mime"
/obj/item/clothing/gloves/color/random/New()
..()
var/list/gloves = list(
/obj/item/clothing/gloves/color/orange = 1,
/obj/item/clothing/gloves/color/red = 1,
/obj/item/clothing/gloves/color/blue = 1,
/obj/item/clothing/gloves/color/purple = 1,
/obj/item/clothing/gloves/color/green = 1,
/obj/item/clothing/gloves/color/grey = 1,
/obj/item/clothing/gloves/color/light_brown = 1,
/obj/item/clothing/gloves/color/brown = 1)
var/obj/item/clothing/gloves/color/selected = pick(gloves)
name = initial(selected.name)
desc = initial(selected.desc)
icon_state = initial(selected.icon_state)
item_state = initial(selected.item_state)
item_color = initial(selected.item_color)
+2 -2
View File
@@ -7,8 +7,8 @@
flags_1 = MASKINTERNALS_1
visor_flags = MASKINTERNALS_1
w_class = WEIGHT_CLASS_SMALL
gas_transfer_coefficient = 0.10
permeability_coefficient = 0.50
gas_transfer_coefficient = 0.1
permeability_coefficient = 0.5
actions_types = list(/datum/action/item_action/adjust)
flags_cover = MASKCOVERSMOUTH
visor_flags_cover = MASKCOVERSMOUTH
+2 -2
View File
@@ -5,7 +5,7 @@
item_state = "blindfold"
flags_cover = MASKCOVERSMOUTH
w_class = WEIGHT_CLASS_SMALL
gas_transfer_coefficient = 0.90
gas_transfer_coefficient = 0.9
equip_delay_other = 20
/obj/item/clothing/mask/muzzle/attack_paw(mob/user)
@@ -26,7 +26,7 @@
flags_cover = MASKCOVERSMOUTH
visor_flags_inv = HIDEFACE
visor_flags_cover = MASKCOVERSMOUTH
gas_transfer_coefficient = 0.90
gas_transfer_coefficient = 0.9
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 25, rad = 0, fire = 0, acid = 0)
actions_types = list(/datum/action/item_action/adjust)
+9 -29
View File
@@ -5,59 +5,39 @@
desc = "Lost prototype of advanced clown tech. Powered by bananium, these shoes leave a trail of chaos in their wake."
icon_state = "clown_prototype_off"
var/on = FALSE
var/datum/material_container/bananium
actions_types = list(/datum/action/item_action/toggle)
/obj/item/clothing/shoes/clown_shoes/banana_shoes/New()
..()
bananium = new/datum/material_container(src,list(MAT_BANANIUM),200000)
/obj/item/clothing/shoes/clown_shoes/banana_shoes/Initialize()
. = ..()
AddComponent(/datum/component/material_container, list(MAT_BANANIUM), 200000, TRUE)
AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 75)
/obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action()
. = ..()
if(on)
if(footstep > 1)//honks when its on
playsound(src, 'sound/items/bikehorn.ogg', 75, 1)
footstep = 0
else
footstep++
new/obj/item/grown/bananapeel/specialpeel(get_step(src,turn(usr.dir, 180))) //honk
GET_COMPONENT(bananium, /datum/component/material_container)
bananium.use_amount_type(100, MAT_BANANIUM)
if(bananium.amount(MAT_BANANIUM) < 100)
on = !on
flags_1 &= ~NOSLIP_1
update_icon()
to_chat(loc, "<span class='warning'>You ran out of bananium!</span>")
else
..()
/obj/item/clothing/shoes/clown_shoes/banana_shoes/attack_self(mob/user)
GET_COMPONENT(bananium, /datum/component/material_container)
var/sheet_amount = bananium.retrieve_all()
if(sheet_amount)
to_chat(user, "<span class='notice'>You retrieve [sheet_amount] sheets of bananium from the prototype shoes.</span>")
else
to_chat(user, "<span class='notice'>You cannot retrieve any bananium from the prototype shoes.</span>")
/obj/item/clothing/shoes/clown_shoes/banana_shoes/attackby(obj/item/O, mob/user, params)
if(!bananium.get_item_material_amount(O))
to_chat(user, "<span class='notice'>This item has no bananium!</span>")
return
if(!user.dropItemToGround(O))
to_chat(user, "<span class='notice'>You can't drop [O]!</span>")
return
var/bananium_amount = bananium.insert_item(O)
if(bananium_amount)
to_chat(user, "<span class='notice'>You insert [O] into the prototype shoes.</span>")
qdel(O)
else
to_chat(user, "<span class='notice'>You are unable to insert more bananium!</span>")
/obj/item/clothing/shoes/clown_shoes/banana_shoes/examine(mob/user)
..()
var/ban_amt = bananium.amount(MAT_BANANIUM)
to_chat(user, "<span class='notice'>The shoes are [on ? "enabled" : "disabled"]. There is [ban_amt ? ban_amt : "no"] bananium left.</span>")
to_chat(user, "<span class='notice'>The shoes are [on ? "enabled" : "disabled"]</span>")
/obj/item/clothing/shoes/clown_shoes/banana_shoes/ui_action_click(mob/user)
GET_COMPONENT(bananium, /datum/component/material_container)
if(bananium.amount(MAT_BANANIUM))
on = !on
update_icon()
+13 -14
View File
@@ -1,4 +1,5 @@
/obj/item/clothing/shoes/proc/step_action() //this was made to rewrite clown shoes squeaking
SendSignal(COMSIG_SHOES_STEP_ACTION)
/obj/item/clothing/shoes/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is bashing [user.p_their()] own head in with [src]! Ain't that a kick in the head?</span>")
@@ -79,15 +80,11 @@
item_state = "clown_shoes"
slowdown = SHOES_SLOWDOWN+1
item_color = "clown"
var/footstep = 1 //used for squeeks whilst walking
pockets = /obj/item/storage/internal/pocket/shoes/clown
/obj/item/clothing/shoes/clown_shoes/step_action()
if(footstep > 1)
playsound(src, "clownstep", 50, 1)
footstep = 0
else
footstep++
/obj/item/clothing/shoes/clown_shoes/Initialize()
. = ..()
AddComponent(/datum/component/squeak, list('sound/effects/clownstep1.ogg'=1,'sound/effects/clownstep2.ogg'=1), 50)
/obj/item/clothing/shoes/clown_shoes/jester
name = "jester shoes"
@@ -198,22 +195,24 @@
var/jumping = FALSE //are we mid-jump?
/obj/item/clothing/shoes/bhop/ui_action_click(mob/user, action)
if(!isliving(usr))
if(!isliving(user))
return
if(jumping)
return
if(recharging_time > world.time)
to_chat(usr, "<span class='warning'>The boot's internal propulsion needs to recharge still!</span>")
to_chat(user, "<span class='warning'>The boot's internal propulsion needs to recharge still!</span>")
return
var/atom/target = get_edge_target_turf(usr, usr.dir) //gets the user's direction
var/atom/target = get_edge_target_turf(user, user.dir) //gets the user's direction
jumping = TRUE
playsound(src.loc, 'sound/effects/stealthoff.ogg', 50, 1, 1)
usr.visible_message("<span class='warning'>[usr] dashes forward into the air!</span>")
usr.throw_at(target, jumpdistance, jumpspeed, spin=0, diagonals_first = 1, callback = CALLBACK(src, .proc/hop_end))
if (user.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE, callback = CALLBACK(src, .proc/hop_end)))
jumping = TRUE
playsound(src, 'sound/effects/stealthoff.ogg', 50, 1, 1)
user.visible_message("<span class='warning'>[usr] dashes forward into the air!</span>")
else
to_chat(user, "<span class='warning'>Something prevents you from dashing forward!</span>")
/obj/item/clothing/shoes/bhop/proc/hop_end()
jumping = FALSE
+41 -12
View File
@@ -18,7 +18,7 @@
var/icon_state_boost = "flightpack_boost"
var/item_state_boost = "flightpack_boost"
actions_types = list(/datum/action/item_action/flightpack/toggle_flight, /datum/action/item_action/flightpack/engage_boosters, /datum/action/item_action/flightpack/toggle_stabilizers, /datum/action/item_action/flightpack/change_power, /datum/action/item_action/flightpack/toggle_airbrake)
armor = list(melee = 20, bullet = 20, laser = 20, energy = 10, bomb = 30, bio = 100, rad = 75, fire = 100, acid = 75)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 10, bomb = 30, bio = 100, rad = 10, fire = 50, acid = 35)
w_class = WEIGHT_CLASS_BULKY
slot_flags = SLOT_BACK
@@ -34,7 +34,7 @@
var/flight = FALSE
var/flight_passflags = PASSTABLE
var/powersetting = 1
var/powersetting_high = 3
var/powersetting_high = 6
var/powersetting_low = 1
var/override_safe = FALSE
@@ -84,7 +84,7 @@
var/emp_disable_threshold = 3 //3 weak ion, 2 strong ion hits.
var/emp_disabled = FALSE
var/crash_damage = 0 //Same thing, but for crashes. This is in addition to possible amounts of brute damage to the wearer.
var/crash_damage = 10 //Same thing, but for crashes. This is in addition to possible amounts of brute damage to the wearer.
var/crash_damage_low = 1
var/crash_damage_high = 2.5
var/crash_disable_threshold = 5
@@ -102,9 +102,13 @@
var/obj/item/stock_parts/capacitor/part_cap = null
var/obj/item/stock_parts/micro_laser/part_laser = null
var/obj/item/stock_parts/matter_bin/part_bin = null
var/obj/item/stock_parts/cell/cell = null //Wew lad. about damn time now
var/crashing = FALSE //Are we currently getting wrecked?
var/s_delay = 50 // cell replacement delay
/obj/item/device/flightpack/proc/changeWearer(mob/changeto)
if(wearer)
LAZYREMOVE(wearer.user_movement_hooks, src)
@@ -128,6 +132,8 @@
part_cap = new /obj/item/stock_parts/capacitor/super(src)
part_laser = new /obj/item/stock_parts/micro_laser/ultra(src)
part_bin = new /obj/item/stock_parts/matter_bin/super(src)
cell = new/obj/item/stock_parts/cell/high
cell.charge = 9000
..()
/obj/item/device/flightpack/proc/usermessage(message, span = "boldnotice", mob/mob_override = null)
@@ -816,6 +822,22 @@
part_cap.forceMove(get_turf(src))
part_cap = I
changed = TRUE
if(istype(S, /obj/item/stock_parts/cell))
var/obj/item/stock_parts/cell/CELL = S
if(CELL.maxcharge > cell.maxcharge)
usermessage("<span class='notice'>Higher maximum capacity detected.\nUpgrading...</span>", mob_override = user)
if (do_after(user,s_delay, target = src))
user.transferItemToLoc(CELL, src)
CELL.charge = min(CELL.charge+cell.charge, CELL.maxcharge)
var/obj/item/stock_parts/cell/old_cell = cell
old_cell.charge = 0
user.put_in_hands(old_cell)
old_cell.add_fingerprint(user)
old_cell.update_icon()
cell = CELL
usermessage("<span class='notice'>Upgrade complete. Maximum capacity: <b>[round(cell.maxcharge/100)]</b>%</span>", mob_override = user)
else
usermessage("<span class='danger'>Procedure interrupted. Protocol terminated.</span>", mob_override = user)
if(changed)
update_parts()
..()
@@ -847,7 +869,7 @@
var/obj/item/device/flightpack/pack = null
var/mob/living/carbon/human/wearer = null
var/active = FALSE
resistance_flags = FIRE_PROOF | ACID_PROOF
resistance_flags = FIRE_PROOF
/obj/item/clothing/shoes/flightshoes/Destroy()
pack = null
@@ -901,22 +923,28 @@
var/deployedpack = FALSE
var/deployedshoes = FALSE
var/locked = FALSE
resistance_flags = FIRE_PROOF | ACID_PROOF
resistance_flags = FIRE_PROOF
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/flightsuit
jetpack = null
var/flightpack
var/flight = FALSE
allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals, /obj/item/gun, /obj/item/reagent_containers/spray/pepper, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs)
actions_types = list(/datum/action/item_action/flightsuit/toggle_helmet, /datum/action/item_action/flightsuit/toggle_boots, /datum/action/item_action/flightsuit/toggle_flightpack, /datum/action/item_action/flightsuit/lock_suit)
armor = list(melee = 20, bullet = 20, laser = 20, energy = 10, bomb = 30, bio = 100, rad = 75, fire = 100, acid = 100)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 10, bomb = 30, bio = 100, rad = 10, fire = 50, acid = 35)
var/maint_panel = FALSE
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
var/obj/item/stock_parts/cell/cell
var/s_delay = 50
/obj/item/clothing/suit/space/hardsuit/flightsuit/get_cell()
return cell
/obj/item/clothing/suit/space/hardsuit/flightsuit/full/Initialize()
. = ..()
makepack()
makeshoes()
resync()
get_cell()
/obj/item/clothing/suit/space/hardsuit/flightsuit/proc/usermessage(message, span = "boldnotice")
var/mob/targ = user
@@ -931,6 +959,7 @@
to_chat(user, "<span class='boldnotice'>SUIT: [locked ? "LOCKED" : "UNLOCKED"]</span>")
to_chat(user, "<span class='boldnotice'>FLIGHTPACK: [deployedpack ? "ENGAGED" : "DISENGAGED"] FLIGHTSHOES : [deployedshoes ? "ENGAGED" : "DISENGAGED"] HELMET : [suittoggled ? "ENGAGED" : "DISENGAGED"]</span>")
to_chat(user, "<span class='boldnotice'>Its maintainence panel is [maint_panel ? "OPEN" : "CLOSED"]</span>")
to_chat(user, "<span class='boldnotice'>Current energy capacity: <B>[DisplayPower(cell.charge)]</span>")
/obj/item/clothing/suit/space/hardsuit/flightsuit/Destroy()
dropped()
@@ -1223,12 +1252,12 @@
icon_state = "flighthelmet"
item_state = "flighthelmet"
item_color = "flight"
resistance_flags = FIRE_PROOF | ACID_PROOF
brightness_on = 7
resistance_flags = FIRE_PROOF
brightness_on = 4
light_color = "#30ffff"
armor = list(melee = 20, bullet = 20, laser = 20, energy = 10, bomb = 30, bio = 100, rad = 75, fire = 100, acid = 100)
max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
var/list/datahuds = list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 10, bomb = 30, bio = 100, rad = 10, fire = 50, acid = 35)
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
var/list/datahuds = list(DATA_HUD_SECURITY_BASIC , DATA_HUD_MEDICAL_BASIC, DATA_HUD_DIAGNOSTIC)
var/zoom_range = 14
var/zoom = FALSE
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/flightpack/zoom)
+1 -1
View File
@@ -362,7 +362,7 @@
icon_state = "heavy"
item_state = "swat_suit"
w_class = WEIGHT_CLASS_BULKY
gas_transfer_coefficient = 0.90
gas_transfer_coefficient = 0.9
flags_1 = THICKMATERIAL_1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
slowdown = 3
+2 -2
View File
@@ -70,8 +70,8 @@
desc = "An apron-jacket used by a high class chef."
icon_state = "chef"
item_state = "chef"
gas_transfer_coefficient = 0.90
permeability_coefficient = 0.50
gas_transfer_coefficient = 0.9
permeability_coefficient = 0.5
body_parts_covered = CHEST|GROIN|ARMS
allowed = list(/obj/item/kitchen)
togglename = "sleeves"
+4 -4
View File
@@ -15,8 +15,8 @@
icon_state = "fire"
item_state = "ro_suit"
w_class = WEIGHT_CLASS_BULKY
gas_transfer_coefficient = 0.90
permeability_coefficient = 0.50
gas_transfer_coefficient = 0.9
permeability_coefficient = 0.5
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/extinguisher, /obj/item/crowbar)
slowdown = 1
@@ -122,8 +122,8 @@
icon_state = "rad"
item_state = "rad_suit"
w_class = WEIGHT_CLASS_BULKY
gas_transfer_coefficient = 0.90
permeability_coefficient = 0.50
gas_transfer_coefficient = 0.9
permeability_coefficient = 0.5
flags_1 = THICKMATERIAL_1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/device/geiger_counter)
+1 -1
View File
@@ -76,7 +76,7 @@
icon_state = "hydroponics"
item_state = "g_suit"
item_color = "hydroponics"
permeability_coefficient = 0.50
permeability_coefficient = 0.5
/obj/item/clothing/under/rank/janitor
desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards."
+121 -121
View File
@@ -1,121 +1,121 @@
/*
* Science
*/
/obj/item/clothing/under/rank/research_director
desc = "It's a suit worn by those with the know-how to achieve the position of \"Research Director\". Its fabric provides minor protection from biological contaminants."
name = "research director's vest suit"
icon_state = "director"
item_state = "lb_suit"
item_color = "director"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 35)
can_adjust = 0
/obj/item/clothing/under/rank/research_director/alt
desc = "Maybe you'll engineer your own half-man, half-pig creature some day. Its fabric provides minor protection from biological contaminants."
name = "research director's tan suit"
icon_state = "rdwhimsy"
item_state = "rdwhimsy"
item_color = "rdwhimsy"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 1
alt_covers_chest = 1
/obj/item/clothing/under/rank/research_director/turtleneck
desc = "A dark purple turtleneck and tan khakis, for a director with a superior sense of style."
name = "research director's turtleneck"
icon_state = "rdturtle"
item_state = "p_suit"
item_color = "rdturtle"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 1
alt_covers_chest = 1
/obj/item/clothing/under/rank/scientist
desc = "It's made of a special fiber that provides minor protection against explosives. It has markings that denote the wearer as a scientist."
name = "scientist's jumpsuit"
icon_state = "toxins"
item_state = "w_suit"
item_color = "toxinswhite"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/chemist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it."
name = "chemist's jumpsuit"
icon_state = "chemistry"
item_state = "w_suit"
item_color = "chemistrywhite"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 50, acid = 65)
/*
* Medical
*/
/obj/item/clothing/under/rank/chief_medical_officer
desc = "It's a jumpsuit worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection."
name = "chief medical officer's jumpsuit"
icon_state = "cmo"
item_state = "w_suit"
item_color = "cmo"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/geneticist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it."
name = "geneticist's jumpsuit"
icon_state = "genetics"
item_state = "w_suit"
item_color = "geneticswhite"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/virologist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it."
name = "virologist's jumpsuit"
icon_state = "virology"
item_state = "w_suit"
item_color = "virologywhite"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/nursesuit
desc = "It's a jumpsuit commonly worn by nursing staff in the medical department."
name = "nurse's suit"
icon_state = "nursesuit"
item_state = "w_suit"
item_color = "nursesuit"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
fitted = NO_FEMALE_UNIFORM
can_adjust = 0
/obj/item/clothing/under/rank/medical
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel."
name = "medical doctor's jumpsuit"
icon_state = "medical"
item_state = "w_suit"
item_color = "medical"
permeability_coefficient = 0.50
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/medical/blue
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue."
icon_state = "scrubsblue"
item_color = "scrubsblue"
can_adjust = 0
/obj/item/clothing/under/rank/medical/green
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green."
icon_state = "scrubsgreen"
item_color = "scrubsgreen"
can_adjust = 0
/obj/item/clothing/under/rank/medical/purple
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple."
icon_state = "scrubspurple"
item_color = "scrubspurple"
can_adjust = 0
/*
* Science
*/
/obj/item/clothing/under/rank/research_director
desc = "It's a suit worn by those with the know-how to achieve the position of \"Research Director\". Its fabric provides minor protection from biological contaminants."
name = "research director's vest suit"
icon_state = "director"
item_state = "lb_suit"
item_color = "director"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 35)
can_adjust = 0
/obj/item/clothing/under/rank/research_director/alt
desc = "Maybe you'll engineer your own half-man, half-pig creature some day. Its fabric provides minor protection from biological contaminants."
name = "research director's tan suit"
icon_state = "rdwhimsy"
item_state = "rdwhimsy"
item_color = "rdwhimsy"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 1
alt_covers_chest = 1
/obj/item/clothing/under/rank/research_director/turtleneck
desc = "A dark purple turtleneck and tan khakis, for a director with a superior sense of style."
name = "research director's turtleneck"
icon_state = "rdturtle"
item_state = "p_suit"
item_color = "rdturtle"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 1
alt_covers_chest = 1
/obj/item/clothing/under/rank/scientist
desc = "It's made of a special fiber that provides minor protection against explosives. It has markings that denote the wearer as a scientist."
name = "scientist's jumpsuit"
icon_state = "toxins"
item_state = "w_suit"
item_color = "toxinswhite"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/chemist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it."
name = "chemist's jumpsuit"
icon_state = "chemistry"
item_state = "w_suit"
item_color = "chemistrywhite"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 50, acid = 65)
/*
* Medical
*/
/obj/item/clothing/under/rank/chief_medical_officer
desc = "It's a jumpsuit worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection."
name = "chief medical officer's jumpsuit"
icon_state = "cmo"
item_state = "w_suit"
item_color = "cmo"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/geneticist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it."
name = "geneticist's jumpsuit"
icon_state = "genetics"
item_state = "w_suit"
item_color = "geneticswhite"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/virologist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it."
name = "virologist's jumpsuit"
icon_state = "virology"
item_state = "w_suit"
item_color = "virologywhite"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/nursesuit
desc = "It's a jumpsuit commonly worn by nursing staff in the medical department."
name = "nurse's suit"
icon_state = "nursesuit"
item_state = "w_suit"
item_color = "nursesuit"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
fitted = NO_FEMALE_UNIFORM
can_adjust = 0
/obj/item/clothing/under/rank/medical
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel."
name = "medical doctor's jumpsuit"
icon_state = "medical"
item_state = "w_suit"
item_color = "medical"
permeability_coefficient = 0.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
/obj/item/clothing/under/rank/medical/blue
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue."
icon_state = "scrubsblue"
item_color = "scrubsblue"
can_adjust = 0
/obj/item/clothing/under/rank/medical/green
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green."
icon_state = "scrubsgreen"
item_color = "scrubsgreen"
can_adjust = 0
/obj/item/clothing/under/rank/medical/purple
name = "medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple."
icon_state = "scrubspurple"
item_color = "scrubspurple"
can_adjust = 0
+4 -15
View File
@@ -204,9 +204,9 @@
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/meteorshot
name = "Meteorshot Shell"
result = /obj/item/ammo_casing/shotgun/meteorshot
/datum/crafting_recipe/meteorslug
name = "Meteorslug Shell"
result = /obj/item/ammo_casing/shotgun/meteorslug
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/obj/item/rcd_ammo = 1,
/obj/item/stock_parts/manipulator = 2)
@@ -228,7 +228,7 @@
/datum/crafting_recipe/dragonsbreath
name = "Dragonsbreath Shell"
result = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath
result = /obj/item/ammo_casing/shotgun/dragonsbreath
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, /datum/reagent/phosphorus = 5)
tools = list(/obj/item/screwdriver)
time = 5
@@ -270,17 +270,6 @@
category = CAT_WEAPONRY
subcategory = CAT_AMMO
/datum/crafting_recipe/improvisedslugoverload
name = "Overload Improvised Shell"
result = /obj/item/ammo_casing/shotgun/improvised/overload
reqs = list(/obj/item/ammo_casing/shotgun/improvised = 1,
/datum/reagent/blackpowder = 10,
/datum/reagent/toxin/plasma = 20)
tools = list(/obj/item/screwdriver)
time = 5
category = CAT_WEAPONRY
subcategory = CAT_AMMO
/datum/crafting_recipe/laserslug
name = "Laser Slug Shell"
result = /obj/item/ammo_casing/shotgun/laserslug
+2 -2
View File
@@ -43,7 +43,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
configured_error_silence_time = config.error_silence_time
//Each occurence of an unique error adds to its cooldown time...
//Each occurence of a unique error adds to its cooldown time...
cooldown = max(0, cooldown - (world.time - last_seen)) + configured_error_cooldown
// ... which is used to silence an error if it occurs too often, too fast
if(cooldown > configured_error_cooldown * configured_error_limit)
@@ -88,7 +88,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
if(usrinfo) //If this info isn't null, it hasn't been added yet
desclines.Add(usrinfo)
if(silencing)
desclines += " (This error will now be silenced for [configured_error_silence_time / 600] minutes)"
desclines += " (This error will now be silenced for [DisplayTimeText(configured_error_silence_time)])"
if(GLOB.error_cache)
GLOB.error_cache.log_error(E, desclines)
+6 -31
View File
@@ -3,9 +3,7 @@
typepath = /datum/round_event/ghost_role/abductor
weight = 10
max_occurrences = 1
min_players = 20
gamemode_blacklist = list("nuclear","wizard","revolution","abduction")
/datum/round_event/ghost_role/abductor
@@ -17,40 +15,17 @@
if(candidates.len < 2)
return NOT_ENOUGH_PLAYERS
//Oh god why we can't have static functions
// I feel your pain, bro
var/number = SSticker.mode.abductor_teams + 1
var/datum/game_mode/abduction/temp
var/datum/game_mode/abduction/GM
if(SSticker.mode.config_tag == "abduction")
temp = SSticker.mode
GM = SSticker.mode
else
temp = new
GM = new
var/agent_mind = pick_n_take(candidates)
var/scientist_mind = pick_n_take(candidates)
var/mob/living/carbon/human/agent = makeBody(pick_n_take(candidates))
var/mob/living/carbon/human/scientist = makeBody(pick_n_take(candidates))
var/mob/living/carbon/human/agent = makeBody(agent_mind)
var/mob/living/carbon/human/scientist = makeBody(scientist_mind)
agent_mind = agent.mind
scientist_mind = scientist.mind
temp.scientists.len = number
temp.agents.len = number
temp.abductors.len = 2*number
temp.team_objectives.len = number
temp.team_names.len = number
temp.scientists[number] = scientist_mind
temp.agents[number] = agent_mind
temp.abductors |= list(agent_mind,scientist_mind)
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
temp.post_setup_team(number)
SSticker.mode.abductor_teams++
if(SSticker.mode.config_tag != "abduction")
SSticker.mode.abductors |= temp.abductors
GM.post_setup_team(GM.make_abductor_team(agent.mind, scientist.mind))
spawned_mobs += list(agent, scientist)
return SUCCESSFUL_SPAWN
+1 -1
View File
@@ -88,7 +88,7 @@
..()
if(FESTIVE_SEASON in SSevents.holidays)
new tree(get_turf(src))
qdel(src)
return INITIALIZE_HINT_QDEL
/obj/effect/landmark/xmastree/rdrod
name = "festivus pole spawner"
+1 -1
View File
@@ -43,7 +43,7 @@
/mob/living/simple_animal/hostile/carp/ranged/Initialize()
projectiletype = pick(allowed_projectile_types)
..()
. = ..()
/mob/living/simple_animal/hostile/carp/ranged/chaos
name = "chaos magicarp"
@@ -176,6 +176,22 @@
color = "#DA00FFFF"
bonus_reagents = list("purplecrayonpowder" = 10, "vitamin" = 5)
foodtype = GRAIN | MEAT
/obj/item/reagent_containers/food/snacks/burger/black
name = "black burger"
desc = "This is overcooked."
icon_state = "cburger"
color = "#1C1C1C"
bonus_reagents = list("blackcrayonpowder" = 10, "vitamin" = 5)
foodtype = GRAIN | MEAT
/obj/item/reagent_containers/food/snacks/burger/white
name = "white burger"
desc = "Delicous Titanium!"
icon_state = "cburger"
color = "#FFFFFF"
bonus_reagents = list("whitecrayonpowder" = 10, "vitamin" = 5)
foodtype = GRAIN | MEAT
/obj/item/reagent_containers/food/snacks/burger/spell
name = "spell burger"
@@ -251,4 +267,4 @@
icon_state = "baconburger"
bonus_reagents = list("nutriment" = 8, "vitamin" = 1)
tastes = list("bun" = 4, "bacon" = 2)
foodtype = GRAIN | MEAT
foodtype = GRAIN | MEAT
@@ -188,6 +188,24 @@
tastes = list("cobwebs" = 1)
foodtype = MEAT | TOXIC
/obj/item/reagent_containers/food/snacks/spiderling
name = "spiderling"
desc = "It's slightly twitching in your hand. Ew..."
icon_state = "spiderling"
list_reagents = list("nutrient" = 1, "toxin" = 4)
filling_color = "#00800"
tastes = list("cobwebs" = 1, "guts" = 2)
foodtype = MEAT | TOXIC
/obj/item/reagent_containers/food/snacks/spiderlollipop
name = "spider lollipop"
desc = "Still gross, but at least it has a mountain of sugar on it."
icon_state = "spiderlollipop"
list_reagents = list("nutriment" = 1, "toxin" = 1, "iron" = 10, "sugar" = 5, "omnizine" = 2) //lollipop, but vitamins = toxins
filling_color = "#00800"
tastes = list("cobwebs" = 1, "sugar" = 2)
foodtype = JUNKFOOD | SUGAR
/obj/item/reagent_containers/food/snacks/chococoin
name = "chocolate coin"
desc = "A completely edible but nonflippable festive coin."
@@ -158,10 +158,11 @@
for (var/I in src)
var/atom/movable/O = I
if (!QDELETED(O))
if (listofitems[O.name])
listofitems[O.name]["amount"]++
var/md5name = md5(O.name) // This needs to happen because of a bug in a TGUI component, https://github.com/ractivejs/ractive/issues/744
if (listofitems[md5name]) // which is fixed in a version we cannot use due to ie8 incompatibility
listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating
else
listofitems[O.name] = list("name" = O.name, "type" = O.type, "amount" = 1)
listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1)
sortList(listofitems)
.["contents"] = listofitems
@@ -176,6 +176,26 @@
)
result = /obj/item/reagent_containers/food/snacks/burger/purple
subcategory = CAT_BURGER
/datum/crafting_recipe/food/blackburger
name = "Black burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/black = 1,
/obj/item/reagent_containers/food/snacks/bun = 1
)
result = /obj/item/reagent_containers/food/snacks/burger/black
subcategory = CAT_BURGER
/datum/crafting_recipe/food/whiteburger
name = "White burger"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/steak/plain = 1,
/obj/item/toy/crayon/white = 1,
/obj/item/reagent_containers/food/snacks/bun = 1
)
result = /obj/item/reagent_containers/food/snacks/burger/white
subcategory = CAT_BURGER
/datum/crafting_recipe/food/spellburger
name = "Spell burger"
@@ -12,6 +12,16 @@
result = /obj/item/reagent_containers/food/snacks/candiedapple
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/spiderlollipop
name = "Spider Lollipop"
reqs = list(/obj/item/stack/rods = 1,
/datum/reagent/consumable/sugar = 5,
/datum/reagent/water = 5,
/obj/item/reagent_containers/food/snacks/spiderling = 1
)
result = /obj/item/reagent_containers/food/snacks/spiderlollipop
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/chococoin
name = "Choco coin"
reqs = list(
+1 -1
View File
@@ -126,7 +126,7 @@
/obj/item/toy/foamblade,
/obj/item/toy/prize/ripley,
/obj/item/toy/prize/honk,
/obj/item/toy/carpplushie,
/obj/item/toy/plush/carpplushie,
/obj/item/toy/redbutton,
/obj/item/clothing/head/collectable/rabbitears)
new won(where)
-1
View File
@@ -485,7 +485,6 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
begin_day += 31
begin_month-- //begins in march, ends in april
// to_chat(world, "Easter calculates to be on [begin_day] of [begin_month] ([days_early] early) to [end_day] of [end_month] ([days_extra] extra) for 20[yy]")
return ..()
/datum/holiday/easter/celebrate()
+1 -1
View File
@@ -622,7 +622,7 @@
adjustHealth(round(salt * 0.25))
if (myseed)
myseed.adjust_production(-round(salt/100)-prob(salt%100))
myseed.adjust_potency(round(salt*0.50))
myseed.adjust_potency(round(salt*0.5))
// Ash is also used IRL in gardening, as a fertilizer enhancer and weed killer
if(S.has_reagent("ash", 1))
adjustHealth(round(S.get_reagent_amount("ash") * 0.25))
-108
View File
@@ -1,108 +0,0 @@
diff a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm (rejected hunks)
@@ -140,15 +140,12 @@ GLOBAL_PROTECT(exp_to_update)
//resets a client's exp to what was in the db.
/client/proc/set_exp_from_db()
if(!config.use_exp_tracking)
- return
+ return -1
if(!SSdbcore.Connect())
return -1
var/datum/DBQuery/exp_read = SSdbcore.NewQuery("SELECT job, minutes FROM [format_table_name("role_time")] WHERE ckey = '[sanitizeSQL(ckey)]'")
if(!exp_read.Execute())
- var/err = exp_read.ErrorMsg()
- log_sql("SQL ERROR during exp_update_client read. Error : \[[err]\]\n")
- message_admins("SQL ERROR during exp_update_client read. Error : \[[err]\]\n")
- return
+ return -1
var/list/play_records = list()
while(exp_read.NextRow())
play_records[exp_read.item[1]] = text2num(exp_read.item[2])
@@ -172,42 +169,24 @@ GLOBAL_PROTECT(exp_to_update)
if(!set_db_player_flags())
return -1
- var/datum/DBQuery/flag_read = SSdbcore.NewQuery("SELECT flags FROM [format_table_name("player")] WHERE ckey='[sanitizeSQL(ckey)]'")
-
- if(!flag_read.Execute())
- var/err = flag_read.ErrorMsg()
- log_sql("SQL ERROR during player flags read. Error : \[[err]\]\n")
- message_admins("SQL ERROR during player flags read. Error : \[[err]\]\n")
- return
-
- var/playerflags = null
- if(flag_read.NextRow())
- playerflags = text2num(flag_read.item[1])
-
- if((playerflags & newflag) && !state)
+ if((prefs.db_flags & newflag) && !state)
prefs.db_flags &= ~newflag
else
prefs.db_flags |= newflag
var/datum/DBQuery/flag_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET flags = '[prefs.db_flags]' WHERE ckey='[sanitizeSQL(ckey)]'")
-
if(!flag_update.Execute())
- var/err = flag_update.ErrorMsg()
- log_sql("SQL ERROR during exp_exempt update. Error : \[[err]\]\n")
- message_admins("SQL ERROR during exp_exempt update. Error : \[[err]\]\n")
- return
+ return -1
+
/client/proc/update_exp_list(minutes, announce_changes = FALSE)
if(!config.use_exp_tracking)
- return
+ return -1
if(!SSdbcore.Connect())
return -1
var/datum/DBQuery/exp_read = SSdbcore.NewQuery("SELECT job, minutes FROM [format_table_name("role_time")] WHERE ckey = '[sanitizeSQL(ckey)]'")
if(!exp_read.Execute())
- var/err = exp_read.ErrorMsg()
- log_sql("SQL ERROR during exp_update_client read. Error : \[[err]\]\n")
- message_admins("SQL ERROR during exp_update_client read. Error : \[[err]\]\n")
return -1
var/list/play_records = list()
while(exp_read.NextRow())
@@ -241,9 +220,13 @@ GLOBAL_PROTECT(exp_to_update)
if(announce_changes)
to_chat(mob,"<span class='notice'>You got: [minutes] [role] EXP!</span>")
if(mob.mind.special_role && !mob.mind.var_edited)
- play_records[mob.mind.special_role] += minutes
+ var/trackedrole = mob.mind.special_role
+ var/gangrole = lookforgangrole(mob.mind.special_role)
+ if(gangrole)
+ trackedrole = gangrole
+ play_records[trackedrole] += minutes
if(announce_changes)
- to_chat(src,"<span class='notice'>You got: [minutes] [mob.mind.special_role] EXP!</span>")
+ to_chat(src,"<span class='notice'>You got: [minutes] [trackedrole] EXP!</span>")
if(!rolefound)
play_records["Unknown"] += minutes
else
@@ -276,11 +259,21 @@ GLOBAL_PROTECT(exp_to_update)
var/datum/DBQuery/flags_read = SSdbcore.NewQuery("SELECT flags FROM [format_table_name("player")] WHERE ckey='[ckey]'")
if(!flags_read.Execute())
- var/err = flags_read.ErrorMsg()
- log_sql("SQL ERROR during player flags read. Error : \[[err]\]\n")
- message_admins("SQL ERROR during player flags read. Error : \[[err]\]\n")
return FALSE
if(flags_read.NextRow())
prefs.db_flags = text2num(flags_read.item[1])
+ else if(isnull(prefs.db_flags))
+ prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry.
return TRUE
+
+//Since each gang is tracked as a different antag type, records need to be generalized or you get up to 57 different possible records
+/proc/lookforgangrole(rolecheck)
+ if(findtext(rolecheck,"Gangster"))
+ return "Gangster"
+ else if(findtext(rolecheck,"Gang Boss"))
+ return "Gang Boss"
+ else if(findtext(rolecheck,"Gang Lieutenant"))
+ return "Gang Lieutenant"
+ else
+ return FALSE
\ No newline at end of file
+289 -289
View File
@@ -1,31 +1,31 @@
//Warden and regular officers add this result to their get_access()
/datum/job/proc/check_config_for_sec_maint()
if(config.jobs_have_maint_access & SECURITY_HAS_MAINT_ACCESS)
//Warden and regular officers add this result to their get_access()
/datum/job/proc/check_config_for_sec_maint()
if(config.jobs_have_maint_access & SECURITY_HAS_MAINT_ACCESS)
return list(ACCESS_MAINT_TUNNELS)
return list()
/*
Head of Security
*/
/datum/job/hos
title = "Head of Security"
flag = HOS
department_head = list("Captain")
department_flag = ENGSEC
head_announce = list("Security")
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the captain"
selection_color = "#ffdddd"
req_admin_notify = 1
minimal_player_age = 14
return list()
/*
Head of Security
*/
/datum/job/hos
title = "Head of Security"
flag = HOS
department_head = list("Captain")
department_flag = ENGSEC
head_announce = list("Security")
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the captain"
selection_color = "#ffdddd"
req_admin_notify = 1
minimal_player_age = 14
exp_requirements = 300
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/hos
outfit = /datum/outfit/job/hos
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS,
ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
@@ -34,284 +34,284 @@ Head of Security
ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS,
ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS)
/datum/outfit/job/hos
name = "Head of Security"
jobtype = /datum/job/hos
id = /obj/item/card/id/silver
belt = /obj/item/device/pda/heads/hos
ears = /obj/item/device/radio/headset/heads/hos/alt
uniform = /obj/item/clothing/under/rank/head_of_security
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/hos/trenchcoat
gloves = /obj/item/clothing/gloves/color/black/hos
head = /obj/item/clothing/head/HoS/beret
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
suit_store = /obj/item/gun/energy/e_gun
r_pocket = /obj/item/device/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/*
Warden
*/
/datum/job/warden
title = "Warden"
flag = WARDEN
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 7
/datum/outfit/job/hos
name = "Head of Security"
jobtype = /datum/job/hos
id = /obj/item/card/id/silver
belt = /obj/item/device/pda/heads/hos
ears = /obj/item/device/radio/headset/heads/hos/alt
uniform = /obj/item/clothing/under/rank/head_of_security
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/hos/trenchcoat
gloves = /obj/item/clothing/gloves/color/black/hos
head = /obj/item/clothing/head/HoS/beret
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
suit_store = /obj/item/gun/energy/e_gun
r_pocket = /obj/item/device/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/*
Warden
*/
/datum/job/warden
title = "Warden"
flag = WARDEN
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 7
exp_requirements = 300
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/warden
outfit = /datum/outfit/job/warden
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_FORENSICS_LOCKERS)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS) //SEE /DATUM/JOB/WARDEN/GET_ACCESS()
/datum/job/warden/get_access()
var/list/L = list()
L = ..() | check_config_for_sec_maint()
return L
/datum/outfit/job/warden
name = "Warden"
jobtype = /datum/job/warden
belt = /obj/item/device/pda/warden
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/warden
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/vest/warden/alt
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/warden
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
r_pocket = /obj/item/device/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
suit_store = /obj/item/gun/energy/e_gun/advtaser
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/*
Detective
*/
/datum/job/detective
title = "Detective"
flag = DETECTIVE
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 7
/datum/job/warden/get_access()
var/list/L = list()
L = ..() | check_config_for_sec_maint()
return L
/datum/outfit/job/warden
name = "Warden"
jobtype = /datum/job/warden
belt = /obj/item/device/pda/warden
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/warden
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/vest/warden/alt
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/warden
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
r_pocket = /obj/item/device/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
suit_store = /obj/item/gun/energy/e_gun/advtaser
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/*
Detective
*/
/datum/job/detective
title = "Detective"
flag = DETECTIVE
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 7
exp_requirements = 300
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/detective
outfit = /datum/outfit/job/detective
access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS)
minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS)
/datum/outfit/job/detective
name = "Detective"
jobtype = /datum/job/detective
belt = /obj/item/device/pda/detective
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/det
shoes = /obj/item/clothing/shoes/sneakers/brown
suit = /obj/item/clothing/suit/det_suit
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/fedora/det_hat
l_pocket = /obj/item/toy/crayon/white
r_pocket = /obj/item/lighter
backpack_contents = list(/obj/item/storage/box/evidence=1,\
/obj/item/device/detective_scanner=1,\
/obj/item/melee/classic_baton=1)
mask = /obj/item/clothing/mask/cigarette
implants = list(/obj/item/implant/mindshield)
/datum/outfit/job/detective/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
var/obj/item/clothing/mask/cigarette/cig = H.wear_mask
cig.light("")
if(visualsOnly)
return
/*
Security Officer
*/
/datum/job/officer
title = "Security Officer"
flag = OFFICER
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
supervisors = "the head of security, and the head of your assigned department (if applicable)"
selection_color = "#ffeeee"
minimal_player_age = 7
/datum/outfit/job/detective
name = "Detective"
jobtype = /datum/job/detective
belt = /obj/item/device/pda/detective
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/det
shoes = /obj/item/clothing/shoes/sneakers/brown
suit = /obj/item/clothing/suit/det_suit
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/fedora/det_hat
l_pocket = /obj/item/toy/crayon/white
r_pocket = /obj/item/lighter
backpack_contents = list(/obj/item/storage/box/evidence=1,\
/obj/item/device/detective_scanner=1,\
/obj/item/melee/classic_baton=1)
mask = /obj/item/clothing/mask/cigarette
implants = list(/obj/item/implant/mindshield)
/datum/outfit/job/detective/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
var/obj/item/clothing/mask/cigarette/cig = H.wear_mask
cig.light("")
if(visualsOnly)
return
/*
Security Officer
*/
/datum/job/officer
title = "Security Officer"
flag = OFFICER
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
supervisors = "the head of security, and the head of your assigned department (if applicable)"
selection_color = "#ffeeee"
minimal_player_age = 7
exp_requirements = 300
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/security
outfit = /datum/outfit/job/security
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_FORENSICS_LOCKERS)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_WEAPONS) //BUT SEE /DATUM/JOB/WARDEN/GET_ACCESS()
/datum/job/officer/get_access()
var/list/L = list()
L |= ..() | check_config_for_sec_maint()
return L
GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY))
/datum/job/officer/after_spawn(mob/living/carbon/human/H, mob/M)
// Assign department security
var/department
if(M && M.client && M.client.prefs)
department = M.client.prefs.prefered_security_department
if(!LAZYLEN(GLOB.available_depts) || department == "None")
return
else if(department in GLOB.available_depts)
LAZYREMOVE(GLOB.available_depts, department)
else
department = pick_n_take(GLOB.available_depts)
var/ears = null
var/accessory = null
var/list/dep_access = null
var/destination = null
var/spawn_point = null
switch(department)
if(SEC_DEPT_SUPPLY)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/supply
/datum/job/officer/get_access()
var/list/L = list()
L |= ..() | check_config_for_sec_maint()
return L
GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY))
/datum/job/officer/after_spawn(mob/living/carbon/human/H, mob/M)
// Assign department security
var/department
if(M && M.client && M.client.prefs)
department = M.client.prefs.prefered_security_department
if(!LAZYLEN(GLOB.available_depts) || department == "None")
return
else if(department in GLOB.available_depts)
LAZYREMOVE(GLOB.available_depts, department)
else
department = pick_n_take(GLOB.available_depts)
var/ears = null
var/accessory = null
var/list/dep_access = null
var/destination = null
var/spawn_point = null
switch(department)
if(SEC_DEPT_SUPPLY)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/supply
dep_access = list(ACCESS_MAILSORTING, ACCESS_MINING, ACCESS_MINING_STATION)
destination = /area/security/checkpoint/supply
spawn_point = locate(/obj/effect/landmark/start/depsec/supply) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/cargo
if(SEC_DEPT_ENGINEERING)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/engi
destination = /area/security/checkpoint/supply
spawn_point = locate(/obj/effect/landmark/start/depsec/supply) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/cargo
if(SEC_DEPT_ENGINEERING)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/engi
dep_access = list(ACCESS_CONSTRUCTION, ACCESS_ENGINE)
destination = /area/security/checkpoint/engineering
spawn_point = locate(/obj/effect/landmark/start/depsec/engineering) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/engine
if(SEC_DEPT_MEDICAL)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/med
destination = /area/security/checkpoint/engineering
spawn_point = locate(/obj/effect/landmark/start/depsec/engineering) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/engine
if(SEC_DEPT_MEDICAL)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/med
dep_access = list(ACCESS_MEDICAL)
destination = /area/security/checkpoint/medical
spawn_point = locate(/obj/effect/landmark/start/depsec/medical) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/medblue
if(SEC_DEPT_SCIENCE)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/sci
destination = /area/security/checkpoint/medical
spawn_point = locate(/obj/effect/landmark/start/depsec/medical) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/medblue
if(SEC_DEPT_SCIENCE)
ears = /obj/item/device/radio/headset/headset_sec/alt/department/sci
dep_access = list(ACCESS_RESEARCH)
destination = /area/security/checkpoint/science
spawn_point = locate(/obj/effect/landmark/start/depsec/science) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/science
if(accessory)
var/obj/item/clothing/under/U = H.w_uniform
U.attach_accessory(new accessory)
if(ears)
if(H.ears)
qdel(H.ears)
H.equip_to_slot_or_del(new ears(H),slot_ears)
var/obj/item/card/id/W = H.wear_id
W.access |= dep_access
var/teleport = 0
if(!config.sec_start_brig)
if(destination || spawn_point)
teleport = 1
if(teleport)
var/turf/T
if(spawn_point)
T = get_turf(spawn_point)
H.Move(T)
else
var/safety = 0
while(safety < 25)
T = safepick(get_area_turfs(destination))
if(T && !H.Move(T))
safety += 1
continue
else
break
if(department)
to_chat(M, "<b>You have been assigned to [department]!</b>")
else
to_chat(M, "<b>You have not been assigned to any department. Patrol the halls and help where needed.</b>")
/datum/outfit/job/security
name = "Security Officer"
jobtype = /datum/job/officer
belt = /obj/item/device/pda/security
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/security
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/helmet/sec
suit = /obj/item/clothing/suit/armor/vest/alt
shoes = /obj/item/clothing/shoes/jackboots
l_pocket = /obj/item/restraints/handcuffs
r_pocket = /obj/item/device/assembly/flash/handheld
suit_store = /obj/item/gun/energy/e_gun/advtaser
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/obj/item/device/radio/headset/headset_sec/alt/department/Initialize()
wires = new/datum/wires/radio(src)
secure_radio_connections = new
recalculateChannels()
..()
/obj/item/device/radio/headset/headset_sec/alt/department/engi
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_sec/alt/department/supply
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_sec/alt/department/med
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sec/alt/department/sci
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_sci
destination = /area/security/checkpoint/science
spawn_point = locate(/obj/effect/landmark/start/depsec/science) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/science
if(accessory)
var/obj/item/clothing/under/U = H.w_uniform
U.attach_accessory(new accessory)
if(ears)
if(H.ears)
qdel(H.ears)
H.equip_to_slot_or_del(new ears(H),slot_ears)
var/obj/item/card/id/W = H.wear_id
W.access |= dep_access
var/teleport = 0
if(!config.sec_start_brig)
if(destination || spawn_point)
teleport = 1
if(teleport)
var/turf/T
if(spawn_point)
T = get_turf(spawn_point)
H.Move(T)
else
var/safety = 0
while(safety < 25)
T = safepick(get_area_turfs(destination))
if(T && !H.Move(T))
safety += 1
continue
else
break
if(department)
to_chat(M, "<b>You have been assigned to [department]!</b>")
else
to_chat(M, "<b>You have not been assigned to any department. Patrol the halls and help where needed.</b>")
/datum/outfit/job/security
name = "Security Officer"
jobtype = /datum/job/officer
belt = /obj/item/device/pda/security
ears = /obj/item/device/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/security
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/helmet/sec
suit = /obj/item/clothing/suit/armor/vest/alt
shoes = /obj/item/clothing/shoes/jackboots
l_pocket = /obj/item/restraints/handcuffs
r_pocket = /obj/item/device/assembly/flash/handheld
suit_store = /obj/item/gun/energy/e_gun/advtaser
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
/obj/item/device/radio/headset/headset_sec/alt/department/Initialize()
. = ..()
wires = new/datum/wires/radio(src)
secure_radio_connections = new
recalculateChannels()
/obj/item/device/radio/headset/headset_sec/alt/department/engi
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_sec/alt/department/supply
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_sec/alt/department/med
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sec/alt/department/sci
keyslot = new /obj/item/device/encryptionkey/headset_sec
keyslot2 = new /obj/item/device/encryptionkey/headset_sci
+7 -7
View File
@@ -14,8 +14,8 @@
name = "bookcase"
icon = 'icons/obj/library.dmi'
icon_state = "bookempty"
anchored = FALSE
density = TRUE
anchored = FALSE
density = TRUE
opacity = 0
resistance_flags = FLAMMABLE
max_integrity = 200
@@ -25,12 +25,12 @@
/obj/structure/bookcase/Initialize(mapload)
..()
. = ..()
if(!mapload)
return
state = 2
icon_state = "book-0"
anchored = TRUE
anchored = TRUE
for(var/obj/item/I in loc)
if(istype(I, /obj/item/book))
I.loc = src
@@ -44,7 +44,7 @@
playsound(loc, I.usesound, 100, 1)
if(do_after(user, 20*I.toolspeed, target = src))
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
anchored = TRUE
anchored = TRUE
state = 1
if(istype(I, /obj/item/crowbar))
playsound(loc, I.usesound, 100, 1)
@@ -63,7 +63,7 @@
if(istype(I, /obj/item/wrench))
playsound(loc, I.usesound, 100, 1)
to_chat(user, "<span class='notice'>You unwrench the frame.</span>")
anchored = FALSE
anchored = FALSE
state = 0
if(2)
@@ -317,4 +317,4 @@
to_chat(user, "<font color=green>Computer has been associated with this unit.</font>")
else
to_chat(user, "<font color=red>No associated computer found. Only local scans will function properly.</font>")
to_chat(user, "\n")
to_chat(user, "\n")
+4 -4
View File
@@ -1,18 +1,18 @@
/obj/item/book/manual/random/Initialize()
. = ..()
..()
var/static/banned_books = list(/obj/item/book/manual/random, /obj/item/book/manual/nuclear, /obj/item/book/manual/wiki)
var/newtype = pick(subtypesof(/obj/item/book/manual) - banned_books)
new newtype(loc)
qdel(src)
return INITIALIZE_HINT_QDEL
/obj/item/book/random
var/amount = 1
var/category = null
/obj/item/book/random/Initialize()
. = ..()
..()
create_random_books(amount, src.loc, TRUE, category)
qdel(src)
return INITIALIZE_HINT_QDEL
/obj/item/book/random/triple
amount = 3
+1 -1
View File
@@ -83,7 +83,7 @@
new /obj/item/clothing/suit/hooded/ian_costume(src)
if(67 to 68)
for(var/i in 1 to rand(4, 7))
var /newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace)
var/newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace)
new newitem(src)
if(69 to 70)
for(var/i in 1 to 5)
@@ -292,7 +292,7 @@
//ash drake
/obj/item/crusher_trophy/tail_spike
desc = "A spike taken from a ash drake's tail. Suitable as a trophy for a kinetic crusher."
desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher."
denied_type = /obj/item/crusher_trophy/tail_spike
bonus_value = 5
@@ -11,7 +11,7 @@
desc = "It's watching you suspiciously."
/obj/structure/closet/crate/necropolis/tendril/PopulateContents()
var/loot = rand(1,28)
var/loot = rand(1,27)
switch(loot)
if(1)
new /obj/item/device/shared_storage/red(src)
@@ -28,7 +28,10 @@
if(7)
new /obj/item/pickaxe/diamond(src)
if(8)
new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src)
if(prob(50))
new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src)
else
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
if(9)
new /obj/item/organ/brain/alien(src)
if(10)
@@ -38,7 +41,7 @@
if(12)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker(src)
if(13)
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
new /obj/item/jacobs_ladder(src)
if(14)
new /obj/item/nullrod/scythe/talking(src)
if(15)
@@ -46,7 +49,10 @@
if(16)
new /obj/item/guardiancreator(src)
if(17)
new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
if(prob(50))
new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
else
new /obj/item/disk/design_disk/modkit_disc/bounty(src)
if(18)
new /obj/item/device/warp_cube/red(src)
if(19)
@@ -69,8 +75,7 @@
if(27)
new /obj/item/borg/upgrade/modkit/lifesteal(src)
new /obj/item/bedsheet/cult(src)
if(28)
new /obj/item/disk/design_disk/modkit_disc/bounty(src)
//KA modkit design discs
/obj/item/disk/design_disk/modkit_disc
@@ -331,7 +336,7 @@
if(cooldown < world.time)
SSblackbox.add_details("immortality_talisman","Activated") // usage
cooldown = world.time + 600
user.visible_message("<span class='danger'>[user] vanishes from reality, leaving a a hole in [user.p_their()] place!</span>")
user.visible_message("<span class='danger'>[user] vanishes from reality, leaving a hole in [user.p_their()] place!</span>")
var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc))
Z.name = "hole in reality"
Z.desc = "It's shaped an awful lot like [user.name]."
@@ -563,7 +568,28 @@
..()
/obj/item/jacobs_ladder
name = "jacob's ladder"
desc = "A celestial ladder that violates the laws of physics."
icon = 'icons/obj/structures.dmi'
icon_state = "ladder00"
/obj/item/jacobs_ladder/attack_self(mob/user)
var/turf/T = get_turf(src)
var/ladder_x = T.x
var/ladder_y = T.y
to_chat(user, "<span class='notice'>You unfold the ladder. It extends much farther than you were expecting.</span>")
for(var/i in 1 to world.maxz)
if(i == ZLEVEL_CENTCOM || i == ZLEVEL_TRANSIT)
continue
var/turf/T2 = locate(ladder_x, ladder_y, i)
new /obj/structure/ladder/unbreakable/jacob(T2)
qdel(src)
/obj/structure/ladder/unbreakable/jacob
name = "jacob's ladder"
desc = "An indestructible celestial ladder that violates the laws of physics."
auto_connect = TRUE
///Bosses
@@ -1263,3 +1289,5 @@
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check)
B.damage = 15 //keeps monster damage boost due to lower damage
+7 -3
View File
@@ -66,7 +66,6 @@
density = TRUE
anchored = TRUE
var/obj/machinery/mineral/CONSOLE = null
var/datum/material_container/materials
var/on = FALSE
var/selected_material = MAT_METAL
var/selected_alloy = null
@@ -75,12 +74,11 @@
/obj/machinery/mineral/processing_unit/Initialize()
. = ..()
proximity_monitor = new(src, 1)
materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY)
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), INFINITY)
files = new /datum/research/smelter(src)
/obj/machinery/mineral/processing_unit/Destroy()
CONSOLE = null
QDEL_NULL(materials)
QDEL_NULL(files)
return ..()
@@ -89,6 +87,7 @@
process_ore(AM)
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/ore/O)
GET_COMPONENT(materials, /datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!materials.has_space(material_amount))
unload_mineral(O)
@@ -100,6 +99,7 @@
/obj/machinery/mineral/processing_unit/proc/get_machine_data()
var/dat = "<b>Smelter control console</b><br><br>"
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
dat += "<span class=\"res_name\">[M.name]: </span>[M.amount] cm&sup3;"
@@ -165,6 +165,7 @@
continue*/
/obj/machinery/mineral/processing_unit/proc/smelt_ore()
GET_COMPONENT(materials, /datum/component/material_container)
var/datum/material/mat = materials.materials[selected_material]
if(mat)
var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT)
@@ -187,6 +188,7 @@
on = FALSE
return
GET_COMPONENT(materials, /datum/component/material_container)
materials.use_amount(alloy.materials, amount)
generate_mineral(alloy.build_path)
@@ -197,6 +199,7 @@
var/build_amount = SMELT_AMOUNT
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
@@ -214,6 +217,7 @@
unload_mineral(O)
/obj/machinery/mineral/processing_unit/on_deconstruction()
GET_COMPONENT(materials, /datum/component/material_container)
materials.retrieve_all()
..()
+8 -10
View File
@@ -22,17 +22,15 @@
var/list/ore_values = list(MAT_GLASS = 1, MAT_METAL = 1, MAT_PLASMA = 15, MAT_SILVER = 16, MAT_GOLD = 18, MAT_TITANIUM = 30, MAT_URANIUM = 30, MAT_DIAMOND = 50, MAT_BLUESPACE = 50, MAT_BANANIUM = 60)
var/message_sent = FALSE
var/list/ore_buffer = list()
var/datum/material_container/materials
var/datum/research/files
var/obj/item/disk/design_disk/inserted_disk
/obj/machinery/mineral/ore_redemption/Initialize()
. = ..()
materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY)
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY)
files = new /datum/research/smelter(src)
/obj/machinery/mineral/ore_redemption/Destroy()
QDEL_NULL(materials)
QDEL_NULL(files)
return ..()
@@ -57,6 +55,7 @@
if(O && O.refined_type)
points += O.points * point_upgrade
GET_COMPONENT(materials, /datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!material_amount)
@@ -75,6 +74,7 @@
var/build_amount = 0
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
var/datum/material/redemption_mat = materials.materials[mat_id]
@@ -110,6 +110,7 @@
var/has_minerals = FALSE
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
@@ -148,6 +149,7 @@
/obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params)
if(exchange_parts(user, W))
return
GET_COMPONENT(materials, /datum/component/material_container)
if(default_pry_open(W))
materials.retrieve_all()
return
@@ -181,16 +183,10 @@
if(user.transferItemToLoc(W, src))
inserted_disk = W
return TRUE
if(istype(W, /obj/item/stack/sheet))
var/obj/item/stack/sheet/S = W
var/inserted = materials.insert_stack(S, S.amount)
to_chat(user, "<span class='notice'>You add [inserted] [S] sheets to \the [src].</span>")
return
return ..()
/obj/machinery/mineral/ore_redemption/on_deconstruction()
GET_COMPONENT(materials, /datum/component/material_container)
materials.retrieve_all()
..()
@@ -213,6 +209,7 @@
data["claimedPoints"] = inserted_id.mining_points
data["materials"] = list()
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
var/sheet_amount = M.amount ? M.amount / MINERAL_MATERIAL_AMOUNT : "0"
@@ -236,6 +233,7 @@
/obj/machinery/mineral/ore_redemption/ui_act(action, params)
if(..())
return
GET_COMPONENT(materials, /datum/component/material_container)
switch(action)
if("Eject")
if(!inserted_id)
+1
View File
@@ -67,6 +67,7 @@
possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public"
no_destination_swap = 1
var/global/list/dumb_rev_heads = list()
req_access = list(ACCESS_MINING) // should slow the ashwalkers down.
/obj/machinery/computer/shuttle/mining/attack_hand(mob/user)
if((user.z in GLOB.station_z_levels) && user.mind && (user.mind in SSticker.mode.head_revolutionaries) && !(user.mind in dumb_rev_heads))
+95 -99
View File
@@ -1,107 +1,103 @@
/**********************Mint**************************/
/obj/machinery/mineral/mint
name = "coin press"
icon = 'icons/obj/economy.dmi'
icon_state = "coinpress0"
/**********************Mint**************************/
/obj/machinery/mineral/mint
name = "coin press"
icon = 'icons/obj/economy.dmi'
icon_state = "coinpress0"
density = TRUE
anchored = TRUE
var/datum/material_container/materials
var/newCoins = 0 //how many coins the machine made in it's last load
var/newCoins = 0 //how many coins the machine made in it's last load
var/processing = FALSE
var/chosen = MAT_METAL //which material will be used to make coins
var/coinsToProduce = 10
speed_process = 1
var/chosen = MAT_METAL //which material will be used to make coins
var/coinsToProduce = 10
speed_process = 1
/obj/machinery/mineral/mint/Initialize()
. = ..()
materials = new /datum/material_container(src,
list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM),
max_amt = MINERAL_MATERIAL_AMOUNT*50)
/obj/machinery/mineral/mint/Destroy()
QDEL_NULL(materials)
return ..()
/obj/machinery/mineral/mint/process()
var/turf/T = get_step(src, input_dir)
if(!T)
return
for(var/obj/item/stack/sheet/O in T)
materials.insert_stack(O, O.amount)
/obj/machinery/mineral/mint/attack_hand(mob/user)
var/dat = "<b>Coin Press</b><br>"
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(!M.amount && chosen != mat_id)
continue
dat += "<br><b>[M.name] amount:</b> [M.amount] cm<sup>3</sup> "
if (chosen == mat_id)
dat += "<b>Chosen</b>"
else
dat += "<A href='?src=\ref[src];choose=[mat_id]'>Choose</A>"
var/datum/material/M = materials.materials[chosen]
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
dat += "<A href='?src=\ref[src];chooseAmt=-10'>-10</A> "
dat += "<A href='?src=\ref[src];chooseAmt=-5'>-5</A> "
dat += "<A href='?src=\ref[src];chooseAmt=-1'>-1</A> "
dat += "<A href='?src=\ref[src];chooseAmt=1'>+1</A> "
dat += "<A href='?src=\ref[src];chooseAmt=5'>+5</A> "
dat += "<A href='?src=\ref[src];chooseAmt=10'>+10</A> "
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
dat += "<br><A href='?src=\ref[src];makeCoins=[1]'>Make coins</A>"
user << browse(dat, "window=mint")
/obj/machinery/mineral/mint/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(processing==1)
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
return
if(href_list["choose"])
if(materials.materials[href_list["choose"]])
chosen = href_list["choose"]
if(href_list["chooseAmt"])
coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
if(href_list["makeCoins"])
var/temp_coins = coinsToProduce
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), MINERAL_MATERIAL_AMOUNT * 50)
/obj/machinery/mineral/mint/process()
var/turf/T = get_step(src, input_dir)
if(!T)
return
GET_COMPONENT(materials, /datum/component/material_container)
for(var/obj/item/stack/sheet/O in T)
materials.insert_stack(O, O.amount)
/obj/machinery/mineral/mint/attack_hand(mob/user)
var/dat = "<b>Coin Press</b><br>"
GET_COMPONENT(materials, /datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(!M.amount && chosen != mat_id)
continue
dat += "<br><b>[M.name] amount:</b> [M.amount] cm<sup>3</sup> "
if (chosen == mat_id)
dat += "<b>Chosen</b>"
else
dat += "<A href='?src=\ref[src];choose=[mat_id]'>Choose</A>"
var/datum/material/M = materials.materials[chosen]
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
dat += "<A href='?src=\ref[src];chooseAmt=-10'>-10</A> "
dat += "<A href='?src=\ref[src];chooseAmt=-5'>-5</A> "
dat += "<A href='?src=\ref[src];chooseAmt=-1'>-1</A> "
dat += "<A href='?src=\ref[src];chooseAmt=1'>+1</A> "
dat += "<A href='?src=\ref[src];chooseAmt=5'>+5</A> "
dat += "<A href='?src=\ref[src];chooseAmt=10'>+10</A> "
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
dat += "<br><A href='?src=\ref[src];makeCoins=[1]'>Make coins</A>"
user << browse(dat, "window=mint")
/obj/machinery/mineral/mint/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(processing==1)
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
return
GET_COMPONENT(materials, /datum/component/material_container)
if(href_list["choose"])
if(materials.materials[href_list["choose"]])
chosen = href_list["choose"]
if(href_list["chooseAmt"])
coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
if(href_list["makeCoins"])
var/temp_coins = coinsToProduce
processing = TRUE
icon_state = "coinpress1"
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
var/datum/material/M = materials.materials[chosen]
if(!M || !M.coin_type)
updateUsrDialog()
return
while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen))
create_coins(M.coin_type)
coinsToProduce--
newCoins++
src.updateUsrDialog()
sleep(5)
icon_state = "coinpress0"
icon_state = "coinpress1"
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
var/datum/material/M = materials.materials[chosen]
if(!M || !M.coin_type)
updateUsrDialog()
return
while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen))
create_coins(M.coin_type)
coinsToProduce--
newCoins++
src.updateUsrDialog()
sleep(5)
icon_state = "coinpress0"
processing = FALSE
coinsToProduce = temp_coins
src.updateUsrDialog()
return
/obj/machinery/mineral/mint/proc/create_coins(P)
var/turf/T = get_step(src,output_dir)
if(T)
var/obj/item/O = new P(src)
var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T)
if(!M)
M = new /obj/item/storage/bag/money(src)
unload_mineral(M)
coinsToProduce = temp_coins
src.updateUsrDialog()
return
/obj/machinery/mineral/mint/proc/create_coins(P)
var/turf/T = get_step(src,output_dir)
if(T)
var/obj/item/O = new P(src)
var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T)
if(!M)
M = new /obj/item/storage/bag/money(src)
unload_mineral(M)
O.loc = M
@@ -1,9 +0,0 @@
diff a/code/modules/mob/dead/new_player/login.dm b/code/modules/mob/dead/new_player/login.dm (rejected hunks)
@@ -1,5 +1,6 @@
/mob/dead/new_player/Login()
- client.update_exp_client(0, 0)
+ if(config.use_exp_tracking)
+ client.update_exp_client(0, 0)
if(!mind)
mind = new /datum/mind(key)
mind.active = 1
@@ -329,6 +329,9 @@
if(SSshuttle.arrivals.damaged && config.arrivals_shuttle_require_safe_latejoin)
src << alert("The arrivals shuttle is currently malfunctioning! You cannot join.")
return FALSE
if(config.arrivals_shuttle_require_undocked)
SSshuttle.arrivals.RequireUndocked(src)
arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL
//Remove the player from the join queue if he was in one and reset the timer
@@ -394,12 +397,7 @@
/mob/dead/new_player/proc/LateChoices()
var/mills = world.time - SSticker.round_start_time // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = (mills % 36000) / 600
var/hours = mills / 36000
var/dat = "<div class='notice'>Round Duration: [round(hours)]h [round(mins)]m</div>"
var/dat = "<div class='notice'>Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]</div>"
if(SSshuttle.emergency)
switch(SSshuttle.emergency.mode)
+1 -1
View File
@@ -417,7 +417,7 @@
to_chat(src, "<span class='danger'>Invalid vote data</span>")
return 0
//lets add the vote, first we generate a insert statement.
//lets add the vote, first we generate an insert statement.
var/sqlrowlist = ""
for (var/vote in numberedvotelist)
@@ -1,100 +1,84 @@
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
if(gender_override)
gender = gender_override
else
gender = pick(MALE,FEMALE)
skin_tone = random_skin_tone()
hair_style = random_hair_style(gender)
facial_hair_style = random_facial_hair_style(gender)
hair_color = random_short_color()
facial_hair_color = hair_color
eye_color = random_eye_color()
if(!pref_species)
var/rando_race = pick(config.roundstart_races)
pref_species = new rando_race()
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(nude = 0)
var/wide_icon = 0
var/stamp_x = 0
var/stamp_y = 1
if(features["taur"] != "None")
wide_icon = 1
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
if(AI_JF)
preview_icon = icon('icons/mob/AI.dmi', "AI", SOUTH)
preview_icon.Scale(64, 64)
return
if(CYBORG)
preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
preview_icon.Scale(64, 64)
return
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = new()
copy_to(mannequin)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob
var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
if(job_civilian_low & ASSISTANT)
previewJob = SSjob.GetJob("Assistant")
else if(highRankFlag)
var/highDeptFlag
if(job_civilian_high)
highDeptFlag = CIVILIAN
else if(job_medsci_high)
highDeptFlag = MEDSCI
else if(job_engsec_high)
highDeptFlag = ENGSEC
for(var/datum/job/job in SSjob.occupations)
if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
previewJob = job
break
if(previewJob && !nude)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
mannequin.update_body()
CHECK_TICK
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale((112), (32))
CHECK_TICK
mannequin.setDir(NORTH)
var/icon/stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = 16
else
stamp_x = 32
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
mannequin.setDir(WEST)
stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = 48
else
stamp_x = 64
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
mannequin.setDir(SOUTH)
stamp = getFlatIcon(mannequin)
CHECK_TICK
if(wide_icon)
stamp_x = -15
else
stamp_x = 1
preview_icon.Blend(stamp, ICON_OVERLAY, stamp_x, stamp_y)
CHECK_TICK
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
CHECK_TICK
qdel(mannequin)
//The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
if(gender_override)
gender = gender_override
else
gender = pick(MALE,FEMALE)
underwear = random_underwear(gender)
undershirt = random_undershirt(gender)
socks = random_socks()
skin_tone = random_skin_tone()
hair_style = random_hair_style(gender)
facial_hair_style = random_facial_hair_style(gender)
hair_color = random_short_color()
facial_hair_color = hair_color
eye_color = random_eye_color()
if(!pref_species)
var/rando_race = pick(config.roundstart_races)
pref_species = new rando_race()
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(nude = 0)
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
if(AI_JF)
preview_icon = icon('icons/mob/ai.dmi', "AI", SOUTH)
preview_icon.Scale(64, 64)
return
if(CYBORG)
preview_icon = icon('icons/mob/robots.dmi', "robot", SOUTH)
preview_icon.Scale(64, 64)
return
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
copy_to(mannequin)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob
var/highRankFlag = job_civilian_high | job_medsci_high | job_engsec_high
if(job_civilian_low & ASSISTANT)
previewJob = SSjob.GetJob("Assistant")
else if(highRankFlag)
var/highDeptFlag
if(job_civilian_high)
highDeptFlag = CIVILIAN
else if(job_medsci_high)
highDeptFlag = MEDSCI
else if(job_engsec_high)
highDeptFlag = ENGSEC
for(var/datum/job/job in SSjob.occupations)
if(job.flag == highRankFlag && job.department_flag == highDeptFlag)
previewJob = job
break
if(previewJob && !nude)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
CHECK_TICK
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale(48+32, 16+32)
CHECK_TICK
mannequin.setDir(NORTH)
var/icon/stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
CHECK_TICK
mannequin.setDir(WEST)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
CHECK_TICK
mannequin.setDir(SOUTH)
stamp = getFlatIcon(mannequin)
CHECK_TICK
preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
CHECK_TICK
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
CHECK_TICK
unset_busy_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
+1 -3
View File
@@ -711,9 +711,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
/mob/dead/observer/canUseTopic(atom/movable/AM,be_close = FALSE)
if(check_rights(R_ADMIN, 0))
return 1
return
return IsAdminGhost(usr)
/mob/dead/observer/is_literate()
return 1
+4 -2
View File
@@ -13,6 +13,7 @@
var/obj/item/organ/brain/brain = null //The actual brain
var/datum/ai_laws/laws = new()
var/force_replace_ai_name = FALSE
var/overrides_aicore_laws = FALSE // Whether the laws on the MMI, if any, override possible pre-existing laws loaded on the AI core.
/obj/item/device/mmi/update_icon()
if(brain)
@@ -203,8 +204,9 @@
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
origin_tech = "biotech=4;programming=4;syndicate=2"
overrides_aicore_laws = TRUE
/obj/item/device/mmi/syndie/New()
..()
/obj/item/device/mmi/syndie/Initialize()
. = ..()
laws = new /datum/ai_laws/syndicate_override()
radio.on = 0
@@ -40,7 +40,7 @@
create_internal_organs()
..()
. = ..()
/mob/living/carbon/alien/create_internal_organs()
internal_organs += new /obj/item/organ/brain/alien
@@ -8,7 +8,7 @@
/mob/living/carbon/alien/humanoid/drone/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
..()
. = ..()
/mob/living/carbon/alien/humanoid/drone/create_internal_organs()
@@ -38,11 +38,11 @@
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
if(!canmove || leaping)
return
if(leaping || stat || buckled || lying)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
return
if(!has_gravity() || !A.has_gravity())
@@ -66,6 +66,7 @@
if(!leaping)
return ..()
pounce_cooldown = world.time + pounce_cooldown_time
if(A)
if(isliving(A))
var/mob/living/L = A
@@ -83,7 +84,6 @@
Knockdown(40, 1, 1)
toggle_leap(0)
pounce_cooldown = world.time + pounce_cooldown_time
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
Knockdown(40, 1, 1)
@@ -13,7 +13,7 @@
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
..()
. = ..()
/mob/living/carbon/alien/humanoid/royal/praetorian/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
@@ -48,4 +48,4 @@
return 1
else
to_chat(user, "<span class='notice'>We already have an alive queen.</span>")
return 0
return 0

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