Destroy several sources of lag (#21422)

Destroys a ton of sources of lag:

- /obj/machinery/biogenerator/interact and
/obj/machinery/computer/rdconsole/attack_hand

Both of these call REF(src) constantly on their UI update, which also
happens constantly. Death by a thousand cuts

- /obj/machinery/button/ignition/attack_hand and
/obj/machinery/button/switch/holosign/attack_hand

Sleeps rather than timers, iterating the entire machinery list rather
than just storing the IDs we need at roundstart

- /obj/machinery/telecomms/update_icon and /obj/machinery/meter/process

Calling overlay updates WAY TOO MUCH. UpdateOverlays is a significant
overhead for the server at this point and the two of these combined are
responsible for a little over 20% of updates. They now should only
update overlays when necessary rather than every tick.

- NEW! /obj/machinery/disposal/proc/update and
/obj/machinery/portable_atmospherics/hydroponics/update_icon

These two were also offenders, worse than telecomms but better than
meters. They have also been brought into line.

- /mob/living/carbon/slime

Hard-del'd if grinded into slime extract less than two minutes after
being "born". Fixed by adding TIMER_DELETE_ME flag.

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
This commit is contained in:
Wildkins
2025-10-04 11:05:07 +00:00
committed by GitHub
co-authored by Matt Atlas
parent c553281d69
commit 5fec421dae
33 changed files with 526 additions and 284 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ on:
env:
MACRO_COUNT: 0
GENDER_COUNT: 6
TO_WORLD_COUNT: 179
TO_WORLD_COUNT: 178
#These variables are filled from dependencies.sh inside the steps, DO NOT SET THEM HERE
BYOND_MAJOR: ""
+1
View File
@@ -2438,6 +2438,7 @@
#include "code\modules\hydroponics\spreading\spreading.dm"
#include "code\modules\hydroponics\spreading\spreading_growth.dm"
#include "code\modules\hydroponics\spreading\spreading_response.dm"
#include "code\modules\hydroponics\trays\_defines.dm"
#include "code\modules\hydroponics\trays\tray.dm"
#include "code\modules\hydroponics\trays\tray_process.dm"
#include "code\modules\hydroponics\trays\tray_reagents.dm"
+5 -2
View File
@@ -16,8 +16,10 @@
#define SPATIAL_GRID_CONTENTS_TYPE_CLIENTS RECURSIVE_CONTENTS_CLIENT_MOBS
///all atmos machines are stored in this channel (I'm sorry kyler)
#define SPATIAL_GRID_CONTENTS_TYPE_ATMOS "spatial_grid_contents_type_atmos"
/// everything that can be targeted
#define SPATIAL_GRID_CONTENTS_TYPE_TARGETS RECURSIVE_CONTENTS_AI_TARGETS
#define ALL_CONTENTS_OF_CELL(cell) (cell.hearing_contents | cell.client_contents | cell.atmos_contents)
#define ALL_CONTENTS_OF_CELL(cell) (cell.hearing_contents | cell.client_contents | cell.atmos_contents | cell.target_contents)
///whether movable is itself or containing something which should be in one of the spatial grid channels.
#define HAS_SPATIAL_GRID_CONTENTS(movable) (movable.spatial_grid_key)
@@ -52,4 +54,5 @@
#define GRID_CELL_REMOVE_ALL(cell, movable) \
GRID_CELL_REMOVE(cell.hearing_contents, movable) \
GRID_CELL_REMOVE(cell.client_contents, movable) \
GRID_CELL_REMOVE(cell.atmos_contents, movable)
GRID_CELL_REMOVE(cell.atmos_contents, movable) \
GRID_CELL_REMOVE(cell.target_contents, movable)
+84 -8
View File
@@ -28,6 +28,8 @@
var/list/client_contents
///every atmos machine inside this cell
var/list/atmos_contents
///every valid ai turret target inside this cell
var/list/target_contents
/datum/spatial_grid_cell/New(cell_x, cell_y, cell_z)
. = ..()
@@ -43,6 +45,7 @@
hearing_contents = dummy_list
client_contents = dummy_list
atmos_contents = dummy_list
target_contents = dummy_list
/datum/spatial_grid_cell/Destroy(force)
if(force)//the response to someone trying to qdel this is a right proper fuck you
@@ -85,7 +88,7 @@ SUBSYSTEM_DEF(spatial_grid)
///list of the spatial_grid_cell datums per z level, arranged in the order of y index then x index
var/list/grids_by_z_level = list()
///everything that spawns before us is added to this list until we initialize
var/list/waiting_to_add_by_type = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(), SPATIAL_GRID_CONTENTS_TYPE_ATMOS = list())
var/list/waiting_to_add_by_type = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(), SPATIAL_GRID_CONTENTS_TYPE_ATMOS = list(), SPATIAL_GRID_CONTENTS_TYPE_TARGETS = list())
///associative list of the form: movable.spatial_grid_key (string) -> inner list of spatial grid types for that key.
///inner lists contain contents channel types such as SPATIAL_GRID_CONTENTS_TYPE_HEARING etc.
///we use this to make adding to a cell static cost, and to save on memory
@@ -257,6 +260,12 @@ SUBSYSTEM_DEF(spatial_grid)
for(var/x_index in BOUNDING_BOX_MIN(center_x) to BOUNDING_BOX_MAX(center_x, cells_on_x_axis))
. += grid_level[row][x_index].atmos_contents
if(SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
for(var/row in BOUNDING_BOX_MIN(center_y) to BOUNDING_BOX_MAX(center_y, cells_on_y_axis))
for(var/x_index in BOUNDING_BOX_MIN(center_x) to BOUNDING_BOX_MAX(center_x, cells_on_x_axis))
. += grid_level[row][x_index].target_contents
return .
///get the grid cell encomapassing targets coordinates
@@ -378,6 +387,11 @@ SUBSYSTEM_DEF(spatial_grid)
GRID_CELL_SET(intersecting_cell.hearing_contents, new_target.important_recursive_contents[SPATIAL_GRID_CONTENTS_TYPE_HEARING])
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_HEARING), new_target_contents[SPATIAL_GRID_CONTENTS_TYPE_HEARING])
if(SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
var/list/new_target_contents = new_target.important_recursive_contents
GRID_CELL_SET(intersecting_cell.target_contents, new_target.important_recursive_contents[SPATIAL_GRID_CONTENTS_TYPE_TARGETS])
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_TARGETS), new_target_contents[SPATIAL_GRID_CONTENTS_TYPE_TARGETS])
if(SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
GRID_CELL_SET(intersecting_cell.atmos_contents, new_target)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_ATMOS), new_target)
@@ -408,6 +422,11 @@ SUBSYSTEM_DEF(spatial_grid)
GRID_CELL_SET(intersecting_cell.hearing_contents, new_target.important_recursive_contents[SPATIAL_GRID_CONTENTS_TYPE_HEARING])
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_HEARING), new_target_contents[SPATIAL_GRID_CONTENTS_TYPE_HEARING])
if(SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
var/list/new_target_contents = new_target.important_recursive_contents
GRID_CELL_SET(intersecting_cell.target_contents, new_target.important_recursive_contents[SPATIAL_GRID_CONTENTS_TYPE_TARGETS])
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_TARGETS), new_target_contents[SPATIAL_GRID_CONTENTS_TYPE_TARGETS])
if(SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
GRID_CELL_SET(intersecting_cell.atmos_contents, new_target)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_ATMOS), new_target)
@@ -447,6 +466,11 @@ SUBSYSTEM_DEF(spatial_grid)
GRID_CELL_REMOVE(intersecting_cell.hearing_contents, old_target_contents)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(type), old_target_contents)
if(SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
var/list/old_target_contents = old_target.important_recursive_contents?[type] || old_target
GRID_CELL_REMOVE(intersecting_cell.target_contents, old_target_contents)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(type), old_target_contents)
if(SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
GRID_CELL_REMOVE(intersecting_cell.atmos_contents, old_target)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(type), old_target)
@@ -479,6 +503,11 @@ SUBSYSTEM_DEF(spatial_grid)
GRID_CELL_REMOVE(intersecting_cell.hearing_contents, old_target_contents)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(exclusive_type), old_target_contents)
if(SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
var/list/old_target_contents = old_target.important_recursive_contents?[exclusive_type] || old_target
GRID_CELL_REMOVE(intersecting_cell.target_contents, old_target_contents)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(exclusive_type), old_target_contents)
if(SPATIAL_GRID_CONTENTS_TYPE_ATMOS)
GRID_CELL_REMOVE(intersecting_cell.atmos_contents, old_target)
SEND_SIGNAL(intersecting_cell, SPATIAL_GRID_CELL_EXITED(exclusive_type), old_target)
@@ -521,6 +550,12 @@ SUBSYSTEM_DEF(spatial_grid)
if(movable_to_check in cell.hearing_contents)
contents = "hearing"
if(movable_to_check in cell.target_contents)
if(length(contents) > 0)
contents = "[contents], target"
else
contents = "target"
if(movable_to_check in cell.client_contents)
if(length(contents) > 0)
contents = "[contents], client"
@@ -566,7 +601,7 @@ SUBSYSTEM_DEF(spatial_grid)
remove_from_pre_init_queue(to_remove)//the spatial grid doesnt exist yet, so just take it out of the queue
return
#ifdef UNIT_TESTS
#ifdef UNIT_TEST
if(untracked_movable_error(to_remove))
find_hanging_cell_refs_for_movable(to_remove, remove_from_cells=FALSE) //dont remove from cells because we should be able to see 2 errors
return
@@ -604,7 +639,7 @@ SUBSYSTEM_DEF(spatial_grid)
for(var/list/z_level_grid as anything in grids_by_z_level)
for(var/list/cell_row as anything in z_level_grid)
for(var/datum/spatial_grid_cell/cell as anything in cell_row)
if(to_remove in (cell.hearing_contents | cell.client_contents | cell.atmos_contents))
if(to_remove in (cell.hearing_contents | cell.client_contents | cell.atmos_contents | cell.target_contents))
containing_cells += cell
if(remove_from_cells)
force_remove_from_cell(to_remove, cell)
@@ -677,14 +712,17 @@ SUBSYSTEM_DEF(spatial_grid)
var/raw_clients = 0
var/raw_hearables = 0
var/raw_atmos = 0
var/raw_targets = 0
var/cells_with_clients = 0
var/cells_with_hearables = 0
var/cells_with_atmos = 0
var/cells_with_targets = 0
var/list/client_list = list()
var/list/hearable_list = list()
var/list/atmos_list = list()
var/list/target_list = list()
var/x_cell_count = world.maxx / SPATIAL_GRID_CELLSIZE
var/y_cell_count = world.maxy / SPATIAL_GRID_CELLSIZE
@@ -694,6 +732,7 @@ SUBSYSTEM_DEF(spatial_grid)
var/average_clients_per_cell = 0
var/average_hearables_per_cell = 0
var/average_atmos_mech_per_call = 0
var/average_targets_per_cell
var/hearable_min_x = x_cell_count
var/hearable_max_x = 1
@@ -707,6 +746,12 @@ SUBSYSTEM_DEF(spatial_grid)
var/client_min_y = y_cell_count
var/client_max_y = 1
var/target_min_x = x_cell_count
var/target_max_x = 1
var/target_min_y = y_cell_count
var/target_max_y = 1
var/atmos_min_x = x_cell_count
var/atmos_max_x = 1
@@ -727,7 +772,7 @@ SUBSYSTEM_DEF(spatial_grid)
for(var/client_to_insert in 0 to insert_clients)
var/turf/random_turf = pick(turfs)
var/mob/fake_client = new()
fake_client.important_recursive_contents = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(fake_client))
fake_client.important_recursive_contents = list(SPATIAL_GRID_CONTENTS_TYPE_HEARING = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_CLIENTS = list(fake_client), SPATIAL_GRID_CONTENTS_TYPE_TARGETS = list(fake_client))
fake_client.forceMove(random_turf)
inserted_clients += fake_client
@@ -737,10 +782,12 @@ SUBSYSTEM_DEF(spatial_grid)
var/client_length = length(cell.client_contents)
var/hearable_length = length(cell.hearing_contents)
var/atmos_length = length(cell.atmos_contents)
var/target_length = length(cell.target_contents)
raw_clients += client_length
raw_hearables += hearable_length
raw_atmos += atmos_length
raw_targets += target_length
if(client_length)
cells_with_clients++
@@ -776,6 +823,23 @@ SUBSYSTEM_DEF(spatial_grid)
if(cell.cell_y > hearable_max_y)
hearable_max_y = cell.cell_y
if(target_length)
cells_with_targets++
target_list += cell.target_contents
if(cell.cell_x < hearable_min_x)
target_min_x = cell.cell_x
if(cell.cell_x > hearable_max_x)
target_max_x = cell.cell_x
if(cell.cell_y < hearable_min_y)
target_min_y = cell.cell_y
if(cell.cell_y > hearable_max_y)
target_max_y = cell.cell_y
if(raw_atmos)
cells_with_atmos++
@@ -796,10 +860,12 @@ SUBSYSTEM_DEF(spatial_grid)
var/total_client_distance = 0
var/total_hearable_distance = 0
var/total_atmos_distance = 0
var/total_target_distance = 0
var/average_client_distance = 0
var/average_hearable_distance = 0
var/average_atmos_distance = 0
var/average_target_distance = 0
for(var/hearable in hearable_list)//n^2 btw
for(var/other_hearable in hearable_list)
@@ -813,6 +879,12 @@ SUBSYSTEM_DEF(spatial_grid)
continue
total_client_distance += get_dist(client, other_client)
for(var/target in target_list)//n^2 btw
for(var/other_target in target_list)
if(target == other_target)
continue
total_target_distance += get_dist(target, other_target)
for(var/atmos in atmos_list)//n^2 btw
for(var/other_atmos in atmos_list)
if(atmos == other_atmos)
@@ -825,24 +897,28 @@ SUBSYSTEM_DEF(spatial_grid)
average_client_distance = total_client_distance / length(client_list)
if(length(atmos_list))
average_atmos_distance = total_atmos_distance / length(atmos_list)
if(length(target_list))
average_target_distance = total_target_distance / length(target_list)
average_clients_per_cell = raw_clients / total_cells
average_hearables_per_cell = raw_hearables / total_cells
average_atmos_mech_per_call = raw_atmos / total_cells
average_targets_per_cell = raw_targets / total_cells
for(var/mob/inserted_client as anything in inserted_clients)
qdel(inserted_client)
message_admins("on z level [z] there are [raw_clients] clients ([insert_clients] of whom are fakes inserted to random station turfs)\
, [raw_hearables] hearables, and [raw_atmos] atmos machines. all of whom are inside the bounding box given by \
, [raw_hearables] hearables, [raw_targets] targets, and [raw_atmos] atmos machines. all of whom are inside the bounding box given by \
clients: ([client_min_x], [client_min_y]) x ([client_max_x], [client_max_y]), \
hearables: ([hearable_min_x], [hearable_min_y]) x ([hearable_max_x], [hearable_max_y]) \
targets: ([target_min_x], [target_min_y] x [target_max_x], [target_max_y]) \
and atmos machines: ([atmos_min_x], [atmos_min_y]) x ([atmos_max_x], [atmos_max_y]), \
on average there are [average_clients_per_cell] clients per cell, [average_hearables_per_cell] hearables per cell, \
and [average_atmos_mech_per_call] per cell, \
[cells_with_clients] cells have clients, [cells_with_hearables] have hearables, and [cells_with_atmos] have atmos machines \
[average_targets_per_cell] targets per cell, and [average_atmos_mech_per_call] atmos machines per cell, \
[cells_with_clients] cells have clients, [cells_with_hearables] have hearables, [cells_with_targets] have targets, and [cells_with_atmos] have atmos machines \
the average client distance is: [average_client_distance], the average hearable_distance is [average_hearable_distance], \
and the average atmos distance is [average_atmos_distance] ")
the average target distance is [average_target_distance], and the average atmos distance is [average_atmos_distance] ")
#undef BOUNDING_BOX_MAX
#undef BOUNDING_BOX_MIN
+19 -15
View File
@@ -580,7 +580,7 @@
LAZYINITLIST(recursive_contents[channel])
recursive_contents[channel] -= gone.important_recursive_contents[channel]
switch(channel)
if(RECURSIVE_CONTENTS_CLIENT_MOBS, RECURSIVE_CONTENTS_HEARING_SENSITIVE)
if(RECURSIVE_CONTENTS_CLIENT_MOBS, RECURSIVE_CONTENTS_HEARING_SENSITIVE,RECURSIVE_CONTENTS_AI_TARGETS)
if(!length(recursive_contents[channel]))
// This relies on a nice property of the linked recursive and gridmap types
// They're defined in relation to each other, so they have the same value
@@ -601,7 +601,7 @@
var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity
LAZYINITLIST(recursive_contents[channel])
switch(channel)
if(RECURSIVE_CONTENTS_CLIENT_MOBS, RECURSIVE_CONTENTS_HEARING_SENSITIVE)
if(RECURSIVE_CONTENTS_CLIENT_MOBS, RECURSIVE_CONTENTS_HEARING_SENSITIVE,RECURSIVE_CONTENTS_AI_TARGETS)
if(!length(recursive_contents[channel]))
SSspatial_grid.add_grid_awareness(location, channel)
recursive_contents[channel] |= arrived.important_recursive_contents[channel]
@@ -701,25 +701,29 @@
// This proc adds atom/movables to the AI targetable list, i.e. things that the AI (turrets, hostile animals) will attempt to target
/atom/movable/proc/add_to_target_grid()
for (var/atom/movable/location as anything in get_nested_locs(src) + src)
LAZYADDASSOCLIST(location.important_recursive_contents, RECURSIVE_CONTENTS_AI_TARGETS, src)
LAZYINITLIST(location.important_recursive_contents)
var/list/recursive_contents = location.important_recursive_contents
if(!length(recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS]))
SSspatial_grid.add_grid_awareness(location, SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
LAZYINITLIST(recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS])
recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS] |= src
var/turf/our_turf = get_turf(src)
if(our_turf && SSspatial_grid.initialized)
SSspatial_grid.add_grid_awareness(src, RECURSIVE_CONTENTS_AI_TARGETS)
SSspatial_grid.add_grid_membership(src, our_turf, RECURSIVE_CONTENTS_AI_TARGETS)
else if(our_turf && !SSspatial_grid.initialized)//SSspatial_grid isnt init'd yet, add ourselves to the queue
SSspatial_grid.enter_pre_init_queue(src, RECURSIVE_CONTENTS_AI_TARGETS)
SSspatial_grid.add_grid_membership(src, our_turf, SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
/atom/movable/proc/clear_from_target_grid()
var/turf/our_turf = get_turf(src)
if(our_turf && SSspatial_grid.initialized)
SSspatial_grid.exit_cell(src, our_turf, RECURSIVE_CONTENTS_AI_TARGETS)
else if(our_turf && !SSspatial_grid.initialized)
SSspatial_grid.remove_from_pre_init_queue(src, RECURSIVE_CONTENTS_AI_TARGETS)
SSspatial_grid.remove_grid_membership(src, our_turf, SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
for(var/atom/movable/location as anything in get_nested_locs(src) + src)
LAZYREMOVEASSOC(location.important_recursive_contents, RECURSIVE_CONTENTS_AI_TARGETS, src)
for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src)
LAZYINITLIST(movable_loc.important_recursive_contents)
var/list/recursive_contents = movable_loc.important_recursive_contents // blue hedgehog velocity
LAZYINITLIST(recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS])
recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS] -= src
if(!length(recursive_contents[RECURSIVE_CONTENTS_AI_TARGETS]))
SSspatial_grid.remove_grid_awareness(movable_loc, SPATIAL_GRID_CONTENTS_TYPE_TARGETS)
ASSOC_UNSETEMPTY(recursive_contents, RECURSIVE_CONTENTS_AI_TARGETS)
UNSETEMPTY(movable_loc.important_recursive_contents)
/atom/movable/proc/do_simple_ranged_interaction(var/mob/user)
return FALSE
+32 -27
View File
@@ -38,22 +38,20 @@
if (!target)
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
/obj/machinery/meter/process()
ClearOverlays()
if(!target)
AddOverlays("pressure_off")
AddOverlays("buttons-x")
return FALSE
if(stat & (BROKEN|NOPOWER))
AddOverlays("pressure_off")
return FALSE
/obj/machinery/meter/update_icon()
var/list/new_overlays = get_rebuild_overlays()
if(LAZYLEN(new_overlays))
ClearOverlays()
AddOverlays(new_overlays)
/obj/machinery/meter/proc/get_rebuild_overlays()
if (!target)
return list("pressure_off", "buttons_x")
if (stat & (BROKEN|NOPOWER))
return list("pressure_off")
var/datum/gas_mixture/environment = target.return_air()
if(!environment)
AddOverlays("buttons_x")
AddOverlays("pressure0")
return FALSE
return list("pressure0", "buttons_x")
var/button_overlay_name
var/atmos_overlay_name
@@ -76,19 +74,16 @@
else
atmos_overlay_name = "pressure4"
button_overlay = overlay_image(icon, button_overlay_name)
atmos_overlay = overlay_image(icon, atmos_overlay_name)
button_emissive = emissive_appearance(icon, button_overlay_name)
atmos_emissive = emissive_appearance(icon, atmos_overlay_name)
if (!button_overlay || button_overlay.icon_state != button_overlay_name)
button_overlay = overlay_image(icon, button_overlay_name)
button_emissive = emissive_appearance(icon, button_overlay_name)
. = TRUE
var/env_temperature = environment.temperature
var/temp_color
var/temp_color = COLOR_GRAY
if(env_pressure == 0 || env_temperature == 0)
temp_color = COLOR_GRAY
else
if(env_pressure != 0 && env_temperature != 0)
switch(env_temperature)
if((BODYTEMP_HEAT_DAMAGE_LIMIT + 360) to INFINITY)
temp_color = COLOR_RED
@@ -105,13 +100,23 @@
else
temp_color = COLOR_VIOLET
if(atmos_overlay.color != temp_color)
if (!atmos_overlay || atmos_overlay.icon_state != atmos_overlay_name || atmos_overlay.color != temp_color)
atmos_overlay = overlay_image(icon, atmos_overlay_name)
atmos_emissive = emissive_appearance(icon, atmos_overlay_name)
atmos_overlay.color = temp_color
. = TRUE
AddOverlays(button_overlay)
AddOverlays(atmos_overlay)
AddOverlays(button_emissive)
AddOverlays(atmos_emissive)
if (.)
return list(button_overlay, button_emissive, atmos_overlay, atmos_emissive)
/obj/machinery/meter/process()
update_icon()
if (!target || (stat & (BROKEN|NOPOWER)))
return FALSE
var/datum/gas_mixture/environment = target.return_air()
if(!environment)
return FALSE
var/env_pressure = environment.return_pressure()
if(frequency)
var/datum/radio_frequency/radio_connection = SSradio.return_frequency(frequency)
+8 -6
View File
@@ -13,6 +13,7 @@
var/build_eff = 1
var/eat_eff = 1
var/capacity = 100
var/ref_for_ui
component_types = list(
/obj/item/circuitboard/biogenerator,
@@ -536,6 +537,7 @@ EMAG/ILLEGAL
R.my_atom = src
beaker = new /obj/item/reagent_containers/glass/bottle(src)
update_icon()
ref_for_ui = "[REF(src)]"
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
@@ -618,8 +620,8 @@ EMAG/ILLEGAL
if("menu")
if (beaker)
dat += "<table style='width:100%'><tr><td colspan='6'><H2>Commands</H2></td></tr>"
dat += "<tr><td colspan='2'><A href='byond://?src=[REF(src)];action=activate'>Activate Biogenerator</A></td></tr>"
dat += "<tr><td colspan='2'><A href='byond://?src=[REF(src)];action=detach'>Detach Container</A><BR></td></tr>"
dat += "<tr><td colspan='2'><A href='byond://?src=[ref_for_ui];action=activate'>Activate Biogenerator</A></td></tr>"
dat += "<tr><td colspan='2'><A href='byond://?src=[ref_for_ui];action=detach'>Detach Container</A><BR></td></tr>"
dat += "<tr><td colspan='2'>Name</td><td colspan='2'>Cost</td><td colspan='4'>Production Amount</td></tr>"
var/lastclass = "Commands"
@@ -639,7 +641,7 @@ EMAG/ILLEGAL
if(num*round(current_recipe.cost/build_eff) > points)
dat += "<div class='no-build inline'>([fakenum][num])</div>"
else
dat += "<A href='byond://?src=[REF(src)];action=create;itemtype=[current_recipe.type];count=[num]'>([fakenum][num])</A>"
dat += "<A href='byond://?src=[ref_for_ui];action=create;itemtype=[current_recipe.type];count=[num]'>([fakenum][num])</A>"
dat += "</td>"
dat += "</tr>"
@@ -649,13 +651,13 @@ EMAG/ILLEGAL
dat += "<BR><FONT COLOR=red>No beaker inside. Please insert a beaker.</FONT><BR>"
if("nopoints")
dat += "You do not have biomass to create products.<BR>Please put growns into the reactor and activate it.<BR>"
dat += "<A href='byond://?src=[REF(src)];action=menu'>Return to menu</A>"
dat += "<A href='byond://?src=[ref_for_ui];action=menu'>Return to menu</A>"
if("complete")
dat += "Operation complete.<BR>"
dat += "<A href='byond://?src=[REF(src)];action=menu'>Return to menu</A>"
dat += "<A href='byond://?src=[ref_for_ui];action=menu'>Return to menu</A>"
if("void")
dat += "<FONT COLOR=red>Error: No growns inside.</FONT><BR>Please put growns into the reactor.<BR>"
dat += "<A href='byond://?src=[REF(src)];action=menu'>Return to menu</A>"
dat += "<A href='byond://?src=[ref_for_ui];action=menu'>Return to menu</A>"
dat += "</body></html>"
var/datum/browser/biogen_win = new(user, "biogenerator", "Biogenerator", 450, 500)
+11 -7
View File
@@ -7,6 +7,7 @@
var/id = null
var/active = 0
var/operating = 0
var/active_time = 1 SECOND
anchored = 1.0
idle_power_usage = 2
active_power_usage = 4
@@ -38,19 +39,22 @@
activate(user)
intent_message(BUTTON_FLICK, 5)
/obj/machinery/button/proc/deactivate(mob/living/user)
active = FALSE
update_icon()
operating = FALSE
/obj/machinery/button/proc/activate(mob/living/user)
if(operating || !istype(wifi_sender))
return
return FALSE
operating = 1
active = 1
operating = TRUE
active = TRUE
use_power_oneoff(5)
update_icon()
wifi_sender.activate(user)
sleep(10)
active = 0
update_icon()
operating = 0
addtimer(CALLBACK(src, PROC_REF(deactivate)), active_time, TIMER_DELETE_ME)
return TRUE
/obj/machinery/button/update_icon()
if(active)
+3
View File
@@ -17,12 +17,15 @@
detectTime = world.time // start the clock
if (!(target in motionTargets) && !QDELING(target))
motionTargets += target
RegisterSignal(target, COMSIG_QDELETING, PROC_REF(lostTarget))
return TRUE
/obj/machinery/camera/proc/lostTarget(var/mob/target)
SIGNAL_HANDLER
if (target in motionTargets)
motionTargets -= target
UnregisterSignal(target, COMSIG_QDELETING)
if (motionTargets.len == 0)
cancelAlarm()
+15 -5
View File
@@ -66,18 +66,28 @@
name = "holosign switch"
desc = "A remote control switch for a holosign."
icon_state = "light0"
var/list/datum/weakref/linked_signs
/obj/machinery/button/switch/holosign/Initialize()
..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/button/switch/holosign/LateInitialize()
. = ..()
for(var/obj/machinery/holosign/H in SSmachinery.machinery)
if(H.id == id)
LAZYADD(linked_signs, WEAKREF(H))
/obj/machinery/button/switch/holosign/attack_hand(mob/user as mob)
if(..())
return
add_fingerprint(user)
use_power_oneoff(5)
active = !active
update_icon()
for(var/obj/machinery/holosign/M in SSmachinery.machinery)
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/holosign, toggle))
for(var/datum/weakref/W in linked_signs)
var/obj/machinery/holosign/H = W.resolve()
if(!isnull(H))
INVOKE_ASYNC(H, TYPE_PROC_REF(/obj/machinery/holosign, toggle))
return
+26 -19
View File
@@ -146,28 +146,35 @@
/obj/machinery/button/ignition
name = "ignition switch"
desc = "A remote control switch for a mounted igniter."
active_time = 5 SECONDS
var/list/datum/weakref/linked_sparkers
var/list/datum/weakref/linked_igniters
/obj/machinery/button/ignition/attack_hand(mob/user as mob)
/obj/machinery/button/ignition/Initialize()
..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/button/ignition/LateInitialize()
. = ..()
for (var/obj/machinery/M in SSmachinery.machinery)
var/obj/machinery/sparker/S = M
if (istype(S) && S.id == id)
LAZYADD(linked_sparkers, WEAKREF(S))
else
var/obj/machinery/igniter/I = M
if (istype(I) && I.id == id)
LAZYADD(linked_igniters, WEAKREF(I))
/obj/machinery/button/ignition/activate(mob/living/user)
if(..())
return
use_power_oneoff(5)
for (var/datum/weakref/W in linked_sparkers)
var/obj/machinery/sparker/S = W.resolve()
if(!isnull(S))
INVOKE_ASYNC(S, TYPE_PROC_REF(/obj/machinery/sparker, ignite))
active = 1
icon_state = "launcheract"
for(var/obj/machinery/sparker/M in SSmachinery.machinery)
if (M.id == id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/sparker, ignite))
for(var/obj/machinery/igniter/M in SSmachinery.machinery)
if(M.id == id)
M.ignite()
sleep(50)
icon_state = "launcherbtt"
active = 0
return
for (var/datum/weakref/W in linked_igniters)
var/obj/machinery/igniter/I = W.resolve()
if(!isnull(I))
I.ignite()
@@ -152,8 +152,9 @@
AddOverlays("[icon_state]_panel")
/obj/machinery/telecomms/process()
update_icon()
if(!use_power) return PROCESS_KILL
if(!use_power)
update_icon()
return PROCESS_KILL
if(!operable(EMPED))
toggle_power(additional_flags = EMPED)
return PROCESS_KILL
+21 -20
View File
@@ -207,28 +207,29 @@
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents)
spawn(rand(20,60))
loc = exit_vent
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
spawn(travel_time)
if(!QDELETED(src))
loc = exit_vent
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
spawn(travel_time)
if(!QDELETED(src))
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
if(prob(50))
visible_message(SPAN_NOTICE("You hear something squeezing through the ventilation ducts."), range = 2)
sleep(travel_time)
if(prob(50))
visible_message(SPAN_NOTICE("You hear something squeezing through the ventilation ducts."), range = 2)
sleep(travel_time)
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
loc = exit_vent.loc
entry_vent = null
var/area/new_area = get_area(loc)
if(new_area)
new_area.Entered(src)
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
loc = exit_vent.loc
entry_vent = null
var/area/new_area = get_area(loc)
if(new_area)
new_area.Entered(src)
else
entry_vent = null
else if(prob(25) && isturf(loc))
+3
View File
@@ -531,6 +531,9 @@ GLOBAL_LIST_INIT(localhost_addresses, list(
holder.owner = null
GLOB.staff -= src
if(mob)
mob.clear_important_client_contents()
SSping.currentrun -= src
QDEL_NULL(tooltips)
@@ -400,6 +400,7 @@
name = "drill head"
desc = "A replaceable drill head usually used in exosuit drills."
icon_state = "drill_head"
var/obj/item/mecha_equipment/drill/mounted_drill
/obj/item/material/drill_head/condition_hints(mob/user, distance, is_adjacent)
. += ..()
@@ -419,6 +420,12 @@
/obj/item/material/drill_head/Initialize(newloc, material_key)
. = ..()
durability = 2 * material.integrity
if(istype(newloc, /obj/item/mecha_equipment/drill))
mounted_drill = newloc
/obj/item/material/drill_head/Destroy()
mounted_drill = null
. = ..()
/obj/item/material/drill_head/proc/get_durability_percentage()
return (durability * 100) / (2 * material.integrity)
@@ -445,6 +452,10 @@
. = ..()
drill_head = new /obj/item/material/drill_head(src, DEFAULT_WALL_MATERIAL)//You start with a basic steel head
/obj/item/mecha_equipment/drill/Destroy()
QDEL_NULL(drill_head)
. = ..()
/obj/item/mecha_equipment/drill/attack_self(var/mob/user)
. = ..()
if(.)
@@ -469,8 +480,10 @@
if(drill_head)
owner.visible_message(SPAN_NOTICE("\The [owner] detaches the [drill_head] mounted on the [src]."))
drill_head.forceMove(owner.loc)
drill_head.mounted_drill = null
DH.forceMove(src)
drill_head = DH
drill_head.mounted_drill = src
owner.visible_message(SPAN_NOTICE("\The [owner] mounts the [drill_head] on the [src]."))
return
@@ -0,0 +1,10 @@
#define TRAY_LOW_HEALTH BITFLAG(0)
#define TRAY_LOW_WATER BITFLAG(1)
#define TRAY_LOW_NUT BITFLAG(2)
#define TRAY_ALERT BITFLAG(3)
#define TRAY_STASIS BITFLAG(4)
#define TRAY_COVERED BITFLAG(5)
#define TRAY_PLANT_DEAD BITFLAG(6)
#define TRAY_PLANT_LIVE BITFLAG(7)
#define TRAY_PLANT_HARVEST BITFLAG(8)
#define TRAY_HARVEST BITFLAG(9)
+7
View File
@@ -80,6 +80,11 @@
/// Seed details/line data.
var/datum/seed/seed = null // The currently planted seed
/// BITFLAG of TRAY_ defines, set in update_icon. Used to determine if we need to update.
var/icon_status = 0
/// Currently displayed growth stage, set in update_icon.
var/displayed_stage
/**
Reagent information for process(), consider moving this to a controller along
@@ -308,6 +313,7 @@
if(GET_SEED_TRAIT(seed, TRAIT_SPOROUS) && !closed_system)
seed.create_spores(get_turf(src))
visible_message(SPAN_DANGER("\The [src] releases its spores!"))
update_icon()
/// Process reagents being input into the tray.
/obj/machinery/portable_atmospherics/hydroponics/proc/process_reagents()
@@ -482,6 +488,7 @@
else
health = 0
dead = FALSE
update_icon()
mutation_level = max(0,min(mutation_level,100))
nutrilevel = max(0,min(nutrilevel,10))
@@ -1,3 +1,87 @@
/obj/machinery/portable_atmospherics/hydroponics/proc/need_update_icon()
. = 0
var/overlay_stage
if (seed)
if (mechanical && health <= (GET_SEED_TRAIT(seed, TRAIT_ENDURANCE) / 2))
. |= TRAY_LOW_HEALTH
if (dead)
. |= TRAY_PLANT_DEAD
else
. |= TRAY_PLANT_LIVE
if (harvest)
. |= TRAY_PLANT_HARVEST
if (. & TRAY_PLANT_LIVE)
if(!seed.growth_stages)
seed.update_growth_stages()
overlay_stage = 1
if(age >= GET_SEED_TRAIT(seed, TRAIT_MATURATION))
overlay_stage = seed.growth_stages
else
var/maturation = GET_SEED_TRAIT(seed, TRAIT_MATURATION)/seed.growth_stages
if(maturation < 1)
maturation = 1
overlay_stage = maturation ? max(1,round(age/maturation)) : 1
if (mechanical)
if (waterlevel <= 10)
. |= TRAY_LOW_WATER
if (nutrilevel <= 2)
. |= TRAY_LOW_NUT
if (pestlevel >= 5 || toxins >= 40)
. |= TRAY_ALERT
if (harvest)
. |= TRAY_HARVEST
if (stasis)
. |= TRAY_STASIS
if (closed_system)
. |= TRAY_COVERED
if (. != icon_status)
do_update_icon(., overlay_stage)
/obj/machinery/portable_atmospherics/hydroponics/proc/do_update_icon(var/needed_state, var/plant_stage)
. = list()
if (needed_state & TRAY_PLANT_DEAD)
var/ikey = "[GET_SEED_TRAIT(seed, TRAIT_PLANT_ICON)]"
var/image/dead_overlay = SSplants.plant_icon_cache["[ikey]"]
if(!dead_overlay)
dead_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
dead_overlay.color = DEAD_PLANT_COLOUR
. += dead_overlay
else if (needed_state & TRAY_PLANT_LIVE)
var/image/plant_overlay = seed.get_icon(plant_stage ? plant_stage : displayed_stage)
. += plant_overlay
if (plant_stage) displayed_stage = plant_stage
if (needed_state & TRAY_PLANT_HARVEST)
var/ikey = "[GET_SEED_TRAIT(seed, TRAIT_PRODUCT_ICON)]"
var/image/harvest_overlay = SSplants.plant_icon_cache["product-[ikey]-[GET_SEED_TRAIT(seed, TRAIT_PLANT_COLOUR)]"]
if(!harvest_overlay)
harvest_overlay = image('icons/obj/hydroponics_products.dmi', "[ikey]")
harvest_overlay.color = GET_SEED_TRAIT(seed, TRAIT_PRODUCT_COLOUR)
SSplants.plant_icon_cache["product-[ikey]-[GET_SEED_TRAIT(seed, TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay
. += harvest_overlay
if (mechanical)
if (needed_state & TRAY_LOW_HEALTH)
. += "over_lowhealth3"
if (needed_state & TRAY_LOW_WATER)
. += "over_lowwater3"
if (needed_state & TRAY_LOW_NUT)
. += "over_lownutri3"
if (needed_state & TRAY_ALERT)
. += "over_alert3"
if (needed_state & TRAY_HARVEST)
. += "over_harvest3"
if (needed_state & TRAY_STASIS)
. += "stasis"
if (needed_state & TRAY_COVERED)
. += "hydrocover"
SetOverlays(.)
icon_status = .
/// Refreshes the icon and sets the luminosity.
/obj/machinery/portable_atmospherics/hydroponics/update_icon()
// Update name.
@@ -12,62 +96,7 @@
if(labelled)
name += " ([labelled])"
ClearOverlays()
// Updates the plant overlay.
if(!isnull(seed))
if(mechanical && health <= (GET_SEED_TRAIT(seed, TRAIT_ENDURANCE) / 2))
AddOverlays("over_lowhealth3")
if(dead)
var/ikey = "[GET_SEED_TRAIT(seed, TRAIT_PLANT_ICON)]-dead"
var/image/dead_overlay = SSplants.plant_icon_cache["[ikey]"]
if(!dead_overlay)
dead_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
dead_overlay.color = DEAD_PLANT_COLOUR
AddOverlays(dead_overlay)
else
if(!seed.growth_stages)
seed.update_growth_stages()
if(!seed.growth_stages)
to_world(SPAN_DANGER("Seed type [GET_SEED_TRAIT(seed, TRAIT_PLANT_ICON)] cannot find a growth stage value."))
return
var/overlay_stage = 1
if(age >= GET_SEED_TRAIT(seed, TRAIT_MATURATION))
overlay_stage = seed.growth_stages
else
var/maturation = GET_SEED_TRAIT(seed, TRAIT_MATURATION)/seed.growth_stages
if(maturation < 1)
maturation = 1
overlay_stage = maturation ? max(1,round(age/maturation)) : 1
var/image/plant_overlay = seed.get_icon(overlay_stage)
AddOverlays(plant_overlay)
if(harvest && overlay_stage == seed.growth_stages)
var/ikey = "[GET_SEED_TRAIT(seed, TRAIT_PRODUCT_ICON)]"
var/image/harvest_overlay = SSplants.plant_icon_cache["product-[ikey]-[GET_SEED_TRAIT(seed, TRAIT_PLANT_COLOUR)]"]
if(!harvest_overlay)
harvest_overlay = image('icons/obj/hydroponics_products.dmi', "[ikey]")
harvest_overlay.color = GET_SEED_TRAIT(seed, TRAIT_PRODUCT_COLOUR)
SSplants.plant_icon_cache["product-[ikey]-[GET_SEED_TRAIT(seed, TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay
AddOverlays(harvest_overlay)
//Draw the cover.
if(closed_system)
AddOverlays("hydrocover")
//Updated the various alert icons.
if(mechanical)
if(waterlevel <= 10)
AddOverlays("over_lowwater3")
if(nutrilevel <= 2)
AddOverlays("over_lownutri3")
if(pestlevel >= 5 || toxins >= 40) // Hydroponics trays no longer face issues with weeds. GET OUTTA HERE.
AddOverlays("over_alert3")
if(harvest)
AddOverlays("over_harvest3")
if(stasis)
AddOverlays("stasis")
need_update_icon()
// Apply density and opacity if a large plant is growing in the plot. Exempt mechanical trays from density alterations, since they're always dense.
if(seed && GET_SEED_TRAIT(seed, TRAIT_LARGE))
@@ -96,3 +125,13 @@
set_light(0)
last_biolum = null
return
#undef TRAY_LOW_HEALTH
#undef TRAY_LOW_WATER
#undef TRAY_LOW_NUT
#undef TRAY_ALERT
#undef TRAY_STASIS
#undef TRAY_COVERED
#undef TRAY_PLANT_DEAD
#undef TRAY_PLANT_LIVE
#undef TRAY_HARVEST
@@ -167,7 +167,7 @@
M.mutation_chance = clamp(mutation_chance + rand(-3, 3), 0, 100)
babies += M
M.set_content(TRUE)
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob/living/carbon/slime, set_content), FALSE), 1200) // You get two minutes of safety
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob/living/carbon/slime, set_content), FALSE), 1200, TIMER_DELETE_ME) // You get two minutes of safety
feedback_add_details("slime_babies_born", "slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/carbon/slime/new_slime = pick(babies)
-1
View File
@@ -951,7 +951,6 @@ default behaviour is:
qdel(M)
QDEL_NULL(reagents)
clear_from_target_grid()
if(auras)
for(var/a in auras)
+2 -2
View File
@@ -97,8 +97,8 @@
winset(src, null, "mainwindow.macro=macro hotkey_toggle.is-checked=false input.focus=true")
MOB_STOP_THINKING(src)
clear_important_client_contents(client)
enable_client_mobs_in_contents(client)
clear_important_client_contents()
enable_client_mobs_in_contents()
AddDefaultRenderers()
update_client_color()
+1 -2
View File
@@ -11,8 +11,7 @@
log_access("Logout: [key_name(src)]")
SSstatistics.update_status()
ClearRenderers()
if(client)
clear_important_client_contents(client)
clear_important_client_contents()
my_client = null
-1
View File
@@ -10,7 +10,6 @@
GLOB.living_mob_list -= src
unset_machine()
QDEL_NULL(hud_used)
lose_hearing_sensitivity()
QDEL_LIST(spell_masters)
remove_screen_obj_references()
+4 -1
View File
@@ -436,7 +436,10 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
var/obj/item/organ/external/affected = owner.get_organ(parent_organ)
if(affected) affected.internal_organs -= src
loc = get_turf(owner)
var/turf/T = get_turf(owner)
// to avoid brains and things like that getting put into nullspace and thus entering spatial grids
if(!isnull(T))
loc = T
START_PROCESSING(SSprocessing, src)
rejecting = null
if (!reagents)
@@ -8,6 +8,11 @@
var/ammo_type // the type of ammo this ammo pile accepts
var/max_ammo = 5
/obj/item/ammo_pile/Destroy()
ammo.Cut()
ammo_overlays.Cut()
. = ..()
/obj/item/ammo_pile/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(is_adjacent)
@@ -136,6 +141,7 @@
/obj/item/ammo_pile/proc/add_ammo(var/obj/item/ammo_casing/bullet)
if(!bullet.BB)
return
RegisterSignal(bullet, COMSIG_QDELETING, PROC_REF(clear_ammo))
if(ismob(bullet.loc))
var/mob/gunman = bullet.loc
gunman.drop_from_inventory(bullet, src)
@@ -150,12 +156,20 @@
ammo_overlays[bullet] = ammo_picture
AddOverlays(ammo_overlays[bullet])
/// Called when one of our contained bullets is qdel'd -- why does this happen? it is a mystery
/obj/item/ammo_pile/proc/clear_ammo(datum/source)
SIGNAL_HANDLER
CutOverlays(ammo_overlays[source])
ammo -= source
UnregisterSignal(source, COMSIG_QDELETING)
/obj/item/ammo_pile/proc/remove_ammo(var/atom/target)
var/obj/bullet = ammo[1]
if(target)
bullet.forceMove(target)
CutOverlays(ammo_overlays[bullet])
ammo -= bullet
UnregisterSignal(bullet, COMSIG_QDELETING)
check_ammo()
/obj/item/ammo_pile/proc/scatter()
+1
View File
@@ -235,6 +235,7 @@ Pins Below.
/obj/item/device/firing_pin/Destroy()
if(gun)
gun.pin = null
gun = null
return ..()
//this firing pin checks for access
+20 -8
View File
@@ -33,6 +33,10 @@
/// Internal reservoir
var/datum/gas_mixture/air_contents
var/mode = MODE_PRESSURIZING
/// MODE_X define that was set when we last updated overlays.
var/mode_icon
/// Whether or not we are currently indicating as occupied.
var/showing_full = FALSE
/// Controlled by flush wire status
var/can_flush = TRUE
/// TRUE if flush handle is pulled
@@ -436,30 +440,43 @@
* Update the icon & overlays to reflect mode & status
*/
/obj/machinery/disposal/proc/update()
ClearOverlays()
if(stat & BROKEN)
if(!isnull(mode_icon) && (stat & BROKEN))
ClearOverlays()
icon_state = "[icon_state]-broken"
mode_icon = null
mode = MODE_OFF
flush = 0
return
var/has_contents = !!length(contents)
if (mode_icon == mode && showing_full == has_contents)
return
// if we're here, we must rebuild...
ClearOverlays()
// flush handle
if(flush)
AddOverlays("[icon_state]-handle")
// only handle is shown if no power
if(stat & NOPOWER || mode == MODE_OFF)
mode_icon = MODE_OFF
return
// check for items in disposal - occupied light
if(length(contents))
if(has_contents)
AddOverlays("[icon_state]-full")
showing_full = has_contents
// charging and ready light
if(mode == MODE_PRESSURIZING)
AddOverlays("[icon_state]-charge")
mode_icon = MODE_PRESSURIZING
else if(mode == MODE_READY)
AddOverlays("[icon_state]-ready")
mode_icon = MODE_READY
/**
* Timed process. Charge the gas reservoir and perform flush if ready.
@@ -1731,8 +1748,3 @@
dirs = GLOB.alldirs.Copy()
src.streak(dirs)
#undef MODE_OFF
#undef MODE_PRESSURIZING
#undef MODE_READY
#undef MODE_FLUSHING
+10 -4
View File
@@ -260,16 +260,17 @@
/obj/item/device/destTagger/proc/openwindow(mob/user)
var/dat = "<tt><center><h1><b>TagMaster 2.3</b></h1></center>"
var/ui_ref = REF(src)
dat += "<table style='width:100%; padding:4px;'><tr>"
for(var/i = 1, i <= SSdisposals.tagger_locations.len, i++)
dat += "<td><a href='byond://?src=[REF(src)];nextTag=[html_encode(SSdisposals.tagger_locations[i])]'>[SSdisposals.tagger_locations[i]]</a></td>"
dat += "<td><a href='byond://?src=[ui_ref];nextTag=[html_encode(SSdisposals.tagger_locations[i])]'>[SSdisposals.tagger_locations[i]]</a></td>"
if (i % 4==0)
dat += "</tr><tr>"
dat += "</tr></table><br>Current Selection: [currTag ? currTag : "None"]</tt>"
dat += "<br><a href='byond://?src=[REF(src)];nextTag=CUSTOM'>Enter custom location.</a>"
dat += "<br><a href='byond://?src=[ui_ref];nextTag=CUSTOM'>Enter custom location.</a>"
user << browse(HTML_SKELETON(dat), "window=destTagScreen;size=450x375")
onclose(user, "destTagScreen")
@@ -353,8 +354,8 @@
flushing = FALSE
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
if(mode == MODE_READY) // if was ready,
mode = MODE_PRESSURIZING // switch to charging
update()
return
@@ -399,3 +400,8 @@
if(trunk)
trunk.linked = null
return ..()
#undef MODE_OFF
#undef MODE_PRESSURIZING
#undef MODE_READY
#undef MODE_FLUSHING
@@ -10,12 +10,12 @@
build_path = /obj/item/circuitboard/rig_assembly/civilian/industrial
/datum/design/circuit/hardsuit/eva
name = "EVA suit central circuit Board"
name = "EVA Suit Central Circuit Board"
req_tech = list(TECH_DATA = 3)
build_path = /obj/item/circuitboard/rig_assembly/civilian/eva
/datum/design/circuit/hardsuit/eva/pilot
name = "pilot suit central circuit Board"
name = "Pilot Suit Central Circuit Board"
req_tech = list(TECH_DATA = 3)
build_path = /obj/item/circuitboard/rig_assembly/civilian/eva/pilot
@@ -147,22 +147,22 @@
build_path = /obj/item/circuitboard/candymachine
/datum/design/circuit/machine/portgen
name = "portable generator"
name = "Portable Generator"
req_tech = list(TECH_DATA = 3, TECH_PHORON = 3, TECH_POWER = 3, TECH_ENGINEERING = 3)
build_path = /obj/item/circuitboard/portgen
/datum/design/circuit/machine/advancedportgen
name = "advanced portable generator"
name = "Advanced Portable Generator"
req_tech = list(TECH_DATA = 3, TECH_POWER = 4, TECH_ENGINEERING = 4)
build_path = /obj/item/circuitboard/portgen/advanced
/datum/design/circuit/machine/superportgen
name = "super portable generator"
name = "Super Portable Generator"
req_tech = list(TECH_DATA = 3, TECH_POWER = 5, TECH_ENGINEERING = 5)
build_path = /obj/item/circuitboard/portgen/super
/datum/design/circuit/machine/fusionportgen
name = "miniature fusion reactor"
name = "Miniature Fusion Reactor"
req_tech = list(TECH_DATA = 3, TECH_POWER = 6, TECH_ENGINEERING = 6)
build_path = /obj/item/circuitboard/portgen/fusion
@@ -238,12 +238,12 @@
build_path = /obj/item/circuitboard/slime_extractor
/datum/design/circuit/machine/iv_drip
name = "IV drip"
name = "IV Drip"
req_tech = list(TECH_DATA = 1, TECH_BIO = 2)
build_path = /obj/item/circuitboard/iv_drip
/datum/design/circuit/oxyregenerator
name = "oxygen regenerator"
name = "Oxygen Regenerator"
req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2)
build_path = /obj/item/circuitboard/oxyregenerator
@@ -27,7 +27,7 @@
materials = list(MATERIAL_ALUMINIUM = 12500, MATERIAL_GLASS = 12500, DEFAULT_WALL_MATERIAL = 7000, MATERIAL_LEAD = 5500)
/datum/design/rig/eva/pilot
name = "pilot Suit Control Module Assembly"
name = "Pilot Suit Control Module Assembly"
desc = "An assembly for a light hardsuit that is designed for pilots. It features a plasteel lining that offers excellent protection from shrapnel."
build_path = /obj/item/rig_assembly/eva/pilot
materials = list(DEFAULT_WALL_MATERIAL = 25000, MATERIAL_GLASS = 12500, MATERIAL_PLASTEEL = 5500)
+90 -87
View File
@@ -55,6 +55,8 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/protolathe_category = "All"
var/imprinter_category = "All"
var/ref_for_ui
req_access = list(ACCESS_TOX) //Data and setting manipulation requires scientist access.
/obj/machinery/computer/rdconsole/proc/CallMaterialName(var/ID)
@@ -134,6 +136,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
S.setup()
break
SyncRDevices()
ref_for_ui = "[REF(src)]"
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/rdconsole/LateInitialize()
@@ -505,7 +508,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(0.2)
dat += "SYSTEM LOCKED<BR><BR>"
dat += "<A href='byond://?src=[REF(src)];lock=1.6'>Unlock</A>"
dat += "<A href='byond://?src=[ref_for_ui];lock=1.6'>Unlock</A>"
if(0.3)
dat += "Constructing Prototype. Please Wait..."
@@ -521,70 +524,70 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "Loaded disk: "
dat += (t_disk || d_disk) ? (t_disk ? "technology storage disk" : "design storage disk") : "None"
dat += "<HR><UL>"
dat += "<LI><A href='byond://?src=[REF(src)];menu=1.1'>Current Research Levels</A>"
dat += "<LI><A href='byond://?src=[REF(src)];menu=5.0'>View Researched Technologies</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=1.1'>Current Research Levels</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=5.0'>View Researched Technologies</A>"
if(t_disk)
dat += "<LI><A href='byond://?src=[REF(src)];menu=1.2'>Disk Operations</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=1.2'>Disk Operations</A>"
else if(d_disk)
dat += "<LI><A href='byond://?src=[REF(src)];menu=1.4'>Disk Operations</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=1.4'>Disk Operations</A>"
else
dat += "<LI><div class='no-build'>Disk Operations</div>"
if(linked_destroy)
dat += "<LI><A href='byond://?src=[REF(src)];menu=2.2'>Destructive Analyzer Menu</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=2.2'>Destructive Analyzer Menu</A>"
if(linked_lathe)
dat += "<LI><A href='byond://?src=[REF(src)];menu=3.1'>Protolathe Construction Menu</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=3.1'>Protolathe Construction Menu</A>"
if(linked_imprinter)
dat += "<LI><A href='byond://?src=[REF(src)];menu=4.1'>Circuit Construction Menu</A>"
dat += "<LI><A href='byond://?src=[REF(src)];menu=1.6'>Settings</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=4.1'>Circuit Construction Menu</A>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=1.6'>Settings</A>"
dat += "</UL>"
dat += "</div>"
if(1.1) //Research viewer
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];print=1'>Print This Page</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];print=1'>Print This Page</A><HR>"
dat += "<b><u>Current Research Levels:</u></b><HR>"
dat += GetResearchLevelsInfo()
dat += "</UL>"
if(1.2) //Technology Disk Menu
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "Disk Contents: (Technology Data Disk)<BR><BR>"
dat += "<div class='menu'>"
if(t_disk.stored == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='byond://?src=[REF(src)];menu=1.3'>Load Tech to Disk</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=1.3'>Load Tech to Disk</A> || "
else
dat += "Name: [t_disk.stored.name]<BR>"
dat += "Level: [t_disk.stored.level]<BR>"
dat += "Description: [t_disk.stored.desc]<HR>"
dat += "Operations: "
dat += "<A href='byond://?src=[REF(src)];updt_tech=1'>Upload to Database</A> || "
dat += "<A href='byond://?src=[REF(src)];clear_tech=1'>Clear Disk</A> || "
dat += "<A href='byond://?src=[REF(src)];eject_tech=1'>Eject Disk</A>"
dat += "<A href='byond://?src=[ref_for_ui];updt_tech=1'>Upload to Database</A> || "
dat += "<A href='byond://?src=[ref_for_ui];clear_tech=1'>Clear Disk</A> || "
dat += "<A href='byond://?src=[ref_for_ui];eject_tech=1'>Eject Disk</A>"
dat += "</div>"
if(1.3) //Technology Disk submenu
dat += "<BR><A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=1.2'>Return to Disk Operations</A><HR>"
dat += "<BR><A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=1.2'>Return to Disk Operations</A><HR>"
dat += "<div class='menu'>"
dat += "Load Technology to Disk:<BR><BR>"
dat += "<UL>"
for(var/tech_id in files.known_tech)
var/datum/tech/T = files.known_tech[tech_id]
dat += "<LI>[T.name] "
dat += "\[<A href='byond://?src=[REF(src)];copy_tech=1;copy_tech_sent=[T.id]'>copy to disk</A>\]"
dat += "\[<A href='byond://?src=[ref_for_ui];copy_tech=1;copy_tech_sent=[T.id]'>copy to disk</A>\]"
dat += "</UL>"
dat += "</div>"
if(1.4) //Design Disk menu.
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "<div class='menu'>"
if(d_disk.blueprint == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='byond://?src=[REF(src)];menu=1.5'>Load Design to Disk</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=1.5'>Load Design to Disk</A> || "
else
dat += "Name: [d_disk.blueprint.name]<BR>"
switch(d_disk.blueprint.build_type)
@@ -595,14 +598,14 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]<BR>"
else dat += "* [M] x [d_disk.blueprint.materials[M]]<BR>"
dat += "<HR>Operations: "
dat += "<A href='byond://?src=[REF(src)];updt_design=1'>Upload to Database</A> || "
dat += "<A href='byond://?src=[REF(src)];clear_design=1'>Clear Disk</A> || "
dat += "<A href='byond://?src=[REF(src)];eject_design=1'>Eject Disk</A>"
dat += "<A href='byond://?src=[ref_for_ui];updt_design=1'>Upload to Database</A> || "
dat += "<A href='byond://?src=[ref_for_ui];clear_design=1'>Clear Disk</A> || "
dat += "<A href='byond://?src=[ref_for_ui];eject_design=1'>Eject Disk</A>"
dat += "</div>"
if(1.5) //Technology disk submenu
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=1.4'>Return to Disk Operations</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=1.4'>Return to Disk Operations</A><HR>"
dat += "<div class='menu'>"
dat += "Load Design to Disk:<BR><BR>"
dat += "<UL>"
@@ -610,50 +613,50 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/datum/design/D = files.known_designs[path]
if(D.build_path)
dat += "<LI>[D.name] "
dat += "<A href='byond://?src=[REF(src)];copy_design=1;copy_design_sent=[D.type]'>\[copy to disk\]</A>"
dat += "<A href='byond://?src=[ref_for_ui];copy_design=1;copy_design_sent=[D.type]'>\[copy to disk\]</A>"
dat += "</UL>"
dat += "</div>"
if(1.6) //R&D console settings
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "<b><u>R&D Console Setting:</u></b><HR>"
dat += "<div class='menu'>"
dat += "<UL>"
if(sync)
dat += "<LI><A href='byond://?src=[REF(src)];sync=1'>Sync Database with Network</A><BR>"
dat += "<LI><A href='byond://?src=[REF(src)];togglesync=1'>Disconnect from Research Network</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];sync=1'>Sync Database with Network</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];togglesync=1'>Disconnect from Research Network</A><BR>"
else
dat += "<LI><A href='byond://?src=[REF(src)];togglesync=1'>Connect to Research Network</A><BR>"
dat += "<LI><A href='byond://?src=[REF(src)];menu=1.7'>Device Linkage Menu</A><BR>"
dat += "<LI><A href='byond://?src=[REF(src)];lock=0.2'>Lock Console</A><BR>"
dat += "<LI><A href='byond://?src=[REF(src)];reset=1'>Reset R&D Database</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];togglesync=1'>Connect to Research Network</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];menu=1.7'>Device Linkage Menu</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];lock=0.2'>Lock Console</A><BR>"
dat += "<LI><A href='byond://?src=[ref_for_ui];reset=1'>Reset R&D Database</A><BR>"
dat += "<UL>"
dat += "</div>"
if(1.7) //R&D device linkage
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=1.6'>Settings Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=1.6'>Settings Menu</A><HR>"
dat += "<b><u>R&D Console Device Linkage Menu:</u></b><HR>"
dat += "<div class='menu'>"
dat += "<A href='byond://?src=[REF(src)];find_device=1'>Re-sync with Nearby Devices</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];find_device=1'>Re-sync with Nearby Devices</A><HR>"
dat += "Linked Devices:"
dat += "<UL>"
if(allow_analyzer)
if(linked_destroy)
dat += "<LI>Destructive Analyzer <A href='byond://?src=[REF(src)];disconnect=destroy'>Disconnect</A>"
dat += "<LI>Destructive Analyzer <A href='byond://?src=[ref_for_ui];disconnect=destroy'>Disconnect</A>"
else
dat += "<LI>(No Destructive Analyzer Linked)"
if(allow_lathe)
if(linked_lathe)
dat += "<LI>Protolathe <A href='byond://?src=[REF(src)];disconnect=lathe'>Disconnect</A>"
dat += "<LI>Protolathe <A href='byond://?src=[ref_for_ui];disconnect=lathe'>Disconnect</A>"
else
dat += "<LI>(No Protolathe Linked)"
if(allow_imprinter)
if(linked_imprinter)
dat += "<LI>Circuit Imprinter <A href='byond://?src=[REF(src)];disconnect=imprinter'>Disconnect</A>"
dat += "<LI>Circuit Imprinter <A href='byond://?src=[ref_for_ui];disconnect=imprinter'>Disconnect</A>"
else
dat += "<LI>(No Circuit Imprinter Linked)"
dat += "</UL>"
@@ -661,44 +664,44 @@ won't update every console in existence) but it's more of a hassle to do. Also,
////////////////////DESTRUCTIVE ANALYZER SCREENS////////////////////////////
if(2.0)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE<BR><BR>"
if(2.1)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "No Item Loaded. Standing-by...<BR><HR>"
if(2.2)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "<b><u>Deconstruction Menu</u></b><HR>"
dat += "Name: [linked_destroy.loaded_item.name]<BR>"
dat += "Origin Tech:"
dat += "<UL>"
for(var/tech_id in linked_destroy.loaded_item.origin_tech)
var/datum/tech/T = files.known_tech[tech_id]
dat += "<LI>[capitalize_first_letters(T.name)]: \[Level: [linked_destroy.loaded_item.origin_tech[tech_id]] || Progress Contribution: [files.get_level_value(linked_destroy.loaded_item.origin_tech[tech_id])]\]"
dat += "<LI>[T.name]: \[Level: [linked_destroy.loaded_item.origin_tech[tech_id]] || Progress Contribution: [files.get_level_value(linked_destroy.loaded_item.origin_tech[tech_id])]\]"
dat += " (Current Level: [T.level] || Current Progress: [T.next_level_progress]/[T.next_level_threshold])"
dat += "</UL>"
if(!istype(linked_destroy.loaded_item, /obj/item/stack))
dat += "<HR><A href='byond://?src=[REF(src)];deconstruct=1'>Deconstruct Item</A> || "
dat += "<HR><A href='byond://?src=[ref_for_ui];deconstruct=1'>Deconstruct Item</A> || "
else
dat += "<HR><A href='byond://?src=[REF(src)];deconstruct=1'>Deconstruct One In Stack</A> || "
dat += "<A href='byond://?src=[REF(src)];eject_item=1'>Eject Item</A>"
dat += "<HR><A href='byond://?src=[ref_for_ui];deconstruct=1'>Deconstruct One In Stack</A> || "
dat += "<A href='byond://?src=[ref_for_ui];eject_item=1'>Eject Item</A>"
/////////////////////PROTOLATHE SCREENS/////////////////////////
if(3.0)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "NO PROTOLATHE LINKED TO CONSOLE<BR><BR>"
if(3.1)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.4'>View Queue</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.2'>Material Storage</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.3'>Chemical Storage</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.4'>View Queue</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.2'>Material Storage</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.3'>Chemical Storage</A><HR>"
dat += "<b><u>Protolathe Menu:</u></b><HR>"
dat += "<B>Material Amount:</B> [linked_lathe.TotalMaterials()] cm<sup>3</sup> (MAX: [linked_lathe.max_material_storage])<BR>"
dat += "<B>Chemical Volume:</B> [linked_lathe.reagents.total_volume] (MAX: [linked_lathe.reagents.maximum_volume])<HR>"
dat += "<font size='3'; color='#5c87a8'><b>Category:</b></font> <a href='byond://?src=[REF(src)];protolathe_category=1'>[protolathe_category]</a><hr>"
dat += "<font size='3'; color='#5c87a8'><b>Category:</b></font> <a href='byond://?src=[ref_for_ui];protolathe_category=1'>[protolathe_category]</a><hr>"
dat += "<div class='rdconsole-build'>"
dat += "<ul>"
var/last_category = ""
@@ -719,16 +722,16 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(temp_dat)
temp_dat = " \[[copytext(temp_dat, 3)]\]"
if(linked_lathe.canBuild(D))
dat += "<li class='highlight'><b><a href='byond://?src=[REF(src)];build=[D.type]'>[capitalize_first_letters(D.name)]</a></b>"
dat += "<li class='highlight'><b><a href='byond://?src=[ref_for_ui];build=[D.type]'>[D.name]</a></b>"
else
dat += "<li class='highlight'><b><div class='no-build'>[capitalize_first_letters(D.name)]</div></b>"
dat += "<li class='highlight'><b><div class='no-build'>[D.name]</div></b>"
dat += "[temp_dat]<br><i>[D.desc]</i>"
dat += "</ul>"
dat += "</div>"
if(3.2) //Protolathe Material Storage Sub-menu
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<b><u>Material Storage</u></b><BR><HR>"
dat += "<UL>"
for(var/M in linked_lathe.materials)
@@ -739,25 +742,25 @@ won't update every console in existence) but it's more of a hassle to do. Also,
for (var/C in list(1, 3, 5, 10, 15, 20, 25, 30, 40))
if(amount < C * SHEET_MATERIAL_AMOUNT)
break
dat += "[C > 1 ? ", " : ""]<A href='byond://?src=[REF(src)];lathe_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += "[C > 1 ? ", " : ""]<A href='byond://?src=[ref_for_ui];lathe_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += " or <A href='byond://?src=[REF(src)];lathe_ejectsheet=[M];amount=50'>max</A> sheets"
dat += " or <A href='byond://?src=[ref_for_ui];lathe_ejectsheet=[M];amount=50'>max</A> sheets"
dat += ""
dat += "</UL>"
if(3.3) //Protolathe Chemical Storage Submenu
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<b><u>Chemical Storage</u></b><BR><HR>"
for(var/_R in linked_lathe.reagents.reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
dat += "Name: [R.name] | Units: [linked_lathe.reagents.reagent_volumes[_R]] "
dat += "<A href='byond://?src=[REF(src)];disposeP=[_R]'>(Purge)</A><BR>"
dat += "<A href='byond://?src=[REF(src)];disposeallP=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
dat += "<A href='byond://?src=[ref_for_ui];disposeP=[_R]'>(Purge)</A><BR>"
dat += "<A href='byond://?src=[ref_for_ui];disposeallP=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
if(3.4) // Protolathe queue
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=3.1'>Protolathe Menu</A><HR>"
dat += "<b><u>Queue</u></b><BR><HR>"
if(!linked_lathe.queue.len)
dat += "Empty"
@@ -768,25 +771,25 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(linked_lathe.busy)
dat += "<B>1: [D.name]</B><BR>"
else
dat += "<B>1: [D.name]</B> (Awaiting materials) <A href='byond://?src=[REF(src)];removeP=[tmp]'>Remove</A><BR>"
dat += "<B>1: [D.name]</B> (Awaiting materials) <A href='byond://?src=[ref_for_ui];removeP=[tmp]'>Remove</A><BR>"
else
dat += "[tmp]: [D.name] <A href='byond://?src=[REF(src)];removeP=[tmp]'>Remove</A><BR>"
dat += "[tmp]: [D.name] <A href='byond://?src=[ref_for_ui];removeP=[tmp]'>Remove</A><BR>"
++tmp
///////////////////CIRCUIT IMPRINTER SCREENS////////////////////
if(4.0)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A><HR>"
dat += "NO CIRCUIT IMPRINTER LINKED TO CONSOLE<BR><BR>"
if(4.1)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.4'>View Queue</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.3'>Material Storage</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.2'>Chemical Storage</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.4'>View Queue</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.3'>Material Storage</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.2'>Chemical Storage</A><HR>"
dat += "<b><u>Circuit Imprinter Menu:</u></b><BR><HR>"
dat += "Material Amount: [linked_imprinter.TotalMaterials()] cm<sup>3</sup><BR>"
dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]<HR>"
dat += "<font size='3'; color='#5c87a8'><b>Category:</b></font> <a href='byond://?src=[REF(src)];imprinter_category=1'>[imprinter_category]</a><hr>"
dat += "<font size='3'; color='#5c87a8'><b>Category:</b></font> <a href='byond://?src=[ref_for_ui];imprinter_category=1'>[imprinter_category]</a><hr>"
dat += "<div class='rdconsole-build'>"
dat += "<ul>"
var/last_category = ""
@@ -807,7 +810,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(temp_dat)
temp_dat = " \[[copytext(temp_dat,3)]\]"
if(linked_imprinter.canBuild(D))
dat += "<li class='highlight'><b><a href='byond://?src=[REF(src)];imprint=[D.type]'>[D.name]</a></b>"
dat += "<li class='highlight'><b><a href='byond://?src=[ref_for_ui];imprint=[D.type]'>[D.name]</a></b>"
else
dat += "<li class='highlight'><b><div class='no-build'>[D.name]</div></b>"
dat += "[temp_dat]<br><i>[D.desc]</i>"
@@ -815,18 +818,18 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "</div>"
if(4.2)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.1'>Imprinter Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.1'>Imprinter Menu</A><HR>"
dat += "<b><u>Chemical Storage</u></b><BR><HR>"
for(var/_R in linked_imprinter.reagents.reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
dat += "Name: [R.name] | Units: [linked_imprinter.reagents.reagent_volumes[_R]] "
dat += "<A href='byond://?src=[REF(src)];disposeI=[_R]'>(Purge)</A><BR>"
dat += "<A href='byond://?src=[REF(src)];disposeallI=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
dat += "<A href='byond://?src=[ref_for_ui];disposeI=[_R]'>(Purge)</A><BR>"
dat += "<A href='byond://?src=[ref_for_ui];disposeallI=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
if(4.3)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "<b><u>Material Storage</u></b><BR><HR>"
dat += "<UL>"
for(var/M in linked_imprinter.materials)
@@ -837,15 +840,15 @@ won't update every console in existence) but it's more of a hassle to do. Also,
for (var/C in list(1, 3, 5, 10, 15, 20, 25, 30, 40))
if(amount < C * SHEET_MATERIAL_AMOUNT)
break
dat += "[C > 1 ? ", " : ""]<A href='byond://?src=[REF(src)];imprinter_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += "[C > 1 ? ", " : ""]<A href='byond://?src=[ref_for_ui];imprinter_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += " or <A href='byond://?src=[REF(src)];imprinter_ejectsheet=[M];amount=50'>max</A> sheets"
dat += " or <A href='byond://?src=[ref_for_ui];imprinter_ejectsheet=[M];amount=50'>max</A> sheets"
dat += ""
dat += "</UL>"
if(4.4)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "<b><u>Queue</u></b><BR><HR>"
if(linked_imprinter.queue.len == 0)
dat += "Empty"
@@ -855,13 +858,13 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(tmp == 1)
dat += "<B>1: [D.name]</B><BR>"
else
dat += "[tmp]: [D.name] <A href='byond://?src=[REF(src)];removeI=[tmp]'>Remove</A><BR>"
dat += "[tmp]: [D.name] <A href='byond://?src=[ref_for_ui];removeI=[tmp]'>Remove</A><BR>"
++tmp
///////////////////Research Information Browser////////////////////
if(5.0)
dat += "<A href='byond://?src=[REF(src)];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[REF(src)];print=2'>Print This Page</A><HR>"
dat += "<A href='byond://?src=[ref_for_ui];menu=1.0'>Main Menu</A> || "
dat += "<A href='byond://?src=[ref_for_ui];print=2'>Print This Page</A><HR>"
dat += "<b><u>List of Researched Technologies and Designs:</u></b><HR>"
dat += GetResearchListInfo()
+17
View File
@@ -0,0 +1,17 @@
# Your name.
author: JohnWildkins
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
changes:
- refactor: "Refactored several machines backend code to reduce server load."
- refactor: "Fixed an issue where slimes would hard-delete, causing server lag."
- refactor: "Optimized igniter and holosign buttons to reduce server load when used."
- refactor: "Optimized atmos meters, hydroponics trays, tcomms machines, and disposal units to only update their icon state when necessary."
- refactor: "Refactors motion sensors, spiderlings, guns, ammo piles, and mecha equipment to remove costly hard-dels."