mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-28 07:38:35 +01:00
Merge branch 'master' into pol-moved
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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.
|
||||
@@ -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)) { \
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]'")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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. \
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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!"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)]°C)"
|
||||
. += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user