diff --git a/byond-extools.dll b/byond-extools.dll index ea5491a741..c404bf1be5 100644 Binary files a/byond-extools.dll and b/byond-extools.dll differ diff --git a/byond-extools.pdb b/byond-extools.pdb new file mode 100644 index 0000000000..f89dc06441 Binary files /dev/null and b/byond-extools.pdb differ diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index a3fdf762c2..9deddd4b46 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -122,6 +122,7 @@ #define FIRE_PRIORITY_PROJECTILES 200 #define FIRE_PRIORITY_TICKER 200 #define FIRE_PRIORITY_ATMOS_ADJACENCY 300 +#define FIRE_PRIORITY_STATPANEL 390 #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_OVERLAYS 500 #define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 0171057286..3efb50ef65 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -553,12 +553,6 @@ if(D.vars[varname] == value) return D -//remove all nulls from a list -/proc/removeNullsFromList(list/L) - while(L.Remove(null)) - continue - return L - //Copies a list, and all lists inside it recusively //Does not copy any other reference type /proc/deepCopyList(list/l) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 2bd477d98c..4723577fad 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1223,7 +1223,7 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico return "" //Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs. -/proc/costly_icon2html(thing, target) +/proc/costly_icon2html(thing, target, sourceonly = FALSE) if (!thing) return @@ -1231,4 +1231,5 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico return icon2html(thing, target) var/icon/I = getFlatIcon(thing) - return icon2html(I, target) + return icon2html(I, target, sourceonly = sourceonly) + diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index dfd8d4c873..e207fe838a 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -16,7 +16,6 @@ SUBSYSTEM_DEF(air) var/cost_atmos_machinery = 0 var/cost_equalize = 0 - var/list/active_turfs = list() var/list/hotspots = list() var/list/networks = list() var/list/pipenets_needing_rebuilt = list() @@ -54,13 +53,16 @@ SUBSYSTEM_DEF(air) msg += "PN:[round(cost_pipenets,1)]|" msg += "AM:[round(cost_atmos_machinery,1)]" msg += "} " - msg += "AT:[active_turfs.len]|" + var/active_turfs_len = get_amt_active_turfs() + msg += "AT:[active_turfs_len]|" msg += "EG:[get_amt_excited_groups()]|" msg += "HS:[hotspots.len]|" msg += "PN:[networks.len]|" msg += "HP:[high_pressure_delta.len]|" msg += "AS:[active_super_conductivity.len]|" - msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]" + msg += "GA:[get_amt_gas_mixes()]|" + msg += "MG:[get_max_gas_mixes()]|" + msg += "AT/MS:[round((cost ? active_turfs_len/cost : 0),0.1)]" return ..() /datum/controller/subsystem/air/Initialize(timeofday) @@ -70,9 +72,11 @@ SUBSYSTEM_DEF(air) setup_atmos_machinery() setup_pipenets() gas_reactions = init_gas_reactions() + extools_update_reactions() return ..() /datum/controller/subsystem/air/proc/extools_update_ssair() +/datum/controller/subsystem/air/proc/extools_update_reactions() /datum/controller/subsystem/air/fire(resumed = 0) var/timer = TICK_USAGE_REAL @@ -237,6 +241,8 @@ SUBSYSTEM_DEF(air) return /datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0) + return process_turf_equalize_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + /* //cache for sanic speed var/fire_count = times_fired if (!resumed) @@ -251,8 +257,11 @@ SUBSYSTEM_DEF(air) //equalize_pressure_in_zone(T, fire_count) if (MC_TICK_CHECK) return + */ /datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0) + return process_active_turfs_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + /* //cache for sanic speed var/fire_count = times_fired if (!resumed) @@ -266,10 +275,10 @@ SUBSYSTEM_DEF(air) T.process_cell(fire_count) if (MC_TICK_CHECK) return + */ /datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0) - if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) - sleep() + return process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) /* if (!resumed) src.currentrun = excited_groups.Copy() @@ -288,13 +297,20 @@ SUBSYSTEM_DEF(air) return */ +/datum/controller/subsystem/air/proc/process_active_turfs_extools() +/datum/controller/subsystem/air/proc/process_turf_equalize_extools() /datum/controller/subsystem/air/proc/process_excited_groups_extools() /datum/controller/subsystem/air/proc/get_amt_excited_groups() +/datum/controller/subsystem/air/proc/get_amt_active_turfs() +/datum/controller/subsystem/air/proc/get_amt_gas_mixes() +/datum/controller/subsystem/air/proc/get_max_gas_mixes() +/datum/controller/subsystem/air/proc/add_to_active_extools() +/datum/controller/subsystem/air/proc/remove_from_active_extools() +/datum/controller/subsystem/air/proc/get_active_turfs() +/datum/controller/subsystem/air/proc/clear_active_turfs() /datum/controller/subsystem/air/proc/remove_from_active(turf/open/T) - active_turfs -= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun -= T + remove_from_active_extools(T) #ifdef VISUALIZE_ACTIVE_TURFS T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00") #endif @@ -308,9 +324,7 @@ SUBSYSTEM_DEF(air) T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY) #endif T.set_excited(TRUE) - active_turfs |= T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun |= T + add_to_active_extools(T) if(blockchanges) T.eg_garbage_collect() else if(T.flags_1 & INITIALIZED_1) @@ -335,12 +349,11 @@ SUBSYSTEM_DEF(air) /datum/controller/subsystem/air/proc/setup_allturfs() var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz)) - var/list/active_turfs = src.active_turfs var/times_fired = ++src.times_fired // Clear active turfs - faster than removing every single turf in the world // one-by-one, and Initalize_Atmos only ever adds `src` back in. - active_turfs.Cut() + clear_active_turfs() for(var/thing in turfs_to_init) var/turf/T = thing @@ -348,28 +361,27 @@ SUBSYSTEM_DEF(air) continue T.Initalize_Atmos(times_fired) CHECK_TICK - - if(active_turfs.len) - var/starting_ats = active_turfs.len + var/starting_ats = get_amt_active_turfs() + if(starting_ats) sleep(world.tick_lag) var/timer = world.timeofday log_mapping("There are [starting_ats] active turfs at roundstart caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required).") - for(var/turf/T in active_turfs) + var/list/turfs_to_check = get_amt_active_turfs() + for(var/T in turfs_to_check) GLOB.active_turfs_startlist += T //now lets clear out these active turfs - var/list/turfs_to_check = active_turfs.Copy() do var/list/new_turfs_to_check = list() for(var/turf/open/T in turfs_to_check) new_turfs_to_check += T.resolve_active_graph() CHECK_TICK - - active_turfs += new_turfs_to_check + for(var/T in new_turfs_to_check) + add_to_active_extools(T) turfs_to_check = new_turfs_to_check while (turfs_to_check.len) - var/ending_ats = active_turfs.len + var/ending_ats = get_amt_active_turfs() /*for(var/thing in excited_groups) var/datum/excited_group/EG = thing //EG.self_breakdown(space_is_all_consuming = 1) @@ -445,6 +457,8 @@ SUBSYSTEM_DEF(air) return pipe_init_dirs_cache[type]["[dir]"] +/proc/get_extools_benchmarks() + #undef SSAIR_PIPENETS #undef SSAIR_ATMOSMACHINERY #undef SSAIR_ACTIVETURFS diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 4731940f41..cf7d4ba533 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -1,7 +1,8 @@ SUBSYSTEM_DEF(statpanels) name = "Stat Panels" wait = 4 - init_order = INIT_ORDER_STATPANELS //Really early so we can debug MC roundstart + init_order = INIT_ORDER_STATPANELS + priority = FIRE_PRIORITY_STATPANEL runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY var/list/currentrun = list() var/encoded_global_data @@ -9,13 +10,15 @@ SUBSYSTEM_DEF(statpanels) var/list/cached_images = list() /datum/controller/subsystem/statpanels/fire(resumed = FALSE) - if(!resumed) + if (!resumed) var/datum/map_config/cached = SSmapping.next_map_config + var/round_time = world.time - SSticker.round_start_time var/list/global_data = list( "Map: [SSmapping.config?.map_name || "Loading..."]", cached ? "Next Map: [cached.map_name]" : null, "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]", - "[SStime_track.stat_time_text]", + "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]", + "Round Time: [round_time > MIDNIGHT_ROLLOVER ? "[round(round_time/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]", "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]", "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)" ) @@ -24,96 +27,169 @@ SUBSYSTEM_DEF(statpanels) var/ETA = SSshuttle.emergency.getModeStr() if(ETA) global_data += "[ETA] [SSshuttle.emergency.getTimerStr()]" +/* Please fix + if(SSvote.mode) + var/static/list/supported = list(PLURALITY_VOTING, APPROVAL_VOTING) + global_data += "Vote active!, There is currently a vote running. Question: [SSvote.question]" + if(!(SSvote.vote_system in supported)) + global_data += ", The current vote system is not supported by statpanel rendering. Please vote manually by opening the vote popup using the action button or chat link." + return + global_data += "Time Left:, [round(SSvote.end_time - world.time)] seconds" + + global_data += "Choices:" + for(var/i in 1 to SSvote.choice_statclicks.len) + var/choice = SSvote.choice_statclicks[i] + var/ivotedforthis = FALSE + if(usr.ckey) + switch(SSvote.vote_system) + if(APPROVAL_VOTING) + ivotedforthis = SSvote.voted[usr.ckey] && (i in SSvote.voted[usr.ckey]) + if(PLURALITY_VOTING) + ivotedforthis = SSvote.voted[usr.ckey] == i + + global_data += (ivotedforthis? "\[X\]" : "\[ \]", SSvote.choice_statclicks[choice]) +*/ + encoded_global_data = url_encode(json_encode(global_data)) - - var/list/mc_data = list( - list("CPU:", world.cpu), - list("Instances:", "[num2text(world.contents.len, 10)]"), - list("World Time:", "[world.time]"), - list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"), - list("[config]:", config.stat_entry(), "\ref[config]"), - list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), - list("Master Controller:", Master.stat_entry(), "\ref[Master]"), - list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"), - list("","") - ) - for(var/ss in Master.subsystems) - var/datum/controller/subsystem/sub_system = ss - mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]") - mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", "\ref[GLOB.cameranet]") - mc_data_encoded = url_encode(json_encode(mc_data)) src.currentrun = GLOB.clients.Copy() - + mc_data_encoded = null var/list/currentrun = src.currentrun while(length(currentrun)) var/client/target = currentrun[length(currentrun)] currentrun.len-- - var/ping_str = url_encode("Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)") - var/other_str = url_encode(json_encode(target.mob.get_status_tab_items())) - target << output("[encoded_global_data];[ping_str];[other_str]", "statbrowser:update") + if(!target.statbrowser_ready) + continue + if(target.stat_tab == "Status") + var/ping_str = url_encode("Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)") + var/other_str = url_encode(json_encode(target.mob.get_status_tab_items())) + target << output("[encoded_global_data];[ping_str];[other_str]", "statbrowser:update") if(!target.holder) target << output("", "statbrowser:remove_admin_tabs") else - var/turf/eye_turf = get_turf(target.eye) - var/coord_entry = url_encode(COORD(eye_turf)) - target << output("[mc_data_encoded];[coord_entry];[url_encode(target.holder.href_token)]", "statbrowser:update_mc") - var/list/ahelp_tickets = GLOB.ahelp_tickets.stat_entry() - target << output("[url_encode(json_encode(ahelp_tickets))];", "statbrowser:update_tickets") - if(!length(GLOB.sdql2_queries)) + if(!("MC" in target.panel_tabs) || !("Tickets" in target.panel_tabs)) + target << output("[url_encode(target.holder.href_token)]", "statbrowser:add_admin_tabs") + if(target.stat_tab == "MC") + var/turf/eye_turf = get_turf(target.eye) + var/coord_entry = url_encode(COORD(eye_turf)) + if(!mc_data_encoded) + generate_mc_data() + target << output("[mc_data_encoded];[coord_entry]", "statbrowser:update_mc") + if(target.stat_tab == "Tickets") + var/list/ahelp_tickets = GLOB.ahelp_tickets.stat_entry() + target << output("[url_encode(json_encode(ahelp_tickets))];", "statbrowser:update_tickets") + if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs)) target << output("", "statbrowser:remove_sdql2") - else - var/list/sqdl2A = list() - sqdl2A[++sqdl2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj)) - var/list/sqdl2B = list() + else if(length(GLOB.sdql2_queries) && (target.stat_tab == "SDQL2" || !("SDQL2" in target.panel_tabs))) + var/list/sdql2A = list() + sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj)) + var/list/sdql2B = list() for(var/i in GLOB.sdql2_queries) var/datum/SDQL2_query/Q = i - sqdl2B = Q.generate_stat() - sqdl2A += sqdl2B - target << output(url_encode(json_encode(sqdl2A)), "statbrowser:update_sdql2") - var/list/proc_holders = target.mob.get_proc_holders() - target.spell_tabs.Cut() - for(var/phl in proc_holders) - var/list/proc_holder_list = phl - target.spell_tabs |= proc_holder_list[1] - var/proc_holders_encoded = "" - if(length(proc_holders)) - proc_holders_encoded = url_encode(json_encode(proc_holders)) - target << output("[url_encode(json_encode(target.spell_tabs))];[proc_holders_encoded]", "statbrowser:update_spells") - if(target.mob?.listed_turf) - var/mob/target_mob = target.mob - if(!target_mob.TurfAdjacent(target_mob.listed_turf)) - target << output("", "statbrowser:remove_listedturf") - target_mob.listed_turf = null - else - var/list/overrides = list() - var/list/turfitems = list() - for(var/img in target.images) - var/image/target_image = img - if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override) - continue - overrides += target_image.loc - if(!(REF(target_mob.listed_turf) in cached_images)) - target << browse_rsc(getFlatIcon(target_mob.listed_turf, no_anim = TRUE), "[REF(target_mob.listed_turf)].png") - cached_images += REF(target_mob.listed_turf) - turfitems[++turfitems.len] = list("[target_mob.listed_turf]", REF(target_mob.listed_turf), "[REF(target_mob.listed_turf)].png") - for(var/tc in target_mob.listed_turf) - var/atom/movable/turf_content = tc - if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) - continue - if(turf_content.invisibility > target_mob.see_invisible) - continue - if(turf_content in overrides) - continue - if(turf_content.IsObscured()) - continue - if(length(turfitems) < 30) // only create images for the first 30 items on the turf, for performance reasons - if(!(REF(turf_content) in cached_images)) - target << browse_rsc(getFlatIcon(turf_content, no_anim = TRUE), "[REF(turf_content)].png") - cached_images += REF(turf_content) - turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), "[REF(turf_content)].png") - else - turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content)) - turfitems = url_encode(json_encode(turfitems)) - target << output("[turfitems];", "statbrowser:update_listedturf") + sdql2B = Q.generate_stat() + sdql2A += sdql2B + target << output(url_encode(json_encode(sdql2A)), "statbrowser:update_sdql2") + if(target.mob) + var/mob/M = target.mob + if((target.stat_tab in target.spell_tabs) || !length(target.spell_tabs) && (length(M.mob_spell_list) || length(M.mind?.spell_list))) + var/list/proc_holders = M.get_proc_holders() + target.spell_tabs.Cut() + for(var/phl in proc_holders) + var/list/proc_holder_list = phl + target.spell_tabs |= proc_holder_list[1] + var/proc_holders_encoded = "" + if(length(proc_holders)) + proc_holders_encoded = url_encode(json_encode(proc_holders)) + target << output("[url_encode(json_encode(target.spell_tabs))];[proc_holders_encoded]", "statbrowser:update_spells") + if(M?.listed_turf) + var/mob/target_mob = M + if(!target_mob.TurfAdjacent(target_mob.listed_turf)) + target << output("", "statbrowser:remove_listedturf") + target_mob.listed_turf = null + else if(target.stat_tab == M?.listed_turf.name || !(M?.listed_turf.name in target.panel_tabs)) + var/list/overrides = list() + var/list/turfitems = list() + for(var/img in target.images) + var/image/target_image = img + if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override) + continue + overrides += target_image.loc + turfitems[++turfitems.len] = list("[target_mob.listed_turf]", REF(target_mob.listed_turf), icon2html(target_mob.listed_turf, target, sourceonly=TRUE)) + for(var/tc in target_mob.listed_turf) + var/atom/movable/turf_content = tc + if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) + continue + if(turf_content.invisibility > target_mob.see_invisible) + continue + if(turf_content in overrides) + continue + if(turf_content.IsObscured()) + continue + if(length(turfitems) < 30) // only create images for the first 30 items on the turf, for performance reasons + if(!(REF(turf_content) in cached_images)) + cached_images += REF(turf_content) + turf_content.RegisterSignal(turf_content, COMSIG_PARENT_QDELETING, /atom/.proc/remove_from_cache) // we reset cache if anything in it gets deleted + if(ismob(turf_content) || length(turf_content.overlays) > 2) + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), costly_icon2html(turf_content, target, sourceonly=TRUE)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content), icon2html(turf_content, target, sourceonly=TRUE)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content)) + else + turfitems[++turfitems.len] = list("[turf_content.name]", REF(turf_content)) + turfitems = url_encode(json_encode(turfitems)) + target << output("[turfitems];", "statbrowser:update_listedturf") if(MC_TICK_CHECK) return + + +/datum/controller/subsystem/statpanels/proc/generate_mc_data() + var/list/mc_data = list( + list("CPU:", world.cpu), + list("Instances:", "[num2text(world.contents.len, 10)]"), + list("World Time:", "[world.time]"), + list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"), + list("[config]:", config.stat_entry(), "\ref[config]"), + list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), + list("Master Controller:", Master.stat_entry(), "\ref[Master]"), + list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"), + list("","") + ) + for(var/ss in Master.subsystems) + var/datum/controller/subsystem/sub_system = ss + mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]") + mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", "\ref[GLOB.cameranet]") + mc_data_encoded = url_encode(json_encode(mc_data)) + +/atom/proc/remove_from_cache() + SSstatpanels.cached_images -= REF(src) + +/// verbs that send information from the browser UI +/client/verb/set_tab(tab as text|null) + set name = "Set Tab" + set hidden = TRUE + + stat_tab = tab + +/client/verb/send_tabs(tabs as text|null) + set name = "Send Tabs" + set hidden = TRUE + + panel_tabs |= tabs + +/client/verb/remove_tabs(tabs as text|null) + set name = "Remove Tabs" + set hidden = TRUE + + panel_tabs -= tabs + +/client/verb/reset_tabs() + set name = "Reset Tabs" + set hidden = TRUE + + panel_tabs = list() + +/client/verb/panel_ready() + set name = "Panel Ready" + set hidden = TRUE + + statbrowser_ready = TRUE diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 8fdeaa0f9f..db29614f20 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -718,8 +718,9 @@ GENETICS SCANNER to_chat(user, "Pressure: [round(pressure,0.01)] kPa") for(var/id in air_contents.get_gases()) - var/gas_concentration = air_contents.get_moles(id)/total_moles - to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") + if(air_contents.get_moles(id) >= 0.005) + var/gas_concentration = air_contents.get_moles(id)/total_moles + to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") to_chat(user, "Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") else diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 6552e29246..1ff056c572 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -210,7 +210,7 @@ if(!get_excited() && air.compare(enemy_air)) //testing("Active turf found. Return value of compare(): [is_active]") set_excited(TRUE) - SSair.active_turfs |= src + SSair.add_to_active_extools(src) /turf/open/proc/GetHeatCapacity() . = air.heat_capacity() diff --git a/code/game/world.dm b/code/game/world.dm index 121d51136d..42c90d8be1 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -273,12 +273,6 @@ GLOBAL_LIST(topic_status_cache) ..() /world/Del() - // memory leaks bad - var/num_deleted = 0 - for(var/datum/gas_mixture/GM) - GM.__gasmixture_unregister() - num_deleted++ - log_world("Deallocated [num_deleted] gas mixtures") shutdown_logging() // makes sure the thread is closed before end, else we terminate ..() diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index e498ff05c9..3cc597ec31 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -196,7 +196,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //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) +/datum/gas_mixture/proc/react(datum/holder) //Performs various reactions such as combustion or fusion (LOL) //Returns: 1 if any reaction took place; 0 otherwise @@ -243,7 +243,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) set_moles(path, text2num(gas[id])) archive() return 1 - +/* /datum/gas_mixture/react(datum/holder) . = NO_REACTION if(!total_moles()) @@ -291,7 +291,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) . |= reaction.react(src, holder) if (. & STOP_REACTIONS) break - +*/ //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: diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index bb65bdcaa4..7f073567c5 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -275,7 +275,7 @@ for (var/gas_id in air.get_gases()) gas_power += (gas_fusion_powers[gas_id]*air.get_moles(gas_id)) var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is - cached_scan_results[id] = instability//used for analyzer feedback + cached_scan_results["fusion"] = instability//used for analyzer feedback var/plasma = (initial_plasma-FUSION_MOLE_THRESHOLD)/(scale_factor) //We have to scale the amounts of carbon and plasma down a significant amount in order to show the chaotic dynamics we want var/carbon = (initial_carbon-FUSION_MOLE_THRESHOLD)/(scale_factor) //We also subtract out the threshold amount to make it harder for fusion to burn itself out. diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 098df67321..6c732e3ee1 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -206,7 +206,7 @@ . = other_airs + air if(null in .) stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") - return removeNullsFromList(.) + return listclearnulls(.) /datum/pipeline/proc/reconcile_air() var/list/datum/gas_mixture/GL = list() diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index d4f8547c34..755665583a 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -130,6 +130,15 @@ /// datum wrapper for client view var/datum/view_data/view_size + /// our current tab + var/stat_tab + + /// whether our browser is ready or not yet + var/statbrowser_ready = FALSE + + /// list of all tabs + var/list/panel_tabs = list() + /// list of tabs containing spells and abilities var/list/spell_tabs = list() /// list of tabs containing verbs diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index f0e4bd4a53..7c55bbfcd1 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -64,7 +64,7 @@ originMachine.visible_message("[originMachine] beeps and seems lifeless.") kill() return - vendingMachines = removeNullsFromList(vendingMachines) + vendingMachines = listclearnulls(vendingMachines) if(!vendingMachines.len) //if every machine is infected for(var/obj/machinery/vending/upriser in infectedMachines) if(prob(70) && !QDELETED(upriser)) diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index 806782a8b2..b675925aeb 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -5,7 +5,8 @@ default_color = "00FF00" blacklisted = 0 sexes = 0 - species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE) + species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR) + hair_alpha = 210 inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc diff --git a/html/changelog.html b/html/changelog.html index 4ca8081fa6..4dffb85ae0 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,6 +50,18 @@ -->
+

25 September 2020

+

Putnam3145 updated:

+ + +

24 September 2020

+

Putnam3145 updated:

+ +

22 September 2020

Arturlang updated:

GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 1c89f98a85..b5492c9d68 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -27361,3 +27361,10 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - imageadd: Mechsuits, robotics jumpsuits added to RoboDrobe timothyteakettle: - tweak: character previews should be more consistent now +2020-09-24: + Putnam3145: + - refactor: Atmos is free. +2020-09-25: + Putnam3145: + - bugfix: Removed a non-working proc that already had its functionality implemented + in another proc in the same file. diff --git a/html/changelogs/AutoChangeLog-pr-13426.yml b/html/changelogs/AutoChangeLog-pr-13426.yml new file mode 100644 index 0000000000..fcce56a747 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-13426.yml @@ -0,0 +1,4 @@ +author: "CoreFlare" +delete-after: True +changes: + - rscadd: "IPC's can have hair. Why wasn't this added earlier. Use the bald hairstyle for no hair." diff --git a/libbyond-extools.so b/libbyond-extools.so index 052a8cb037..bdae36893f 100644 Binary files a/libbyond-extools.so and b/libbyond-extools.so differ