Merge branch 'master' into pol-moved

This commit is contained in:
Aronai Sieyes
2020-05-12 11:22:43 -04:00
committed by GitHub
608 changed files with 8598 additions and 5698 deletions
@@ -6,8 +6,8 @@
/obj/machinery/atmospherics/binary/circulator
name = "circulator"
desc = "A gas circulator turbine and heat exchanger."
icon = 'icons/obj/pipes.dmi'
icon_state = "circ-off"
icon = 'icons/obj/power.dmi'
icon_state = "circ-unassembled"
anchored = 0
pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
@@ -22,6 +22,7 @@
var/last_stored_energy_transferred = 0
var/volume_capacity_used = 0
var/stored_energy = 0
var/temperature_overlay
density = 1
@@ -76,15 +77,19 @@
update_icon()
/obj/machinery/atmospherics/binary/circulator/update_icon()
if(stat & (BROKEN|NOPOWER) || !anchored)
icon_state = "circ-p"
else if(last_pressure_delta > 0 && recent_moles_transferred > 0)
if(last_pressure_delta > 5*ONE_ATMOSPHERE)
icon_state = "circ-run"
icon_state = anchored ? "circ-assembled" : "circ-unassembled"
cut_overlays()
if (stat & (BROKEN|NOPOWER) || !anchored)
return 1
if (last_pressure_delta > 0 && recent_moles_transferred > 0)
if (temperature_overlay)
add_overlay(temperature_overlay)
if (last_pressure_delta > 5*ONE_ATMOSPHERE)
add_overlay("circ-run")
else
icon_state = "circ-slow"
add_overlay("circ-slow")
else
icon_state = "circ-off"
add_overlay("circ-off")
return 1
@@ -97,6 +102,7 @@
"You hear a ratchet.")
if(anchored)
temperature_overlay = null
if(dir & (NORTH|SOUTH))
initialize_directions = NORTH|SOUTH
else if(dir & (EAST|WEST))
@@ -176,7 +176,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -200,8 +200,9 @@
set_frequency(frequency)
/obj/machinery/atmospherics/binary/dp_vent_pump/examine(mob/user)
if(..(user, 1))
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
. = ..()
if(Adjacent(user))
. += "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
/obj/machinery/atmospherics/unary/vent_pump/power_change()
@@ -151,7 +151,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -128,7 +128,7 @@ Thus, the two variables affect pump operation are set in New():
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
+2 -2
View File
@@ -15,8 +15,8 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
icon_state = "vclamp[open]"
/obj/machinery/atmospherics/valve/shutoff/examine(var/mob/user)
..()
to_chat(user, "The automatic shutoff circuit is [close_on_leaks ? "enabled" : "disabled"].")
. = ..()
. += "The automatic shutoff circuit is [close_on_leaks ? "enabled" : "disabled"]."
/obj/machinery/atmospherics/valve/shutoff/Initialize()
. = ..()
@@ -21,15 +21,9 @@
var/set_temperature = T20C // Thermostat
var/cooling = 0
/obj/machinery/atmospherics/unary/freezer/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/atmospherics/unary/freezer/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/atmospherics/unary/freezer/atmos_init()
if(node)
@@ -178,6 +172,6 @@
..()
/obj/machinery/atmospherics/unary/freezer/examine(mob/user)
..(user)
. = ..()
if(panel_open)
to_chat(user, "The maintenance hatch is open.")
. += "The maintenance hatch is open."
@@ -21,15 +21,9 @@
var/set_temperature = T20C //thermostat
var/heating = 0 //mainly for icon updates
/obj/machinery/atmospherics/unary/heater/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
/obj/machinery/atmospherics/unary/heater/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/atmospherics/unary/heater/atmos_init()
if(node)
@@ -165,6 +159,6 @@
..()
/obj/machinery/atmospherics/unary/heater/examine(mob/user)
..(user)
..()
if(panel_open)
to_chat(user, "The maintenance hatch is open.")
. += "The maintenance hatch is open."
@@ -107,7 +107,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -247,7 +247,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -398,12 +398,13 @@
..()
/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user)
if(..(user, 1))
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
. = ..()
if(Adjacent(user))
. += "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
else
to_chat(user, "You are too far away to read the gauge.")
. += "You are too far away to read the gauge."
if(welded)
to_chat(user, "It seems welded shut.")
. += "It seems welded shut."
/obj/machinery/atmospherics/unary/vent_pump/power_change()
var/old_stat = stat
@@ -93,7 +93,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"area" = area_uid,
@@ -287,7 +287,8 @@
deconstruct()
/obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user)
if(..(user, 1))
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
. = ..()
if(Adjacent(user))
. += "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
else
to_chat(user, "You are too far away to read the gauge.")
. += "You are too far away to read the gauge."
+2 -2
View File
@@ -307,5 +307,5 @@
deconstruct()
/obj/machinery/atmospherics/valve/examine(mob/user)
..()
to_chat(user, "It is [open ? "open" : "closed"].")
. = ..()
. += "It is [open ? "open" : "closed"]."
+19 -4
View File
@@ -16,13 +16,19 @@
// Inputs: The turf the airflow is from, which may not be the same as loc. is_zone is for conditionally disallowing merging.
// Outputs: Boolean if airflow can pass.
/atom/proc/CanZASPass(turf/T, is_zone)
// Behaviors defined here so when people directly call c_airblock it will still obey can_atmos_pass
switch(can_atmos_pass)
if(ATMOS_PASS_YES)
return TRUE
if(ATMOS_PASS_NO)
return FALSE
if(ATMOS_PASS_DENSITY)
return !density
if(ATMOS_PASS_PROC)
// Cowardly refuse to recursively self-call CanZASPass. The hero BYOND needs?
CRASH("can_atmos_pass = ATMOS_PASS_PROC but CanZASPass not overridden on [src] ([type])")
else
return can_atmos_pass
/turf/can_atmos_pass = ATMOS_PASS_NO
CRASH("Invalid can_atmos_pass = [can_atmos_pass] on [src] ([type])")
/turf/CanPass(atom/movable/mover, turf/target)
if(!target) return FALSE
@@ -89,6 +95,15 @@ turf/c_airblock(turf/other)
var/result = 0
for(var/mm in contents)
var/atom/movable/M = mm
result |= M.c_airblock(other)
switch(M.can_atmos_pass)
if(ATMOS_PASS_YES)
continue
if(ATMOS_PASS_NO)
return BLOCKED
if(ATMOS_PASS_DENSITY)
if(M.density)
return BLOCKED
if(ATMOS_PASS_PROC)
result |= M.c_airblock(other)
if(result == BLOCKED) return BLOCKED
return result
+7
View File
@@ -4,3 +4,10 @@
#define BLOCKED 3 // Blocked, zone boundaries will not cross even if opened.
#define ZONE_MIN_SIZE 14 // Zones with less than this many turfs will always merge, even if the connection is not direct
// Used for quickly making certain things allow airflow or not.
// More complicated, conditional airflow should override CanZASPass().
#define ATMOS_PASS_YES 1 // Always blocks air and zones.
#define ATMOS_PASS_NO 2 // Never blocks air or zones.
#define ATMOS_PASS_DENSITY 3 // Blocks air and zones if density = 1, allows both if density = 0
#define ATMOS_PASS_PROC 4 // Call CanZASPass() using c_airblock
+1 -3
View File
@@ -1,6 +1,6 @@
#if DM_VERSION < 513
#define ismovableatom(A) (istype(A, /atom/movable))
#define ismovable(A) (istype(A, /atom/movable))
#define islist(L) (istype(L, /list))
@@ -18,8 +18,6 @@
#else
#define ismovableatom(A) ismovable(A)
#define CLAMP01(x) clamp(x, 0, 1)
#define CLAMP(CLVALUE, CLMIN, CLMAX) clamp(CLVALUE, CLMIN, CLMAX)
-6
View File
@@ -94,9 +94,3 @@
#define ATMOSTANK_CO2 25000 // CO2 and PH are not critically important for station, only for toxins and alternative coolants, no need to store a lot of those.
#define ATMOSTANK_PHORON 25000
#define ATMOSTANK_NITROUSOXIDE 10000 // N2O doesn't have a real useful use, i guess it's on station just to allow refilling of sec's riot control canisters?
// Used for quickly making certain things allow airflow or not.
// More complicated, conditional airflow should override CanZASPass().
#define ATMOS_PASS_YES 1
#define ATMOS_PASS_NO 0
#define ATMOS_PASS_DENSITY -1 // Just checks density.
+22
View File
@@ -63,6 +63,28 @@
#define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT
#define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build.
// Disposals Construction
// Future: Eliminate these type codes by adding disposals equivilent of pipe_state.
#define DISPOSAL_PIPE_STRAIGHT 0
#define DISPOSAL_PIPE_CORNER 1
#define DISPOSAL_PIPE_JUNCTION 2
#define DISPOSAL_PIPE_JUNCTION_FLIPPED 3
#define DISPOSAL_PIPE_JUNCTION_Y 4
#define DISPOSAL_PIPE_TRUNK 5
#define DISPOSAL_PIPE_BIN 6
#define DISPOSAL_PIPE_OUTLET 7
#define DISPOSAL_PIPE_CHUTE 8
#define DISPOSAL_PIPE_SORTER 9
#define DISPOSAL_PIPE_SORTER_FLIPPED 10
#define DISPOSAL_PIPE_UPWARD 11
#define DISPOSAL_PIPE_DOWNWARD 12
#define DISPOSAL_PIPE_TAGGER 13
#define DISPOSAL_PIPE_TAGGER_PARTIAL 14
#define DISPOSAL_SORT_NORMAL 0
#define DISPOSAL_SORT_WILDCARD 1
#define DISPOSAL_SORT_UNTAGGED 2
// Macro for easy use of boilerplate code for searching for a valid node connection.
#define STANDARD_ATMOS_CHOOSE_NODE(node_num, direction) \
for(var/obj/machinery/atmospherics/target in get_step(src, direction)) { \
+4 -4
View File
@@ -35,8 +35,8 @@
#define BE_RAIDER 0x800
#define BE_PLANT 0x1000
#define BE_MUTINEER 0x2000
#define BE_PAI 0x4000
#define BE_LOYALIST 0x8000
#define BE_LOYALIST 0x4000
#define BE_PAI 0x8000
var/list/be_special_flags = list(
"Traitor" = BE_TRAITOR,
@@ -45,7 +45,6 @@ var/list/be_special_flags = list(
"Wizard" = BE_WIZARD,
"Malf AI" = BE_MALF,
"Revolutionary" = BE_REV,
"Loyalist" = BE_LOYALIST,
"Xenomorph" = BE_ALIEN,
"Positronic Brain" = BE_AI,
"Cultist" = BE_CULTIST,
@@ -54,7 +53,8 @@ var/list/be_special_flags = list(
"Raider" = BE_RAIDER,
"Diona" = BE_PLANT,
"Mutineer" = BE_MUTINEER,
"pAI" = BE_PAI
"Loyalist" = BE_LOYALIST,
"pAI" = BE_PAI,
)
+2 -1
View File
@@ -53,4 +53,5 @@
//---------------
//#define isturf(D) istype(D, /turf) //Built in
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isspace(A) istype(A, /turf/space)
+1
View File
@@ -82,6 +82,7 @@
#define LIGHT_COLOR_INCANDESCENT_TUBE "#FFFEB8"
#define LIGHT_COLOR_INCANDESCENT_BULB "#FFDDBB"
#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66"
#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86"
//Fake ambient occlusion filter
#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, offset=3, color="#04080F80")
+16
View File
@@ -2,6 +2,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
#define CELLRATE 0.002 // Multiplier for watts per tick <> cell storage (e.g., 0.02 means if there is a load of 1000 watts, 20 units will be taken from a cell per second)
// It's a conversion constant. power_used*CELLRATE = charge_provided, or charge_used/CELLRATE = power_provided
#define SMESRATE 0.03333 // Same for SMESes. A different number for some reason.
#define KILOWATTS *1000
#define MEGAWATTS *1000000
@@ -74,6 +75,21 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
// Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them.
var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret", NETWORK_COMMUNICATORS)
#define TRANSMISSION_WIRE 0 //Is this ever used? I don't think it is.
#define TRANSMISSION_RADIO 1 //Radio transmissions (like airlock controller to pump)
#define TRANSMISSION_SUBSPACE 2 //Like headsets
#define TRANSMISSION_BLUESPACE 3 //Point-to-point links
#define SIGNAL_NORMAL 0 //Normal subspace signals
#define SIGNAL_SIMPLE 1 //Normal inter-machinery(?) signals
#define SIGNAL_FAKE 2 //Untrackable signals
#define SIGNAL_TEST 4 //Unlogged signals
#define DATA_NORMAL 0 //Normal data
#define DATA_INTERCOM 1 //Intercoms only
#define DATA_LOCAL 2 //Intercoms and SBRs
#define DATA_ANTAG 3 //Antag interception
#define DATA_FAKE 4 //Not from a real mob
//singularity defines
#define STAGE_ONE 1
+5
View File
@@ -372,3 +372,8 @@ var/global/list/##LIST_NAME = list();\
// Used by radios to indicate that they have sent a message via something other than subspace
#define RADIO_CONNECTION_FAIL 0
#define RADIO_CONNECTION_NON_SUBSPACE 1
#define JOB_CARBON 0x1
#define JOB_SILICON_ROBOT 0x2
#define JOB_SILICON_AI 0x4
#define JOB_SILICON 0x6 // 2|4, probably don't set jobs to this, but good for checking
+3 -1
View File
@@ -426,4 +426,6 @@
#define EXAMINE_SKIPARMS 0x0020
#define EXAMINE_SKIPHANDS 0x0040
#define EXAMINE_SKIPLEGS 0x0080
#define EXAMINE_SKIPFEET 0x0100
#define EXAMINE_SKIPFEET 0x0100
#define MAX_NUTRITION 500
+10 -1
View File
@@ -1,6 +1,15 @@
// Modes for examine text output
#define EXAMINE_MODE_DEFAULT 0
#define EXAMINE_MODE_INCLUDE_USAGE 1
#define EXAMINE_MODE_SWITCH_TO_PANEL 2
// Should be one higher than the above
#define EXAMINE_MODE_MAX 3
#define EXAMINE_MODE_MAX 3
// Modes for parsing multilingual speech
#define MULTILINGUAL_DEFAULT 0
#define MULTILINGUAL_SPACE 1
#define MULTILINGUAL_DOUBLE_DELIMITER 2
#define MULTILINGUAL_OFF 3
#define MULTILINGUAL_MODE_MAX 4
+2 -1
View File
@@ -53,13 +53,14 @@
#define LANGUAGE_AKHANI "Akhani"
#define LANGUAGE_ALAI "Alai"
#define LANGUAGE_ZADDAT "Vedahq"
#define LANGUAGE_PROMETHEAN "Promethean Biolinguistics"
#define LANGUAGE_BLOB "Blob"
#define LANGUAGE_GIBBERISH "Babel"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
#define RESTRICTED 2 // Language can only be acquired by spawning or an admin.
#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight.
#define NONVERBAL 4 // Language uses both verbal and non-verbal components completely to communicate. Out-of-sight speech is garbled.
#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
#define HIVEMIND 16 // Broadcast to all mobs with this language.
#define NONGLOBAL 32 // Do not add to general languages list.
+6 -3
View File
@@ -68,13 +68,15 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_ASSETS -3
#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_HOLOMAPS -5
#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_ALARM -7
#define INIT_ORDER_NIGHTSHIFT -6
#define INIT_ORDER_OVERLAY -7
#define INIT_ORDER_ALARM -8
#define INIT_ORDER_OPENSPACE -10
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
#define INIT_ORDER_AI -22
#define INIT_ORDER_GAME_MASTER -24
#define INIT_ORDER_AI_FAST -23
#define INIT_ORDER_GAME_MASTER -24
#define INIT_ORDER_TICKER -50
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
@@ -83,6 +85,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_SUPPLY 5
#define FIRE_PRIORITY_NIGHTSHIFT 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
+1 -1
View File
@@ -246,7 +246,7 @@
var/turf/speaker = get_turf(R)
if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker))
speaker_coverage[T] = T
speaker_coverage[T] = R
// Try to find all the players who can hear the message
+19 -16
View File
@@ -35,25 +35,25 @@
return wtime + (time_offset + wusage) * world.tick_lag
var/roundstart_hour
GLOBAL_VAR_INIT(roundstart_hour, pick(2,7,12,17))
var/station_date = ""
var/next_station_date_change = 1 DAY
#define duration2stationtime(time) time2text(station_time_in_ticks + time, "hh:mm")
#define worldtime2stationtime(time) time2text(roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0)
#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks)
#define duration2stationtime(time) time2text(station_time_in_ds + time, "hh:mm")
#define worldtime2stationtime(time) time2text(GLOB.roundstart_hour HOURS + time, "hh:mm")
#define round_duration_in_ds (GLOB.round_start_time ? world.time - GLOB.round_start_time : 0)
#define station_time_in_ds (GLOB.roundstart_hour HOURS + round_duration_in_ds)
/proc/stationtime2text()
return time2text(station_time_in_ticks, "hh:mm")
return time2text(station_time_in_ds + GLOB.timezoneOffset, "hh:mm")
/proc/stationdate2text()
var/update_time = FALSE
if(station_time_in_ticks > next_station_date_change)
if(station_time_in_ds > next_station_date_change)
next_station_date_change += 1 DAY
update_time = TRUE
if(!station_date || update_time)
var/extra_days = round(station_time_in_ticks / (1 DAY)) DAYS
var/extra_days = round(station_time_in_ds / (1 DAY)) DAYS
var/timeofday = world.timeofday + extra_days
station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD")
return station_date
@@ -64,6 +64,13 @@ var/next_station_date_change = 1 DAY
var/time_portion = time2text(world.timeofday, "hh:mm:ss")
return "[date_portion]T[time_portion]"
/proc/get_timezone_offset()
var/midnight_gmt_here = text2num(time2text(0,"hh")) * 36000
if(midnight_gmt_here > 12 HOURS)
return 24 HOURS - midnight_gmt_here
else
return midnight_gmt_here
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
@@ -83,19 +90,19 @@ proc/isDay(var/month, var/day)
var/next_duration_update = 0
var/last_round_duration = 0
var/round_start_time = 0
GLOBAL_VAR_INIT(round_start_time, 0)
/hook/roundstart/proc/start_timer()
round_start_time = world.time
GLOB.round_start_time = world.time
return 1
/proc/roundduration2text()
if(!round_start_time)
if(!GLOB.round_start_time)
return "00:00"
if(last_round_duration && world.time < next_duration_update)
return last_round_duration
var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
var/mills = round_duration_in_ds // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
@@ -112,10 +119,6 @@ var/round_start_time = 0
var/datum/controller/process/process = processScheduler.getProcess(process_name)
return process.schedule_interval
/hook/startup/proc/set_roundstart_hour()
roundstart_hour = pick(2,7,12,17)
return 1
/var/midnight_rollovers = 0
/var/rollovercheck_last_timeofday = 0
/proc/update_midnight_rollover()
+3
View File
@@ -28,6 +28,7 @@
inv_box.icon = ui_style
inv_box.color = ui_color
inv_box.alpha = ui_alpha
inv_box.hud = src
var/list/slot_data = hud_data.gear[gear_slot]
inv_box.name = gear_slot
@@ -192,6 +193,7 @@
using.screen_loc = ui_swaphand1
using.color = ui_color
using.alpha = ui_alpha
using.hud = src
src.adding += using
using = new /obj/screen/inventory()
@@ -201,6 +203,7 @@
using.screen_loc = ui_swaphand2
using.color = ui_color
using.alpha = ui_alpha
using.hud = src
src.adding += using
if(hud_data.has_resist)
+101 -34
View File
@@ -31,7 +31,36 @@
/obj/screen/inventory
var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
var/list/object_overlays = list() // Required for inventory/screen overlays.
/obj/screen/inventory/MouseEntered()
..()
add_overlays()
/obj/screen/inventory/MouseExited()
..()
cut_overlay(object_overlays)
object_overlays.Cut()
/obj/screen/inventory/proc/add_overlays()
var/mob/user = hud.mymob
if(hud && user && slot_id)
var/obj/item/holding = user.get_active_hand()
if(!holding || user.get_equipped_item(slot_id))
return
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
if(!holding.mob_can_equip(user, slot_id, disable_warning = TRUE))
item_overlay.color = "#ff0000"
else
item_overlay.color = "#00ff00"
object_overlays += item_overlay
add_overlay(object_overlays)
/obj/screen/close
name = "close"
@@ -102,78 +131,116 @@
icon_state = "zone_sel"
screen_loc = ui_zonesel
var/selecting = BP_TORSO
var/static/list/hover_overlays_cache = list()
var/hovering_choice
var/mutable_appearance/selecting_appearance
/obj/screen/zone_sel/Click(location, control,params)
if(isobserver(usr))
return
var/list/PL = params2list(params)
var/icon_x = text2num(PL["icon-x"])
var/icon_y = text2num(PL["icon-y"])
var/old_selecting = selecting //We're only going to update_icon() if there's been a change
var/choice = get_zone_at(icon_x, icon_y)
if(!choice)
return 1
return set_selected_zone(choice, usr)
/obj/screen/zone_sel/MouseEntered(location, control, params)
MouseMove(location, control, params)
/obj/screen/zone_sel/MouseMove(location, control, params)
if(isobserver(usr))
return
var/list/PL = params2list(params)
var/icon_x = text2num(PL["icon-x"])
var/icon_y = text2num(PL["icon-y"])
var/choice = get_zone_at(icon_x, icon_y)
if(hovering_choice == choice)
return
vis_contents -= hover_overlays_cache[hovering_choice]
hovering_choice = choice
var/obj/effect/overlay/zone_sel/overlay_object = hover_overlays_cache[choice]
if(!overlay_object)
overlay_object = new
overlay_object.icon_state = "[choice]"
hover_overlays_cache[choice] = overlay_object
vis_contents += overlay_object
/obj/effect/overlay/zone_sel
icon = 'icons/mob/zone_sel.dmi'
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
alpha = 128
anchored = TRUE
layer = LAYER_HUD_ABOVE
plane = PLANE_PLAYER_HUD_ABOVE
/obj/screen/zone_sel/MouseExited(location, control, params)
if(!isobserver(usr) && hovering_choice)
vis_contents -= hover_overlays_cache[hovering_choice]
hovering_choice = null
/obj/screen/zone_sel/proc/get_zone_at(icon_x, icon_y)
switch(icon_y)
if(1 to 3) //Feet
switch(icon_x)
if(10 to 15)
selecting = BP_R_FOOT
return BP_R_FOOT
if(17 to 22)
selecting = BP_L_FOOT
else
return 1
return BP_L_FOOT
if(4 to 9) //Legs
switch(icon_x)
if(10 to 15)
selecting = BP_R_LEG
return BP_R_LEG
if(17 to 22)
selecting = BP_L_LEG
else
return 1
return BP_L_LEG
if(10 to 13) //Hands and groin
switch(icon_x)
if(8 to 11)
selecting = BP_R_HAND
return BP_R_HAND
if(12 to 20)
selecting = BP_GROIN
return BP_GROIN
if(21 to 24)
selecting = BP_L_HAND
else
return 1
return BP_L_HAND
if(14 to 22) //Chest and arms to shoulders
switch(icon_x)
if(8 to 11)
selecting = BP_R_ARM
return BP_R_ARM
if(12 to 20)
selecting = BP_TORSO
return BP_TORSO
if(21 to 24)
selecting = BP_L_ARM
else
return 1
return BP_L_ARM
if(23 to 30) //Head, but we need to check for eye or mouth
if(icon_x in 12 to 20)
selecting = BP_HEAD
switch(icon_y)
if(23 to 24)
if(icon_x in 15 to 17)
selecting = O_MOUTH
return O_MOUTH
if(26) //Eyeline, eyes are on 15 and 17
if(icon_x in 14 to 18)
selecting = O_EYES
return O_EYES
if(25 to 27)
if(icon_x in 15 to 17)
selecting = O_EYES
return O_EYES
return BP_HEAD
if(old_selecting != selecting)
update_icon()
return 1
/obj/screen/zone_sel/proc/set_selected_zone(bodypart)
var/old_selecting = selecting
selecting = bodypart
if(old_selecting != selecting)
/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user)
if(isobserver(user))
return
if(choice != selecting)
selecting = choice
update_icon()
/obj/screen/zone_sel/update_icon()
overlays.Cut()
overlays += image('icons/mob/zone_sel.dmi', "[selecting]")
cut_overlay(selecting_appearance)
selecting_appearance = mutable_appearance('icons/mob/zone_sel.dmi', "[selecting]")
add_overlay(selecting_appearance)
/obj/screen/Click(location, control, params)
if(!usr) return 1
+2 -2
View File
@@ -50,8 +50,8 @@
/obj/machinery/teleport/hub/attack_ghost(mob/user as mob)
var/atom/l = loc
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
if(com.locked)
user.loc = get_turf(com.locked)
if(com?.teleport_control.locked)
user.loc = get_turf(com.teleport_control.locked)
/obj/effect/portal/attack_ghost(mob/user as mob)
if(target)
+1 -1
View File
@@ -12,6 +12,6 @@ datum/controller/transfer_controller/Destroy()
datum/controller/transfer_controller/process()
currenttick = currenttick + 1
if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
if (round_duration_in_ds >= timerbuffer - 1 MINUTE)
SSvote.autotransfer()
timerbuffer = timerbuffer + config.vote_autotransfer_interval
+6
View File
@@ -270,6 +270,9 @@ var/list/gamemode_cache = list()
// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
var/disable_cid_warn_popup = FALSE
// whether or not to use the nightshift subsystem to perform lighting changes
var/static/enable_night_shifts = FALSE
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -888,6 +891,9 @@ var/list/gamemode_cache = list()
if("disable_cid_warn_popup")
config.disable_cid_warn_popup = TRUE
if("enable_night_shifts")
config.enable_night_shifts = TRUE
else
log_misc("Unknown setting in configuration: '[name]'")
+3 -7
View File
@@ -2,8 +2,8 @@ SUBSYSTEM_DEF(ai)
name = "AI"
init_order = INIT_ORDER_AI
priority = FIRE_PRIORITY_AI
wait = 5 // This gets run twice a second, however this is technically two loops in one, with the second loop being run every four iterations.
flags = SS_NO_INIT|SS_TICKER
wait = 2 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/processing = list()
@@ -22,15 +22,11 @@ SUBSYSTEM_DEF(ai)
var/list/currentrun = src.currentrun
while(currentrun.len)
// var/mob/living/L = currentrun[currentrun.len]
var/datum/ai_holder/A = currentrun[currentrun.len]
--currentrun.len
if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
continue
if(times_fired % 4 == 0 && A.holder.stat != DEAD)
A.handle_strategicals()
if(A.holder.stat != DEAD) // The /TG/ version checks stat twice, presumably in-case processing somehow got the mob killed in that instant.
A.handle_tactics()
A.handle_strategicals()
if(MC_TICK_CHECK)
return
+32
View File
@@ -0,0 +1,32 @@
SUBSYSTEM_DEF(aifast)
name = "AI (Fast)"
init_order = INIT_ORDER_AI_FAST
priority = FIRE_PRIORITY_AI
wait = 0.25 SECONDS // Every quarter second
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/processing = list()
var/list/currentrun = list()
/datum/controller/subsystem/aifast/stat_entry(msg_prefix)
var/list/msg = list(msg_prefix)
msg += "P:[processing.len]"
..(msg.Join())
/datum/controller/subsystem/aifast/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/ai_holder/A = currentrun[currentrun.len]
--currentrun.len
if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
continue
A.handle_tactics()
if(MC_TICK_CHECK)
return
+5 -3
View File
@@ -6,9 +6,11 @@ SUBSYSTEM_DEF(assets)
var/list/preload = list()
/datum/controller/subsystem/assets/Initialize(timeofday)
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
var/datum/asset/A = new type()
A.register()
for(var/type in typesof(/datum/asset))
var/datum/asset/A = type
if (type != initial(A._abstract))
get_asset_datum(type)
preload = cache.Copy() //don't preload assets generated during the round
+1 -1
View File
@@ -109,7 +109,7 @@ SUBSYSTEM_DEF(game_master)
return FALSE
// Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
+62
View File
@@ -0,0 +1,62 @@
SUBSYSTEM_DEF(nightshift)
name = "Night Shift"
init_order = INIT_ORDER_NIGHTSHIFT
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 60 SECONDS
flags = SS_NO_TICK_CHECK
var/nightshift_active = FALSE
var/nightshift_first_check = 30 SECONDS
var/high_security_mode = FALSE
/datum/controller/subsystem/nightshift/Initialize()
if(!config.enable_night_shifts)
can_fire = FALSE
/*
if(config.randomize_shift_time)
GLOB.gametime_offset = rand(0, 23) HOURS
*/
return ..()
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
if(round_duration_in_ds < nightshift_first_check)
return
check_nightshift()
/datum/controller/subsystem/nightshift/proc/announce(message)
var/announce_z
if(using_map.station_levels.len)
announce_z = pick(using_map.station_levels)
priority_announcement.Announce(message, new_title = "Automated Lighting System Announcement", new_sound = 'sound/misc/notice2.ogg', zlevel = announce_z)
/datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) //This is called from elsewhere, like setting the alert levels
if(check_canfire && !can_fire)
return
var/emergency = security_level > SEC_LEVEL_GREEN
var/announcing = TRUE
var/night_time = using_map.get_nightshift()
if(high_security_mode != emergency)
high_security_mode = emergency
if(night_time)
announcing = FALSE
if(!emergency)
announce("Restoring night lighting configuration to normal operation.")
else
announce("Disabling night lighting: Station is in a state of emergency.")
if(emergency)
night_time = FALSE
if(nightshift_active != night_time)
update_nightshift(night_time, announcing)
/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE)
nightshift_active = active
if(announce)
if(active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
for(var/obj/machinery/power/apc/apc in machines)
if(apc.z in using_map.station_levels)
apc.set_nightshift(active, TRUE)
CHECK_TICK
+7 -7
View File
@@ -6,16 +6,16 @@ SUBSYSTEM_DEF(planets)
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/new_outdoor_turfs = list()
var/list/new_outdoor_walls = list()
var/static/list/new_outdoor_turfs = list()
var/static/list/new_outdoor_walls = list()
var/list/planets = list()
var/list/z_to_planet = list()
var/static/list/planets = list()
var/static/list/z_to_planet = list()
var/list/currentrun = list()
var/static/list/currentrun = list()
var/list/needs_sun_update = list()
var/list/needs_temp_update = list()
var/static/list/needs_sun_update = list()
var/static/list/needs_temp_update = list()
/datum/controller/subsystem/planets/Initialize(timeofday)
admin_notice("<span class='danger'>Initializing planetary weather.</span>", R_DEBUG)
+1 -1
View File
@@ -104,7 +104,7 @@ SUBSYSTEM_DEF(shuttles)
try_add_landmark_tag(shuttle_landmark_tag, O)
landmarks_still_needed -= shuttle_landmark_tag
else if(istype(shuttle_landmark, /obj/effect/shuttle_landmark/automatic)) //These find their sector automatically
O = map_sectors["[shuttle_landmark.z]"]
O = get_overmap_sector(get_z(shuttle_landmark))
O ? O.add_landmark(shuttle_landmark, shuttle_landmark.shuttle_restricted) : (landmarks_awaiting_sector += shuttle_landmark)
/datum/controller/subsystem/shuttles/proc/get_landmark(var/shuttle_landmark_tag)
+1 -1
View File
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(skybox)
res.overlays += base
if(global.using_map.use_overmap && settings.use_overmap_details)
var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
var/obj/effect/overmap/visitable/O = get_overmap_sector(z)
if(istype(O))
var/image/overmap = image(settings.icon)
overmap.overlays += O.generate_skybox()
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -4,10 +4,12 @@
var/lock = TRUE
var/turf/lastloc
var/lastprocess
var/matrix/init_transform
/datum/orbit/New(_orbiter, _orbiting, _lock)
/datum/orbit/New(var/atom/movable/_orbiter, var/atom/_orbiting, _lock)
orbiter = _orbiter
orbiting = _orbiting
init_transform = _orbiter.transform
SSorbit.processing += src
if (!orbiting.orbiters)
orbiting.orbiters = list()
@@ -24,6 +26,7 @@
SSorbit.processing -= src
if (orbiter)
orbiter.orbiting = null
orbiter.transform = init_transform
orbiter = null
if (orbiting)
if (orbiting.orbiters)
@@ -84,7 +87,6 @@
new/datum/orbit(src, A, lockinorbit)
if (!orbiting) //something failed, and our orbit datum deleted itself
return
var/matrix/initial_transform = matrix(transform)
//Head first!
if (pre_rotation)
@@ -101,9 +103,6 @@
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
transform = initial_transform
/atom/movable/proc/stop_orbit()
SpinAnimation(0,0)
qdel(orbiting)
+17 -2
View File
@@ -14,10 +14,25 @@ var/global/datum/repository/cameras/camera_repository = new()
networks = list()
..()
/datum/repository/cameras/proc/cameras_in_network(var/network)
/datum/repository/cameras/proc/cameras_in_network(var/network, var/list/zlevels)
setup_cache()
var/list/network_list = networks[network]
return network_list
if(LAZYLEN(zlevels))
var/list/filtered_cameras = list()
for(var/list/C in network_list)
//Camera is marked as always-visible
if(C["omni"])
filtered_cameras[++filtered_cameras.len] = C
continue
//Camera might be in an adjacent zlevel
var/camz = C["z"]
if(!camz) //It's inside something (helmet, communicator, etc) or nullspace or who knows
camz = get_z(locate(C["camera"]) in cameranet.cameras)
if(camz in zlevels)
filtered_cameras[++filtered_cameras.len] = C //Can't add lists to lists with +=
return filtered_cameras
else
return network_list
/datum/repository/cameras/proc/setup_cache()
if(!invalidated)
+4
View File
@@ -65,6 +65,10 @@
name = "Anti-Materiel Rifle ammo box (14.5mm)"
path = /obj/item/weapon/storage/box/sniperammo
/datum/uplink_item/item/ammo/sniperammo_highvel
name = "Anti-Materiel Rifle ammo box (14.5mm sabot)"
path = /obj/item/weapon/storage/box/sniperammo/highvel
/datum/uplink_item/item/ammo/c545
name = "Rifle Magazine (5.45mm)"
path = /obj/item/ammo_magazine/m545
+1 -1
View File
@@ -11,7 +11,7 @@ var/const/SMES_WIRE_FAILSAFES = 16 // Cut to disable failsafes, mend to reenable
/datum/wires/smes/CanUse(var/mob/living/L)
var/obj/machinery/power/smes/buildable/S = holder
if(S.open_hatch)
if(S.panel_open)
return 1
return 0
-7
View File
@@ -230,13 +230,6 @@
desc = "Heavy-duty switching circuits for power control."
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
/obj/item/weapon/module/power_control/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if (istype(W, /obj/item/device/multitool))
var/obj/item/weapon/circuitboard/ghettosmes/newcircuit = new/obj/item/weapon/circuitboard/ghettosmes(user.loc)
qdel(src)
user.put_in_hands(newcircuit)
/obj/item/weapon/module/id_auth
name = "\improper ID authentication module"
icon_state = "id_mod"
+23 -13
View File
@@ -30,7 +30,7 @@
title = "Security Announcement"
announcement_type = "Security Announcement"
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0)
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0, var/zlevel)
if(!message)
return
var/message_title = new_title ? new_title : title
@@ -40,13 +40,17 @@
message = sanitize(message, extra = 0)
message_title = sanitizeSafe(message_title)
Message(message, message_title)
var/list/zlevels
if(zlevel)
zlevels = using_map.get_map_levels(zlevel, TRUE)
Message(message, message_title, zlevels)
if(do_newscast)
NewsCast(message, message_title)
Sound(message_sound)
Sound(message_sound, zlevels)
Log(message, message_title)
datum/announcement/proc/Message(message as text, message_title as text)
datum/announcement/proc/Message(message as text, message_title as text, var/list/zlevels)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !isdeaf(M))
to_chat(M, "<h2 class='alert'>[title]</h2>")
@@ -54,6 +58,7 @@ datum/announcement/proc/Message(message as text, message_title as text)
if (announcer)
to_chat(M, "<span class='alert'> -[html_encode(announcer)]</span>")
// You'll need to update these to_world usages if you want to make these z-level specific ~Aro
datum/announcement/minor/Message(message as text, message_title as text)
to_world("<b>[message]</b>")
@@ -64,7 +69,7 @@ datum/announcement/priority/Message(message as text, message_title as text)
to_world("<span class='alert'> -[html_encode(announcer)]</span>")
to_world("<br>")
datum/announcement/priority/command/Message(message as text, message_title as text)
datum/announcement/priority/command/Message(message as text, message_title as text, var/list/zlevels)
var/command
command += "<h1 class='alert'>[command_name()] Update</h1>"
if (message_title)
@@ -73,6 +78,8 @@ datum/announcement/priority/command/Message(message as text, message_title as te
command += "<br><span class='alert'>[message]</span><br>"
command += "<br>"
for(var/mob/M in player_list)
if(zlevels && !(get_z(M) in zlevels))
continue
if(!istype(M,/mob/new_player) && !isdeaf(M))
to_chat(M, command)
@@ -92,15 +99,18 @@ datum/announcement/proc/NewsCast(message as text, message_title as text)
news.can_be_redacted = 0
announce_newscaster_news(news)
datum/announcement/proc/PlaySound(var/message_sound)
datum/announcement/proc/PlaySound(var/message_sound, var/list/zlevels)
if(!message_sound)
return
for(var/mob/M in player_list)
if(zlevels && !(M.z in zlevels))
continue
if(!istype(M,/mob/new_player) && !isdeaf(M))
M << message_sound
datum/announcement/proc/Sound(var/message_sound)
PlaySound(message_sound)
datum/announcement/proc/Sound(var/message_sound, var/list/zlevels)
PlaySound(message_sound, zlevels)
datum/announcement/priority/Sound(var/message_sound)
if(message_sound)
@@ -124,12 +134,12 @@ datum/announcement/proc/Log(message as text, message_title as text)
/proc/ion_storm_announcement()
command_announcement.Announce("It has come to our attention that \the [station_name()] passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message)
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message, var/channel = "Common", var/zlevel)
if (ticker.current_state == GAME_STATE_PLAYING)
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
if(character.mind.role_alt_title)
rank = character.mind.role_alt_title
AnnounceArrivalSimple(character.real_name, rank, join_message)
AnnounceArrivalSimple(character.real_name, rank, join_message, channel, zlevels)
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive to the station shortly by shuttle", new_sound = 'sound/misc/notice3.ogg')
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer")
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive at the station shortly", var/channel = "Common", var/list/zlevels)
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer", channel, zlevels)
+1
View File
@@ -4,6 +4,7 @@
var/list/restricted_jobs = list() // Jobs that cannot be this antagonist (depending on config)
var/list/protected_jobs = list() // As above.
var/list/roundstart_restricted = list() //Jobs that can be this antag, but not at roundstart
var/avoid_silicons = FALSE // If we won't hand this antag role to silicons (AI, borg, etc)
// Strings.
var/welcome_text = "Cry havoc and let slip the dogs of war!"
@@ -10,6 +10,10 @@
return FALSE
if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs))
return FALSE
if(avoid_silicons)
var/datum/job/J = SSjob.get_job(player.assigned_role)
if(J.mob_type & JOB_SILICON)
return FALSE
return TRUE
/datum/antagonist/proc/antags_are_dead()
+1 -1
View File
@@ -5,7 +5,7 @@
role_text_plural = "Changelings"
bantype = "changeling"
feedback_tag = "changeling_objective"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director")
welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
antag_sound = 'sound/effects/antag_notice/ling_alert.ogg'
+2 -1
View File
@@ -11,7 +11,8 @@ var/datum/antagonist/cultist/cult
role_text = "Cultist"
role_text_plural = "Cultists"
bantype = "cultist"
restricted_jobs = list("Chaplain","AI", "Cyborg")
restricted_jobs = list("Chaplain")
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Colony Director")
role_type = BE_CULTIST
+1 -1
View File
@@ -29,7 +29,7 @@ var/datum/antagonist/loyalists/loyalists
faction_welcome = "Preserve NanoTrasen's interests against the traitorous recidivists amongst the crew. Protect the heads of staff with your life."
faction_indicator = "loyal"
faction_invisible = 1
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
/datum/antagonist/loyalists/New()
..()
+1 -1
View File
@@ -6,7 +6,7 @@ var/datum/antagonist/renegade/renegades
role_text = "Renegade"
role_text_plural = "Renegades"
bantype = "renegade"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
welcome_text = "Something's going to go wrong today, you can just feel it. You're paranoid, you've got a gun, and you're going to survive."
antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are a <b>minor</b> antagonist! Within the rules, \
@@ -29,7 +29,7 @@ var/datum/antagonist/revolutionary/revs
faction_indicator = "rev"
faction_invisible = 1
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
roundstart_restricted = list("Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
+1 -1
View File
@@ -6,7 +6,7 @@ var/datum/antagonist/stowaway/stowaways
role_text = "Stowaway"
role_text_plural = "Stowaways"
bantype = "renegade"
restricted_jobs = list("AI")
avoid_silicons = TRUE // This was previously allowing cyborgs to be stowaways, but given that they would just connect to the AI, it didn't make much sense
welcome_text = "People are known to run from many things, or to many things, for many different reasons. You happen to be one of those people."
antag_text = "You are a <b>minor</b> antagonist! Within the server rules, do whatever it is \
that you came to the station to do. Espionage, thievery, or just running from the law are all examples. \
+1 -1
View File
@@ -6,7 +6,7 @@ var/datum/antagonist/thug/thugs
role_text = "Thug"
role_text_plural = "Thugs"
bantype = "renegade"
restricted_jobs = list("AI", "Cyborg")
avoid_silicons = TRUE
welcome_text = "Sometimes, people just need to get messed up. Luckily, that's what you're here to do."
antag_text = "You are a <b>minor</b> antagonist! Within the server rules, do whatever it is \
that you came to the station to do, be it violence, theft, or just extreme self-defense. \
+13 -10
View File
@@ -47,7 +47,7 @@
luminosity = !(dynamic_lighting)
icon_state = ""
return INITIALIZE_HINT_LATELOAD // Areas tradiationally are initialized AFTER other atoms.
/area/LateInitialize()
@@ -338,17 +338,20 @@ var/list/mob/living/forced_ambiance_list = new
to_chat(mob, "<span class='notice'>The sudden appearance of gravity makes you fall to the floor!</span>")
playsound(get_turf(src), "bodyfall", 50, 1)
/area/proc/prison_break()
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = TRUE)
var/obj/machinery/power/apc/theAPC = get_apc()
if(theAPC.operating)
for(var/obj/machinery/power/apc/temp_apc in src)
temp_apc.overload_lighting(70)
for(var/obj/machinery/door/airlock/temp_airlock in src)
temp_airlock.prison_open()
for(var/obj/machinery/door/window/temp_windoor in src)
temp_windoor.open()
for(var/obj/machinery/door/blast/temp_blast in src)
temp_blast.open()
if(break_lights)
for(var/obj/machinery/power/apc/temp_apc in src)
temp_apc.overload_lighting(70)
if(open_doors)
for(var/obj/machinery/door/airlock/temp_airlock in src)
temp_airlock.prison_open()
for(var/obj/machinery/door/window/temp_windoor in src)
temp_windoor.open()
if(open_blast_doors)
for(var/obj/machinery/door/blast/temp_blast in src)
temp_blast.open()
/area/has_gravity()
return has_gravity
+6 -7
View File
@@ -169,7 +169,7 @@
return found
//All atoms
/atom/proc/examine(mob/user, var/distance = -1, var/infix = "", var/suffix = "")
/atom/proc/examine(mob/user, var/infix = "", var/suffix = "")
//This reformat names to get a/an properly working on item descriptions when they are bloody
var/f_name = "\a [src][infix]."
if(src.blood_DNA && !istype(src, /obj/effect/decal))
@@ -182,16 +182,15 @@
else
f_name += "oil-stained [name][infix]."
to_chat(user, "[bicon(src)] That's [f_name] [suffix]")
to_chat(user,desc)
var/list/output = list("[bicon(src)] That's [f_name] [suffix]", desc)
if(user.client?.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
to_chat(user, description_info)
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
output += description_info
if(user.client?.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL)
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL)
user.client.statpanel = "Examine" // Switch to stat panel
return distance == -1 || (get_dist(src, user) <= distance)
return output
// called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set.
// see code/modules/mob/mob_movement.dm for more.
+3 -10
View File
@@ -56,16 +56,9 @@
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/opened = 0
/obj/machinery/dna_scannernew/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src)
component_parts += new /obj/item/stack/cable_coil(src)
RefreshParts()
/obj/machinery/dna_scannernew/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
if (user.stat)
@@ -24,6 +24,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too.
var/last_shriek = null // world.time when the ling last used a shriek.
var/next_escape = 0 // world.time when the ling can next use Escape Restraints
var/thermal_sight = FALSE // Is our Vision Augmented? With thermals?
/datum/changeling/New(var/gender=FEMALE)
..()
@@ -64,8 +65,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind) return
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
verbs += /datum/changeling/proc/EvolutionMenu
verbs += /mob/proc/changeling_respec
verbs.Add(/datum/changeling/proc/EvolutionMenu)
verbs.Add(/mob/proc/changeling_respec)
add_language("Changeling")
var/lesser_form = !ishuman(src)
@@ -84,7 +85,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform) continue
if(!(P in src.verbs))
src.verbs += P.verbpath
verbs.Add(P.verbpath)
if(P.make_hud_button)
if(!src.ability_master)
src.ability_master = new /obj/screen/movable/ability_master(src)
@@ -111,7 +112,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind || !mind.changeling) return
for(var/datum/power/changeling/P in mind.changeling.purchased_powers)
if(P.isVerb)
verbs -= P.verbpath
verbs.Remove(P.verbpath)
var/obj/screen/ability/verb_based/changeling/C = ability_master.get_ability_by_proc_ref(P.verbpath)
if(C)
ability_master.remove_ability(C)
@@ -3,11 +3,11 @@
desc = "Permits us to syphon the DNA from a human. They become one with us, and we become stronger if they were of our kind."
ability_icon_state = "ling_absorb_dna"
genomecost = 0
verbpath = /mob/proc/changeling_absorb_dna
verbpath = /mob/living/proc/changeling_absorb_dna
//Absorbs the victim's DNA. Requires a strong grip on the victim.
//Doesn't cost anything as it's the most basic ability.
/mob/proc/changeling_absorb_dna()
/mob/living/proc/changeling_absorb_dna()
set category = "Changeling"
set name = "Absorb DNA"
@@ -67,8 +67,7 @@
to_chat(src, "<span class='notice'>We have absorbed [T]!</span>")
src.visible_message("<span class='danger'>[src] sucks the fluids from [T]!</span>")
to_chat(T, "<span class='danger'>You have been absorbed by the changeling!</span>")
if(src.nutrition < 400)
src.nutrition = min((src.nutrition + T.nutrition), 400)
adjust_nutrition(T.nutrition)
changeling.chem_charges += 10
if(changeling.readapts <= 0)
changeling.readapts = 0 //SANITYYYYYY
@@ -1,12 +1,11 @@
//Augmented Eyesight: Gives you thermal and night vision - bye bye, flashlights. Also, high DNA cost because of how powerful it is.
//Augmented Eyesight: Gives you thermal vision. Also, higher DNA cost because of how powerful it is.
/datum/power/changeling/augmented_eyesight
name = "Augmented Eyesight"
desc = "Creates heat receptors in our eyes and dramatically increases light sensing ability."
helptext = "Grants us night vision and thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
helptext = "Grants us thermal vision. It may be toggled on or off. We will become more vulnerable to flash-based devices while active."
ability_icon_state = "ling_augmented_eyesight"
genomecost = 2
var/active = 0 //Whether or not vision is enhanced
verbpath = /mob/proc/changeling_augmented_eyesight
/mob/proc/changeling_augmented_eyesight()
@@ -17,23 +16,22 @@
var/datum/changeling/changeling = changeling_power(5,0,100,CONSCIOUS)
if(!changeling)
return 0
src.mind.changeling.chem_charges -= 5
src.sight |= SEE_MOBS
/*
var/mob/living/carbon/human/C = src
active = !active
changeling.thermal_sight = !changeling.thermal_sight
var/active = changeling.thermal_sight
if(active)
to_chat(C, "<span class='notice'>We feel a minute twitch in our eyes, and darkness creeps away.</span>")
C.sight |= SEE_MOBS
C.permanent_sight_flags |= SEE_MOBS
C.see_in_dark = 8
C.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
src.mind.changeling.chem_charges -= 5
to_chat(C, "<span class='notice'>We feel a minute twitch in our eyes, and a hidden layer to the world is revealed.</span>")
C.add_modifier(/datum/modifier/changeling/thermal_sight, 0, src)
// C.permanent_sight_flags |= SEE_MOBS
// C.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
else
to_chat(C, "<span class='notice'>Our vision dulls. Shadows gather.</span>")
C.sight &= ~SEE_MOBS
C.permanent_sight_flags &= ~SEE_MOBS
C.see_in_dark = 0
C.dna.species.invis_sight = initial(user.dna.species.invis_sight)
to_chat(C, "<span class='notice'>Our vision dulls.</span>")
C.remove_modifiers_of_type(/datum/modifier/changeling/thermal_sight)
// C.permanent_sight_flags &= ~SEE_MOBS
// C.dna.species.invis_sight = initial(user.dna.species.invis_sight)
return 1
*/
@@ -14,7 +14,6 @@
on_expired_text = "<span class='notice'>Our protective armor underneath our skin fades as we absorb it.</span>"
max_health_flat = 50
//Increases macimum chemical storage
/mob/proc/changeling_endoarmor()
if(ishuman(src))
var/mob/living/carbon/human/H = src
@@ -43,7 +43,10 @@
spawn(rand(2 MINUTES, 4 MINUTES))
//The ling will now be able to choose when to revive
src.verbs += /mob/proc/changeling_revive
verbs.Add(/mob/proc/changeling_revive)
new /obj/changeling_revive_holder(src)
to_chat(src, "<span class='notice'><font size='5'>We are ready to rise. Use the <b>Revive</b> verb when you are ready.</font></span>")
feedback_add_details("changeling_powers","FD")
@@ -17,6 +17,7 @@
ling_datum.purchased_powers = list() //Then wipe all the powers we bought.
ling_datum.geneticpoints = ling_datum.max_geneticpoints //Now refund our points to the maximum.
ling_datum.chem_recharge_rate = 0.5 //If glands were bought, revert that upgrade.
ling_datum.thermal_sight = FALSE
src.mind.changeling.recursive_enhancement = 0 //Ensures this is cleared
ling_datum.chem_storage = 50
@@ -82,10 +82,28 @@
C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
src.verbs -= /mob/proc/changeling_revive
verbs.Remove(/mob/proc/changeling_revive)
// re-add our changeling powers
C.make_changeling()
return 1
//Revive from revival stasis, but one level removed, as the tab refuses to update. Placed in its own tab to avoid hyper-exploding the original tab through the same name being used.
/obj/changeling_revive_holder
name = "strange object"
desc = "Please report this object's existence to the dev team! You shouldn't see it."
mouse_opacity = FALSE
alpha = 1
/obj/changeling_revive_holder/verb/ling_revive()
set src = usr.contents
set category = "Regenerate"
set name = "Revive"
set desc = "We are ready to revive ourselves on command."
if(iscarbon(usr))
var/mob/living/carbon/C = usr
C.changeling_revive()
qdel(src)
+5 -4
View File
@@ -84,9 +84,9 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
..()
examine(mob/user)
..()
. = ..()
if(iscultist(user))
to_chat(user, "This spell circle reads: <i>[word1] [word2] [word3]</i>.")
. += "This spell circle reads: <i>[word1] [word2] [word3]</i>."
attackby(I as obj, user as mob)
@@ -422,10 +422,11 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
return
examine(mob/user)
. = ..()
if(!iscultist(user))
to_chat(user, "An old, dusty tome with frayed edges and a sinister looking cover.")
. += "An old, dusty tome with frayed edges and a sinister looking cover."
else
to_chat(user, "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though.")
. += "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though."
/obj/item/weapon/book/tome/cultify()
return
+1 -1
View File
@@ -34,7 +34,7 @@
if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT))
return // Don't do anything if the shuttle's coming.
var/mills = round_duration_in_ticks
var/mills = round_duration_in_ds
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)
+2 -2
View File
@@ -51,10 +51,10 @@
icon_state = "pinonfar"
/obj/item/weapon/pinpointer/examine(mob/user)
..(user)
. = ..()
for(var/obj/machinery/nuclearbomb/bomb in machines)
if(bomb.timing)
to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]")
. += "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]"
@@ -23,8 +23,8 @@
uses = 1
/obj/item/weapon/disposable_teleporter/examine(mob/user)
..()
to_chat(user, "[uses] uses remaining.")
. = ..()
. += "[uses] uses remaining."
/obj/item/weapon/disposable_teleporter/attack_self(mob/user as mob)
if(!uses)
@@ -83,7 +83,7 @@
#define SIPHON_CORE_TO_ENERGY 0.5
// This is called every tick, so long as a link exists between the target and the Technomancer.
/obj/item/weapon/spell/energy_siphon/proc/siphon(atom/movable/siphoning, mob/user)
/obj/item/weapon/spell/energy_siphon/proc/siphon(atom/movable/siphoning, mob/living/user)
var/list/things_to_drain = things_to_siphon // Temporary list copy of what we're gonna steal from.
var/charge_to_give = 0 // How much energy to give to the Technomancer at the end.
var/flow_remaining = calculate_spell_power(flow_rate)
@@ -141,7 +141,7 @@
if( (core.max_energy - core.energy) < charge_to_give ) // We have some overflow, if this is true.
if(user.isSynthetic()) // Let's do something with it, if we're a robot.
charge_to_give = charge_to_give - (core.max_energy - core.energy)
user.nutrition = min(user.nutrition + (charge_to_give / SIPHON_FBP_TO_ENERGY), 400)
user.adjust_nutrition(charge_to_give / SIPHON_FBP_TO_ENERGY)
to_chat(user, "<span class='notice'>Redirected energy to internal microcell.</span>")
else
to_chat(user, "<span class='notice'>Stolen [charge_to_give * CELLRATE] kJ.</span>")
+1
View File
@@ -31,6 +31,7 @@
var/outfit_type // What outfit datum does this job use in its default title?
var/offmap_spawn = FALSE // Do we require weird and special spawning and datacore handling?
var/mob_type = JOB_CARBON // Bitflags representing mob type this job spawns
// Description of the job's role and minimum responsibilities.
var/job_description = "This Job doesn't have a description! Please report it!"
+2
View File
@@ -18,6 +18,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
mob_type = JOB_SILICON_AI
outfit_type = /decl/hierarchy/outfit/job/silicon/ai
job_description = "The AI oversees the operation of the station and its crew, but has no real authority over them. \
The AI is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \
@@ -54,6 +55,7 @@
economic_modifier = 0
has_headset = FALSE
assignable = FALSE
mob_type = JOB_SILICON_ROBOT
outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg
job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \
to follow its Laws."
+60 -48
View File
@@ -360,54 +360,64 @@ var/global/datum/controller/occupations/job_master
//Equip custom gear loadout.
var/list/custom_equip_slots = list() //If more than one item takes the same slot, all after the first one spawn in storage.
var/list/custom_equip_leftovers = list()
if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI")
if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON))
for(var/thing in H.client.prefs.gear)
var/datum/gear/G = gear_datums[thing]
if(G)
var/permitted
if(G.allowed_roles)
for(var/job_name in G.allowed_roles)
if(job.title == job_name)
permitted = 1
if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile)
continue
var/permitted
// Check if it is restricted to certain roles
if(G.allowed_roles)
for(var/job_name in G.allowed_roles)
if(job.title == job_name)
permitted = 1
else
permitted = 1
// Check if they're whitelisted for this gear (in alien whitelist? seriously?)
if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
permitted = 0
// If they aren't, tell them
if(!permitted)
to_chat(H, "<span class='warning'>Your current species, job or whitelist status does not permit you to spawn with [thing]!</span>")
continue
// Implants get special treatment
if(G.slot == "implant")
var/obj/item/weapon/implant/I = G.spawn_item(H)
I.invisibility = 100
I.implant_loadout(H)
continue
// Try desperately (and sorta poorly) to equip the item
if(G.slot && !(G.slot in custom_equip_slots))
var/metadata = H.client.prefs.gear[G.display_name]
if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
custom_equip_leftovers += thing
else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
to_chat(H, "<span class='notice'>Equipping you with \the [thing]!</span>")
custom_equip_slots.Add(G.slot)
else
permitted = 1
custom_equip_leftovers.Add(thing)
else
spawn_in_storage += thing
if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted]))
//if(G.whitelisted && (G.whitelisted != H.species.name || !is_alien_whitelisted(H, G.whitelisted)))
permitted = 0
if(!permitted)
to_chat(H, "<span class='warning'>Your current species, job or whitelist status does not permit you to spawn with [thing]!</span>")
continue
if(G.slot == "implant")
var/obj/item/weapon/implant/I = G.spawn_item(H)
I.invisibility = 100
I.implant_loadout(H)
continue
if(G.slot && !(G.slot in custom_equip_slots))
// This is a miserable way to fix the loadout overwrite bug, but the alternative requires
// adding an arg to a bunch of different procs. Will look into it after this merge. ~ Z
var/metadata = H.client.prefs.gear[G.display_name]
if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
custom_equip_leftovers += thing
else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
to_chat(H, "<span class='notice'>Equipping you with \the [thing]!</span>")
custom_equip_slots.Add(G.slot)
else
custom_equip_leftovers.Add(thing)
else
spawn_in_storage += thing
//Equip job items.
// Set up their account
job.setup_account(H)
// Equip job items.
job.equip(H, H.mind ? H.mind.role_alt_title : "")
// Stick their fingerprints on literally everything
job.apply_fingerprints(H)
if(job.title != "Cyborg" && job.title != "AI")
// Only non-silicons get post-job-equip equipment
if(!(job.mob_type & JOB_SILICON))
H.equip_post_job()
//If some custom items could not be equipped before, try again now.
// If some custom items could not be equipped before, try again now.
for(var/thing in custom_equip_leftovers)
var/datum/gear/G = gear_datums[thing]
if(G.slot in custom_equip_slots)
@@ -442,14 +452,16 @@ var/global/datum/controller/occupations/job_master
H.mind.assigned_role = rank
alt_title = H.mind.role_alt_title
switch(rank)
if("Cyborg")
return H.Robotize()
if("AI")
return H
if("Colony Director")
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
// If we're a silicon, we may be done at this point
if(job.mob_type & JOB_SILICON_ROBOT)
return H.Robotize()
if(job.mob_type & JOB_SILICON_AI)
return H
// TWEET PEEP
if(rank == "Colony Director")
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
//Deferred item spawning.
if(spawn_in_storage && spawn_in_storage.len)
@@ -559,7 +571,7 @@ var/global/datum/controller/occupations/job_master
if(!J) continue
J.total_positions = text2num(value)
J.spawn_positions = text2num(value)
if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now
if(J.mob_type & JOB_SILICON)
J.total_positions = 0
return 1
+2 -2
View File
@@ -49,8 +49,8 @@
to_chat(usr, "<span class='warning'>There's no more cable on the reel.</span>")
/obj/machinery/cablelayer/examine(mob/user)
..()
to_chat(user, "\The [src]'s cable reel has [cable.amount] length\s left.")
. = ..()
. += "[src]'s cable reel has [cable.amount] length\s left."
/obj/machinery/cablelayer/proc/load_cable(var/obj/item/stack/cable_coil/CC)
if(istype(CC) && CC.amount)
+3 -14
View File
@@ -180,21 +180,10 @@
idle_power_usage = 15
active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors.
/obj/machinery/sleeper/New()
..()
/obj/machinery/sleeper/Initialize()
. = ..()
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
default_apply_parts()
/obj/machinery/sleeper/Destroy()
if(console)
+3 -8
View File
@@ -15,14 +15,9 @@
light_color = "#00FF00"
var/obj/machinery/body_scanconsole/console
/obj/machinery/bodyscanner/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
RefreshParts()
/obj/machinery/bodyscanner/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/bodyscanner/Destroy()
if(console)
+2 -2
View File
@@ -383,7 +383,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = command
@@ -445,7 +445,7 @@
var/datum/signal/alert_signal = new
alert_signal.source = src
alert_signal.transmission_method = 1
alert_signal.transmission_method = TRANSMISSION_RADIO
alert_signal.data["zone"] = alarm_area.name
alert_signal.data["type"] = "Atmospheric"
+7 -7
View File
@@ -29,7 +29,7 @@
/obj/machinery/air_sensor/process()
if(on)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
@@ -212,7 +212,7 @@ obj/machinery/computer/general_air_control/Destroy()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
if(href_list["in_refresh_status"])
input_info = null
@@ -322,7 +322,7 @@ obj/machinery/computer/general_air_control/Destroy()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
if(href_list["in_refresh_status"])
input_info = null
@@ -383,7 +383,7 @@ obj/machinery/computer/general_air_control/Destroy()
injecting = 1
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -445,7 +445,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
@@ -463,7 +463,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
@@ -478,7 +478,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
+8 -10
View File
@@ -67,7 +67,7 @@
var/datum/signal/signal = new
signal.source = src
signal.transmission_method = 1
signal.transmission_method = TRANSMISSION_RADIO
signal.data = list(
"tag" = id,
"device" = "AM",
@@ -77,24 +77,22 @@
radio_connection.post_signal(src, signal)
/obj/machinery/meter/examine(mob/user)
var/t = "A gas flow meter. "
. = ..()
if(get_dist(user, src) > 3 && !(istype(user, /mob/living/silicon/ai) || istype(user, /mob/observer/dead)))
t += "<span class='warning'>You are too far away to read it.</span>"
. += "<span class='warning'>You are too far away to read it.</span>"
else if(stat & (NOPOWER|BROKEN))
t += "<span class='warning'>The display is off.</span>"
. += "<span class='warning'>The display is off.</span>"
else if(src.target)
else if(target)
var/datum/gas_mixture/environment = target.return_air()
if(environment)
t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]&deg;C)"
. += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]&deg;C)"
else
t += "The sensor error light is blinking."
. += "The sensor error light is blinking."
else
t += "The connect error light is blinking."
to_chat(user,t)
. += "The connect error light is blinking."
/obj/machinery/meter/Click()
+334 -322
View File
@@ -1,322 +1,334 @@
/obj/machinery/autolathe
name = "autolathe"
desc = "It produces items using metal and glass."
icon_state = "autolathe"
density = 1
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
var/mat_efficiency = 1
var/build_time = 50
var/datum/wires/autolathe/wires = null
/obj/machinery/autolathe/New()
..()
wires = new(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
wires = null
return ..()
/obj/machinery/autolathe/proc/update_recipe_list()
if(!machine_recipes)
if(!autolathe_recipes)
autolathe_recipes = new()
machine_recipes = autolathe_recipes
current_category = machine_recipes.categories[1]
/obj/machinery/autolathe/interact(mob/user as mob)
update_recipe_list()
if(..() || (disabled && !panel_open))
to_chat(user, "<span class='danger'>\The [src] is disabled!</span>")
return
if(shocked)
shock(user, 50)
var/list/dat = list()
dat += "<center><h1>Autolathe Control Panel</h1><hr/>"
if(!disabled)
dat += "<table width = '100%'>"
var/list/material_top = list("<tr>")
var/list/material_bottom = list("<tr>")
for(var/material in stored_material)
material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
dat += "[material_top.Join()]</tr>[material_bottom.Join()]</tr></table><hr>"
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked)
continue
var/can_make = 1
var/list/material_string = list()
var/list/multiplier_string = list()
var/max_sheets
var/comma
if(!R.resources || !R.resources.len)
material_string += "No resources required.</td>"
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
var/coeff = (R.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(R.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(R.resources[material]*coeff))
can_make = 0
if(!comma)
comma = 1
else
material_string += ", "
material_string += "[round(R.resources[material] * coeff)] [material]"
material_string += ".<br></td>"
//Build list of multipliers for sheets.
if(R.is_stack)
if(max_sheets && max_sheets > 0)
max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type.
multiplier_string += "<br>"
for(var/i = 5;i<max_sheets;i*=2) //5,10,20,40...
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[i]'>\[x[i]\]</a>"
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[max_sheets]'>\[x[max_sheets]\]</a>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : ""][R.name][can_make ? "</a>" : ""]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string.Join()]</td><td align = right>[material_string.Join()]</tr>"
dat += "</table><hr>"
user << browse(dat.Join(), "window=autolathe")
onclose(user, "autolathe")
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(stat)
return
if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(O.is_multitool() || O.is_wirecutter())
wires.Interact(user)
return
if(O.loc != user && !(istype(O,/obj/item/stack)))
return 0
if(is_robot_module(O))
return 0
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38)) // Prevents ammo recycling exploit with speedloaders.
to_chat(user, "\The [O] is too hazardous to recycle with the autolathe!")
return
/* ToDo: Make this actually check for ammo and change the value of the magazine if it's empty. -Spades
var/obj/item/ammo_magazine/speedloader = O
if(speedloader.stored_ammo)
to_chat(user, "\The [speedloader] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return
else
speedloader.matter = list(DEFAULT_WALL_MATERIAL = 75) // It's just a hunk of scrap metal now.
if(istype(O,/obj/item/ammo_magazine)) // This was just for immersion consistency with above.
var/obj/item/ammo_magazine/mag = O
if(mag.stored_ammo)
to_chat(user, "\The [mag] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return*/
//Resources are being loaded.
var/obj/item/eating = O
if(!eating.matter)
to_chat(user, "\The [eating] does not contain significant amounts of useful materials and cannot be accepted.")
return
var/filltype = 0 // Used to determine message.
var/total_used = 0 // Amount of material used.
var/mass_per_sheet = 0 // Amount of material constituting one sheet.
for(var/material in eating.matter)
if(isnull(stored_material[material]) || isnull(storage_capacity[material]))
continue
if(stored_material[material] >= storage_capacity[material])
continue
var/total_material = eating.matter[material]
//If it's a stack, we eat multiple sheets.
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
total_material *= stack.get_amount()
if(stored_material[material] + total_material > storage_capacity[material])
total_material = storage_capacity[material] - stored_material[material]
filltype = 1
else
filltype = 2
stored_material[material] += total_material
total_used += total_material
mass_per_sheet += eating.matter[material]
if(!filltype)
to_chat(user, "<span class='notice'>\The [src] is full. Please remove material from the autolathe in order to insert more.</span>")
return
else if(filltype == 1)
to_chat(user, "You fill \the [src] to capacity with \the [eating].")
else
to_chat(user, "You fill \the [src] with \the [eating].")
flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
else
user.remove_from_mob(O)
qdel(O)
updateUsrDialog()
return
/obj/machinery/autolathe/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["change_category"])
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
if(href_list["make"] && machine_recipes)
var/multiplier = text2num(href_list["multiplier"])
var/datum/category_item/autolathe/making = locate(href_list["make"]) in current_category.items
//Exploit detection, not sure if necessary after rewrite.
if(!making || multiplier < 0 || multiplier > 100)
var/turf/exploit_loc = get_turf(usr)
message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate an item! ([exploit_loc ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[exploit_loc.x];Y=[exploit_loc.y];Z=[exploit_loc.z]'>JMP</a>" : "null"])", 0)
log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate an item!")
return
busy = 1
update_use_power(USE_POWER_ACTIVE)
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
update_icon() // So lid closes
sleep(build_time)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
if(!making || !src) return
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
updateUsrDialog()
/obj/machinery/autolathe/update_icon()
if(panel_open)
icon_state = "autolathe_t"
else if(busy)
icon_state = "autolathe_n"
else
if(icon_state == "autolathe_n")
flick("autolathe_u", src) // If lid WAS closed, show opening animation
icon_state = "autolathe"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
var/mb_rating = 0
var/man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
var/material/M = get_material_by_name(mat)
if(!istype(M))
continue
var/obj/item/stack/material/S = new M.stack_type(get_turf(src))
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
else
qdel(S)
..()
return 1
/obj/machinery/autolathe
name = "autolathe"
desc = "It produces items using metal and glass."
icon_state = "autolathe"
density = 1
anchored = 1
use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
var/shocked = 0
var/busy = 0
var/mat_efficiency = 1
var/build_time = 50
var/datum/wires/autolathe/wires = null
var/filtertext
/obj/machinery/autolathe/Initialize()
. = ..()
wires = new(src)
default_apply_parts()
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
wires = null
return ..()
/obj/machinery/autolathe/proc/update_recipe_list()
if(!machine_recipes)
if(!autolathe_recipes)
autolathe_recipes = new()
machine_recipes = autolathe_recipes
current_category = machine_recipes.categories[1]
/obj/machinery/autolathe/interact(mob/user as mob)
update_recipe_list()
if(..() || (disabled && !panel_open))
to_chat(user, "<span class='danger'>\The [src] is disabled!</span>")
return
if(shocked)
shock(user, 50)
var/list/dat = list()
dat += "<center><h1>Autolathe Control Panel</h1><hr/>"
if(!disabled)
dat += "<table width = '100%'>"
var/list/material_top = list("<tr>")
var/list/material_bottom = list("<tr>")
for(var/material in stored_material)
material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
dat += "[material_top.Join()]</tr>[material_bottom.Join()]</tr></table><hr>"
dat += "<b>Filter:</b> <a href='?src=\ref[src];setfilter=1'>[filtertext ? filtertext : "None Set"]</a><br>"
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked)
continue
if(filtertext && findtext(R.name, filtertext) == 0)
continue
var/can_make = 1
var/list/material_string = list()
var/list/multiplier_string = list()
var/max_sheets
var/comma
if(!R.resources || !R.resources.len)
material_string += "No resources required.</td>"
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
var/coeff = (R.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(R.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(R.resources[material]*coeff))
can_make = 0
if(!comma)
comma = 1
else
material_string += ", "
material_string += "[round(R.resources[material] * coeff)] [material]"
material_string += ".<br></td>"
//Build list of multipliers for sheets.
if(R.is_stack)
if(max_sheets && max_sheets > 0)
max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type.
multiplier_string += "<br>"
for(var/i = 5;i<max_sheets;i*=2) //5,10,20,40...
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[i]'>\[x[i]\]</a>"
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[max_sheets]'>\[x[max_sheets]\]</a>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : "<span class='linkOff'>"][R.name][can_make ? "</a>" : "</span>"]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string.Join()]</td><td align = right>[material_string.Join()]</tr>"
dat += "</table><hr>"
dat = jointext(dat, null)
var/datum/browser/popup = new(user, "autolathe", "Autolathe Production Menu", 550, 700)
popup.set_content(dat)
popup.open()
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
return
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(stat)
return
if(panel_open)
//Don't eat multitools or wirecutters used on an open lathe.
if(O.is_multitool() || O.is_wirecutter())
wires.Interact(user)
return
if(O.loc != user && !(istype(O,/obj/item/stack)))
return 0
if(is_robot_module(O))
return 0
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38)) // Prevents ammo recycling exploit with speedloaders.
to_chat(user, "\The [O] is too hazardous to recycle with the autolathe!")
return
/* ToDo: Make this actually check for ammo and change the value of the magazine if it's empty. -Spades
var/obj/item/ammo_magazine/speedloader = O
if(speedloader.stored_ammo)
to_chat(user, "\The [speedloader] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return
else
speedloader.matter = list(DEFAULT_WALL_MATERIAL = 75) // It's just a hunk of scrap metal now.
if(istype(O,/obj/item/ammo_magazine)) // This was just for immersion consistency with above.
var/obj/item/ammo_magazine/mag = O
if(mag.stored_ammo)
to_chat(user, "\The [mag] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return*/
//Resources are being loaded.
var/obj/item/eating = O
if(!eating.matter)
to_chat(user, "\The [eating] does not contain significant amounts of useful materials and cannot be accepted.")
return
var/filltype = 0 // Used to determine message.
var/total_used = 0 // Amount of material used.
var/mass_per_sheet = 0 // Amount of material constituting one sheet.
for(var/material in eating.matter)
if(isnull(stored_material[material]) || isnull(storage_capacity[material]))
continue
if(stored_material[material] >= storage_capacity[material])
continue
var/total_material = eating.matter[material]
//If it's a stack, we eat multiple sheets.
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
total_material *= stack.get_amount()
if(stored_material[material] + total_material > storage_capacity[material])
total_material = storage_capacity[material] - stored_material[material]
filltype = 1
else
filltype = 2
stored_material[material] += total_material
total_used += total_material
mass_per_sheet += eating.matter[material]
if(!filltype)
to_chat(user, "<span class='notice'>\The [src] is full. Please remove material from the autolathe in order to insert more.</span>")
return
else if(filltype == 1)
to_chat(user, "You fill \the [src] to capacity with \the [eating].")
else
to_chat(user, "You fill \the [src] with \the [eating].")
flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z
if(istype(eating,/obj/item/stack))
var/obj/item/stack/stack = eating
stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials.
else
user.remove_from_mob(O)
qdel(O)
updateUsrDialog()
return
/obj/machinery/autolathe/attack_hand(mob/user as mob)
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
return
else if(href_list["setfilter"])
var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", filtertext) as null|text
if(!Adjacent(usr))
return
if(isnull(filterstring)) //Clicked Cancel
return
if(filterstring == "") //Cleared value
filtertext = null
filtertext = sanitize(filterstring, 25)
if(href_list["change_category"])
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
if(href_list["make"] && machine_recipes)
var/multiplier = text2num(href_list["multiplier"])
var/datum/category_item/autolathe/making = locate(href_list["make"]) in current_category.items
//Exploit detection, not sure if necessary after rewrite.
if(!making || multiplier < 0 || multiplier > 100)
var/turf/exploit_loc = get_turf(usr)
message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate an item! ([exploit_loc ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[exploit_loc.x];Y=[exploit_loc.y];Z=[exploit_loc.z]'>JMP</a>" : "null"])", 0)
log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate an item!")
return
busy = 1
update_use_power(USE_POWER_ACTIVE)
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
update_icon() // So lid closes
sleep(build_time)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
if(!making || !src) return
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
updateUsrDialog()
/obj/machinery/autolathe/update_icon()
if(panel_open)
icon_state = "autolathe_t"
else if(busy)
icon_state = "autolathe_n"
else
if(icon_state == "autolathe_n")
flick("autolathe_u", src) // If lid WAS closed, show opening animation
icon_state = "autolathe"
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
var/mb_rating = 0
var/man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
var/material/M = get_material_by_name(mat)
if(!istype(M))
continue
var/obj/item/stack/material/S = new M.stack_type(get_turf(src))
if(stored_material[mat] > S.perunit)
S.amount = round(stored_material[mat] / S.perunit)
else
qdel(S)
..()
return 1
+3 -6
View File
@@ -15,17 +15,14 @@
var/build_eff = 1
var/eat_eff = 1
/obj/machinery/biogenerator/New()
..()
/obj/machinery/biogenerator/Initialize()
. = ..()
var/datum/reagents/R = new/datum/reagents(1000)
reagents = R
R.my_atom = src
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
default_apply_parts()
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
+7 -11
View File
@@ -75,21 +75,17 @@
if(printing)
overlays += "bioprinter_working"
/obj/machinery/organ_printer/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
/obj/machinery/organ_printer/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/organ_printer/examine(var/mob/user)
. = ..()
var/biomass = get_biomass_volume()
if(biomass)
to_chat(user, "<span class='notice'>It is loaded with [biomass] units of biomass.</span>")
. += "<span class='notice'>It is loaded with [biomass] units of biomass.</span>"
else
to_chat(user, "<span class='notice'>It is not loaded with any biomass.</span>")
. += "<span class='notice'>It is not loaded with any biomass.</span>"
/obj/machinery/organ_printer/RefreshParts()
// Print Delay updating
@@ -272,7 +268,7 @@
icon_state = "bioprinter"
circuit = /obj/item/weapon/circuitboard/bioprinter
/obj/machinery/organ_printer/flesh/full/New()
/obj/machinery/organ_printer/flesh/full/Initialize()
. = ..()
container = new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src)
+2
View File
@@ -33,6 +33,7 @@
var/busy = 0
var/on_open_network = 0
var/always_visible = FALSE //Visable from any map, good for entertainment network cameras
var/affected_by_emp_until = 0
@@ -467,6 +468,7 @@
cam["name"] = sanitize(c_tag)
cam["deact"] = !can_use()
cam["camera"] = "\ref[src]"
cam["omni"] = always_visible
cam["x"] = x
cam["y"] = y
cam["z"] = z
+1
View File
@@ -102,6 +102,7 @@ var/global/list/engineering_networks = list(
/obj/machinery/camera/network/thunder
network = list(NETWORK_THUNDER)
invuln = 1
always_visible = TRUE
// EMP
+8 -13
View File
@@ -13,13 +13,9 @@
var/chargelevel = -1
circuit = /obj/item/weapon/circuitboard/cell_charger
/obj/machinery/cell_charger/New()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
..()
return
/obj/machinery/cell_charger/Initialize()
. = ..()
default_apply_parts()
/obj/machinery/cell_charger/update_icon()
icon_state = "ccharger[charging ? 1 : 0]"
@@ -39,12 +35,11 @@
overlays.Cut()
/obj/machinery/cell_charger/examine(mob/user)
if(!..(user, 5))
return
to_chat(user, "[charging ? "[charging]" : "Nothing"] is in [src].")
if(charging)
to_chat(user, "Current charge: [charging.charge] / [charging.maxcharge]")
. = ..()
if(get_dist(user, src) <= 5)
. += "[charging ? "[charging]" : "Nothing"] is in [src]."
if(charging)
. += "Current charge: [charging.charge] / [charging.maxcharge]"
/obj/machinery/cell_charger/attackby(obj/item/weapon/W, mob/user)
if(stat & BROKEN)
+5 -14
View File
@@ -46,17 +46,9 @@
var/list/containers = list() // Beakers for our liquid biomass
var/container_limit = 3 // How many beakers can the machine hold?
/obj/machinery/clonepod/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
/obj/machinery/clonepod/Initialize()
. = ..()
default_apply_parts()
update_icon()
/obj/machinery/clonepod/attack_ai(mob/user as mob)
@@ -534,9 +526,8 @@
to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
/obj/item/weapon/disk/data/examine(mob/user)
..(user)
to_chat(user, text("The write-protect tab is set to [read_only ? "protected" : "unprotected"]."))
return
. = ..()
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
/*
* Diskette Box
+7 -8
View File
@@ -384,7 +384,7 @@
spaceport_freebie = 0
last_spaceport_action = ""
/obj/machinery/computer/arcade/orion_trail/attack_hand(mob/user)
/obj/machinery/computer/arcade/orion_trail/attack_hand(mob/living/user)
if(..())
return
if(fuel <= 0 || food <=0 || settlers.len == 0)
@@ -1020,13 +1020,12 @@
var/active = 0 //if the ship is on
/obj/item/weapon/orion_ship/examine(mob/user)
..()
if(!(in_range(user, src)))
return
if(!active)
to_chat(user, span("notice", "There's a little switch on the bottom. It's flipped down."))
else
to_chat(user, span("notice", "There's a little switch on the bottom. It's flipped up."))
. = ..()
if(in_range(user, src))
if(!active)
. += span("notice", "There's a little switch on the bottom. It's flipped down.")
else
. += span("notice", "There's a little switch on the bottom. It's flipped up.")
/obj/item/weapon/orion_ship/attack_self(mob/user)
if(active)
@@ -21,7 +21,7 @@
/obj/machinery/computer/atmoscontrol/laptop
name = "Atmospherics Laptop"
desc = "A cheap laptop."
icon_screen = "atmoslaptop"
icon_screen = "medlaptop"
icon_state = "laptop"
icon_keyboard = "laptop_key"
density = 0
+5 -5
View File
@@ -43,11 +43,14 @@
data["current_camera"] = current_camera ? current_camera.nano_structure() : null
data["current_network"] = current_network
data["networks"] = network ? network : list()
var/map_levels = using_map.get_map_levels(src.z, TRUE)
data["map_levels"] = map_levels
if(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels)
if(current_camera)
switch_to_camera(user, current_camera)
data["map_levels"] = using_map.get_map_levels(src.z)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -91,9 +94,6 @@
. = ..()
/obj/machinery/computer/security/attack_hand(var/mob/user as mob)
if (using_map && !(src.z in using_map.contact_levels))
to_chat(user, "<span class='danger'>Unable to establish a connection:</span> You're too far away from the station!")
return
if(stat & (NOPOWER|BROKEN)) return
if(!isAI(user))
@@ -544,7 +544,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
+3 -3
View File
@@ -19,11 +19,11 @@
return temp_access
/obj/item/weapon/card/id/guest/examine(mob/user)
..(user)
. = ..()
if (world.time < expiration_time)
to_chat(user, "<span class='notice'>This pass expires at [worldtime2stationtime(expiration_time)].</span>")
. += "<span class='notice'>This pass expires at [worldtime2stationtime(expiration_time)].</span>"
else
to_chat(user, "<span class='warning'>It expired at [worldtime2stationtime(expiration_time)].</span>")
. += "<span class='warning'>It expired at [worldtime2stationtime(expiration_time)].</span>"
/obj/item/weapon/card/id/guest/read()
if(!Adjacent(usr))
@@ -121,7 +121,7 @@ var/prison_shuttle_timeleft = 0
if(!frequency) return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
frequency.post_signal(src, status_signal)
return
+16 -55
View File
@@ -2,69 +2,30 @@
name = "automated shutoff valve monitor"
desc = "Console used to remotely monitor shutoff valves on the station."
icon_keyboard = "power_key"
icon_screen = "power:0"
icon_screen = "power_monitor"
light_color = "#a97faa"
circuit = /obj/item/weapon/circuitboard/shutoff_monitor
var/datum/nano_module/shutoff_monitor/monitor
/obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user)
/obj/machinery/computer/shutoff_monitor/New()
..()
monitor = new(src)
/obj/machinery/computer/shutoff_monitor/Destroy()
qdel(monitor)
monitor = null
..()
/obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user as mob)
..()
ui_interact(user)
/obj/machinery/computer/shutoff_monitor/attack_robot(var/mob/user) // Borgs and AI will want to see this too
..()
ui_interact(user)
/obj/machinery/computer/shutoff_monitor/attack_ai(var/mob/user)
ui_interact(user)
/obj/machinery/computer/shutoff_monitor/ui_interact(mob/user, ui_key = "shutoff_monitor", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
var/data[0]
data["valves"] = list()
for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves)
data["valves"][++data["valves"].len] = list("name" = S.name, "enable" = S.close_on_leaks, "open" = S.open, "x" = S.x, "y" = S.y, "z" = S.z, "ref" = "\ref[S]")
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "shutoff_monitor.tmpl", "Automated Shutoff Valve Monitor", 625, 700, state = key_state)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every 20 Master Controller tick
ui.set_auto_update(20) // Longer term to reduce the rate of data collection and processing
/obj/machinery/computer/shutoff_monitor/Topic(href, href_list)
if(..())
return 1
if(href_list["toggle_enable"])
var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_enable"])
// Invalid ref
if(!istype(S))
return 0
S.close_on_leaks = !S.close_on_leaks
if(href_list["toggle_open"])
var/obj/machinery/atmospherics/valve/shutoff/S = locate(href_list["toggle_open"])
// Invalid ref
if(!istype(S))
return 0
if(S.open)
S.close()
else
S.open()
return
/obj/machinery/computer/shutoff_monitor/ui_interact(mob/user, ui_key = "shutoff_monitor", var/datum/nanoui/ui = null, var/force_open = 1)
monitor.ui_interact(user, ui_key, ui, force_open)
/obj/machinery/computer/shutoff_monitor/update_icon()
..()
if(!(stat & (NOPOWER|BROKEN)))
add_overlay("ai-fixer-empty")
else
cut_overlay("ai-fixer-empty")
+1 -1
View File
@@ -421,7 +421,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
frequency.post_signal(src, status_signal)
+2 -1
View File
@@ -215,6 +215,7 @@
var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward."
var/on_store_visible_message_1 = "hums and hisses as it moves" //We need two variables because byond doesn't let us have variables inside strings at compile-time.
var/on_store_visible_message_2 = "into storage."
var/announce_channel = "Common"
var/allow_occupant_types = list(/mob/living/carbon/human)
var/disallow_occupant_types = list()
@@ -467,7 +468,7 @@
control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]"
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE))
//visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3)
visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].</span>", 3)
+4 -4
View File
@@ -91,7 +91,7 @@ obj/machinery/door/airlock/proc/command_completed(var/command)
obj/machinery/door/airlock/proc/send_status(var/bumped = 0)
if(radio_connection)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
@@ -172,7 +172,7 @@ obj/machinery/airlock_sensor/update_icon()
obj/machinery/airlock_sensor/attack_hand(mob/user)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = master_tag
signal.data["command"] = command
@@ -186,7 +186,7 @@ obj/machinery/airlock_sensor/process()
if(abs(pressure - previousPressure) > 0.001 || previousPressure == null)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
signal.data["pressure"] = num2text(pressure)
@@ -263,7 +263,7 @@ obj/machinery/access_button/attack_hand(mob/user)
else if(radio_connection)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = master_tag
signal.data["command"] = command
+112 -72
View File
@@ -1,5 +1,3 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/obj/item/weapon/airlock_electronics
name = "airlock electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
@@ -8,106 +6,148 @@
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
req_access = list(access_engine)
req_one_access = list(access_engine) // Access to unlock the device, ignored if emagged
var/list/apply_any_access = list(access_engine) // Can apply any access, not just their own
var/secure = 0 //if set, then wires will be randomized and bolts will drop if the door is broken
var/list/conf_access = null
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
var/last_configurator = null
var/locked = 1
var/emagged = 0
attack_self(mob/user as mob)
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
return ..(user)
/obj/item/weapon/airlock_electronics/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
emagged = 1
to_chat(user, "<span class='notice'>You remove the access restrictions on [src]!</span>")
return 1
var/t1 = text("<B>Access control</B><br>\n")
/obj/item/weapon/airlock_electronics/attack_self(mob/user as mob)
if (!ishuman(user) && !istype(user,/mob/living/silicon/robot))
return ..(user)
if (last_configurator)
t1 += "Operator: [last_configurator]<br>"
var/t1 = text("<B>Access control</B><br>\n")
if (locked)
t1 += "<a href='?src=\ref[src];login=1'>Swipe ID</a><hr>"
else
t1 += "<a href='?src=\ref[src];logout=1'>Block</a><hr>"
if (last_configurator)
t1 += "Operator: [last_configurator]<br>"
t1 += "Access requirement is set to "
t1 += one_access ? "<a style='color: green' href='?src=\ref[src];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=\ref[src];one_access=1'>ALL</a><hr>"
if (locked)
t1 += "<a href='?src=\ref[src];login=1'>Unlock Interface</a><hr>"
else
t1 += "<a href='?src=\ref[src];logout=1'>Lock Interface</a><hr>"
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=\ref[src];access=all'>All</a><br>"
t1 += "Access requirement is set to "
t1 += one_access ? "<a style='color: green' href='?src=\ref[src];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=\ref[src];one_access=1'>ALL</a><hr>"
t1 += "<br>"
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=\ref[src];access=all'>All</a><br>"
var/list/accesses = get_all_station_access()
for (var/acc in accesses)
var/aname = get_access_desc(acc)
t1 += "<br>"
if (!conf_access || !conf_access.len || !(acc in conf_access))
t1 += "<a href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else if(one_access)
t1 += "<a style='color: green' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else
t1 += "<a style='color: red' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
var/list/accesses = get_available_accesses(user)
for (var/acc in accesses)
var/aname = get_access_desc(acc)
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
user << browse(t1, "window=airlock_electronics")
onclose(user, "airlock")
Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon)))
return
if (href_list["close"])
usr << browse(null, "window=airlock")
return
if (href_list["login"])
if(istype(usr,/mob/living/silicon))
src.locked = 0
src.last_configurator = usr.name
if (!conf_access || !conf_access.len || !(acc in conf_access))
t1 += "<a href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else if(one_access)
t1 += "<a style='color: green' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/device/pda))
var/obj/item/device/pda/pda = I
I = pda.id
if (I && src.check_access(I))
t1 += "<a style='color: red' href='?src=\ref[src];access=[acc]'>[aname]</a><br>"
t1 += text("<p><a href='?src=\ref[];close=1'>Close</a></p>\n", src)
user << browse(t1, "window=airlock_electronics")
onclose(user, "airlock")
/obj/item/weapon/airlock_electronics/Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon)))
return
if (href_list["close"])
usr << browse(null, "window=airlock_electronics")
return
if (href_list["login"])
if(emagged)
src.locked = 0
src.last_configurator = usr.name
else if(issilicon(usr))
src.locked = 0
src.last_configurator = usr.name
else if(isliving(usr))
var/obj/item/weapon/card/id/id
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
id = H.get_idcard()
// In their ID slot?
if(id && src.check_access(id))
src.locked = 0
src.last_configurator = I:registered_name
src.last_configurator = id.registered_name
// Still locked, human handling didn't do it!
if(locked)
var/obj/item/I = usr.get_active_hand()
id = I?.GetID()
if(id && src.check_access(id))
src.locked = 0
src.last_configurator = id.registered_name
if (locked)
return
if (locked)
return
if (href_list["logout"])
locked = 1
if (href_list["logout"])
locked = 1
if (href_list["one_access"])
one_access = !one_access
if (href_list["one_access"])
one_access = !one_access
if (href_list["access"])
toggle_access(href_list["access"])
if (href_list["access"])
toggle_access(href_list["access"])
attack_self(usr)
attack_self(usr)
proc
toggle_access(var/acc)
if (acc == "all")
/obj/item/weapon/airlock_electronics/proc/toggle_access(var/acc)
if (acc == "all")
conf_access = null
else
var/req = text2num(acc)
if (conf_access == null)
conf_access = list()
if (!(req in conf_access))
conf_access += req
else
conf_access -= req
if (!conf_access.len)
conf_access = null
else
var/req = text2num(acc)
if (conf_access == null)
conf_access = list()
if (!(req in conf_access))
conf_access += req
else
conf_access -= req
if (!conf_access.len)
conf_access = null
/obj/item/weapon/airlock_electronics/proc/get_available_accesses(var/mob/user)
var/obj/item/weapon/card/id/id
if(ishuman(user))
var/mob/living/carbon/human/H = user
id = H.get_idcard()
else if(issilicon(user))
var/mob/living/silicon/R = user
id = R.idcard
// Nothing
if(!id || !id.access)
return list()
// Has engineer access, can put any access
else if(has_access(null, apply_any_access, id.access))
return get_all_station_access()
// Not an engineer, can only pick your own accesses to program
else
return id.access
/obj/item/weapon/airlock_electronics/secure
name = "secure airlock electronics"
desc = "designed to be somewhat more resistant to hacking than standard electronics."
origin_tech = list(TECH_DATA = 2)
secure = 1
/obj/item/weapon/airlock_electronics/secure/emag_act(var/remaining_charges, var/mob/user)
to_chat(user, "<span class='warning'>You don't appear to be able to bypass this hardened device!</span>")
return -1
+1 -1
View File
@@ -269,7 +269,7 @@
// If for some reason this is actually needed for something important, uncomment this.
/obj/machinery/door/blast/CanZASPass(turf/T, is_zone)
if(is_zone)
return ATMOS_PASS_YES
return TRUE
return ..()
*/
+7 -7
View File
@@ -9,7 +9,7 @@
anchored = 1
opacity = 1
density = 1
can_atmos_pass = ATMOS_PASS_DENSITY
can_atmos_pass = ATMOS_PASS_PROC
layer = DOOR_OPEN_LAYER
var/open_layer = DOOR_OPEN_LAYER
var/closed_layer = DOOR_CLOSED_LAYER
@@ -143,8 +143,8 @@
/obj/machinery/door/CanZASPass(turf/T, is_zone)
if(is_zone)
return block_air_zones ? ATMOS_PASS_NO : ATMOS_PASS_YES
return ..()
return !block_air_zones // Block merging unless block_air_zones = 0
return !density // Block airflow unless density = 0
/obj/machinery/door/proc/bumpopen(mob/user as mob)
if(operating) return
@@ -322,13 +322,13 @@
/obj/machinery/door/examine(mob/user)
. = ..()
if(src.health <= 0)
to_chat(user, "\The [src] is broken!")
. += "It is broken!"
else if(src.health < src.maxhealth / 4)
to_chat(user, "\The [src] looks like it's about to break!")
. += "It looks like it's about to break!"
else if(src.health < src.maxhealth / 2)
to_chat(user, "\The [src] looks seriously damaged!")
. += "It looks seriously damaged!"
else if(src.health < src.maxhealth * 3/4)
to_chat(user, "\The [src] shows signs of damage!")
. += "It shows signs of damage!"
/obj/machinery/door/proc/set_broken()

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