Merge branch 'master' into upstream-merge-32280

This commit is contained in:
LetterJay
2017-11-15 10:21:04 -06:00
committed by GitHub
247 changed files with 13614 additions and 3304 deletions
+1 -1
View File
@@ -110,7 +110,7 @@
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define MAX_HIGH_PRESSURE_DAMAGE 4
#define LOW_PRESSURE_DAMAGE 2 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define LOW_PRESSURE_DAMAGE 4 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
+2 -1
View File
@@ -74,7 +74,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define PASSGRILLE 4
#define PASSBLOB 8
#define PASSMOB 16
#define LETPASSTHROW 32
#define PASSCLOSEDTURF 32
#define LETPASSTHROW 64
//Movement Types
+41
View File
@@ -0,0 +1,41 @@
#define IC_INPUT "input"
#define IC_OUTPUT "output"
#define IC_ACTIVATOR "activator"
// Pin functionality.
#define DATA_CHANNEL "data channel"
#define PULSE_CHANNEL "pulse channel"
// Methods of obtaining a circuit.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
// Displayed along with the pin name to show what type of pin it is.
#define IC_FORMAT_ANY "\<ANY\>"
#define IC_FORMAT_STRING "\<TEXT\>"
#define IC_FORMAT_CHAR "\<CHAR\>"
#define IC_FORMAT_COLOR "\<COLOR\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_DIR "\<DIR\>"
#define IC_FORMAT_BOOLEAN "\<BOOL\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
// Used inside input/output list to tell the constructor what pin to make.
#define IC_PINTYPE_ANY /datum/integrated_io
#define IC_PINTYPE_STRING /datum/integrated_io/string
#define IC_PINTYPE_CHAR /datum/integrated_io/char
#define IC_PINTYPE_COLOR /datum/integrated_io/color
#define IC_PINTYPE_NUMBER /datum/integrated_io/number
#define IC_PINTYPE_DIR /datum/integrated_io/dir
#define IC_PINTYPE_BOOLEAN /datum/integrated_io/boolean
#define IC_PINTYPE_REF /datum/integrated_io/ref
#define IC_PINTYPE_LIST /datum/integrated_io/lists
#define IC_PINTYPE_PULSE_IN /datum/integrated_io/activate
#define IC_PINTYPE_PULSE_OUT /datum/integrated_io/activate/out
// Data limits.
#define IC_MAX_LIST_LENGTH 500
+2
View File
@@ -10,6 +10,8 @@
#define isatom(A) (isloc(A))
#define isweakref(D) (istype(D, /datum/weakref))
//Turfs
//#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake.
+18 -16
View File
@@ -1,20 +1,22 @@
//Investigate logging defines
#define INVESTIGATE_ATMOS "atmos"
#define INVESTIGATE_BOTANY "botany"
#define INVESTIGATE_CARGO "cargo"
#define INVESTIGATE_EXPERIMENTOR "experimentor"
#define INVESTIGATE_GRAVITY "gravity"
#define INVESTIGATE_RECORDS "records"
#define INVESTIGATE_SINGULO "singulo"
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_ATMOS "atmos"
#define INVESTIGATE_BOTANY "botany"
#define INVESTIGATE_CARGO "cargo"
#define INVESTIGATE_EXPERIMENTOR "experimentor"
#define INVESTIGATE_GRAVITY "gravity"
#define INVESTIGATE_RECORDS "records"
#define INVESTIGATE_SINGULO "singulo"
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
#define INVESTIGATE_PORTAL "portals"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_HALLUCINATIONS "hallucinations"
#define INVESTIGATE_RADIATION "radiation"
#define INVESTIGATE_EXONET "exonet"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
#define INDIVIDUAL_ATTACK_LOG "Attack log"
#define INDIVIDUAL_SAY_LOG "Say log"
#define INDIVIDUAL_EMOTE_LOG "Emote log"
#define INDIVIDUAL_OOC_LOG "OOC log"
#define INDIVIDUAL_SHOW_ALL_LOG "All logs"
+3
View File
@@ -84,3 +84,6 @@
#define SUPERMATTER_DANGER 4 // Integrity < 50%
#define SUPERMATTER_EMERGENCY 5 // Integrity < 25%
#define SUPERMATTER_DELAMINATING 6 // Pretty obvious.
//R&D Snowflakes
#define RD_CONSOLE_LOCKED_SCREEN 0.2
+3
View File
@@ -475,3 +475,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define MAX_PROC_DEPTH 195 // 200 proc calls deep and shit breaks, this is a bit lower to give some safety room
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define SYRINGE_DRAW 0
#define SYRINGE_INJECT 1
+8 -14
View File
@@ -1,23 +1,17 @@
//Construction Categories
#define PIPE_BINARY 0 //2 directions: N/S, E/W
#define PIPE_STRAIGHT 0 //2 directions: N/S, E/W
#define PIPE_BENDABLE 1 //6 directions: N/S, E/W, N/E, N/W, S/E, S/W
#define PIPE_TRINARY 2 //4 directions: N/E/S, E/S/W, S/W/N, W/N/E
#define PIPE_TRIN_M 3 //8 directions: N->S+E, S->N+E, N->S+W, S->N+W, E->W+S, W->E+S, E->W+N, W->E+N
#define PIPE_UNARY 4 //4 directions: N, S, E, W
#define PIPE_QUAD 5 //1 directions: N/S/E/W
#define PIPE_ONEDIR 5 //1 direction: N/S/E/W
//Disposal piping numbers - do NOT hardcode these, use the defines
#define DISP_PIPE_STRAIGHT 0
#define DISP_PIPE_BENT 1
#define DISP_JUNCTION 2
#define DISP_JUNCTION_FLIP 3
#define DISP_YJUNCTION 4
#define DISP_END_TRUNK 5
#define DISP_END_BIN 6
#define DISP_END_OUTLET 7
#define DISP_END_CHUTE 8
#define DISP_SORTJUNCTION 9
#define DISP_SORTJUNCTION_FLIP 10
//Disposal pipe relative connection directions
#define DISP_DIR_BASE 0
#define DISP_DIR_LEFT 1
#define DISP_DIR_RIGHT 2
#define DISP_DIR_FLIP 4
#define DISP_DIR_NONE 8
//Transit tubes
#define TRANSIT_TUBE_STRAIGHT 0
+2
View File
@@ -67,3 +67,5 @@
'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\
'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint.ogg',\
'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg', 'sound/ambience/ambiodd.ogg')
#define REEBE list('sound/ambience/ambireebe1.ogg', 'sound/ambience/ambireebe2.ogg', 'sound/ambience/ambireebe3.ogg')
+17
View File
@@ -0,0 +1,17 @@
#define STAT_ENTRY_TIME 1
#define STAT_ENTRY_COUNT 2
#define STAT_ENTRY_LENGTH 2
#define STAT_START_STOPWATCH var/STAT_STOP_WATCH = TICK_USAGE
#define STAT_STOP_STOPWATCH var/STAT_TIME = TICK_USAGE_TO_MS(STAT_STOP_WATCH)
#define STAT_LOG_ENTRY(entrylist, entryname) \
var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH));\
STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME;\
var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT));\
if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) {\
STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT;\
};\
+25
View File
@@ -53,6 +53,7 @@
#define INIT_ORDER_ATOMS 11
#define INIT_ORDER_LANGUAGE 10
#define INIT_ORDER_MACHINES 9
#define INIT_ORDER_CIRCUIT 8
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_AIR -1
@@ -76,3 +77,27 @@
#define RUNLEVEL_POSTGAME 8
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/oo = A.our_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(po)){\
if(LAZYLEN(oo)){\
A.overlays = oo + po;\
}\
else{\
A.overlays = po;\
}\
}\
else if(LAZYLEN(oo)){\
A.overlays = oo;\
}\
else{\
A.overlays.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
+4 -3
View File
@@ -1,5 +1,6 @@
#define TOOL_NONE 0
#define TOOL_CROWBAR 1
#define TOOL_SCREWDRIVER 2
#define TOOL_WIRECUTTER 3
#define TOOL_WRENCH 4
#define TOOL_MULTITOOL 2
#define TOOL_SCREWDRIVER 3
#define TOOL_WIRECUTTER 4
#define TOOL_WRENCH 5
+6 -1
View File
@@ -58,7 +58,12 @@ GLOBAL_VAR_INIT(cmp_field, "name")
. = B.failures - A.failures
if (!.)
. = B.qdels - A.qdels
/proc/cmp_generic_stat_item_time(list/A, list/B)
. = B[STAT_ENTRY_TIME] - A[STAT_ENTRY_TIME]
if (!.)
. = B[STAT_ENTRY_COUNT] - A[STAT_ENTRY_COUNT]
/proc/cmp_profile_avg_time_dsc(list/A, list/B)
return (B[PROFILE_ITEM_TIME]/(B[PROFILE_ITEM_COUNT] || 1)) - (A[PROFILE_ITEM_TIME]/(A[PROFILE_ITEM_COUNT] || 1))
+4
View File
@@ -179,6 +179,10 @@
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
underlays = U
// Drop posters which were previously placed on this wall.
for(var/obj/structure/sign/poster/P in src)
P.roll_and_drop(src)
/proc/cardinal_smooth(atom/A, adjacencies)
//NW CORNER
+4 -1
View File
@@ -1006,23 +1006,26 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
if(J)
J.equip(body, TRUE, FALSE)
SSoverlays.Flush()
var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing")
body.setDir(NORTH)
COMPILE_OVERLAYS(body)
var/icon/partial = getFlatIcon(body)
out_icon.Insert(partial,dir=NORTH)
body.setDir(SOUTH)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=SOUTH)
body.setDir(WEST)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=WEST)
body.setDir(EAST)
COMPILE_OVERLAYS(body)
partial = getFlatIcon(body)
out_icon.Insert(partial,dir=EAST)
+16 -16
View File
@@ -1,4 +1,4 @@
/proc/priority_announce(text, title = "", sound = 'sound/ai/attention.ogg', type)
/proc/priority_announce(text, title = "", sound = 'sound/ai/attention.ogg', type , sender_override)
if(!text)
return
@@ -13,13 +13,18 @@
GLOB.news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null)
else
announcement += "<h1 class='alert'>[command_name()] Update</h1>"
if(!sender_override)
announcement += "<h1 class='alert'>[command_name()] Update</h1>"
else
announcement += "<h1 class='alert'>[sender_override]</h1>"
if (title && length(title) > 0)
announcement += "<br><h2 class='alert'>[html_encode(title)]</h2>"
if(title == "")
GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null)
else
GLOB.news_network.SubmitArticle(title + "<br><br>" + text, "Central Command", "Station Announcements", null)
if(!sender_override)
if(title == "")
GLOB.news_network.SubmitArticle(text, "Central Command Update", "Station Announcements", null)
else
GLOB.news_network.SubmitArticle(title + "<br><br>" + text, "Central Command", "Station Announcements", null)
announcement += "<br><span class='alert'>[html_encode(text)]</span><br>"
announcement += "<br>"
@@ -38,16 +43,11 @@
if(announce)
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg')
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && (C.z in GLOB.station_z_levels))
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[title]'"
P.info = text
var/datum/comm_message/message = new
message.title = title
message.content = text
C.add_message(message)
P.update_icon()
var/datum/comm_message/M = new
M.title = title
M.content = text
SScommunications.send_message(M)
/proc/minor_announce(message, title = "Attention:", alert)
if(!message)
+13
View File
@@ -0,0 +1,13 @@
/proc/render_stats(list/stats, user, sort = /proc/cmp_generic_stat_item_time)
sortTim(stats, sort, TRUE)
var/list/lines = list()
for (var/entry in stats)
var/list/data = stats[entry]
lines += "[entry] => [num2text(data[STAT_ENTRY_TIME], 10)]ms ([data[STAT_ENTRY_COUNT]]) (avg:[num2text(data[STAT_ENTRY_TIME]/(data[STAT_ENTRY_COUNT] || 1), 99)])"
if (user)
user << browse("<ol><li>[lines.Join("</li><li>")]</li></ol>", "window=[url_encode("stats:[REF(stats)]")]")
. = lines.Join("\n")
+20
View File
@@ -578,3 +578,23 @@
return "turf"
else //regex everything else (works for /proc too)
return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
/proc/strtohex(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str))
c= text2ascii(str,i)
r+= num2hex(c)
return r
/proc/hextostr(str)
if(!istext(str)||!str)
return
var/r
var/c
for(var/i = 1 to length(str)/2)
c= hex2num(copytext(str,i*2-1,i*2+1))
r+= ascii2text(c)
return r
+41 -1
View File
@@ -506,6 +506,7 @@ Turf and target are separate in case you want to teleport some distance from a t
/*
Gets all contents of contents and returns them all in a list.
*/
/atom/proc/GetAllContents()
var/list/processing_list = list(src)
var/list/assembled = list()
@@ -1425,6 +1426,46 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
/proc/turf_z_is_planet(turf/T)
return GLOB.z_is_planet["[T.z]"]
//same as do_mob except for movables and it allows both to drift and doesn't draw progressbar
/proc/do_atom(atom/movable/user , atom/movable/target, time = 30, uninterruptible = 0,datum/callback/extra_checks = null)
if(!user || !target)
return TRUE
var/user_loc = user.loc
var/drifting = FALSE
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = TRUE
var/target_drifting = FALSE
if(!target.Process_Spacemove(0) && target.inertia_dir)
target_drifting = TRUE
var/target_loc = target.loc
var/endtime = world.time+time
// var/starttime = world.time
. = TRUE
while (world.time < endtime)
stoplag(1)
if(QDELETED(user) || QDELETED(target))
. = 0
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = FALSE
user_loc = user.loc
if(target_drifting && !target.inertia_dir)
target_drifting = FALSE
target_loc = target.loc
if((!drifting && user.loc != user_loc) || (!target_drifting && target.loc != target_loc) || (extra_checks && !extra_checks.Invoke()))
. = FALSE
break
//returns a GUID like identifier (using a mostly made up record format)
//guids are not on their own suitable for access or security tokens, as most of their bits are predictable.
// (But may make a nice salt to one)
@@ -1440,7 +1481,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
var/time_low = num2hex(world.time, 3)
var/time_clock = num2hex(TICK_DELTA_TO_MS(world.tick_usage), 3)
return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}"
// \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
-1
View File
@@ -19,7 +19,6 @@ GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt"))
GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt"))
GLOBAL_LIST_INIT(dream_strings, world.file2list("strings/dreamstrings.txt"))
+2
View File
@@ -14,6 +14,8 @@
return FALSE
if(TOOL_CROWBAR)
return target.crowbar_act(user, src)
if(TOOL_MULTITOOL)
return target.multitool_act(user, src)
if(TOOL_SCREWDRIVER)
return target.screwdriver_act(user, src)
if(TOOL_WRENCH)
-4
View File
@@ -66,10 +66,6 @@
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
/obj/effect/portal/attack_ghost(mob/user)
if(linked)
user.forceMove(get_turf(linked))
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
if(awaygate)
user.forceMove(awaygate.loc)
@@ -262,3 +262,5 @@ CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
min_val = 0
max_val = 1
integer = FALSE
CONFIG_DEF(flag/ic_printing)
@@ -28,5 +28,19 @@ SUBSYSTEM_DEF(communications)
log_talk(user,"[key_name(user)] has made a priority announcement: [input]",LOGSAY)
message_admins("[key_name_admin(user)] has made a priority announcement.")
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && (C.z in GLOB.station_z_levels))
if(unique)
C.add_message(sending)
else //We copy the message for each console, answers and deletions won't be shared
var/datum/comm_message/M = new(sending.title,sending.content,sending.possible_answers.Copy())
C.add_message(M)
if(print)
var/obj/item/paper/P = new /obj/item/paper(C.loc)
P.name = "paper - '[sending.title]'"
P.info = sending.content
P.update_icon()
#undef COMMUNICATION_COOLDOWN
#undef COMMUNICATION_COOLDOWN_AI
@@ -1,4 +1,4 @@
PROCESSING_SUBSYSTEM_DEF(overlays)
SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
wait = 1
@@ -6,62 +6,63 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
init_order = INIT_ORDER_OVERLAY
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_SETUP
stat_tag = "Ov"
currentrun = null
var/list/queue
var/list/stats
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
var/initialized = FALSE
/datum/controller/subsystem/processing/overlays/PreInit()
LAZYINITLIST(overlay_icon_state_caches)
LAZYINITLIST(overlay_icon_cache)
/datum/controller/subsystem/overlays/PreInit()
overlay_icon_state_caches = list()
overlay_icon_cache = list()
queue = list()
stats = list()
/datum/controller/subsystem/processing/overlays/Initialize()
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
Flush()
fire(mc_check = FALSE)
..()
/datum/controller/subsystem/processing/overlays/Recover()
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[length(queue)]")
/datum/controller/subsystem/overlays/Shutdown()
text2file("[GLOB.log_directory]/overlay.log", render_stats(stats))
/datum/controller/subsystem/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
overlay_icon_cache = SSoverlays.overlay_icon_cache
processing = SSoverlays.processing
queue = SSoverlays.queue
#define COMPILE_OVERLAYS(A)\
var/list/oo = A.our_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(po)){\
if(LAZYLEN(oo)){\
A.overlays = oo + po;\
}\
else{\
A.overlays = po;\
}\
}\
else if(LAZYLEN(oo)){\
A.overlays = oo;\
}\
else{\
A.overlays.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1
/datum/controller/subsystem/processing/overlays/fire(resumed = FALSE, mc_check = TRUE)
var/list/processing = src.processing
while(processing.len)
var/atom/thing = processing[processing.len]
processing.len--
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
var/list/queue = src.queue
var/static/count = 0
if (count)
var/c = count
count = 0 //so if we runtime on the Cut, we don't try again.
queue.Cut(1,c+1)
for (var/thing in queue)
count++
if(thing)
COMPILE_OVERLAYS(thing)
STAT_START_STOPWATCH
var/atom/A = thing
COMPILE_OVERLAYS(A)
STAT_STOP_STOPWATCH
STAT_LOG_ENTRY(stats, A.type)
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
/datum/controller/subsystem/processing/overlays/proc/Flush()
if(processing.len)
testing("Flushing [processing.len] overlays")
fire(mc_check = FALSE) //pair this thread up with the MC to get extra compile time
if (count)
queue.Cut(1,count+1)
count = 0
/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
@@ -102,6 +103,10 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
else if(isicon(overlay))
new_overlays += icon2appearance(overlay)
else
if(isloc(overlay))
var/atom/A = overlay
if (A.flags_1 & OVERLAY_QUEUED_1)
COMPILE_OVERLAYS(A)
appearance_bro.appearance = overlay //this works for images and atoms too!
if(!ispath(overlay))
var/image/I = overlay
@@ -110,7 +115,7 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
return new_overlays
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.processing += src;
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
/atom/proc/cut_overlays(priority = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
@@ -0,0 +1,70 @@
PROCESSING_SUBSYSTEM_DEF(circuit)
name = "Circuit"
stat_tag = "CIR"
init_order = INIT_ORDER_CIRCUIT
flags = NONE
var/cipherkey
var/list/all_exonet_connections = list() //Address = connection datum.
var/list/obj/machinery/exonet_node/all_exonet_nodes = list()
var/list/all_circuits = list() // Associative list of [circuit_name]:[circuit_path] pairs
var/list/circuit_fabricator_recipe_list = list() // Associative list of [category_name]:[list_of_circuit_paths] pairs
/datum/controller/subsystem/processing/circuit/Initialize(start_timeofday)
SScircuit.cipherkey = random_string(2000+rand(0,10), GLOB.alphabet)
circuits_init()
return ..()
/datum/controller/subsystem/processing/circuit/proc/circuits_init()
//Cached lists for free performance
var/list/all_circuits = src.all_circuits
var/list/circuit_fabricator_recipe_list = src.circuit_fabricator_recipe_list
for(var/path in typesof(/obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
var/name = initial(IC.name)
all_circuits[name] = IC // Populating the complete list
if(!(initial(IC.spawn_flags) & (IC_SPAWN_DEFAULT | IC_SPAWN_RESEARCH)))
continue
var/category = initial(IC.category_text)
if(!circuit_fabricator_recipe_list[category])
circuit_fabricator_recipe_list[category] = list()
var/list/category_list = circuit_fabricator_recipe_list[category]
category_list += IC // Populating the fabricator categories
circuit_fabricator_recipe_list["Assemblies"] = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone
//new /obj/item/weapon/implant/integrated_circuit,
//new /obj/item/device/assembly/electronic_assembly
)
circuit_fabricator_recipe_list["Tools"] = list(
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger,
/obj/item/device/integrated_electronics/analyzer
)
/datum/controller/subsystem/processing/circuit/proc/get_exonet_node()
for(var/i in 1 to all_exonet_nodes.len)
var/obj/machinery/exonet_node/E = all_exonet_nodes[i]
if(E.is_operating())
return E
/datum/controller/subsystem/processing/circuit/proc/get_exonet_address(addr)
return all_exonet_connections[addr]
// Proc: get_atom_from_address()
// Parameters: 1 (target_address - the desired address to find)
// Description: Searches an address for the atom it is attached for, otherwise returns null.
/datum/controller/subsystem/processing/circuit/proc/get_atom_from_address(var/target_address)
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
return exonet.holder
+8 -31
View File
@@ -4,38 +4,15 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
priority = 25
var/list/warned_atoms = list()
var/list/next_warn = list()
var/last_warn = 0
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive)
if(!radioactive || QDELETED(radioactive))
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive/contamination)
if(!contamination || QDELETED(contamination))
return
if(warned_atoms["[REF(radioactive.parent)]"])
var/ref = REF(contamination.parent)
if(warned_atoms[ref])
return
var/atom/master = radioactive.parent
warned_atoms[ref] = TRUE
var/atom/master = contamination.parent
SSblackbox.add_details("contaminated", "[master.type]")
next_warn["[REF(master)]"] = "[REF(radioactive)]"
var/wait_time = max(0, 500-(world.time-last_warn))+20 // wait at least 20 ticks, longer if we just messaged
addtimer(CALLBACK(src, .proc/send_warn), wait_time, TIMER_UNIQUE | TIMER_OVERRIDE)
/datum/controller/subsystem/processing/radiation/proc/send_warn()
var/msg = "Atom(s) have become contaminated by radiation and are strong enough they could pass it on:"
var/still_alive = FALSE
var/list/next_warn = src.next_warn // It's free performance!
for(var/i in next_warn)
var/atom/parent = locate(i)
var/datum/component/radioactive/radioactive = locate(next_warn[i])
if(!parent || !istype(parent) || !radioactive || !istype(radioactive))
continue
if(!still_alive)
msg += "\n"
still_alive = TRUE
else
msg += ", "
msg += "[parent][ADMIN_VV(parent)]source:[radioactive.source]"
if(!still_alive)
return
warned_atoms += next_warn
src.next_warn = list()
last_warn = world.time
message_admins(msg)
var/msg = "has become contamintaed with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]"
master.investigate_log(msg, INVESTIGATE_RADIATION)
+27 -1
View File
@@ -28,7 +28,9 @@ SUBSYSTEM_DEF(shuttle)
var/emergencyCallAmount = 0 //how many times the escape shuttle was called
var/emergencyNoEscape
var/emergencyNoRecall = FALSE
var/list/hostileEnvironments = list()
var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving
var/list/tradeBlockade = list() //Things blocking cargo from leaving.
var/supplyBlocked = FALSE
//supply shuttle stuff
var/obj/docking_port/mobile/supply/supply
@@ -335,6 +337,30 @@ SUBSYSTEM_DEF(shuttle)
hostileEnvironments -= bad
checkHostileEnvironment()
/datum/controller/subsystem/shuttle/proc/registerTradeBlockade(datum/bad)
tradeBlockade[bad] = TRUE
checkTradeBlockade()
/datum/controller/subsystem/shuttle/proc/clearTradeBlockade(datum/bad)
tradeBlockade -= bad
checkTradeBlockade()
/datum/controller/subsystem/shuttle/proc/checkTradeBlockade()
for(var/datum/d in tradeBlockade)
if(!istype(d) || QDELETED(d))
tradeBlockade -= d
supplyBlocked = tradeBlockade.len
if(supplyBlocked && (supply.mode == SHUTTLE_IGNITING))
supply.mode = SHUTTLE_STRANDED
supply.timer = null
//Make all cargo consoles speak up
if(!supplyBlocked && (supply.mode == SHUTTLE_STRANDED))
supply.mode = SHUTTLE_DOCKED
//Make all cargo consoles speak up
/datum/controller/subsystem/shuttle/proc/checkHostileEnvironment()
for(var/datum/d in hostileEnvironments)
if(!istype(d) || QDELETED(d))
+1 -3
View File
@@ -281,8 +281,6 @@ SUBSYSTEM_DEF(ticker)
collect_minds()
equip_characters()
SSoverlays.Flush() //Flush the majority of the shit
GLOB.data_core.manifest()
transfer_characters() //transfer keys to the new mobs
@@ -315,7 +313,7 @@ SUBSYSTEM_DEF(ticker)
set waitfor = FALSE
mode.post_setup()
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count(1)
GLOB.start_state.count()
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
//Deleting Startpoints but we need the ai point to AI-ize people later
+4 -4
View File
@@ -259,11 +259,11 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/Last = ctts[cttl]
if(Last.timeToRun >= timeToRun)
ctts += src
else if(cttl > 1)
for(var/I in cttl to 1)
var/datum/timedevent/E = ctts[I]
else
for(var/i in cttl to 1 step -1)
var/datum/timedevent/E = ctts[i]
if(E.timeToRun <= timeToRun)
ctts.Insert(src, I)
ctts.Insert(i, src)
break
else
ctts += src
+113
View File
@@ -0,0 +1,113 @@
/*
Exonet Protocol Version 2
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
Version 1 never existed.
*Setting up*
To set up the exonet link, define a variable on your desired atom it is like this;
var/datum/exonet_protocol/exonet = null
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
Destroy() also automatically calls remove_address().
*Sending messages*
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
ping yourself.
*Receiving messages*
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
It's suggested to start with an if or switch statement for the message, to determine what to do.
*/
/datum/exonet_protocol
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
var/atom/holder
/datum/exonet_protocol/New(var/atom/H)
holder = H
/datum/exonet_protocol/Destroy()
remove_address()
holder = null
return ..()
// Proc: make_address()
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
/datum/exonet_protocol/proc/make_address(var/string)
if(!string)
return
var/hex = copytext(md5(string),1,25)
if(!hex)
return
var/addr_1 = copytext(hex,1,5)
var/addr_2 = copytext(hex,5,9)
var/addr_3 = copytext(hex,9,13)
var/addr_4 = copytext(hex,13,17)
address = "fc00:[addr_1]:[addr_2]:[addr_3]:[addr_4]"
if(SScircuit.all_exonet_connections[address])
stack_trace("WARNING: Exonet address collision in make_address. Holder type if applicable is [holder? holder.type : "NO HOLDER"]!")
SScircuit.all_exonet_connections[address] = src
// Proc: make_arbitrary_address()
// Parameters: 1 (new_address - the desired address)
// Description: Allocates that specific address, if it is available.
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
if(new_address)
if(new_address == SScircuit.get_exonet_address(new_address) ) //Collision test.
return FALSE
address = new_address
SScircuit.all_exonet_connections[address] = src
return TRUE
// Proc: remove_address()
// Parameters: None
// Description: Deallocates the address, freeing it for use.
/datum/exonet_protocol/proc/remove_address()
SScircuit.all_exonet_connections -= address
address = ""
// Proc: send_message()
// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for,
// content - the actual 'message' being sent to the address)
// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved.
/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content)
if(!address)
return FALSE
var/obj/machinery/exonet_node/node = SScircuit.get_exonet_node()
if(!node) // Telecomms went boom, ion storm, etc.
return FALSE
var/datum/exonet_protocol/exonet = SScircuit.get_exonet_address(target_address)
if(exonet)
node.write_log(address, target_address, data_type, content)
return exonet.receive_message(holder, address, data_type, content)
// Proc: receive_message()
// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from,
// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom)
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content)
holder.receive_exonet_message(origin_atom, origin_address, data_type, content)
return TRUE // for send_message()
// Proc: receive_exonet_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
// Description: Override this to make your atom do something when a message is received.
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
return
+483
View File
@@ -0,0 +1,483 @@
#define LING_FAKEDEATH_TIME 400 //40 seconds
#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
/datum/antagonist/changeling
name = "Changeling"
job_rank = ROLE_CHANGELING
var/you_are_greet = TRUE
var/give_objectives = TRUE
var/list/objectives = list()
var/team_mode = FALSE //Should assign team objectives ?
//Changeling Stuff
var/list/stored_profiles = list() //list of datum/changelingprofile
var/datum/changelingprofile/first_prof = null
//var/list/absorbed_dna = list()
//var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
var/absorbedcount = 0
var/chem_charges = 20
var/chem_storage = 75
var/chem_recharge_rate = 1
var/chem_recharge_slowdown = 0
var/sting_range = 2
var/changelingID = "Changeling"
var/geneticdamage = 0
var/isabsorbing = 0
var/islinking = 0
var/geneticpoints = 10
var/purchasedpowers = list()
var/mimicing = ""
var/canrespec = 0
var/changeling_speak = 0
var/datum/dna/chosen_dna
var/obj/effect/proc_holder/changeling/sting/chosen_sting
var/datum/cellular_emporium/cellular_emporium
var/datum/action/innate/cellular_emporium/emporium_action
// wip stuff
var/static/list/all_powers = typecacheof(/obj/effect/proc_holder/changeling,TRUE)
/datum/antagonist/changeling/New()
. = ..()
generate_name()
create_actions()
/datum/antagonist/changeling/Destroy()
QDEL_NULL(cellular_emporium)
QDEL_NULL(emporium_action)
. = ..()
/datum/antagonist/changeling/proc/generate_name()
var/honorific
if(owner.current.gender == FEMALE)
honorific = "Ms."
else
honorific = "Mr."
if(GLOB.possible_changeling_IDs.len)
changelingID = pick(GLOB.possible_changeling_IDs)
GLOB.possible_changeling_IDs -= changelingID
changelingID = "[honorific] [changelingID]"
else
changelingID = "[honorific] [rand(1,999)]"
/datum/antagonist/changeling/proc/create_actions()
cellular_emporium = new(src)
emporium_action = new(cellular_emporium)
/datum/antagonist/changeling/on_gain()
reset_powers()
create_initial_profile()
if(give_objectives)
if(team_mode)
forge_team_objectives()
forge_objectives()
remove_clownmut()
. = ..()
/datum/antagonist/changeling/on_removal()
remove_changeling_powers()
owner.objectives -= objectives
. = ..()
/datum/antagonist/changeling/proc/remove_clownmut()
if (owner)
var/mob/living/carbon/human/H = owner.current
if(istype(H) && owner.assigned_role == "Clown")
to_chat(H, "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
/datum/antagonist/changeling/proc/reset_properties()
changeling_speak = 0
chosen_sting = null
geneticpoints = initial(geneticpoints)
sting_range = initial(sting_range)
chem_storage = initial(chem_storage)
chem_recharge_rate = initial(chem_recharge_rate)
chem_charges = min(chem_charges, chem_storage)
chem_recharge_slowdown = initial(chem_recharge_slowdown)
mimicing = ""
/datum/antagonist/changeling/proc/remove_changeling_powers()
if(ishuman(owner.current) || ismonkey(owner.current))
reset_properties()
for(var/obj/effect/proc_holder/changeling/p in purchasedpowers)
if(p.always_keep)
continue
purchasedpowers -= p
p.on_refund(owner.current)
//MOVE THIS
if(owner.current.hud_used)
owner.current.hud_used.lingstingdisplay.icon_state = null
owner.current.hud_used.lingstingdisplay.invisibility = INVISIBILITY_ABSTRACT
/datum/antagonist/changeling/proc/reset_powers()
if(purchasedpowers)
remove_changeling_powers()
//Repurchase free powers.
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = new path()
if(!S.dna_cost)
if(!has_sting(S))
purchasedpowers += S
S.on_purchase(owner.current,TRUE)
/datum/antagonist/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
for(var/obj/effect/proc_holder/changeling/P in purchasedpowers)
if(initial(power.name) == P.name)
return TRUE
return FALSE
/datum/antagonist/changeling/proc/purchase_power(sting_name)
var/obj/effect/proc_holder/changeling/thepower = null
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = path
if(initial(S.name) == sting_name)
thepower = new path()
break
if(!thepower)
to_chat(owner.current, "This is awkward. Changeling power purchase failed, please report this bug to a coder!")
return
if(absorbedcount < thepower.req_dna)
to_chat(owner.current, "We lack the energy to evolve this ability!")
return
if(has_sting(thepower))
to_chat(owner.current, "We have already evolved this ability!")
return
if(thepower.dna_cost < 0)
to_chat(owner.current, "We cannot evolve this ability.")
return
if(geneticpoints < thepower.dna_cost)
to_chat(owner.current, "We have reached our capacity for abilities.")
return
if(owner.current.status_flags & FAKEDEATH)//To avoid potential exploits by buying new powers while in stasis, which clears your verblist.
to_chat(owner.current, "We lack the energy to evolve new abilities right now.")
return
geneticpoints -= thepower.dna_cost
purchasedpowers += thepower
thepower.on_purchase(owner.current)
/datum/antagonist/changeling/proc/readapt()
if(!ishuman(owner.current))
to_chat(owner.current, "<span class='danger'>We can't remove our evolutions in this form!</span>")
return
if(canrespec)
to_chat(owner.current, "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>")
reset_powers()
canrespec = 0
SSblackbox.add_details("changeling_power_purchase","Readapt")
return 1
else
to_chat(owner.current, "<span class='danger'>You lack the power to readapt your evolutions!</span>")
return 0
//Called in life()
/datum/antagonist/changeling/proc/regenerate()
var/mob/living/carbon/the_ling = owner.current
if(istype(the_ling))
emporium_action.Grant(the_ling)
if(the_ling.stat == DEAD)
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
else //not dead? no chem/geneticdamage caps.
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
geneticdamage = max(0, geneticdamage-1)
/datum/antagonist/changeling/proc/get_dna(dna_owner)
for(var/datum/changelingprofile/prof in stored_profiles)
if(dna_owner == prof.name)
return prof
/datum/antagonist/changeling/proc/has_dna(datum/dna/tDNA)
for(var/datum/changelingprofile/prof in stored_profiles)
if(tDNA.is_same_as(prof.dna))
return TRUE
return FALSE
/datum/antagonist/changeling/proc/can_absorb_dna(mob/living/carbon/human/target, var/verbose=1)
var/mob/living/carbon/user = owner.current
if(!istype(user))
return
if(stored_profiles.len)
var/datum/changelingprofile/prof = stored_profiles[1]
if(prof.dna == user.dna && stored_profiles.len >= dna_max)//If our current DNA is the stalest, we gotta ditch it.
if(verbose)
to_chat(user, "<span class='warning'>We have reached our capacity to store genetic information! We must transform before absorbing more.</span>")
return
if(!target)
return
if(NO_DNA_COPY in target.dna.species.species_traits)
if(verbose)
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
return
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
if(verbose)
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
return
if(!ishuman(target))//Absorbing monkeys is entirely possible, but it can cause issues with transforming. That's what lesser form is for anyway!
if(verbose)
to_chat(user, "<span class='warning'>We could gain no benefit from absorbing a lesser creature.</span>")
return
if(has_dna(target.dna))
if(verbose)
to_chat(user, "<span class='warning'>We already have this DNA in storage!</span>")
return
if(!target.has_dna())
if(verbose)
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
return
return 1
/datum/antagonist/changeling/proc/create_profile(mob/living/carbon/human/H, protect = 0)
var/datum/changelingprofile/prof = new
H.dna.real_name = H.real_name //Set this again, just to be sure that it's properly set.
var/datum/dna/new_dna = new H.dna.type
H.dna.copy_dna(new_dna)
prof.dna = new_dna
prof.name = H.real_name
prof.protected = protect
prof.underwear = H.underwear
prof.undershirt = H.undershirt
prof.socks = H.socks
var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
for(var/slot in slots)
if(slot in H.vars)
var/obj/item/I = H.vars[slot]
if(!I)
continue
prof.name_list[slot] = I.name
prof.appearance_list[slot] = I.appearance
prof.flags_cover_list[slot] = I.flags_cover
prof.item_color_list[slot] = I.item_color
prof.item_state_list[slot] = I.item_state
prof.exists_list[slot] = 1
else
continue
return prof
/datum/antagonist/changeling/proc/add_profile(datum/changelingprofile/prof)
if(stored_profiles.len > dna_max)
if(!push_out_profile())
return
if(!first_prof)
first_prof = prof
stored_profiles += prof
absorbedcount++
/datum/antagonist/changeling/proc/add_new_profile(mob/living/carbon/human/H, protect = 0)
var/datum/changelingprofile/prof = create_profile(H, protect)
add_profile(prof)
return prof
/datum/antagonist/changeling/proc/remove_profile(mob/living/carbon/human/H, force = 0)
for(var/datum/changelingprofile/prof in stored_profiles)
if(H.real_name == prof.name)
if(prof.protected && !force)
continue
stored_profiles -= prof
qdel(prof)
/datum/antagonist/changeling/proc/get_profile_to_remove()
for(var/datum/changelingprofile/prof in stored_profiles)
if(!prof.protected)
return prof
/datum/antagonist/changeling/proc/push_out_profile()
var/datum/changelingprofile/removeprofile = get_profile_to_remove()
if(removeprofile)
stored_profiles -= removeprofile
return 1
return 0
/datum/antagonist/changeling/proc/create_initial_profile()
var/mob/living/carbon/C = owner.current //only carbons have dna now, so we have to typecaste
if(ishuman(C))
add_new_profile(C)
/datum/antagonist/changeling/apply_innate_effects()
//Brains optional.
var/mob/living/carbon/C = owner.current
if(istype(C))
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
if(B)
B.vital = FALSE
B.decoy_override = TRUE
update_changeling_icons_added()
return
/datum/antagonist/changeling/remove_innate_effects()
update_changeling_icons_removed()
return
/datum/antagonist/changeling/greet()
if (you_are_greet)
to_chat(owner.current, "<span class='boldannounce'>You are [changelingID], a changeling! You have absorbed and taken the form of a human.</span>")
to_chat(owner.current, "<span class='boldannounce'>Use say \":g message\" to communicate with your fellow changelings.</span>")
to_chat(owner.current, "<b>You must complete the following tasks:</b>")
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ling_aler.ogg', 100, FALSE, pressure_affected = FALSE)
owner.announce_objectives()
/datum/antagonist/changeling/proc/forge_team_objectives()
if(GLOB.changeling_team_objective_type)
var/datum/objective/changeling_team_objective/team_objective = new GLOB.changeling_team_objective_type
team_objective.owner = owner
objectives += team_objective
return
/datum/antagonist/changeling/proc/forge_objectives()
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
var/escape_objective_possible = TRUE
//if there's a team objective, check if it's compatible with escape objectives
for(var/datum/objective/changeling_team_objective/CTO in objectives)
if(!CTO.escape_objective_compatible)
escape_objective_possible = FALSE
break
var/datum/objective/absorb/absorb_objective = new
absorb_objective.owner = owner
absorb_objective.gen_amount_goal(6, 8)
objectives += absorb_objective
if(prob(60))
if(prob(85))
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
objectives += steal_objective
else
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
objectives += download_objective
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = owner
destroy_objective.find_target()
objectives += destroy_objective
else
if(prob(70))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
if(team_mode) //No backstabbing while in a team
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
kill_objective.find_target()
objectives += kill_objective
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
if(team_mode)
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
maroon_objective.find_target()
objectives += maroon_objective
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
identity_theft.target = maroon_objective.target
identity_theft.update_explanation_text()
objectives += identity_theft
escape_objective_possible = FALSE
if (!(locate(/datum/objective/escape) in objectives) && escape_objective_possible)
if(prob(50))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
objectives += escape_objective
else
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = owner
if(team_mode)
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
identity_theft.find_target()
objectives += identity_theft
escape_objective_possible = FALSE
owner.objectives |= objectives
/datum/antagonist/changeling/proc/update_changeling_icons_added()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.join_hud(owner.current)
set_antag_hud(owner.current, "changling")
/datum/antagonist/changeling/proc/update_changeling_icons_removed()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.leave_hud(owner.current)
set_antag_hud(owner.current, null)
// Profile
/datum/changelingprofile
var/name = "a bug"
var/protected = 0
var/datum/dna/dna = null
var/list/name_list = list() //associative list of slotname = itemname
var/list/appearance_list = list()
var/list/flags_cover_list = list()
var/list/exists_list = list()
var/list/item_color_list = list()
var/list/item_state_list = list()
var/underwear
var/undershirt
var/socks
/datum/changelingprofile/Destroy()
qdel(dna)
. = ..()
/datum/changelingprofile/proc/copy_profile(datum/changelingprofile/newprofile)
newprofile.name = name
newprofile.protected = protected
newprofile.dna = new dna.type
dna.copy_dna(newprofile.dna)
newprofile.name_list = name_list.Copy()
newprofile.appearance_list = appearance_list.Copy()
newprofile.flags_cover_list = flags_cover_list.Copy()
newprofile.exists_list = exists_list.Copy()
newprofile.item_color_list = item_color_list.Copy()
newprofile.item_state_list = item_state_list.Copy()
newprofile.underwear = underwear
newprofile.undershirt = undershirt
newprofile.socks = socks
/datum/antagonist/changeling/xenobio
name = "Xenobio Changeling"
give_objectives = FALSE
you_are_greet = FALSE
+135
View File
@@ -0,0 +1,135 @@
/datum/antagonist/pirate
name = "Space Pirate"
job_rank = ROLE_TRAITOR
var/datum/objective_team/pirate/crew
/datum/antagonist/pirate/greet()
to_chat(owner, "<span class='boldannounce'>You are a Space Pirate!</span>")
to_chat(owner, "<B>The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot.</B>")
owner.announce_objectives()
/datum/antagonist/pirate/get_team()
return crew
/datum/antagonist/pirate/create_team(datum/objective_team/pirate/new_team)
if(!new_team)
for(var/datum/antagonist/pirate/P in GLOB.antagonists)
if(P.crew)
new_team = P.crew
if(!new_team)
crew = new /datum/objective_team/pirate
crew.forge_objectives()
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
crew = new_team
/datum/antagonist/pirate/on_gain()
if(crew)
owner.objectives |= crew.objectives
. = ..()
/datum/antagonist/pirate/on_removal()
if(crew)
owner.objectives -= crew.objectives
. = ..()
/datum/objective_team/pirate
name = "Pirate crew"
var/list/objectives = list()
/datum/objective_team/pirate/proc/forge_objectives()
var/datum/objective/loot/getbooty = new()
getbooty.team = src
getbooty.storage_area = locate(/area/shuttle/pirate/vault) in GLOB.sortedAreas
getbooty.update_initial_value()
getbooty.update_explanation_text()
objectives += getbooty
for(var/datum/mind/M in members)
M.objectives |= objectives
GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
/obj/structure/reagent_dispensers/beerkeg,
/mob/living/simple_animal/parrot,
/obj/item/stack/sheet/mineral/gold,
/obj/item/stack/sheet/mineral/diamond,
/obj/item/stack/spacecash,
/obj/item/melee/sabre,)))
/datum/objective/loot
var/area/storage_area //Place where we we will look for the loot.
explanation_text = "Acquire valuable loot and store it in designated area."
var/target_value = 50000
var/initial_value = 0 //Things in the vault at spawn time do not count
/datum/objective/loot/update_explanation_text()
if(storage_area)
explanation_text = "Acquire loot and store [target_value] of credits worth in [storage_area.name]."
/datum/objective/loot/proc/loot_listing()
//Lists notable loot.
if(!storage_area)
return "Nothing"
var/list/loot_table = list()
for(var/atom/movable/AM in storage_area.GetAllContents())
if(is_type_in_typecache(AM,GLOB.pirate_loot_cache))
var/lootname = AM.name
var/count = 1
if(istype(AM,/obj/item/stack)) //Ugh.
var/obj/item/stack/S = AM
lootname = S.singular_name
count = S.amount
if(!loot_table[lootname])
loot_table[lootname] = count
else
loot_table[lootname] += count
var/text = ""
for(var/key in loot_table)
var/amount = loot_table[key]
text += "[amount] [key][amount > 1 ? "s":""], "
return text
/datum/objective/loot/proc/get_loot_value()
if(!storage_area)
return 0
var/value = 0
for(var/turf/T in storage_area.contents)
value += export_item_and_contents(T,TRUE, TRUE, dry_run = TRUE)
return value - initial_value
/datum/objective/loot/proc/update_initial_value()
initial_value = get_loot_value()
/datum/objective/loot/check_completion()
return ..() || get_loot_value() >= target_value
//These need removal ASAP as everything is converted to datum antags.
/datum/game_mode/proc/auto_declare_completion_pirates()
var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate)
var/datum/objective_team/pirate/crew
var/text = ""
if(pirates.len)
text += "<br><b>Space Pirates were:</b>"
for(var/datum/mind/M in pirates)
text += printplayer(M)
if(!crew)
var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
crew = P.crew
if(crew)
text += "<br>Loot stolen: "
var/datum/objective/loot/L = locate() in crew.objectives
text += L.loot_listing()
text += "<br>Total loot value : [L.get_loot_value()]/[L.target_value] credits"
var/all_dead = TRUE
for(var/datum/mind/M in crew.members)
if(considered_alive(M))
all_dead = FALSE
break
if(L.check_completion() && !all_dead)
text += "<br><font color='green'><b>The pirate crew was successful!</b></font>"
else
text += "<br><span class='boldannounce'>The pirate crew has failed.</span>"
to_chat(world, text)
+7 -3
View File
@@ -137,10 +137,14 @@
return
/datum/component/proc/_GetInverseTypeList(our_type = type)
#if DM_VERSION > 511
#warning Remove this hack for http://www.byond.com/forum/?post=73469
#endif
#if DM_VERSION >= 513
#warning 512 is definitely stable now, remove the old code
#endif
#if DM_VERSION < 512
//remove this when we use 512 full time
set invisibility = 101
#endif
//we can do this one simple trick
var/current_type = parent_type
. = list(our_type, current_type)
+2
View File
@@ -4,6 +4,7 @@
var/list/datum_components //for /datum/components
var/ui_screen = "home" //for tgui
var/use_tag = FALSE
var/datum/weakref/weak_reference
#ifdef TESTING
var/running_find_references
@@ -15,6 +16,7 @@
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy(force=FALSE, ...)
tag = null
weak_reference = null //ensure prompt GCing of weakref.
var/list/timers = active_timers
active_timers = null
for(var/thing in timers)
+2 -2
View File
@@ -53,7 +53,7 @@
return
var/title = ""
var/refid = "[REF(D)]"
var/refid = REF(D)
var/icon/sprite
var/hash
@@ -453,7 +453,7 @@
var/val
if (IS_NORMAL_LIST(L) && !isnum(key))
val = L[key]
if (!val)
if (isnull(val)) // we still want to display non-null false values, such as 0 or ""
val = key
key = i
+2 -1
View File
@@ -98,7 +98,8 @@
/obj/structure/cable,
/obj/machinery/atmospherics,
/obj/item/ammo_casing,
/obj/item/implant
/obj/item/implant,
/obj/singularity
))
if(!can_contaminate || blacklisted[thing.type])
continue
+18
View File
@@ -0,0 +1,18 @@
/proc/WEAKREF(datum/input)
if(istype(input) && !QDELETED(input))
if(!input.weak_reference)
input.weak_reference = new /datum/weakref(input)
return input.weak_reference
/datum/weakref
var/reference
/datum/weakref/New(datum/thing)
reference = REF(thing)
/datum/weakref/Destroy()
return QDEL_HINT_LETMELIVE //Let BYOND autoGC thiswhen nothing is using it anymore.
/datum/weakref/proc/resolve()
var/datum/D = locate(reference)
return (!QDELETED(D) && D.weak_reference == src) ? D : null
+2 -2
View File
@@ -2,7 +2,7 @@
name = "AI Monitored Area"
clockwork_warp_allowed = FALSE
var/list/obj/machinery/camera/motioncameras = list()
var/list/motionTargets = list()
var/list/datum/weakref/motionTargets = list()
/area/ai_monitored/Initialize(mapload)
. = ..()
@@ -27,5 +27,5 @@
if (ismob(O) && motioncameras.len)
for(var/X in motioncameras)
var/obj/machinery/camera/cam = X
cam.lostTarget(O)
cam.lostTargetRef(WEAKREF(O))
return
+1
View File
@@ -154,6 +154,7 @@
has_gravity = TRUE
noteleport = TRUE
hidden = TRUE
ambientsounds = REEBE
/area/reebe/city_of_cogs
name = "City of Cogs"
+9
View File
@@ -111,3 +111,12 @@
/area/shuttle/syndicate_scout
name = "Syndicate Scout"
blob_allowed = FALSE
/area/shuttle/pirate
name = "Pirate Shuttle"
blob_allowed = FALSE
requires_power = TRUE
/area/shuttle/pirate/vault
name = "Pirate Shuttle Vault"
requires_power = FALSE
+3 -1
View File
@@ -99,7 +99,6 @@
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(priority_overlays)
//SSoverlays.processing -= src //we COULD do this, but it's better to just let it fall out of the processing queue
QDEL_NULL(light)
@@ -626,6 +625,9 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/crowbar_act(mob/user, obj/item/tool)
return
/atom/proc/multitool_act(mob/user, obj/item/tool)
return
/atom/proc/screwdriver_act(mob/user, obj/item/tool)
return
+39 -48
View File
@@ -6,56 +6,47 @@
var/door = 0
var/grille = 0
var/mach = 0
var/num_territories = 1//Number of total valid territories for gang mode
/datum/station_state/proc/count()
for(var/Z in GLOB.station_z_levels)
for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z)))
// don't count shuttles since they may have just left
if(istype(T.loc, /area/shuttle))
continue
if(isfloorturf(T))
var/turf/open/floor/TF = T
if(!(TF.burnt))
floor += 12
else
floor += 1
if(iswallturf(T))
var/turf/closed/wall/TW = T
if(TW.intact)
wall += 2
else
wall += 1
if(istype(T, /turf/closed/wall/r_wall))
var/turf/closed/wall/r_wall/TRW = T
if(TRW.intact)
r_wall += 2
else
r_wall += 1
/datum/station_state/proc/count(count_territories)
for(var/turf/T in block(locate(1,1,1), locate(world.maxx,world.maxy,1)))
if(isfloorturf(T))
var/turf/open/floor/TF = T
if(!(TF.burnt))
src.floor += 12
else
src.floor += 1
if(iswallturf(T))
var/turf/closed/wall/TW = T
if(TW.intact)
src.wall += 2
else
src.wall += 1
if(istype(T, /turf/closed/wall/r_wall))
var/turf/closed/wall/r_wall/TRW = T
if(TRW.intact)
src.r_wall += 2
else
src.r_wall += 1
for(var/obj/O in T.contents)
if(istype(O, /obj/structure/window))
src.window += 1
else if(istype(O, /obj/structure/grille))
var/obj/structure/grille/GR = O
if(!GR.broken)
src.grille += 1
else if(istype(O, /obj/machinery/door))
src.door += 1
else if(ismachinery(O))
src.mach += 1
if(count_territories)
var/list/valid_territories = list()
for(var/area/A in world) //First, collect all area types on the station zlevel
if(A.z in GLOB.station_z_levels)
if(!(A.type in valid_territories) && A.valid_territory)
valid_territories |= A.type
if(valid_territories.len)
num_territories = valid_territories.len //Add them all up to make the total number of area types
else
to_chat(world, "ERROR: NO VALID TERRITORIES")
for(var/obj/O in T.contents)
if(istype(O, /obj/structure/window))
window += 1
else if(istype(O, /obj/structure/grille))
var/obj/structure/grille/GR = O
if(!GR.broken)
grille += 1
else if(istype(O, /obj/machinery/door))
door += 1
else if(ismachinery(O))
mach += 1
/datum/station_state/proc/score(datum/station_state/result)
if(!result)
+8 -1
View File
@@ -1,3 +1,5 @@
#define CULT_SCALING_COEFFICIENT 9.3 //Roughly one new cultist at roundstart per this many players
/datum/game_mode
var/list/datum/mind/cult = list()
var/list/cult_objectives = list()
@@ -64,7 +66,10 @@
restricted_jobs += "Assistant"
//cult scaling goes here
recommended_enemies = 3 + round(num_players()/15)
recommended_enemies = 1 + round(num_players()/CULT_SCALING_COEFFICIENT)
var/remaining = (num_players() % CULT_SCALING_COEFFICIENT) * 10 //Basically the % of how close the population is toward adding another cultis
if(prob(remaining))
recommended_enemies++
for(var/cultists_number = 1 to recommended_enemies)
@@ -307,3 +312,5 @@
SSticker.news_report = CULT_FAILURE
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
to_chat(world, text)
#undef CULT_SCALING_COEFFICIENT
+4 -2
View File
@@ -464,8 +464,10 @@
text += " <span class='boldannounce'>died</span>"
else
text += " <span class='greenannounce'>survived</span>"
if(fleecheck && (!(ply.current.z in GLOB.station_z_levels)))
text += " while <span class='boldannounce'>fleeing the station</span>"
if(fleecheck)
var/turf/T = get_turf(ply.current)
if(!T || !(T.z in GLOB.station_z_levels))
text += " while <span class='boldannounce'>fleeing the station</span>"
if(ply.current.real_name != ply.name)
text += " as <b>[ply.current.real_name]</b>"
else
+8 -18
View File
@@ -28,12 +28,6 @@ Class Variables:
component_parts (list)
A list of component parts of machine used by frame based machines.
uid (num)
Unique id of machine across all machines.
gl_uid (global num)
Next uid value in sequence
stat (bitflag)
Machine status bit flags.
Possible bit flags:
@@ -77,9 +71,6 @@ Class Procs:
Default definition does nothing.
assign_uid() 'game/machinery/machine.dm'
Called by machine to assign a value to the uid variable.
process() 'game/machinery/machine.dm'
Called by the 'machinery subsystem' once per machinery tick for each machine that is listed in its 'machines' list.
@@ -112,8 +103,6 @@ Class Procs:
var/power_channel = EQUIP
//EQUIP,ENVIRON or LIGHT
var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
var/uid
var/global/gl_uid = 1
var/panel_open = FALSE
var/state_open = FALSE
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
@@ -302,10 +291,6 @@ Class Procs:
/obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames.
return
/obj/machinery/proc/assign_uid()
uid = gl_uid
gl_uid++
/obj/machinery/proc/default_pry_open(obj/item/crowbar/C)
. = !(state_open || panel_open || is_operational() || (flags_1 & NODECONSTRUCT_1)) && istype(C)
if(.)
@@ -508,11 +493,16 @@ Class Procs:
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
#if DM_VERSION > 511
#warn Refactor the loop in /obj/machinery/proc/adjust_item_drop_location() to make use of 512's list-like access to characters in a string
#endif
for (var/i in 1 to 32)
#if DM_VERSION >= 513
#warning 512 is definitely stable now, remove the old code
#endif
#if DM_VERSION >= 512
. += hex2num(md5[i])
#else
. += hex2num(copytext(md5,i,i+1))
#endif
. = . % 9
AM.pixel_x = -8 + ((.%3)*8)
AM.pixel_y = -8 + (round( . / 3)*8)
+15 -14
View File
@@ -1,6 +1,6 @@
/obj/machinery/camera
var/list/localMotionTargets = list()
var/list/datum/weakref/localMotionTargets = list()
var/detectTime = 0
var/area/ai_monitored/area_motion = null
var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
@@ -15,11 +15,11 @@
if (elapsed > alarm_delay)
triggerAlarm()
else if (detectTime == -1)
for (var/targetref in getTargetList())
var/mob/target = locate(targetref) in GLOB.mob_list
if (QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target)))
for (var/datum/weakref/targetref in getTargetList())
var/mob/target = targetref.resolve()
if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target)))
//If not part of a monitored area and the camera is not in range or the target is dead
lostTarget(target)
lostTargetRef(targetref)
/obj/machinery/camera/proc/getTargetList()
if(area_motion)
@@ -28,22 +28,23 @@
/obj/machinery/camera/proc/newTarget(mob/target)
if(isAI(target))
return 0
return FALSE
if (detectTime == 0)
detectTime = world.time // start the clock
var/list/targets = getTargetList()
targets |= "[REF(target)]"
return 1
targets |= WEAKREF(target)
return TRUE
/obj/machinery/camera/Destroy()
var/area/ai_monitored/A = get_area(src)
localMotionTargets = null
if(istype(A))
A.motioncameras -= src
return ..()
/obj/machinery/camera/proc/lostTarget(mob/target)
/obj/machinery/camera/proc/lostTargetRef(datum/weakref/R)
var/list/targets = getTargetList()
targets -= "[REF(target)]"
targets -= R
if (targets.len == 0)
cancelAlarm()
@@ -53,19 +54,19 @@
if (status)
aiPlayer.cancelAlarm("Motion", get_area(src), src)
detectTime = 0
return 1
return TRUE
/obj/machinery/camera/proc/triggerAlarm()
if (!detectTime)
return 0
return FALSE
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
if (status)
aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
detectTime = -1
return 1
return TRUE
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
if (!area_motion)
if(isliving(AM))
newTarget(AM)
newTarget(AM)
+4 -5
View File
@@ -83,10 +83,10 @@
var/obj/machinery/dna_scannernew/scannerf = null
// Loop through every direction
for(dir in list(NORTH,EAST,SOUTH,WEST))
for(var/direction in GLOB.cardinals)
// Try to find a scanner in that direction
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
// If found and operational, return the scanner
if (!isnull(scannerf) && scannerf.is_operational())
@@ -98,10 +98,9 @@
/obj/machinery/computer/cloning/proc/findcloner()
var/obj/machinery/clonepod/podf = null
for(dir in list(NORTH,EAST,SOUTH,WEST))
podf = locate(/obj/machinery/clonepod, get_step(src, dir))
for(var/direction in GLOB.cardinals)
podf = locate(/obj/machinery/clonepod, get_step(src, direction))
if (!isnull(podf) && podf.is_operational())
AttachCloner(podf)
@@ -230,6 +230,10 @@
if(!currmsg || !answer || currmsg.possible_answers.len < answer)
state = STATE_MESSAGELIST
currmsg.answered = answer
log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]")
if(currmsg)
currmsg.answer_callback.Invoke()
state = STATE_VIEWMESSAGE
if("status")
state = STATE_STATUSDISPLAY
@@ -359,6 +363,9 @@
if(!aicurrmsg || !answer || aicurrmsg.possible_answers.len < answer)
aistate = STATE_MESSAGELIST
aicurrmsg.answered = answer
log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]")
if(aicurrmsg.answer_callback)
aicurrmsg.answer_callback.Invoke()
aistate = STATE_VIEWMESSAGE
if("ai-status")
aistate = STATE_STATUSDISPLAY
@@ -733,3 +740,13 @@
var/content
var/list/possible_answers = list()
var/answered
var/datum/callback/answer_callback
/datum/comm_message/New(new_title,new_content,new_possible_answers)
..()
if(title)
title = new_title
if(content)
content = new_content
if(new_possible_answers)
possible_answers = new_possible_answers
+2 -2
View File
@@ -54,8 +54,8 @@
/obj/machinery/computer/scan_consolenew/Initialize()
. = ..()
for(dir in list(NORTH,EAST,SOUTH,WEST))
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
for(var/direction in GLOB.cardinals)
connected = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
if(!isnull(connected))
break
injectorready = world.time + INJECTOR_TIMEOUT
+2 -2
View File
@@ -84,8 +84,8 @@
open_machine()
/obj/machinery/dna_scannernew/proc/locate_computer(type_)
for(dir in list(NORTH,EAST,SOUTH,WEST))
var/C = locate(type_, get_step(src, dir))
for(var/direction in GLOB.cardinals)
var/C = locate(type_, get_step(src, direction))
if(C)
return C
return null
+220 -307
View File
@@ -39,8 +39,7 @@
#define NOT_ELECTRIFIED 0
#define ELECTRIFIED_PERMANENT -1
#define AI_ELECTRIFY_DOOR_TIME 30
/obj/machinery/door/airlock
name = "airlock"
@@ -68,7 +67,7 @@
var/justzap = FALSE
normalspeed = 1
var/obj/item/electronics/airlock/electronics = null
var/hasShocked = FALSE //Prevents multiple shocks from happening
var/shockCooldown = FALSE //Prevents multiple shocks from happening
autoclose = TRUE
var/obj/item/device/doorCharge/charge = null //If applied, causes an explosion upon opening the door
var/obj/item/note //Any papers pinned to the airlock
@@ -364,6 +363,9 @@
/obj/machinery/door/airlock/proc/loseBackupPower()
if(src.secondsBackupPowerLost < 60)
src.secondsBackupPowerLost = 60
if(!spawnPowerRestoreRunning)
spawnPowerRestoreRunning = TRUE
INVOKE_ASYNC(src, .proc/handlePowerRestore)
/obj/machinery/door/airlock/proc/regainBackupPower()
if(src.secondsBackupPowerLost > 0)
@@ -375,14 +377,14 @@
/obj/machinery/door/airlock/proc/shock(mob/user, prb)
if(!hasPower()) // unpowered, no shock
return FALSE
if(hasShocked > world.time)
if(shockCooldown > world.time)
return FALSE //Already shocked someone recently?
if(!prob(prb))
return FALSE //you lucked out, no shock for you
do_sparks(5, TRUE, src)
var/tmp/check_range = TRUE
if(electrocute_mob(user, get_area(src), src, 1, check_range))
hasShocked = world.time + 10
shockCooldown = world.time + 10
return TRUE
else
return FALSE
@@ -612,110 +614,7 @@
to_chat(user, "<span class='warning'>Unable to interface. Airlock control panel damaged.</span>")
return
//Separate interface for the AI.
user.set_machine(src)
var/t1 = text("<B>Airlock Control</B><br>\n")
if(src.secondsMainPowerLost > 0)
if(!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2))
t1 += text("Main power is offline for [] seconds.<br>\n", src.secondsMainPowerLost)
else
t1 += text("Main power is offline indefinitely.<br>\n")
else
t1 += text("Main power is online.")
if(src.secondsBackupPowerLost > 0)
if(!wires.is_cut(WIRE_BACKUP1) && !wires.is_cut(WIRE_BACKUP2))
t1 += text("Backup power is offline for [] seconds.<br>\n", src.secondsBackupPowerLost)
else
t1 += text("Backup power is offline indefinitely.<br>\n")
else if(src.secondsMainPowerLost > 0)
t1 += text("Backup power is online.")
else
t1 += text("Backup power is offline, but will turn on if main power fails.")
t1 += "<br>\n"
if(wires.is_cut(WIRE_IDSCAN))
t1 += text("IdScan wire is cut.<br>\n")
else if(src.aiDisabledIdScanner)
t1 += "IdScan disabled. <A href='?src=[REF(src)];aiEnable=1'>Enable?</a><br>\n"
else
t1 += "IdScan enabled. <A href='?src=[REF(src)];aiDisable=1'>Disable?</a><br>\n"
if(src.emergency)
t1 += "Emergency Access Override is enabled. <A href='?src=[REF(src)];aiDisable=11'>Disable?</a><br>\n"
else
t1 += "Emergency Access Override is disabled. <A href='?src=[REF(src)];aiEnable=11'>Enable?</a><br>\n"
if(wires.is_cut(WIRE_POWER1))
t1 += text("Main Power Input wire is cut.<br>\n")
if(wires.is_cut(WIRE_POWER2))
t1 += text("Main Power Output wire is cut.<br>\n")
if(!secondsMainPowerLost)
t1 += "<A href='?src=[REF(src)];aiDisable=2'>Temporarily disrupt main power?</a>.<br>\n"
if(!secondsBackupPowerLost)
t1 += "<A href='?src=[REF(src)];aiDisable=3'>Temporarily disrupt backup power?</a>.<br>\n"
if(wires.is_cut(WIRE_BACKUP1))
t1 += text("Backup Power Input wire is cut.<br>\n")
if(wires.is_cut(WIRE_BACKUP2))
t1 += text("Backup Power Output wire is cut.<br>\n")
if(wires.is_cut(WIRE_BOLTS))
t1 += text("Door bolt drop wire is cut.<br>\n")
else if(!src.locked)
t1 += "Door bolts are up. <A href='?src=[REF(src)];aiDisable=4'>Drop them?</a><br>\n"
else
t1 += text("Door bolts are down.")
if(src.hasPower())
t1 += " <A href='?src=[REF(src)];aiEnable=4'>Raise?</a><br>\n"
else
t1 += text(" Cannot raise door bolts due to power failure.<br>\n")
if(wires.is_cut(WIRE_LIGHT))
t1 += text("Door bolt lights wire is cut.<br>\n")
else if(!src.lights)
t1 += "Door bolt lights are off. <A href='?src=[REF(src)];aiEnable=10'>Enable?</a><br>\n"
else
t1 += "Door bolt lights are on. <A href='?src=[REF(src)];aiDisable=10'>Disable?</a><br>\n"
if(wires.is_cut(WIRE_SHOCK))
t1 += text("Electrification wire is cut.<br>\n")
if(secondsElectrified==ELECTRIFIED_PERMANENT)
t1 += "Door is electrified indefinitely. <A href='?src=[REF(src)];aiDisable=5'>Un-electrify it?</a><br>\n"
else if(secondsElectrified>NOT_ELECTRIFIED)
t1 += text("Door is electrified temporarily ([] seconds). <A href='?src=[REF(src)];aiDisable=5'>Un-electrify it?</a><br>\n", secondsElectrified)
else
t1 += "Door is not electrified. <A href='?src=[REF(src)];aiEnable=5'>Electrify it for 30 seconds?</a> Or, <A href='?src=[REF(src)];aiEnable=6'>Electrify it indefinitely until someone cancels the electrification?</a><br>\n"
if(wires.is_cut(WIRE_SAFETY))
t1 += text("Door force sensors not responding.</a><br>\n")
else if(src.safe)
t1 += "Door safeties operating normally. <A href='?src=[REF(src)];aiDisable=8'>Override?</a><br>\n"
else
t1 += "Danger. Door safeties disabled. <A href='?src=[REF(src)];aiEnable=8'>Restore?</a><br>\n"
if(wires.is_cut(WIRE_TIMING))
t1 += text("Door timing circuitry not responding.</a><br>\n")
else if(src.normalspeed)
t1 += "Door timing circuitry operating normally. <A href='?src=[REF(src)];aiDisable=9'>Override?</a><br>\n"
else
t1 += "Warning. Door timing circuitry operating abnormally. <A href='?src=[REF(src)];aiEnable=9'>Restore?</a><br>\n"
if(src.welded)
t1 += text("Door appears to have been welded shut.<br>\n")
else if(!src.locked)
if(src.density)
t1 += "<A href='?src=[REF(src)];aiEnable=7'>Open door</a><br>\n"
else
t1 += "<A href='?src=[REF(src)];aiDisable=7'>Close door</a><br>\n"
t1 += "<p><a href='?src=[REF(src)];close=1'>Close</a></p>\n"
user << browse(t1, "window=airlock")
onclose(user, "airlock")
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 11 lift access override
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 11 enable access override
ui_interact(user)
/obj/machinery/door/airlock/proc/hack(mob/user)
set waitfor = 0
@@ -802,11 +701,18 @@
/obj/machinery/door/airlock/proc/electrified_loop()
while (secondsElectrified > 0)
secondsElectrified--
if(secondsElectrified <= 0)
set_electrified(NOT_ELECTRIFIED)
updateUsrDialog()
sleep(10)
sleep(10)
if(QDELETED(src))
return
secondsElectrified -= 1
updateDialog()
// This is to protect against changing to permanent, mid loop.
if(secondsElectrified==0)
set_electrified(NOT_ELECTRIFIED)
else
set_electrified(ELECTRIFIED_PERMANENT)
updateDialog()
/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
// If you add an if(..()) check you must first remove the var/nowindow parameter.
@@ -816,206 +722,16 @@
if(!usr.canUseTopic(src) && !IsAdminGhost(usr))
return
add_fingerprint(usr)
if(href_list["close"])
usr << browse(null, "window=airlock")
if(usr.machine==src)
usr.unset_machine()
return
if((in_range(src, usr) && isturf(loc)) && panel_open)
usr.set_machine(src)
if((issilicon(usr) && src.canAIControl(usr)) || IsAdminGhost(usr))
//AI
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed, 11 emergency access
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed, 11 emergency access
if(href_list["aiDisable"])
var/code = text2num(href_list["aiDisable"])
switch (code)
if(1)
//disable idscan
if(wires.is_cut(WIRE_IDSCAN))
to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.")
else if(src.aiDisabledIdScanner)
to_chat(usr, "You've already disabled the IdScan feature.")
else
aiDisabledIdScanner = TRUE
if(2)
//disrupt main power
if(!secondsMainPowerLost)
src.loseMainPower()
update_icon()
else
to_chat(usr, "Main power is already offline.")
if(3)
//disrupt backup power
if(!secondsBackupPowerLost)
src.loseBackupPower()
update_icon()
else
to_chat(usr, "Backup power is already offline.")
if(4)
//drop door bolts
if(wires.is_cut(WIRE_BOLTS))
to_chat(usr, "You can't drop the door bolts - The door bolt dropping wire has been cut.")
else
bolt()
if(5)
//un-electrify door
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("Can't un-electrify the airlock - The electrification wire is cut."))
else if(isElectrified())
set_electrified(0)
if(8)
// Safeties! We don't need no stinking safeties!
if(wires.is_cut(WIRE_SAFETY))
to_chat(usr, text("Control to door sensors is disabled."))
else if (src.safe)
safe = FALSE
else
to_chat(usr, text("Firmware reports safeties already overriden."))
if(9)
// Door speed control
if(wires.is_cut(WIRE_TIMING))
to_chat(usr, text("Control to door timing circuitry has been severed."))
else if (src.normalspeed)
normalspeed = 0
else
to_chat(usr, text("Door timing circuitry already accelerated."))
if(7)
//close door
if(src.welded)
to_chat(usr, text("The airlock has been welded shut!"))
else if(src.locked)
to_chat(usr, text("The door bolts are down!"))
else if(!src.density)
close()
else
open()
if(10)
// Bolt lights
if(wires.is_cut(WIRE_LIGHT))
to_chat(usr, text("Control to door bolt lights has been severed.</a>"))
else if (src.lights)
lights = FALSE
update_icon()
else
to_chat(usr, text("Door bolt lights are already disabled!"))
if(11)
// Emergency access
if (src.emergency)
emergency = FALSE
update_icon()
else
to_chat(usr, text("Emergency access is already disabled!"))
else if(href_list["aiEnable"])
var/code = text2num(href_list["aiEnable"])
switch (code)
if(1)
//enable idscan
if(wires.is_cut(WIRE_IDSCAN))
to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.")
else if(src.aiDisabledIdScanner)
aiDisabledIdScanner = FALSE
else
to_chat(usr, "The IdScan feature is not disabled.")
if(4)
//raise door bolts
if(wires.is_cut(WIRE_BOLTS))
to_chat(usr, text("The door bolt drop wire is cut - you can't raise the door bolts.<br>\n"))
else if(!src.locked)
to_chat(usr, text("The door bolts are already up.<br>\n"))
else
if(src.hasPower())
unbolt()
else
to_chat(usr, text("Cannot raise door bolts due to power failure.<br>\n"))
if(5)
//electrify door for 30 seconds
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("The electrification wire has been cut.<br>\n"))
else if(secondsElectrified==ELECTRIFIED_PERMANENT)
to_chat(usr, text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.<br>\n"))
else if(isElectrified())
to_chat(usr, text("The door is already electrified. You can't re-electrify it while it's already electrified.<br>\n"))
else
shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])"
add_logs(usr, src, "electrified")
set_electrified(30)
addtimer(CALLBACK(src, .proc/electrified_loop), 10)
if(6)
//electrify door indefinitely
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("The electrification wire has been cut.<br>\n"))
else if(secondsElectrified==ELECTRIFIED_PERMANENT)
to_chat(usr, text("The door is already indefinitely electrified.<br>\n"))
else if(isElectrified())
to_chat(usr, text("The door is already electrified. You can't re-electrify it while it's already electrified.<br>\n"))
else
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, src, "electrified")
set_electrified(ELECTRIFIED_PERMANENT)
if (8) // Not in order >.>
// Safeties! Maybe we do need some stinking safeties!
if(wires.is_cut(WIRE_SAFETY))
to_chat(usr, text("Control to door sensors is disabled."))
else if (!src.safe)
safe = TRUE
src.updateUsrDialog()
else
to_chat(usr, text("Firmware reports safeties already in place."))
if(9)
// Door speed control
if(wires.is_cut(WIRE_TIMING))
to_chat(usr, text("Control to door timing circuitry has been severed."))
else if (!src.normalspeed)
normalspeed = 1
src.updateUsrDialog()
else
to_chat(usr, text("Door timing circuitry currently operating normally."))
if(7)
//open door
if(src.welded)
to_chat(usr, text("The airlock has been welded shut!"))
else if(src.locked)
to_chat(usr, text("The door bolts are down!"))
else if(src.density)
open()
else
close()
if(10)
// Bolt lights
if(wires.is_cut(WIRE_LIGHT))
to_chat(usr, text("Control to door bolt lights has been severed.</a>"))
else if (!src.lights)
lights = TRUE
update_icon()
src.updateUsrDialog()
else
to_chat(usr, text("Door bolt lights are already enabled!"))
if(11)
// Emergency access
if (!src.emergency)
emergency = TRUE
update_icon()
else
to_chat(usr, text("Emergency access is already enabled!"))
add_fingerprint(usr)
if(!nowindow)
updateUsrDialog()
else
updateDialog()
/obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params)
if(!issilicon(user) && !IsAdminGhost(user))
@@ -1571,6 +1287,8 @@
/obj/machinery/door/airlock/proc/set_electrified(seconds)
secondsElectrified = seconds
diag_hud_set_electrified()
if(secondsElectrified > 0)
INVOKE_ASYNC(src, .proc/electrified_loop)
/obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
@@ -1636,6 +1354,200 @@
else if(istype(note, /obj/item/photo))
return "photo"
/obj/machinery/door/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ai_airlock", name, 550, 430, master_ui, state)
ui.open()
/obj/machinery/door/airlock/ui_data()
var/list/data = list()
var/list/power = list()
power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean
power["main_timeleft"] = src.secondsMainPowerLost
power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean
power["backup_timeleft"] = src.secondsBackupPowerLost
data["power"] = power
data["shock"] = secondsElectrified == 0 ? 2 : 0
data["shock_timeleft"] = secondsElectrified
data["id_scanner"] = !aiDisabledIdScanner
data["emergency"] = emergency // access
data["locked"] = locked // bolted
data["lights"] = lights // bolt lights
data["safe"] = safe // safeties
data["speed"] = normalspeed // safe speed
var/list/wire = list()
wire["main_1"] = !wires.is_cut(WIRE_POWER1)
wire["main_2"] = !wires.is_cut(WIRE_POWER2)
wire["backup_1"] = !wires.is_cut(WIRE_BACKUP1)
wire["backup_2"] = !wires.is_cut(WIRE_BACKUP2)
wire["shock"] = !wires.is_cut(WIRE_SHOCK)
wire["id_scanner"] = !wires.is_cut(WIRE_IDSCAN)
wire["bolts"] = !wires.is_cut(WIRE_BOLTS)
wire["lights"] = !wires.is_cut(WIRE_LIGHT)
wire["safe"] = !wires.is_cut(WIRE_SAFETY)
wire["timing"] = !wires.is_cut(WIRE_TIMING)
data["wires"] = wire
return data
/obj/machinery/door/airlock/ui_act(action, params)
if(..())
return
if(!(issilicon(usr) && src.canAIControl(usr)) || IsAdminGhost(usr))
return
switch(action)
if("disrupt-main")
if(!secondsMainPowerLost)
loseMainPower()
update_icon()
else
to_chat(usr, "Main power is already offline.")
. = TRUE
if("disrupt-backup")
if(!secondsBackupPowerLost)
loseBackupPower()
update_icon()
else
to_chat(usr, "Backup power is already offline.")
. = TRUE
if("shock-restore")
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("Can't un-electrify the airlock - The electrification wire is cut."))
else if(isElectrified())
set_electrified(0)
. = TRUE
if("shock-temp")
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("The electrification wire has been cut"))
else
shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])"
add_logs(usr, src, "electrified")
set_electrified(AI_ELECTRIFY_DOOR_TIME)
. = TRUE
if("shock-perm")
if(wires.is_cut(WIRE_SHOCK))
to_chat(usr, text("The electrification wire has been cut"))
else
shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, src, "electrified")
set_electrified(ELECTRIFIED_PERMANENT)
. = TRUE
if("idscan-on")
if(wires.is_cut(WIRE_IDSCAN))
to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.")
else if(src.aiDisabledIdScanner)
aiDisabledIdScanner = FALSE
else
to_chat(usr, "The IdScan feature is not disabled.")
. = TRUE
if("idscan-off")
if(wires.is_cut(WIRE_IDSCAN))
to_chat(usr, "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways.")
else if(aiDisabledIdScanner)
to_chat(usr, "You've already disabled the IdScan feature.")
else
aiDisabledIdScanner = TRUE
. = TRUE
if("emergency-on")
if (!src.emergency)
emergency = TRUE
update_icon()
else
to_chat(usr, text("Emergency access is already enabled!"))
. = TRUE
if("emergency-off")
if (emergency)
emergency = FALSE
update_icon()
else
to_chat(usr, text("Emergency access is already disabled!"))
. = TRUE
if("bolt-raise")
if(wires.is_cut(WIRE_BOLTS))
to_chat(usr, text("The door bolt drop wire is cut - you can't raise the door bolts"))
else if(!src.locked)
to_chat(usr, text("The door bolts are already up"))
else
if(src.hasPower())
unbolt()
else
to_chat(usr, text("Cannot raise door bolts due to power failure"))
. = TRUE
if("bolt-drop")
if(wires.is_cut(WIRE_BOLTS))
to_chat(usr, "You can't drop the door bolts - The door bolt dropping wire has been cut.")
else
bolt()
. = TRUE
if("light-on")
if(wires.is_cut(WIRE_LIGHT))
to_chat(usr, text("Control to door bolt lights has been severed.</a>"))
else if (!src.lights)
lights = TRUE
update_icon()
else
to_chat(usr, text("Door bolt lights are already enabled!"))
. = TRUE
if("light-off")
if(wires.is_cut(WIRE_LIGHT))
to_chat(usr, text("Control to door bolt lights has been severed.</a>"))
else if (lights)
lights = FALSE
update_icon()
else
to_chat(usr, text("Door bolt lights are already disabled!"))
. = TRUE
if("safe-on")
if(wires.is_cut(WIRE_SAFETY))
to_chat(usr, text("Control to door sensors is disabled."))
else if (!src.safe)
safe = TRUE
else
to_chat(usr, text("Firmware reports safeties already in place."))
. = TRUE
if("safe-off")
if(wires.is_cut(WIRE_SAFETY))
to_chat(usr, text("Control to door sensors is disabled."))
else if (safe)
safe = FALSE
else
to_chat(usr, text("Firmware reports safeties already overriden."))
. = TRUE
if("speed-on")
if(wires.is_cut(WIRE_TIMING))
to_chat(usr, text("Control to door timing circuitry has been severed."))
else if (!src.normalspeed)
normalspeed = 1
else
to_chat(usr, text("Door timing circuitry currently operating normally."))
. = TRUE
if("speed-off")
if(wires.is_cut(WIRE_TIMING))
to_chat(usr, text("Control to door timing circuitry has been severed."))
else if (normalspeed)
normalspeed = 0
else
to_chat(usr, text("Door timing circuitry already accelerated."))
. = TRUE
if("open-close")
if(welded)
to_chat(usr, text("The airlock has been welded shut!"))
else if(locked)
to_chat(usr, text("The door bolts are down!"))
else if(!density)
close()
else
open()
. = TRUE
#undef AIRLOCK_CLOSED
#undef AIRLOCK_CLOSING
#undef AIRLOCK_OPEN
@@ -1658,3 +1570,4 @@
#undef NOT_ELECTRIFIED
#undef ELECTRIFIED_PERMANENT
#undef AI_ELECTRIFY_DOOR_TIME
+106
View File
@@ -0,0 +1,106 @@
/obj/machinery/exonet_node
name = "exonet node"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "exonet_node"
idle_power_usage = 25
var/on = TRUE
var/toggle = TRUE
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/machine/exonet_node
max_integrity = 300
integrity_failure = 100
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
desc = "This machine is exonet node."
var/list/logs = list() // Gets written to by exonet's send_message() function.
var/opened = FALSE
/obj/machinery/exonet_node/Initialize()
. = ..()
SScircuit.all_exonet_nodes += src
/obj/machinery/exonet_node/Destroy()
SScircuit.all_exonet_nodes -= src
return ..()
/obj/machinery/exonet_node/proc/is_operating()
return on && !stat
// Proc: update_icon()
// Parameters: None
// Description: Self explanatory.
/obj/machinery/exonet_node/update_icon()
icon_state = "[initial(icon_state)][on? "" : "_off"]"
// Proc: update_power()
// Parameters: None
// Description: Sets the device on/off and adjusts power draw based on stat and toggle variables.
/obj/machinery/exonet_node/proc/update_power()
on = is_operational() && toggle
use_power = on
update_icon()
// Proc: emp_act()
// Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger)
// Description: Shuts off the machine for awhile if an EMP hits it. Ion anomalies also call this to turn it off.
/obj/machinery/exonet_node/emp_act(severity)
if(!(stat & EMPED))
stat |= EMPED
var/duration = (300 * 10)/severity
addtimer(CALLBACK(src, /obj/machinery/exonet_node/proc/unemp_act), rand(duration - 20, duration + 20))
update_icon()
..()
/obj/machinery/exonet_node/proc/unemp_act(severity)
stat &= ~EMPED
// Proc: attackby()
// Parameters: 2 (I - the item being whacked against the machine, user - the person doing the whacking)
// Description: Handles deconstruction.
/obj/machinery/exonet_node/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/screwdriver))
default_deconstruction_screwdriver(user, I)
else if(istype(I, /obj/item/crowbar))
default_deconstruction_crowbar(user, I)
else
return ..()
// Proc: attack_ai()
// Parameters: 1 (user - the AI clicking on the machine)
// Description: Redirects to attack_hand()
/obj/machinery/exonet_node/attack_ai(mob/user)
ui_interact(user)
/obj/machinery/exonet_node/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, var/force_open = 1,datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "exonet_node", name, 600, 300, master_ui, state)
ui.open()
/obj/machinery/exonet_node/ui_data(mob/user)
var/list/data = list()
data["toggle"] = toggle
data["logs"] = logs
return data
/obj/machinery/exonet_node/ui_act(action, params)
if(..())
return
switch(action)
if("toggle_power")
toggle = !toggle
update_power()
if(!toggle)
investigate_log("has been turned off by [key_name(usr)].", INVESTIGATE_EXONET)
. = TRUE
update_icon()
add_fingerprint(usr)
// Proc: get_exonet_node()
// Parameters: None
// Description: Helper proc to get a reference to an Exonet node.
/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content)
var/msg = "[time2text(world.time, "hh:mm:ss")] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]"
logs.Add(msg)
+2 -2
View File
@@ -25,7 +25,7 @@ Buildable meters
/obj/item/pipe/directional
RPD_type = PIPE_UNARY
/obj/item/pipe/binary
RPD_type = PIPE_BINARY
RPD_type = PIPE_STRAIGHT
/obj/item/pipe/binary/bendable
RPD_type = PIPE_BENDABLE
/obj/item/pipe/trinary
@@ -34,7 +34,7 @@ Buildable meters
RPD_type = PIPE_TRIN_M
var/flipped = FALSE
/obj/item/pipe/quaternary
RPD_type = PIPE_QUAD
RPD_type = PIPE_ONEDIR
/obj/item/pipe/examine(mob/user)
..()
+28 -51
View File
@@ -14,35 +14,19 @@
/obj/machinery/pipedispenser/attack_hand(mob/user)
if(..())
return 1
var/dat = {"
PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b><A href='?src=[REF(src)];layer_up=1'>++</A><BR>
<b>Pipes:</b><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/simple];dir=1'>Pipe</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/simple];dir=5'>Bent Pipe</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/manifold];dir=1'>Manifold</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/layer_manifold];dir=1'>Layer Manifold</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/manifold4w];dir=1'>4-Way Manifold</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/binary/valve];dir=1'>Manual Valve</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/binary/valve/digital];dir=1'>Digital Valve</A><BR>
<b>Devices:</b><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/unary/portables_connector];dir=1'>Connector</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/unary/vent_pump];dir=1'>Vent</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/binary/pump];dir=1'>Gas Pump</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/binary/passive_gate];dir=1'>Passive Gate</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/binary/volume_pump];dir=1'>Volume Pump</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/unary/vent_scrubber];dir=1'>Scrubber</A><BR>
<A href='?src=[REF(src)];makemeter=1'>Meter</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/trinary/filter];dir=1'>Gas Filter</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/trinary/mixer];dir=1'>Gas Mixer</A><BR>
<b>Heat exchange:</b><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/simple];dir=1'>Pipe</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/simple];dir=5'>Bent Pipe</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/manifold];dir=1'>Manifold</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w];dir=1'>4-Way Manifold</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/junction];dir=1'>Junction</A><BR>
<A href='?src=[REF(src)];make=[/obj/machinery/atmospherics/components/unary/heat_exchanger];dir=1'>Heat Exchanger</A><BR>
"}
var/dat = "PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b><A href='?src=[REF(src)];layer_up=1'>++</A><BR>"
var/recipes = GLOB.atmos_pipe_recipes
for(var/category in recipes)
var/list/cat_recipes = recipes[category]
dat += "<b>[category]:</b><ul>"
for(var/i in cat_recipes)
var/datum/pipe_info/I = i
dat += I.Render(src)
dat += "</ul>"
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
onclose(user, "pipedispenser")
@@ -56,9 +40,9 @@ PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b>
return 1
usr.set_machine(src)
add_fingerprint(usr)
if(href_list["make"])
if(href_list["makepipe"])
if(wait < world.time)
var/p_type = text2path(href_list["make"])
var/p_type = text2path(href_list["makepipe"])
var/p_dir = text2num(href_list["dir"])
var/obj/item/pipe/P = new (loc, p_type, p_dir)
P.setPipingLayer(piping_layer)
@@ -118,14 +102,6 @@ PIPING LAYER: <A href='?src=[REF(src)];layer_down=1'>--</A><b>[piping_layer]</b>
density = TRUE
anchored = TRUE
/*
//Allow you to push disposal pipes into it (for those with density 1)
/obj/machinery/pipedispenser/disposal/Crossed(var/obj/structure/disposalconstruct/pipe as obj)
if(istype(pipe) && !pipe.anchored)
qdel(pipe)
Nah
*/
//Allow you to drag-drop disposal pipes and transit tubes into it
/obj/machinery/pipedispenser/disposal/MouseDrop_T(obj/structure/pipe, mob/usr)
@@ -147,17 +123,18 @@ Nah
if(..())
return 1
var/dat = {"<b>Disposal Pipes</b><br><br>
<A href='?src=[REF(src)];dmake=[DISP_PIPE_STRAIGHT]'>Pipe</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_PIPE_BENT]'>Bent Pipe</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_JUNCTION]'>Junction</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_YJUNCTION]'>Y-Junction</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_END_TRUNK]'>Trunk</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_END_BIN]'>Bin</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_END_OUTLET]'>Outlet</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_END_CHUTE]'>Chute</A><BR>
<A href='?src=[REF(src)];dmake=[DISP_SORTJUNCTION]'>Sort Junction</A><BR>
"}
var/dat = ""
var/recipes = GLOB.disposal_pipe_recipes
for(var/category in recipes)
var/list/cat_recipes = recipes[category]
dat += "<b>[category]:</b><ul>"
for(var/i in cat_recipes)
var/datum/pipe_info/I = i
dat += I.Render(src)
dat += "</ul>"
user << browse("<HEAD><TITLE>[src]</TITLE></HEAD><TT>[dat]</TT>", "window=pipedispenser")
return
@@ -170,8 +147,8 @@ Nah
add_fingerprint(usr)
if(href_list["dmake"])
if(wait < world.time)
var/p_type = text2num(href_list["dmake"])
var/obj/structure/disposalconstruct/C = new (loc,p_type)
var/p_type = text2path(href_list["dmake"])
var/obj/structure/disposalconstruct/C = new (loc, p_type)
if(!C.can_place())
to_chat(usr, "<span class='warning'>There's not enough room to build that here!</span>")
+12 -12
View File
@@ -140,7 +140,7 @@
if(open_panel && wires.is_all_cut())
if(payload)
to_chat(user, "<span class='notice'>You carefully pry out [payload].</span>")
payload.loc = user.loc
payload.forceMove(drop_location())
payload = null
else
to_chat(user, "<span class='warning'>There isn't anything in here to remove!</span>")
@@ -206,14 +206,14 @@
var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station
timer_set = Clamp(new_timer, minimum_timer, maximum_timer)
src.loc.visible_message("<span class='notice'>[icon2html(src, viewers(src))] timer set for [timer_set] seconds.</span>")
loc.visible_message("<span class='notice'>[icon2html(src, viewers(src))] timer set for [timer_set] seconds.</span>")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user))
if(defused || active)
if(defused)
src.loc.visible_message("<span class='warning'>[icon2html(src, viewers(src))] Device error: User intervention required.</span>")
visible_message("<span class='warning'>[icon2html(src, viewers(src))] Device error: User intervention required.</span>")
return
else
src.loc.visible_message("<span class='danger'>[icon2html(src, viewers(loc))] [timer_set] seconds until detonation, please clear the area.</span>")
visible_message("<span class='danger'>[icon2html(src, viewers(loc))] [timer_set] seconds until detonation, please clear the area.</span>")
activate()
update_icon()
add_fingerprint(user)
@@ -223,7 +223,7 @@
if(payload && !istype(payload, /obj/item/bombcore/training))
message_admins("[ADMIN_LOOKUPFLW(user)] has primed a [name] ([payload]) for detonation at [A.name] [ADMIN_JMP(bombturf)]</a>.")
log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name][COORD(bombturf)]")
payload.adminlog = "The [src.name] that [key_name(user)] had primed detonated!"
payload.adminlog = "The [name] that [key_name(user)] had primed detonated!"
///Bomb Subtypes///
@@ -359,7 +359,7 @@
var/amt_summon = 1
/obj/item/bombcore/badmin/summon/detonate()
var/obj/machinery/syndicatebomb/B = src.loc
var/obj/machinery/syndicatebomb/B = loc
spawn_and_random_walk(summon_path, src, amt_summon, walk_chance=50, admin_spawn=TRUE)
qdel(B)
qdel(src)
@@ -369,7 +369,7 @@
amt_summon = 100
/obj/item/bombcore/badmin/summon/clown/defuse()
playsound(src.loc, 'sound/misc/sadtrombone.ogg', 50)
playsound(src, 'sound/misc/sadtrombone.ogg', 50)
..()
/obj/item/bombcore/large
@@ -454,7 +454,7 @@
if(istype(I, /obj/item/crowbar) && beakers.len > 0)
playsound(loc, I.usesound, 50, 1)
for (var/obj/item/B in beakers)
B.loc = get_turf(src)
B.forceMove(drop_location())
beakers -= B
return
else if(istype(I, /obj/item/reagent_containers/glass/beaker) || istype(I, /obj/item/reagent_containers/glass/bottle))
@@ -485,9 +485,9 @@
for(var/obj/item/slime_extract/S in LG.beakers) // And slime cores.
if(beakers.len < max_beakers)
beakers += S
S.loc = src
S.forceMove(src)
else
S.loc = get_turf(src)
S.forceMove(drop_location())
if(istype(G, /obj/item/grenade/chem_grenade/cryo))
spread_range -= 1 // Reduced range, but increased density.
@@ -502,9 +502,9 @@
for(var/obj/item/reagent_containers/glass/B in G)
if(beakers.len < max_beakers)
beakers += B
B.loc = src
B.forceMove(src)
else
B.loc = get_turf(src)
B.forceMove(drop_location())
qdel(G)
@@ -71,7 +71,8 @@
/obj/machinery/telecomms/relay/preset/reebe
name = "hierophant relay"
desc = "A stolen telecommunications relay that ingeniously combines bluespace technology with the Hierophant network to send and receive messages to and from Reebe."
desc = "An arcane telecommunications relay that ingeniously combines bluespace technology with the Hierophant network to send and receive messages to and from Reebe."
id = "Hierophant Relay"
icon = 'icons/obj/clockwork_objects.dmi'
hide = TRUE
autolinkers = list("h_relay")
+4 -4
View File
@@ -259,7 +259,7 @@
cut_overlays()
if(panel_open)
add_overlay("[initial(icon_state)]-panel")
playsound(src.loc, W.usesound, 50, 1)
playsound(src, W.usesound, 50, 1)
updateUsrDialog()
else
to_chat(user, "<span class='warning'>You must first secure [src].</span>")
@@ -403,7 +403,7 @@
var/datum/browser/popup = new(user, "vending", (name))
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
@@ -443,7 +443,7 @@
dish_quants[N] = max(dish_quants[N] - 1, 0)
for(var/obj/O in contents)
if(O.name == N)
O.loc = src.loc
O.forceMove(drop_location())
break
vend_ready = 1
updateUsrDialog()
@@ -510,7 +510,7 @@
if(icon_vend) //Show the vending animation if needed
flick(icon_vend,src)
new R.product_path(get_turf(src))
SSblackbox.add_details("vending_machine_usage","[src.type]|[R.product_path]")
SSblackbox.add_details("vending_machine_usage","[type]|[R.product_path]")
vend_ready = 1
return
+7
View File
@@ -121,6 +121,13 @@
to_chat(user, "<span class='warning'>[P] has no poster... inside it? Inform a coder!</span>")
return
// Deny placing posters on currently-diagonal walls, although the wall may change in the future.
if (smooth & SMOOTH_DIAGONAL)
for (var/O in our_overlays)
var/image/I = O
if (copytext(I.icon_state, 1, 3) == "d-")
return
var/stuff_on_wall = 0
for(var/obj/O in contents) //Let's see if it already has a poster on it or too much stuff
if(istype(O, /obj/structure/sign/poster))
+12 -1
View File
@@ -24,6 +24,7 @@
var/atmos_link = FALSE //Link source/destination atmos.
var/turf/open/atmos_source //Atmos link source
var/turf/open/atmos_destination //Atmos link destination
var/allow_anchored = FALSE
/obj/effect/portal/anom
name = "wormhole"
@@ -42,6 +43,8 @@
user.forceMove(get_turf(src))
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
if(isobserver(AM))
return ..()
if(linked && (get_turf(oldloc) == get_turf(linked)))
return ..()
if(!teleport(AM))
@@ -51,6 +54,8 @@
return
/obj/effect/portal/attack_hand(mob/user)
if(get_turf(user) == get_turf(src))
teleport(user)
if(Adjacent(user))
user.forceMove(get_turf(src))
@@ -123,12 +128,18 @@
linked = null
return ..()
/obj/effect/portal/attack_ghost(mob/dead/observer/O)
if(!teleport(O))
return ..()
/obj/effect/portal/proc/teleport(atom/movable/M)
if(!istype(M) || istype(M, /obj/effect) || isobserver(M) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M))) //Things that shouldn't teleport.
if(!istype(M) || istype(M, /obj/effect) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M))) //Things that shouldn't teleport.
return
var/turf/real_target = get_link_target_turf()
if(!istype(real_target))
return FALSE
if(!ismecha(M) && M.anchored && !allow_anchored)
return
if(ismegafauna(M))
message_admins("[M] has used a portal at [ADMIN_COORDJMP(src)] made by [usr].")
if(do_teleport(M, real_target, 0))
+168 -154
View File
@@ -1,5 +1,3 @@
/*
CONTAINS:
RPD
@@ -14,109 +12,111 @@ RPD
#define CATEGORY_ATMOS 0
#define CATEGORY_DISPOSALS 1
//find the defines in code\_DEFINES\pipe_construction.dm
GLOBAL_LIST_INIT(atmos_pipe_recipes, list(
"Pipes" = list(
new /datum/pipe_info/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple),
new /datum/pipe_info/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold),
new /datum/pipe_info/pipe("Manual Valve", /obj/machinery/atmospherics/components/binary/valve),
new /datum/pipe_info/pipe("Digital Valve", /obj/machinery/atmospherics/components/binary/valve/digital),
new /datum/pipe_info/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w),
new /datum/pipe_info/pipe("Layer Manifold", /obj/machinery/atmospherics/pipe/layer_manifold),
),
"Devices" = list(
new /datum/pipe_info/pipe("Connector", /obj/machinery/atmospherics/components/unary/portables_connector),
new /datum/pipe_info/pipe("Unary Vent", /obj/machinery/atmospherics/components/unary/vent_pump),
new /datum/pipe_info/pipe("Gas Pump", /obj/machinery/atmospherics/components/binary/pump),
new /datum/pipe_info/pipe("Passive Gate", /obj/machinery/atmospherics/components/binary/passive_gate),
new /datum/pipe_info/pipe("Volume Pump", /obj/machinery/atmospherics/components/binary/volume_pump),
new /datum/pipe_info/pipe("Scrubber", /obj/machinery/atmospherics/components/unary/vent_scrubber),
new /datum/pipe_info/pipe("Injector", /obj/machinery/atmospherics/components/unary/outlet_injector),
new /datum/pipe_info/meter("Meter"),
new /datum/pipe_info/pipe("Gas Filter", /obj/machinery/atmospherics/components/trinary/filter),
new /datum/pipe_info/pipe("Gas Mixer", /obj/machinery/atmospherics/components/trinary/mixer),
),
"Heat Exchange" = list(
new /datum/pipe_info/pipe("Pipe", /obj/machinery/atmospherics/pipe/heat_exchanging/simple),
new /datum/pipe_info/pipe("Manifold", /obj/machinery/atmospherics/pipe/heat_exchanging/manifold),
new /datum/pipe_info/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w),
new /datum/pipe_info/pipe("Junction", /obj/machinery/atmospherics/pipe/heat_exchanging/junction),
new /datum/pipe_info/pipe("Heat Exchanger", /obj/machinery/atmospherics/components/unary/heat_exchanger),
)
))
GLOBAL_LIST_INIT(disposal_pipe_recipes, list(
"Disposal Pipes" = list(
new /datum/pipe_info/disposal("Pipe", /obj/structure/disposalpipe/segment, PIPE_BENDABLE),
new /datum/pipe_info/disposal("Junction", /obj/structure/disposalpipe/junction, PIPE_TRIN_M),
new /datum/pipe_info/disposal("Y-Junction", /obj/structure/disposalpipe/junction/yjunction),
new /datum/pipe_info/disposal("Sort Junction", /obj/structure/disposalpipe/sorting/mail, PIPE_TRIN_M),
new /datum/pipe_info/disposal("Trunk", /obj/structure/disposalpipe/trunk),
new /datum/pipe_info/disposal("Bin", /obj/machinery/disposal/bin, PIPE_ONEDIR),
new /datum/pipe_info/disposal("Outlet", /obj/structure/disposaloutlet),
new /datum/pipe_info/disposal("Chute", /obj/machinery/disposal/deliveryChute),
)
))
/datum/pipe_info
var/id=-1
var/categoryId
var/dir=SOUTH
var/dirtype = PIPE_BENDABLE
var/name
var/icon
var/icon_state
var/selected=0
var/id = -1
var/categoryId
var/dirtype = PIPE_BENDABLE
/datum/pipe_info/proc/Render(dispenser)
return "<li><a href='?src=[REF(dispenser)]&[Params()]'>[name]</a></li>"
/datum/pipe_info/proc/Params()
return ""
/datum/pipe_info/pipe
categoryId = CATEGORY_ATMOS
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
/datum/pipe_info/pipe/New(obj/machinery/atmospherics/path)
/datum/pipe_info/pipe/New(label, obj/machinery/atmospherics/path)
name = label
id = path
icon_state = initial(path.pipe_state)
dirtype = initial(path.construction_type)
/datum/pipe_info/proc/Render(dispenser,label)
/datum/pipe_info/pipe/Params()
return "makepipe=[id]&type=[dirtype]"
/datum/pipe_info/pipe/Render(dispenser,label,dir=NORTH)
return "<li><a href='?src=[REF(dispenser)];makepipe=[id];dir=[dir];type=[dirtype]'>[label]</a></li>"
/datum/pipe_info/meter
categoryId = CATEGORY_ATMOS
icon = 'icons/obj/atmospherics/pipes/simple.dmi'
icon_state = "meterX"
/datum/pipe_info/meter/New()
return
/datum/pipe_info/meter/New(label)
name = label
/datum/pipe_info/meter/Render(dispenser,label)
return "<li><a href='?src=[REF(dispenser)];makemeter=1;type=[dirtype]'>[label]</a></li>" //hardcoding is no
/datum/pipe_info/meter/Params()
return "makemeter=1&type=[dirtype]"
GLOBAL_LIST_INIT(disposalpipeID2State, list(
"pipe-s",
"pipe-c",
"pipe-j1",
"pipe-j2",
"pipe-y",
"pipe-t",
"disposal",
"outlet",
"intake",
"pipe-j1s",
"pipe-j2s"))
/datum/pipe_info/disposal
categoryId = CATEGORY_DISPOSALS
icon = 'icons/obj/atmospherics/pipes/disposal.dmi'
/datum/pipe_info/disposal/New(var/pid,var/dt)
id=pid
icon_state=GLOB.disposalpipeID2State[pid+1]
dir = SOUTH
dirtype=dt
if(pid<DISP_END_BIN || pid>DISP_END_CHUTE)
/datum/pipe_info/disposal/New(label, obj/path, dt=PIPE_UNARY)
name = label
id = path
icon_state = initial(path.icon_state)
if(ispath(path, /obj/structure/disposalpipe))
icon_state = "con[icon_state]"
/datum/pipe_info/disposal/Render(dispenser,label)
return "<li><a href='?src=[REF(dispenser)];dmake=[id];type=[dirtype]'>[label]</a></li>" //avoid hardcoding.
dirtype = dt
/datum/pipe_info/disposal/Params()
return "dmake=[id]&type=[dirtype]"
//find these defines in code\game\machinery\pipe\consruction.dm
GLOBAL_LIST_INIT(RPD_recipes, list(
"Pipes" = list(
"Pipe" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/simple),
"Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/manifold),
"Manual Valve" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/valve),
"Digital Valve" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/valve/digital),
"4-Way Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/manifold4w),
"Layer Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/layer_manifold),
),
"Devices" = list(
"Connector" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/portables_connector),
"Unary Vent" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/vent_pump),
"Gas Pump" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/pump),
"Passive Gate" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/passive_gate),
"Volume Pump" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/volume_pump),
"Scrubber" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/vent_scrubber),
"Injector" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/outlet_injector),
"Meter" = new /datum/pipe_info/meter(),
"Gas Filter" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/trinary/filter),
"Gas Mixer" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/trinary/mixer),
),
"Heat Exchange" = list(
"Pipe" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/simple),
"Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/manifold),
"4-Way Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w),
"Junction" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/junction),
"Heat Exchanger" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/heat_exchanger),
),
"Disposal Pipes" = list(
"Pipe" = new /datum/pipe_info/disposal(DISP_PIPE_STRAIGHT, PIPE_BINARY),
"Bent Pipe" = new /datum/pipe_info/disposal(DISP_PIPE_BENT, PIPE_TRINARY),
"Junction" = new /datum/pipe_info/disposal(DISP_JUNCTION, PIPE_TRINARY),
"Y-Junction" = new /datum/pipe_info/disposal(DISP_YJUNCTION, PIPE_TRINARY),
"Trunk" = new /datum/pipe_info/disposal(DISP_END_TRUNK, PIPE_TRINARY),
"Bin" = new /datum/pipe_info/disposal(DISP_END_BIN, PIPE_QUAD),
"Outlet" = new /datum/pipe_info/disposal(DISP_END_OUTLET, PIPE_UNARY),
"Chute" = new /datum/pipe_info/disposal(DISP_END_CHUTE, PIPE_UNARY),
"Sort Junction" = new /datum/pipe_info/disposal(DISP_SORTJUNCTION, PIPE_TRINARY),
)
))
/obj/item/pipe_dispenser
name = "Rapid Piping Device (RPD)"
@@ -138,7 +138,7 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
var/p_type = /obj/machinery/atmospherics/pipe/simple
var/p_conntype = PIPE_BENDABLE
var/p_dir = 1
var/p_flipped = 0
var/p_flipped = FALSE
var/p_class = ATMOS_MODE
var/list/paint_colors = list(
"grey" = rgb(255,255,255),
@@ -179,6 +179,7 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
selected=" class=\"imglink selected\""
return "<a href=\"?src=[REF(src)];setdir=[_dir];flipped=[flipped]\" title=\"[title]\"[selected]\"><img src=\"[pic]\" /></a>"
/obj/item/pipe_dispenser/proc/show_menu(mob/user)
if(!user || !src)
return 0
@@ -197,38 +198,48 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
dat += "<b>Category:</b><ul>"
if(screen == CATEGORY_ATMOS)
dat += "<span class='linkOn'>Atmospherics</span> <A href='?src=[REF(src)];screen=[CATEGORY_DISPOSALS];dmake=0;type=0'>Disposals</A><BR>"
var/list/recipes = GLOB.disposal_pipe_recipes
var/datum/pipe_info/first_recipe = recipes[recipes[1]][1]
dat += "<span class='linkOn'>Atmospherics</span> "
dat += "<A href='?src=[REF(src)]&screen=[CATEGORY_DISPOSALS]&[first_recipe.Params()]'>Disposals</A><BR>"
dat += "Atmospherics Piping Layer: "
var/layers_total = PIPING_LAYER_MAX - PIPING_LAYER_MIN + 1
for(var/iter = PIPING_LAYER_MIN, iter <= layers_total, iter++)
if(iter == piping_layer)
dat += "<span class='linkOn'>[iter]</span>"
else
dat += "<A href='?src=[REF(src)];setlayer=[iter]'>[iter]</A>"
dat += "<BR>"
else if(screen == CATEGORY_DISPOSALS)
dat += "<A href='?src=[REF(src)];screen=[CATEGORY_ATMOS];makepipe=[/obj/machinery/atmospherics/pipe/simple];dir=1;type=0'>Atmospherics</A> <span class='linkOn'>Disposals</span><BR>"
var/generated_layer_list = ""
var/layers_total = PIPING_LAYER_MAX - PIPING_LAYER_MIN + 1
for(var/iter = PIPING_LAYER_MIN, iter <= layers_total, iter++)
if(iter == piping_layer)
generated_layer_list += "<span class='linkOn'><A href='?src=[REF(src)];setlayer=[iter]'>[iter]</A></span>"
else
generated_layer_list += "<A href='?src=[REF(src)];setlayer=[iter]'>[iter]</A>"
dat += "Atmospherics Piping Layer: [generated_layer_list]<BR>"
var/list/recipes = GLOB.atmos_pipe_recipes
var/datum/pipe_info/first_recipe = recipes[recipes[1]][1]
dat += "<A href='?src=[REF(src)]&screen=[CATEGORY_ATMOS]&[first_recipe.Params()]'>Atmospherics</A> "
dat += "<span class='linkOn'>Disposals</span><BR>"
dat += "</ul>"
var/icon/preview=null
var/datbuild = ""
for(var/category in GLOB.RPD_recipes)
var/list/cat = GLOB.RPD_recipes[category]
for(var/label in cat)
var/datum/pipe_info/I = cat[label]
var/recipes = GLOB.atmos_pipe_recipes + GLOB.disposal_pipe_recipes
for(var/category in recipes)
var/list/cat_recipes = recipes[category]
for(var/i in cat_recipes)
var/datum/pipe_info/I = i
var/found=0
if(I.id == p_type)
if((p_class == ATMOS_MODE || p_class == METER_MODE) && (istype(I, /datum/pipe_info/pipe) || istype(I, /datum/pipe_info/meter)))
found=1
else if(p_class == DISPOSALS_MODE && istype(I, /datum/pipe_info/disposal))
found=1
if((p_class == ATMOS_MODE || p_class == METER_MODE) && I.categoryId == CATEGORY_ATMOS)
found = 1
else if(p_class == DISPOSALS_MODE && I.categoryId == CATEGORY_DISPOSALS)
found = 1
if(found)
preview=new /icon(I.icon,I.icon_state)
preview = new /icon(I.icon, I.icon_state)
if(screen == I.categoryId)
if(I.id == p_type && p_class >= 0)
datbuild += "<span class='linkOn'>[label]</span>"
datbuild += "<li><span class='linkOn'>[I.name]</span></li>"
else
datbuild += I.Render(src,label)
datbuild += I.Render(src)
if(length(datbuild) > 0)
dat += "<b>[category]:</b><ul>"
@@ -264,20 +275,20 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
else
dirsel = ""
if(PIPE_BINARY) // Straight, N-S, W-E
if(PIPE_STRAIGHT) // Straight, N-S, W-E
if(preview)
user << browse_rsc(new /icon(preview, dir=NORTH), "vertical.png")
user << browse_rsc(new /icon(preview, dir=EAST), "horizontal.png")
dirsel += "<p>"
dirsel += render_dir_img(1,"vertical.png","Vertical")
dirsel += render_dir_img(4,"horizontal.png","Horizontal")
dirsel += render_dir_img(NORTH,"vertical.png","Vertical")
dirsel += render_dir_img(EAST,"horizontal.png","Horizontal")
dirsel += "</p>"
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=1; flipped=0" title="vertical">&#8597;</a>
<a href="?src=[REF(src)];setdir=4; flipped=0" title="horizontal">&harr;</a>
<a href="?src=[REF(src)];setdir=[NORTH]" title="vertical">&#8597;</a>
<a href="?src=[REF(src)];setdir=[EAST]" title="horizontal">&harr;</a>
</p>
"}
@@ -291,26 +302,26 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
user << browse_rsc(new /icon(preview, dir=SOUTHEAST), "se.png")
dirsel += "<p>"
dirsel += render_dir_img(1,"vertical.png","Vertical")
dirsel += render_dir_img(4,"horizontal.png","Horizontal")
dirsel += render_dir_img(NORTH,"vertical.png","Vertical")
dirsel += render_dir_img(EAST,"horizontal.png","Horizontal")
dirsel += "<br />"
dirsel += render_dir_img(9,"nw.png","West to North")
dirsel += render_dir_img(5,"ne.png","North to East")
dirsel += render_dir_img(NORTHWEST,"nw.png","West to North")
dirsel += render_dir_img(NORTHEAST,"ne.png","North to East")
dirsel += "<br />"
dirsel += render_dir_img(10,"sw.png","South to West")
dirsel += render_dir_img(6,"se.png","East to South")
dirsel += render_dir_img(SOUTHWEST,"sw.png","South to West")
dirsel += render_dir_img(SOUTHEAST,"se.png","East to South")
dirsel += "</p>"
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=1; flipped=0" title="vertical">&#8597;</a>
<a href="?src=[REF(src)];setdir=4; flipped=0" title="horizontal">&harr;</a>
<a href="?src=[REF(src)];setdir=[NORTH]" title="vertical">&#8597;</a>
<a href="?src=[REF(src)];setdir=[EAST]" title="horizontal">&harr;</a>
<br />
<a href="?src=[REF(src)];setdir=9; flipped=0" title="West to North">&#9565;</a>
<a href="?src=[REF(src)];setdir=5; flipped=0" title="North to East">&#9562;</a>
<a href="?src=[REF(src)];setdir=[NORTHWEST]" title="West to North">&#9565;</a>
<a href="?src=[REF(src)];setdir=[NORTHEAST]" title="North to East">&#9562;</a>
<br />
<a href="?src=[REF(src)];setdir=10; flipped=0" title="South to West">&#9559;</a>
<a href="?src=[REF(src)];setdir=6; flipped=0" title="East to South">&#9556;</a>
<a href="?src=[REF(src)];setdir=[SOUTHWEST]" title="South to West">&#9559;</a>
<a href="?src=[REF(src)];setdir=[SOUTHEAST]" title="East to South">&#9556;</a>
</p>
"}
if(PIPE_TRINARY) // Manifold
@@ -321,20 +332,20 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
user << browse_rsc(new /icon(preview, dir=WEST), "e.png")
dirsel += "<p>"
dirsel += render_dir_img(1,"s.png","West South East")
dirsel += render_dir_img(4,"w.png","North West South")
dirsel += render_dir_img(NORTH,"s.png","West South East")
dirsel += render_dir_img(EAST,"w.png","North West South")
dirsel += "<br />"
dirsel += render_dir_img(2,"n.png","East North West")
dirsel += render_dir_img(8,"e.png","South East North")
dirsel += render_dir_img(SOUTH,"n.png","East North West")
dirsel += render_dir_img(WEST,"e.png","South East North")
dirsel += "</p>"
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=1; flipped=0" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=4; flipped=0" title="North, West, South">&#9571;</a>
<a href="?src=[REF(src)];setdir=[NORTH]" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=[EAST]" title="North, West, South">&#9571;</a>
<br />
<a href="?src=[REF(src)];setdir=2; flipped=0" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=8; flipped=0" title="South, East, North">&#9568;</a>
<a href="?src=[REF(src)];setdir=[SOUTH]" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=[WEST]" title="South, East, North">&#9568;</a>
</p>
"}
if(PIPE_TRIN_M) // Mirrored ones
@@ -349,32 +360,32 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
user << browse_rsc(new /icon(preview, dir=SOUTHWEST), "em.png")
dirsel += "<p>"
dirsel += render_dir_img(1,"s.png","West South East")
dirsel += render_dir_img(4,"w.png","North West South")
dirsel += render_dir_img(NORTH,"s.png","West South East")
dirsel += render_dir_img(EAST,"w.png","North West South")
dirsel += "<br />"
dirsel += render_dir_img(2,"n.png","East North West")
dirsel += render_dir_img(8,"e.png","South East North")
dirsel += render_dir_img(SOUTH,"n.png","East North West")
dirsel += render_dir_img(WEST,"e.png","South East North")
dirsel += "<br />"
dirsel += render_dir_img(6,"sm.png","West South East", 1)
dirsel += render_dir_img(5,"wm.png","North West South", 1)
dirsel += render_dir_img(SOUTHEAST,"sm.png","West South East", 1)
dirsel += render_dir_img(NORTHEAST,"wm.png","North West South", 1)
dirsel += "<br />"
dirsel += render_dir_img(9,"nm.png","East North West", 1)
dirsel += render_dir_img(10,"em.png","South East North", 1)
dirsel += render_dir_img(NORTHWEST,"nm.png","East North West", 1)
dirsel += render_dir_img(SOUTHWEST,"em.png","South East North", 1)
dirsel += "</p>"
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=1; flipped=0" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=4; flipped=0" title="North, West, South">&#9571;</a>
<a href="?src=[REF(src)];setdir=[NORTH]" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=[EAST]" title="North, West, South">&#9571;</a>
<br />
<a href="?src=[REF(src)];setdir=2; flipped=0" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=8; flipped=0" title="South, East, North">&#9568;</a>
<a href="?src=[REF(src)];setdir=[SOUTH]" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=[WEST]" title="South, East, North">&#9568;</a>
<br />
<a href="?src=[REF(src)];setdir=6; flipped=1" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=5; flipped=1" title="North, West, South">&#9571;</a>
<a href="?src=[REF(src)];setdir=[SOUTHEAST];flipped=1" title="West, South, East">&#9574;</a>
<a href="?src=[REF(src)];setdir=[NORTHEAST];flipped=1" title="North, West, South">&#9571;</a>
<br />
<a href="?src=[REF(src)];setdir=9; flipped=1" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=10; flipped=1" title="South, East, North">&#9568;</a>
<a href="?src=[REF(src)];setdir=[NORTHWEST];flipped=1" title="East, North, West">&#9577;</a>
<a href="?src=[REF(src)];setdir=[SOUTHWEST];flipped=1" title="South, East, North">&#9568;</a>
</p>
"}
if(PIPE_UNARY) // Stuff with four directions - includes pumps etc.
@@ -393,23 +404,23 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=[NORTH]; flipped=0" title="North">&uarr;</a>
<a href="?src=[REF(src)];setdir=[EAST]; flipped=0" title="East">&rarr;</a>
<a href="?src=[REF(src)];setdir=[SOUTH]; flipped=0" title="South">&darr;</a>
<a href="?src=[REF(src)];setdir=[WEST]; flipped=0" title="West">&larr;</a>
<a href="?src=[REF(src)];setdir=[NORTH]" title="North">&uarr;</a>
<a href="?src=[REF(src)];setdir=[EAST]" title="East">&rarr;</a>
<a href="?src=[REF(src)];setdir=[SOUTH]" title="South">&darr;</a>
<a href="?src=[REF(src)];setdir=[WEST]" title="West">&larr;</a>
</p>
"}
if(PIPE_QUAD) // Single icon_state (eg 4-way manifolds)
if(PIPE_ONEDIR) // Single icon_state (eg 4-way manifolds)
if(preview)
user << browse_rsc(new /icon(preview), "pipe.png")
dirsel += "<p>"
dirsel += render_dir_img(1,"pipe.png","Pipe")
dirsel += render_dir_img(SOUTH,"pipe.png","Pipe")
dirsel += "</p>"
else
dirsel+={"
<p>
<a href="?src=[REF(src)];setdir=1; flipped=0" title="Pipe">&#8597;</a>
<a href="?src=[REF(src)];setdir=[SOUTH]" title="Pipe">&#8597;</a>
</p>
"}
@@ -472,8 +483,11 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
show_menu(usr)
if(href_list["setdir"])
p_dir= text2num(href_list["setdir"])
p_flipped = text2num(href_list["flipped"])
p_dir = text2num(href_list["setdir"])
if(href_list["flipped"])
p_flipped = text2num(href_list["flipped"])
else
p_flipped = FALSE
show_menu(usr)
if(href_list["setlayer"])
@@ -507,9 +521,9 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
if(href_list["makepipe"])
p_type = text2path(href_list["makepipe"])
p_dir = text2num(href_list["dir"])
var/obj/item/pipe/path = text2path(href_list["type"])
p_conntype = initial(path.RPD_type)
p_dir = NORTH
p_class = ATMOS_MODE
spark_system.start()
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
@@ -518,15 +532,15 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
if(href_list["makemeter"])
p_class = METER_MODE
p_conntype = -1
p_dir = 1
p_dir = NORTH
spark_system.start()
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
show_menu(usr)
if(href_list["dmake"])
p_type = text2num(href_list["dmake"])
p_type = text2path(href_list["dmake"])
p_conntype = text2num(href_list["type"])
p_dir = 1
p_dir = NORTH
p_class = DISPOSALS_MODE
spark_system.start()
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
@@ -614,12 +628,12 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
if(!can_make_pipe)
return ..()
if(isclosedturf(A))
to_chat(user, "<span class='warning'>\the [src]'s error light flickers; there's something in the way!</span>")
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
return
to_chat(user, "<span class='notice'>You start building a disposals pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 4, target = A))
var/obj/structure/disposalconstruct/C = new (A, queued_p_type ,queued_p_dir)
var/obj/structure/disposalconstruct/C = new (A, queued_p_type, queued_p_dir, queued_p_flipped)
if(!C.can_place())
to_chat(user, "<span class='warning'>There's not enough room to build that here!</span>")
@@ -193,6 +193,19 @@
/obj/item/stack/cable_coil = 1,
/obj/item/stock_parts/subspace/filter = 1)
/obj/item/circuitboard/machine/exonet_node
name = "Exonet Node(machine board)"
build_path = /obj/machinery/exonet_node
origin_tech = "programming=3;engineering=4;bluespace=3;materials=3"
req_components = list(
/obj/item/stock_parts/subspace/ansible = 1,
/obj/item/stock_parts/subspace/filter = 1,
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stock_parts/subspace/crystal = 1,
/obj/item/stock_parts/subspace/treatment = 2,
/obj/item/stack/cable_coil = 2)
/obj/item/circuitboard/machine/teleporter_hub
name = "Teleporter Hub (Machine Board)"
build_path = /obj/machinery/teleport/hub
+167 -101
View File
@@ -1,101 +1,167 @@
#define PROXIMITY_NONE ""
#define PROXIMITY_ON_SCREEN "_red"
#define PROXIMITY_NEAR "_yellow"
/**
* Multitool -- A multitool is used for hacking electronic devices.
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
*
*/
/obj/item/device/multitool
name = "multitool"
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
icon_state = "multitool"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
force = 5
w_class = WEIGHT_CLASS_SMALL
throwforce = 0
throw_range = 7
throw_speed = 3
materials = list(MAT_METAL=50, MAT_GLASS=20)
origin_tech = "magnets=1;engineering=2"
var/obj/machinery/buffer // simple machine buffer for device linkage
hitsound = 'sound/weapons/tap.ogg'
toolspeed = 1
// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
/obj/item/device/multitool/ai_detect
var/track_cooldown = 0
var/track_delay = 10 //How often it checks for proximity
var/detect_state = PROXIMITY_NONE
var/rangealert = 8 //Glows red when inside
var/rangewarning = 20 //Glows yellow when inside
origin_tech = "magnets=1;engineering=2;syndicate=1"
/obj/item/device/multitool/ai_detect/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/multitool/ai_detect/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/multitool/ai_detect/process()
if(track_cooldown > world.time)
return
detect_state = PROXIMITY_NONE
multitool_detect()
icon_state = "[initial(icon_state)][detect_state]"
track_cooldown = world.time + track_delay
/obj/item/device/multitool/ai_detect/proc/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
if(AI.cameraFollow == src)
detect_state = PROXIMITY_ON_SCREEN
break
if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))
var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)
if(chunk)
if(chunk.seenby.len)
for(var/mob/camera/aiEye/A in chunk.seenby)
var/turf/detect_turf = get_turf(A)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
if(get_dist(our_turf, detect_turf) < rangewarning)
detect_state = PROXIMITY_NEAR
break
/obj/item/device/multitool/ai_detect/admin
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'." //What else should I say for a meme item?
track_delay = 5
/obj/item/device/multitool/ai_detect/admin/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/J in urange(rangewarning,our_turf))
if(GLOB.admin_datums[J.ckey])
detect_state = PROXIMITY_NEAR
var/turf/detect_turf = get_turf(J)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
/obj/item/device/multitool/cyborg
name = "multitool"
desc = "Optimised and stripped-down version of a regular multitool."
toolspeed = 0.5
/obj/item/device/multitool/abductor
name = "alien multitool"
desc = "An omni-technological interface."
icon = 'icons/obj/abductor.dmi'
icon_state = "multitool"
toolspeed = 0.1
origin_tech = "magnets=5;engineering=5;abductor=3"
#define PROXIMITY_NONE ""
#define PROXIMITY_ON_SCREEN "_red"
#define PROXIMITY_NEAR "_yellow"
/**
* Multitool -- A multitool is used for hacking electronic devices.
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
*
*/
/obj/item/device/multitool
name = "multitool"
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
icon_state = "multitool"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
force = 5
w_class = WEIGHT_CLASS_SMALL
throwforce = 0
throw_range = 7
throw_speed = 3
materials = list(MAT_METAL=50, MAT_GLASS=20)
origin_tech = "magnets=1;engineering=2"
var/obj/machinery/buffer // simple machine buffer for device linkage
hitsound = 'sound/weapons/tap.ogg'
toolspeed = 1
var/datum/integrated_io/selected_io = null //functional for integrated circuits.
var/mode = 0
/obj/item/device/multitool/attack_self(mob/user)
if(selected_io)
selected_io = null
to_chat(user, "<span class='notice'>You clear the wired connection from the multitool.</span>")
else
..()
update_icon()
/obj/item/device/multitool/update_icon()
if(selected_io)
icon_state = "multitool_red"
else
icon_state = "multitool"
/obj/item/device/multitool/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(selected_io)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
else
selected_io = io
to_chat(user, "<span class='notice'>You link \the multitool to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
update_icon()
/obj/item/device/multitool/proc/unwire(var/datum/integrated_io/io1, var/datum/integrated_io/io2, mob/user)
if(!io1.linked.len || !io2.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to the data channel.</span>")
return
if(!(io1 in io2.linked) || !(io2 in io1.linked) )
to_chat(user, "<span class='warning'>These data pins aren't connected!</span>")
return
else
io1.linked.Remove(io2)
io2.linked.Remove(io1)
to_chat(user, "<span class='notice'>You clip the data connection between the [io1.holder.displayed_name]'s \
[io1.name] and the [io2.holder.displayed_name]'s [io2.name].</span>")
io1.holder.interact(user) // This is to update the UI.
update_icon()
// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
/obj/item/device/multitool/ai_detect
var/track_cooldown = 0
var/track_delay = 10 //How often it checks for proximity
var/detect_state = PROXIMITY_NONE
var/rangealert = 8 //Glows red when inside
var/rangewarning = 20 //Glows yellow when inside
origin_tech = "magnets=1;engineering=2;syndicate=1"
/obj/item/device/multitool/ai_detect/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/multitool/ai_detect/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/multitool/ai_detect/process()
if(track_cooldown > world.time)
return
detect_state = PROXIMITY_NONE
multitool_detect()
icon_state = "[initial(icon_state)][detect_state]"
track_cooldown = world.time + track_delay
/obj/item/device/multitool/ai_detect/proc/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/living/silicon/ai/AI in GLOB.ai_list)
if(AI.cameraFollow == src)
detect_state = PROXIMITY_ON_SCREEN
break
if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))
var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)
if(chunk)
if(chunk.seenby.len)
for(var/mob/camera/aiEye/A in chunk.seenby)
var/turf/detect_turf = get_turf(A)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
if(get_dist(our_turf, detect_turf) < rangewarning)
detect_state = PROXIMITY_NEAR
break
/obj/item/device/multitool/ai_detect/admin
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'." //What else should I say for a meme item?
track_delay = 5
/obj/item/device/multitool/ai_detect/admin/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/J in urange(rangewarning,our_turf))
if(GLOB.admin_datums[J.ckey])
detect_state = PROXIMITY_NEAR
var/turf/detect_turf = get_turf(J)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
/obj/item/device/multitool/cyborg
name = "multitool"
desc = "Optimised and stripped-down version of a regular multitool."
toolspeed = 0.5
/obj/item/device/multitool/abductor
name = "alien multitool"
desc = "An omni-technological interface."
icon = 'icons/obj/abductor.dmi'
icon_state = "multitool"
toolspeed = 0.1
origin_tech = "magnets=5;engineering=5;abductor=3"
@@ -35,7 +35,10 @@ MASS SPECTROMETER
var/image/I = new(loc = get_turf(pipe))
var/mutable_appearance/MA = new(pipe)
MA.alpha = 128
MA.dir = pipe.dir
I.appearance = MA
I.dir = pipe.dir
// Workaround for a weird bug with icon direction on T-Ray scan not matching the actual disposal pipe dir.
if(M.client)
flick_overlay(I, list(M.client), 8)
+1 -2
View File
@@ -611,8 +611,7 @@
obj/item/storage/box/clown
name = "clown box"
desc = "A colorful cardboard box for the clown"
icon_state = "clownbox"
illustration = null
illustration = "clown"
/obj/item/storage/box/clown/attackby(obj/item/I, mob/user, params)
if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
+5
View File
@@ -205,6 +205,11 @@ Frequency:
if(A.noteleport)
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
current_location = get_turf(user) //Recheck.
current_area = current_location.loc
if(!current_location || current_area.noteleport || current_location.z > ZLEVEL_SPACEMAX || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
user.show_message("<span class='notice'>Locked In.</span>", 2)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1)
if(!(LAZYLEN(created) == 2))
+4 -4
View File
@@ -309,13 +309,13 @@ LINEN BINS
else
B = new /obj/item/bedsheet(loc)
B.loc = user.loc
B.forceMove(drop_location())
user.put_in_hands(B)
to_chat(user, "<span class='notice'>You take [B] out of [src].</span>")
update_icon()
if(hidden)
hidden.loc = user.loc
hidden.forceMove(drop_location())
to_chat(user, "<span class='notice'>[hidden] falls out of [B]!</span>")
hidden = null
@@ -333,12 +333,12 @@ LINEN BINS
else
B = new /obj/item/bedsheet(loc)
B.loc = loc
B.forceMove(drop_location())
to_chat(user, "<span class='notice'>You telekinetically remove [B] from [src].</span>")
update_icon()
if(hidden)
hidden.loc = loc
hidden.forceMove(drop_location())
hidden = null
+77 -73
View File
@@ -1,3 +1,8 @@
#define AIRLOCK_ASSEMBLY_NEEDS_WIRES 0
#define AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS 1
#define AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER 2
/obj/structure/door_assembly
name = "airlock assembly"
icon = 'icons/obj/doors/airlocks/station/public.dmi'
@@ -6,8 +11,7 @@
anchored = FALSE
density = TRUE
max_integrity = 200
desc = "The mechanical framework for an airlock."
var/state = 0
var/state = AIRLOCK_ASSEMBLY_NEEDS_WIRES
var/mineral = null
var/typetext = ""
var/icontext = ""
@@ -26,7 +30,7 @@
name = "airlock assembly"
airlock_type = /obj/machinery/door/airlock
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_com
name = "command airlock assembly"
@@ -36,7 +40,7 @@
glass_type = /obj/machinery/door/airlock/glass_command
airlock_type = /obj/machinery/door/airlock/command
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_com/glass
mineral = "glass"
@@ -50,7 +54,7 @@
glass_type = /obj/machinery/door/airlock/glass_security
airlock_type = /obj/machinery/door/airlock/security
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_sec/glass
mineral = "glass"
@@ -64,7 +68,7 @@
glass_type = /obj/machinery/door/airlock/glass_engineering
airlock_type = /obj/machinery/door/airlock/engineering
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_eng/glass
mineral = "glass"
@@ -78,7 +82,7 @@
glass_type = /obj/machinery/door/airlock/glass_mining
airlock_type = /obj/machinery/door/airlock/mining
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_min/glass
mineral = "glass"
@@ -92,7 +96,7 @@
glass_type = /obj/machinery/door/airlock/glass_atmos
airlock_type = /obj/machinery/door/airlock/atmos
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_atmo/glass
mineral = "glass"
@@ -106,7 +110,7 @@
glass_type = /obj/machinery/door/airlock/glass_research
airlock_type = /obj/machinery/door/airlock/research
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_research/glass
mineral = "glass"
@@ -120,7 +124,7 @@
glass_type = /obj/machinery/door/airlock/glass_science
airlock_type = /obj/machinery/door/airlock/science
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_science/glass
mineral = "glass"
@@ -134,7 +138,7 @@
glass_type = /obj/machinery/door/airlock/glass_medical
airlock_type = /obj/machinery/door/airlock/medical
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_med/glass
mineral = "glass"
@@ -148,7 +152,7 @@
glass_type = /obj/machinery/door/airlock/glass_maintenance
airlock_type = /obj/machinery/door/airlock/maintenance
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_mai/glass
mineral = "glass"
@@ -163,7 +167,7 @@
glass_type = /obj/machinery/door/airlock/glass_external
airlock_type = /obj/machinery/door/airlock/external
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_ext/glass
mineral = "glass"
@@ -176,7 +180,7 @@
icontext = "fre"
airlock_type = /obj/machinery/door/airlock/freezer
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_hatch
name = "airtight hatch assembly"
@@ -186,7 +190,7 @@
icontext = "hatch"
airlock_type = /obj/machinery/door/airlock/hatch
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_mhatch
name = "maintenance hatch assembly"
@@ -196,7 +200,7 @@
icontext = "mhatch"
airlock_type = /obj/machinery/door/airlock/maintenance_hatch
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_glass
name = "glass airlock assembly"
@@ -204,7 +208,7 @@
overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi'
airlock_type = /obj/machinery/door/airlock/glass
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "glass"
material = "glass"
@@ -213,7 +217,7 @@
icon = 'icons/obj/doors/airlocks/station/gold.dmi'
airlock_type = /obj/machinery/door/airlock/gold
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "gold"
/obj/structure/door_assembly/door_assembly_silver
@@ -221,7 +225,7 @@
icon = 'icons/obj/doors/airlocks/station/silver.dmi'
airlock_type = /obj/machinery/door/airlock/silver
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "silver"
/obj/structure/door_assembly/door_assembly_diamond
@@ -229,7 +233,7 @@
icon = 'icons/obj/doors/airlocks/station/diamond.dmi'
airlock_type = /obj/machinery/door/airlock/diamond
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "diamond"
/obj/structure/door_assembly/door_assembly_uranium
@@ -237,7 +241,7 @@
icon = 'icons/obj/doors/airlocks/station/uranium.dmi'
airlock_type = /obj/machinery/door/airlock/uranium
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "uranium"
/obj/structure/door_assembly/door_assembly_plasma
@@ -245,7 +249,7 @@
icon = 'icons/obj/doors/airlocks/station/plasma.dmi'
airlock_type = /obj/machinery/door/airlock/plasma
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "plasma"
/obj/structure/door_assembly/door_assembly_clown
@@ -254,7 +258,7 @@
icon = 'icons/obj/doors/airlocks/station/bananium.dmi'
airlock_type = /obj/machinery/door/airlock/clown
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "bananium"
/obj/structure/door_assembly/door_assembly_sandstone
@@ -262,7 +266,7 @@
icon = 'icons/obj/doors/airlocks/station/sandstone.dmi'
airlock_type = /obj/machinery/door/airlock/sandstone
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "sandstone"
/obj/structure/door_assembly/door_assembly_titanium
@@ -274,7 +278,7 @@
glass_type = /obj/machinery/door/airlock/glass_titanium
airlock_type = /obj/machinery/door/airlock/titanium
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "titanium"
/obj/structure/door_assembly/door_assembly_titanium/glass
@@ -289,7 +293,7 @@
icontext = "highsec"
airlock_type = /obj/machinery/door/airlock/highsecurity
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_vault
name = "vault door assembly"
@@ -299,7 +303,7 @@
icontext = "vault"
airlock_type = /obj/machinery/door/airlock/vault
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_shuttle
name = "shuttle airlock assembly"
@@ -309,7 +313,7 @@
icontext = "shuttle"
airlock_type = /obj/machinery/door/airlock/shuttle
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_cult
name = "cult airlock assembly"
@@ -319,7 +323,7 @@
icontext = "cult"
airlock_type = /obj/machinery/door/airlock/cult
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_cult/glass
mineral = "glass"
@@ -338,7 +342,7 @@
icon = 'icons/obj/doors/airlocks/station/wood.dmi'
airlock_type = /obj/machinery/door/airlock/wood
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
mineral = "wood"
/obj/structure/door_assembly/door_assembly_viro
@@ -349,7 +353,7 @@
glass_type = /obj/machinery/door/airlock/glass_virology
airlock_type = /obj/machinery/door/airlock/virology
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/door_assembly_viro/glass
mineral = "glass"
@@ -362,7 +366,7 @@
icontext = "ele"
airlock_type = /obj/machinery/door/airlock/centcom
anchored = TRUE
state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
/obj/structure/door_assembly/examine(mob/user)
..()
@@ -383,10 +387,10 @@
/obj/structure/door_assembly/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter the name for the door.", src.name, src.created_name,MAX_NAME_LEN)
var/t = stripped_input(user, "Enter the name for the door.", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && src.loc != usr)
if(!in_range(src, usr) && loc != usr)
return
created_name = t
@@ -410,7 +414,7 @@
icontype = input(user, "Please select a paintjob for this airlock.") in optionlist
if((!in_range(src, usr) && src.loc != usr) || !WT.use(user))
if((!in_range(src, usr) && loc != usr) || !WT.use(user))
return
var/has_solid = FALSE
var/has_glass = FALSE
@@ -525,7 +529,7 @@
if(WT.remove_fuel(0,user))
user.visible_message("<span class='warning'>[user] disassembles the airlock assembly.</span>", \
"You start to disassemble the airlock assembly...")
playsound(src.loc, 'sound/items/welder2.ogg', 50, 1)
playsound(src, 'sound/items/welder2.ogg', 50, 1)
if(do_after(user, 40*W.toolspeed, target = src))
if( !WT.isOn() )
@@ -542,22 +546,22 @@
break
if(door_check)
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] secures the airlock assembly to the floor.", \
"<span class='notice'>You start to secure the airlock assembly to the floor...</span>", \
"<span class='italics'>You hear wrenching.</span>")
if(do_after(user, 40*W.toolspeed, target = src))
if( src.anchored )
if(anchored)
return
to_chat(user, "<span class='notice'>You secure the airlock assembly.</span>")
src.name = "secured airlock assembly"
src.anchored = TRUE
name = "secured airlock assembly"
anchored = TRUE
else
to_chat(user, "There is another door here!")
else
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] unsecures the airlock assembly from the floor.", \
"<span class='notice'>You start to unsecure the airlock assembly from the floor...</span>", \
"<span class='italics'>You hear wrenching.</span>")
@@ -579,63 +583,63 @@
if(C.get_amount() < 1 || state != 0)
return
C.use(1)
src.state = 1
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
to_chat(user, "<span class='notice'>You wire the airlock assembly.</span>")
src.name = "wired airlock assembly"
name = "wired airlock assembly"
else if(istype(W, /obj/item/wirecutters) && state == 1 )
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] cuts the wires from the airlock assembly.", \
"<span class='notice'>You start to cut the wires from the airlock assembly...</span>")
if(do_after(user, 40*W.toolspeed, target = src))
if( src.state != 1 )
if(state != 1)
return
to_chat(user, "<span class='notice'>You cut the wires from the airlock assembly.</span>")
new/obj/item/stack/cable_coil(get_turf(user), 1)
src.state = 0
src.name = "secured airlock assembly"
state = AIRLOCK_ASSEMBLY_NEEDS_WIRES
name = "secured airlock assembly"
else if(istype(W, /obj/item/electronics/airlock) && state == 1 )
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] installs the electronics into the airlock assembly.", \
"<span class='notice'>You start to install electronics into the airlock assembly...</span>")
if(do_after(user, 40, target = src))
if( src.state != 1 )
if( state != 1 )
return
if(!user.transferItemToLoc(W, src))
return
to_chat(user, "<span class='notice'>You install the airlock electronics.</span>")
src.state = 2
src.name = "near finished airlock assembly"
src.electronics = W
state = AIRLOCK_ASSEMBLY_NEEDS_SCREWDRIVER
name = "near finished airlock assembly"
electronics = W
else if(istype(W, /obj/item/crowbar) && state == 2 )
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", \
"<span class='notice'>You start to remove electronics from the airlock assembly...</span>")
if(do_after(user, 40*W.toolspeed, target = src))
if( src.state != 2 )
if(state != 2)
return
to_chat(user, "<span class='notice'>You remove the airlock electronics.</span>")
src.state = 1
src.name = "wired airlock assembly"
state = AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS
name = "wired airlock assembly"
var/obj/item/electronics/airlock/ae
if (!electronics)
ae = new/obj/item/electronics/airlock( src.loc )
ae = new/obj/item/electronics/airlock( loc )
else
ae = electronics
electronics = null
ae.loc = src.loc
ae.forceMove(src.loc)
else if(istype(W, /obj/item/stack/sheet) && !mineral)
var/obj/item/stack/sheet/G = W
if(G)
if(G.get_amount() >= 1)
if(is_glass_sheet(G))
playsound(src.loc, 'sound/items/crowbar.ogg', 100, 1)
playsound(src, 'sound/items/crowbar.ogg', 100, 1)
user.visible_message("[user] adds [G.name] to the airlock assembly.", \
"<span class='notice'>You start to install [G.name] into the airlock assembly...</span>")
if(do_after(user, 40, target = src))
@@ -653,8 +657,8 @@
material = "glass"
//This list contains the airlock paintjobs that have a glass version:
if(icontext in list("eng", "atmo", "sec", "com", "med", "res", "min"))
src.airlock_type = text2path("/obj/machinery/door/airlock/[typetext]")
src.glass_type = text2path("/obj/machinery/door/airlock/glass_[typetext]")
airlock_type = text2path("/obj/machinery/door/airlock/[typetext]")
glass_type = text2path("/obj/machinery/door/airlock/glass_[typetext]")
else
//This airlock is default or does not have a glass version, so we revert to the default glass airlock. |- Ricotez
airlock_type = /obj/machinery/door/airlock
@@ -664,7 +668,7 @@
else if(istype(G, /obj/item/stack/sheet/mineral))
var/M = G.sheettype
if(G.get_amount() >= 2)
playsound(src.loc, 'sound/items/crowbar.ogg', 100, 1)
playsound(src, 'sound/items/crowbar.ogg', 100, 1)
user.visible_message("[user] adds [G.name] to the airlock assembly.", \
"<span class='notice'>You start to install [G.name] into the airlock assembly...</span>")
if(do_after(user, 40, target = src))
@@ -678,28 +682,28 @@
glass_type = /obj/machinery/door/airlock/glass
else if(istype(W, /obj/item/screwdriver) && state == 2 )
playsound(src.loc, W.usesound, 100, 1)
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] finishes the airlock.", \
"<span class='notice'>You start finishing the airlock...</span>")
if(do_after(user, 40*W.toolspeed, target = src))
if(src.loc && state == 2)
if(loc && state == 2)
to_chat(user, "<span class='notice'>You finish the airlock.</span>")
var/obj/machinery/door/airlock/door
if(mineral == "glass")
door = new src.glass_type( src.loc )
door = new glass_type( loc )
else
door = new src.airlock_type( src.loc )
//door.req_access = src.req_access
door.electronics = src.electronics
door.heat_proof = src.heat_proof_finished
if(src.electronics.one_access)
door.req_one_access = src.electronics.accesses
door = new airlock_type( loc )
//door.req_access = req_access
door.electronics = electronics
door.heat_proof = heat_proof_finished
if(electronics.one_access)
door.req_one_access = electronics.accesses
else
door.req_access = src.electronics.accesses
door.req_access = electronics.accesses
if(created_name)
door.name = created_name
src.electronics.loc = door
electronics.forceMove(door)
qdel(src)
else
return ..()
+25 -30
View File
@@ -11,7 +11,7 @@
var/mineral_amount = 2
var/walltype = /turf/closed/wall
var/girder_type = /obj/structure/girder/displaced
var/opening = 0
var/opening = FALSE
density = TRUE
opacity = 1
max_integrity = 100
@@ -50,43 +50,38 @@
if(opening)
return
opening = 1
if(density)
do_the_flick()
sleep(5)
if(!QDELETED(src))
density = FALSE
set_opacity(0)
update_icon()
else
opening = TRUE
update_icon()
if(!density)
var/srcturf = get_turf(src)
for(var/mob/living/obstacle in srcturf) //Stop people from using this as a shield
opening = 0
opening = FALSE
return
do_the_flick()
density = TRUE
sleep(5)
if(!QDELETED(src))
set_opacity(1)
update_icon()
addtimer(CALLBACK(src, /obj/structure/falsewall/proc/toggle_open), 5)
air_update_turf(1)
opening = 0
/obj/structure/falsewall/proc/do_the_flick()
if(density)
smooth = SMOOTH_FALSE
clear_smooth_overlays()
icon_state = "fwall_opening"
else
icon_state = "fwall_closing"
/obj/structure/falsewall/proc/toggle_open()
if(!QDELETED(src))
density = !density
set_opacity(density)
opening = FALSE
update_icon()
/obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open
if(density)
smooth = SMOOTH_TRUE
queue_smooth(src)
icon_state = initial(icon_state)
if(opening)
if(density)
icon_state = "fwall_opening"
smooth = SMOOTH_FALSE
clear_smooth_overlays()
else
icon_state = "fwall_closing"
else
icon_state = "fwall_open"
if(density)
icon_state = initial(icon_state)
smooth = SMOOTH_TRUE
queue_smooth(src)
else
icon_state = "fwall_open"
/obj/structure/falsewall/proc/ChangeToWall(delete = 1)
var/turf/T = get_turf(src)
@@ -168,7 +168,8 @@
return
log_game("[user.ckey] golem-swapped into [src]")
user.visible_message("<span class='notice'>A faint light leaves [user], moving to [src] and animating it!</span>","<span class='notice'>You leave your old body behind, and transfer into [src]!</span>")
create(ckey = user.ckey, flavour = FALSE, name = user.real_name)
show_flavour = FALSE
create(ckey = user.ckey,name = user.real_name)
user.death()
return
..()
@@ -526,3 +527,44 @@
/obj/effect/mob_spawn/human/oldsci/Destroy()
new/obj/structure/showcase/machinery/oldpod/used(drop_location())
return ..()
#define PIRATE_NAMES_FILE "pirates.json"
/obj/effect/mob_spawn/human/pirate
name = "space pirate sleeper"
desc = "A cryo sleeper smelling faintly of rum."
random = TRUE
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "sleeper"
mob_name = "a space pirate"
mob_species = /datum/species/human
outfit = /datum/outfit/pirate/space
roundstart = FALSE
death = FALSE
anchored = TRUE
density = FALSE
show_flavour = FALSE //Flavour only exists for spawners menu
flavour_text = "<font size=3><b>Y</b></font><b>ou are a space pirate. The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot.</b>"
assignedrole = "Space Pirate"
var/rank = "Mate"
/obj/effect/mob_spawn/human/pirate/special(mob/living/new_spawn)
new_spawn.fully_replace_character_name(new_spawn.real_name,generate_pirate_name())
new_spawn.mind.add_antag_datum(/datum/antagonist/pirate)
/obj/effect/mob_spawn/human/pirate/proc/generate_pirate_name()
var/beggings = strings(PIRATE_NAMES_FILE, "beginnings")
var/endings = strings(PIRATE_NAMES_FILE, "endings")
return "[rank] [pick(beggings)][pick(endings)]"
/obj/effect/mob_spawn/human/pirate/Destroy()
new/obj/structure/showcase/machinery/oldpod/used(drop_location())
return ..()
/obj/effect/mob_spawn/human/pirate/captain
rank = "Captain"
outfit = /datum/outfit/pirate/space/captain
/obj/effect/mob_spawn/human/pirate/gunner
rank = "Gunner"
+6
View File
@@ -15,6 +15,12 @@
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/closed/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && mover.checkpass(PASSCLOSEDTURF))
return TRUE
else
..()
/turf/closed/indestructible
name = "wall"
icon = 'icons/turf/walls.dmi'
+1 -1
View File
@@ -124,7 +124,7 @@ GLOBAL_PROTECT(security_mode)
if(I in input)
handler = topic_handlers[I]
break
if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic))
WRITE_FILE(GLOB.world_game_log, "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]")
+1 -2
View File
@@ -4,8 +4,7 @@
var/F = file("[GLOB.log_directory]/[subject].html")
WRITE_FILE(F, "<small>[time_stamp()] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS) )
/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION) )
set name = "Investigate"
set category = "Admin"
if(!holder)
+14
View File
@@ -607,6 +607,20 @@
dat += "<td><A href='?priv_msg=[blob.key]'>PM</A></td></tr>"
dat += "</table>"
var/list/pirates = get_antagonists(/datum/antagonist/pirate)
if(pirates.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Pirates</B></td><td></td></tr>"
for(var/datum/mind/N in pirates)
var/mob/M = N.current
if(!M)
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[N]'>[N.name]([N.key])</a><i>No body.</i></td>"
dat += "<td><A href='?priv_msg=[N.key]'>PM</A></td></tr>"
else
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
dat += "</table>"
if(istype(SSticker.mode, /datum/game_mode/monkey))
var/datum/game_mode/monkey/mode = SSticker.mode
+7
View File
@@ -778,6 +778,13 @@ GLOBAL_PROTECT(LastAdminCalledProc)
usr << browse(dellog.Join(), "window=dellog")
/client/proc/cmd_display_overlay_log()
set category = "Debug"
set name = "Display overlay Log"
set desc = "Display SSoverlays log of everything that's passed through it."
render_stats(SSoverlays.stats, src)
/client/proc/cmd_display_init_log()
set category = "Debug"
set name = "Display Initialize() Log"
@@ -678,15 +678,7 @@
update_icon()
return
else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card
if(stat & (NOPOWER|BROKEN))
to_chat(user, "<span class='warning'>It does nothing!</span>")
else
if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the air alarm interface.</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return
togglelock(user)
else if(panel_open && is_wire_tool(W))
wires.interact(user)
return
@@ -751,6 +743,25 @@
return
return ..()
/obj/machinery/airalarm/AltClick(mob/user)
..()
if(!issilicon(user) && (!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
else
togglelock(user)
/obj/machinery/airalarm/proc/togglelock(mob/living/user)
if(stat & (NOPOWER|BROKEN))
to_chat(user, "<span class='warning'>It does nothing!</span>")
else
if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the air alarm interface.</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return
/obj/machinery/airalarm/power_change()
..()
@@ -18,8 +18,8 @@
var/volume = 100
var/efficiency = 1
var/sleep_factor = 750
var/unconscious_factor = 1000
var/sleep_factor = 0.00125
var/unconscious_factor = 0.001
var/heat_capacity = 20000
var/conduction_coefficient = 0.3
@@ -94,29 +94,29 @@
if(occupant)
var/image/occupant_overlay
if(ismonkey(occupant)) // Monkey
occupant_overlay = image(CRYOMOBS, "monkey")
occupant_overlay.copy_overlays(occupant)
else if(isalienadult(occupant))
if(isalienroyal(occupant)) // Queen and prae
occupant_overlay = image(CRYOMOBS, "alienq")
else if(isalienhunter(occupant)) // Hunter
occupant_overlay = image(CRYOMOBS, "alienh")
else if(isaliensentinel(occupant)) // Sentinel
occupant_overlay = image(CRYOMOBS, "aliens")
else // Drone or other
occupant_overlay = image(CRYOMOBS, "aliend")
else if(ishuman(occupant) || islarva(occupant) || (isanimal(occupant) && !ismegafauna(occupant))) // Mobs that are smaller than cryotube
occupant_overlay = image(occupant.icon, occupant.icon_state)
if(ishuman(occupant) || islarva(occupant) || (isanimal(occupant) && !ismegafauna(occupant))) // Mobs that are smaller than cryotube
occupant_overlay = image(occupant.icon, occupant.icon_state)
occupant_overlay.copy_overlays(occupant)
else if(ismonkey(occupant)) // Monkey
occupant_overlay = image(CRYOMOBS, "monkey")
occupant_overlay.copy_overlays(occupant)
else if(!isalienadult(occupant))
else
occupant_overlay = image(CRYOMOBS, "generic")
else if(isalienroyal(occupant)) // Queen and prae
occupant_overlay = image(CRYOMOBS, "alienq")
else if(isalienhunter(occupant)) // Hunter
occupant_overlay = image(CRYOMOBS, "alienh")
else if(isaliensentinel(occupant)) // Sentinel
occupant_overlay = image(CRYOMOBS, "aliens")
else // Drone or other
occupant_overlay = image(CRYOMOBS, "aliend")
occupant_overlay.dir = SOUTH
occupant_overlay.pixel_y = 22
@@ -182,8 +182,8 @@
if(air1.gases.len)
if(mob_occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
mob_occupant.Sleeping((mob_occupant.bodytemperature / sleep_factor) * 2000)
mob_occupant.Unconscious((mob_occupant.bodytemperature / unconscious_factor) * 2000)
mob_occupant.Sleeping((mob_occupant.bodytemperature * sleep_factor) * 2000)
mob_occupant.Unconscious((mob_occupant.bodytemperature * unconscious_factor) * 2000)
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
@@ -1,16 +0,0 @@
/obj/machinery/atmospherics/components/unary/generator_input
icon_state = "he_intact"
density = TRUE
name = "generator input"
desc = "An input for a generator."
layer = LOW_OBJ_LAYER
var/update_cycle
/obj/machinery/atmospherics/components/unary/generator_input/update_icon()
icon_state = NODE1 ? "intact" : "exposed"
/obj/machinery/atmospherics/components/unary/generator_input/proc/return_exchange_air()
return AIR1
@@ -1,57 +0,0 @@
/obj/machinery/atmospherics/components/unary/oxygen_generator
icon_state = "o2gen_map"
name = "oxygen generator"
desc = "Generates oxygen."
dir = SOUTH
initialize_directions = SOUTH
layer = GAS_SCRUBBER_LAYER
var/on = FALSE
var/oxygen_content = 10
/obj/machinery/atmospherics/components/unary/oxygen_generator/update_icon_nopipes()
cut_overlays()
if(showpipe)
add_overlay(getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions)) //it works for now
if(!NODE1 || !on || !is_operational())
icon_state = "o2gen_off"
return
else
icon_state = "o2gen_on"
/obj/machinery/atmospherics/components/unary/oxygen_generator/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.volume = 50
AIR1 = air_contents
/obj/machinery/atmospherics/components/unary/oxygen_generator/process_atmos()
..()
if(!on)
return 0
var/datum/gas_mixture/air_contents = AIR1
var/total_moles = air_contents.total_moles()
if(total_moles < oxygen_content)
var/current_heat_capacity = air_contents.heat_capacity()
var/added_oxygen = oxygen_content - total_moles
air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
ASSERT_GAS(/datum/gas/oxygen, air_contents)
air_contents.gases[/datum/gas/oxygen][MOLES] += added_oxygen
update_parents()
return 1
@@ -5,6 +5,8 @@
device_type = UNARY
pipe_flags = PIPING_ONE_PER_TURF
construction_type = /obj/item/pipe/directional
var/uid
var/static/gl_uid = 1
/obj/machinery/atmospherics/components/unary/SetInitDirections()
initialize_directions = dir
@@ -16,3 +18,7 @@
/obj/machinery/atmospherics/components/unary/hide(intact)
update_icon()
..(intact)
/obj/machinery/atmospherics/components/unary/proc/assign_uid_vents()
uid = num2text(gl_uid++)
return uid
@@ -50,8 +50,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/New()
..()
if(!id_tag)
assign_uid()
id_tag = num2text(uid)
id_tag = assign_uid_vents()
/obj/machinery/atmospherics/components/unary/vent_pump/Destroy()
var/area/A = get_area(src)
@@ -38,8 +38,7 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
..()
if(!id_tag)
assign_uid()
id_tag = num2text(uid)
id_tag = assign_uid_vents()
/obj/machinery/atmospherics/components/unary/vent_scrubber/on
on = TRUE
+5 -4
View File
@@ -4,6 +4,8 @@
/obj/effect/mob_spawn
name = "Unknown"
density = TRUE
anchored = TRUE
var/mob_type = null
var/mob_name = ""
var/mob_gender = null
@@ -21,8 +23,7 @@
var/burn_damage = 0
var/mob_color //Change the mob's color
var/assignedrole
density = TRUE
anchored = TRUE
var/show_flavour = TRUE
var/banType = "lavaland"
/obj/effect/mob_spawn/attack_ghost(mob/user)
@@ -60,7 +61,7 @@
/obj/effect/mob_spawn/proc/equip(mob/M)
return
/obj/effect/mob_spawn/proc/create(ckey, flavour = TRUE, name)
/obj/effect/mob_spawn/proc/create(ckey, name)
var/mob/living/M = new mob_type(get_turf(src)) //living mobs only
if(!random)
M.real_name = mob_name ? mob_name : M.name
@@ -80,7 +81,7 @@
if(ckey)
M.ckey = ckey
if(flavour)
if(show_flavour)
to_chat(M, "[flavour_text]")
var/datum/mind/MM = M.mind
if(objectives)
+13 -2
View File
@@ -8,6 +8,7 @@
var/safety_warning = "For safety reasons the automated supply shuttle \
cannot transport live organisms, classified nuclear weaponry or \
homing beacons."
var/blockade_warning = "Bluespace instability detected. Shuttle movement impossible."
light_color = "#E2853D"//orange
@@ -54,8 +55,12 @@
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
data["loan"] = !!SSshuttle.shuttle_loan
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
data["message"] = SSshuttle.centcom_message || "Remember to stamp and send back the supply manifests."
var/message = "Remember to stamp and send back the supply manifests."
if(SSshuttle.centcom_message)
message = SSshuttle.centcom_message
if(SSshuttle.supplyBlocked)
message = blockade_warning
data["message"] = message
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
@@ -102,6 +107,9 @@
if(!SSshuttle.supply.canMove())
say(safety_warning)
return
if(SSshuttle.supplyBlocked)
say(blockade_warning)
return
if(SSshuttle.supply.getDockedId() == "supply_home")
SSshuttle.supply.emagged = emagged
SSshuttle.supply.contraband = contraband
@@ -116,6 +124,9 @@
if("loan")
if(!SSshuttle.shuttle_loan)
return
if(SSshuttle.supplyBlocked)
say(blockade_warning)
return
else if(SSshuttle.supply.mode != SHUTTLE_IDLE)
return
else if(SSshuttle.supply.getDockedId() != "supply_away")
+2 -3
View File
@@ -938,10 +938,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("flavor_text")
var/msg = input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(features["flavor_text"])) as message
var/msg = stripped_multiline_input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(features["flavor_text"]), MAX_MESSAGE_LEN*2, TRUE) as message
if(msg != null)
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
msg = html_encode(msg)
msg = copytext(msg, 1, MAX_MESSAGE_LEN*2)
features["flavor_text"] = msg
if("metadata")
+22 -4
View File
@@ -78,20 +78,38 @@
suit_store = /obj/item/gun/energy/laser/bluetag
/datum/outfit/pirate
name = "Pirate"
name = "Space Pirate"
uniform = /obj/item/clothing/under/pirate
shoes = /obj/item/clothing/shoes/sneakers/brown
suit = /obj/item/clothing/suit/pirate
head = /obj/item/clothing/head/bandana
glasses = /obj/item/clothing/glasses/eyepatch
r_hand = /obj/item/melee/transforming/energy/sword/pirate
/datum/outfit/pirate/space
name = "Space Pirate"
suit = /obj/item/clothing/suit/space/pirate
head = /obj/item/clothing/head/helmet/space/pirate/bandana
mask = /obj/item/clothing/mask/breath
suit_store = /obj/item/tank/internals/oxygen
ears = /obj/item/device/radio/headset/syndicate
id = /obj/item/card/id
/datum/outfit/pirate/space/captain
head = /obj/item/clothing/head/helmet/space/pirate
/datum/outfit/pirate/post_equip(mob/living/carbon/human/H)
H.faction |= "pirate"
var/obj/item/device/radio/R = H.ears
if(R)
R.set_frequency(GLOB.SYND_FREQ)
R.freqlock = 1
var/obj/item/card/id/W = H.wear_id
if(W)
W.registered_name = H.real_name
W.update_label(H.real_name)
/datum/outfit/tunnel_clown
name = "Tunnel Clown"
@@ -137,10 +137,16 @@ Contains:
item_state = "pirate"
armor = list(melee = 30, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30, fire = 60, acid = 75)
flags_1 = STOPSPRESSUREDMAGE_1
flags_inv = HIDEHAIR
strip_delay = 40
equip_delay_other = 20
flags_cover = HEADCOVERSEYES
/obj/item/clothing/head/helmet/space/pirate/bandana
name = "pirate bandana"
icon_state = "bandana"
item_state = "bandana"
/obj/item/clothing/suit/space/pirate
name = "pirate coat"
desc = "Yarr."
+4 -3
View File
@@ -108,11 +108,12 @@
var/datum/round_event_control/control
var/startWhen = 0 //When in the lifetime to call start().
var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to >0 if there is an announcement.
var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to -1 if announcement should not be shown.
var/endWhen = 0 //When in the lifetime the event should end.
var/activeFor = 0 //How long the event has existed. You don't need to change this.
var/current_players = 0 //Amount of of alive, non-AFK human players on server at the time of event start
var/fakeable = TRUE //Can be faked by fake news event.
//Called first before processing.
//Allows you to setup your event, such as randomly
@@ -133,7 +134,7 @@
//Called when the tick is equal to the announceWhen variable.
//Allows you to announce before starting or vice versa.
//Only called once.
/datum/round_event/proc/announce()
/datum/round_event/proc/announce(fake)
return
//Called on or after the tick counter is equal to startWhen.
@@ -167,7 +168,7 @@
if(activeFor == announceWhen)
processing = FALSE
announce()
announce(FALSE)
processing = TRUE
if(startWhen < activeFor && activeFor < endWhen)
+1
View File
@@ -9,6 +9,7 @@
/datum/round_event/ghost_role/abductor
minimum_required = 2
role_name = "abductor team"
fakeable = FALSE //Nothing to fake here
/datum/round_event/ghost_role/abductor/spawn_role()
var/list/mob/dead/observer/candidates = get_candidates("abductor", null, ROLE_ABDUCTOR)
+2 -2
View File
@@ -30,8 +30,8 @@
control.occurrences--
return ..()
/datum/round_event/ghost_role/alien_infestation/announce()
if(successSpawn)
/datum/round_event/ghost_role/alien_infestation/announce(fake)
if(successSpawn || fake)
priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
+33 -33
View File
@@ -1,33 +1,33 @@
/datum/round_event_control/anomaly
name = "Anomaly: Energetic Flux"
typepath = /datum/round_event/anomaly
min_players = 1
max_occurrences = 0 //This one probably shouldn't occur! It'd work, but it wouldn't be very fun.
weight = 15
/datum/round_event/anomaly
var/area/impact_area
var/obj/effect/anomaly/newAnomaly
announceWhen = 1
/datum/round_event/anomaly/setup(loop=0)
var/safety_loop = loop + 1
if(safety_loop > 50)
kill()
end()
impact_area = findEventArea()
if(!impact_area)
setup(safety_loop)
var/list/turf_test = get_area_turfs(impact_area)
if(!turf_test.len)
setup(safety_loop)
/datum/round_event/anomaly/announce()
priority_announce("Localized energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/flux(T)
/datum/round_event_control/anomaly
name = "Anomaly: Energetic Flux"
typepath = /datum/round_event/anomaly
min_players = 1
max_occurrences = 0 //This one probably shouldn't occur! It'd work, but it wouldn't be very fun.
weight = 15
/datum/round_event/anomaly
var/area/impact_area
var/obj/effect/anomaly/newAnomaly
announceWhen = 1
/datum/round_event/anomaly/setup(loop=0)
var/safety_loop = loop + 1
if(safety_loop > 50)
kill()
end()
impact_area = findEventArea()
if(!impact_area)
setup(safety_loop)
var/list/turf_test = get_area_turfs(impact_area)
if(!turf_test.len)
setup(safety_loop)
/datum/round_event/anomaly/announce(fake)
priority_announce("Localized energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/flux(T)
+19 -19
View File
@@ -1,19 +1,19 @@
/datum/round_event_control/anomaly/anomaly_bluespace
name = "Anomaly: Bluespace"
typepath = /datum/round_event/anomaly/anomaly_bluespace
max_occurrences = 1
weight = 5
/datum/round_event/anomaly/anomaly_bluespace
startWhen = 3
announceWhen = 10
/datum/round_event/anomaly/anomaly_bluespace/announce()
priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_bluespace/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/bluespace(T)
/datum/round_event_control/anomaly/anomaly_bluespace
name = "Anomaly: Bluespace"
typepath = /datum/round_event/anomaly/anomaly_bluespace
max_occurrences = 1
weight = 5
/datum/round_event/anomaly/anomaly_bluespace
startWhen = 3
announceWhen = 10
/datum/round_event/anomaly/anomaly_bluespace/announce(fake)
priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_bluespace/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/bluespace(T)
+20 -20
View File
@@ -1,20 +1,20 @@
/datum/round_event_control/anomaly/anomaly_flux
name = "Anomaly: Hyper-Energetic Flux"
typepath = /datum/round_event/anomaly/anomaly_flux
min_players = 10
max_occurrences = 5
weight = 20
/datum/round_event/anomaly/anomaly_flux
startWhen = 10
announceWhen = 3
/datum/round_event/anomaly/anomaly_flux/announce()
priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_flux/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/flux(T)
/datum/round_event_control/anomaly/anomaly_flux
name = "Anomaly: Hyper-Energetic Flux"
typepath = /datum/round_event/anomaly/anomaly_flux
min_players = 10
max_occurrences = 5
weight = 20
/datum/round_event/anomaly/anomaly_flux
startWhen = 10
announceWhen = 3
/datum/round_event/anomaly/anomaly_flux/announce(fake)
priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_flux/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/flux(T)
+17 -17
View File
@@ -1,17 +1,17 @@
/datum/round_event_control/anomaly/anomaly_grav
name = "Anomaly: Gravitational"
typepath = /datum/round_event/anomaly/anomaly_grav
max_occurrences = 5
weight = 20
/datum/round_event/anomaly/anomaly_grav
startWhen = 3
announceWhen = 20
/datum/round_event/anomaly/anomaly_grav/announce()
priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_grav/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/grav(T)
/datum/round_event_control/anomaly/anomaly_grav
name = "Anomaly: Gravitational"
typepath = /datum/round_event/anomaly/anomaly_grav
max_occurrences = 5
weight = 20
/datum/round_event/anomaly/anomaly_grav
startWhen = 3
announceWhen = 20
/datum/round_event/anomaly/anomaly_grav/announce(fake)
priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_grav/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/grav(T)
+1 -1
View File
@@ -8,7 +8,7 @@
startWhen = 3
announceWhen = 10
/datum/round_event/anomaly/anomaly_pyro/announce()
/datum/round_event/anomaly/anomaly_pyro/announce(fake)
priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_pyro/start()
+19 -19
View File
@@ -1,19 +1,19 @@
/datum/round_event_control/anomaly/anomaly_vortex
name = "Anomaly: Vortex"
typepath = /datum/round_event/anomaly/anomaly_vortex
min_players = 20
max_occurrences = 2
weight = 5
/datum/round_event/anomaly/anomaly_vortex
startWhen = 10
announceWhen = 3
/datum/round_event/anomaly/anomaly_vortex/announce()
priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_vortex/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/bhole(T)
/datum/round_event_control/anomaly/anomaly_vortex
name = "Anomaly: Vortex"
typepath = /datum/round_event/anomaly/anomaly_vortex
min_players = 20
max_occurrences = 2
weight = 5
/datum/round_event/anomaly/anomaly_vortex
startWhen = 10
announceWhen = 3
/datum/round_event/anomaly/anomaly_vortex/announce(fake)
priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
/datum/round_event/anomaly/anomaly_vortex/start()
var/turf/T = safepick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/bhole(T)
+1 -1
View File
@@ -12,7 +12,7 @@
announceWhen = -1
role_name = "blob overmind"
/datum/round_event/ghost_role/blob/announce()
/datum/round_event/ghost_role/blob/announce(fake)
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
/datum/round_event/ghost_role/blob/spawn_role()
+8 -3
View File
@@ -21,9 +21,14 @@
"You don't want to buy anything? Yeah, well, I didn't want to buy your mom either.")
/datum/round_event/brand_intelligence/announce()
priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please stand by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert")
/datum/round_event/brand_intelligence/announce(fake)
var/source = "unknown machine"
if(fake)
var/obj/machinery/vending/cola/example = /obj/machinery/vending/cola
source = initial(example.name)
else if(originMachine)
source = originMachine.name
priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please stand by. The origin is believed to be \a [source].", "Machine Learning Alert")
/datum/round_event/brand_intelligence/start()
for(var/obj/machinery/vending/V in GLOB.machines)
+1 -1
View File
@@ -8,7 +8,7 @@
/datum/round_event/camera_failure
startWhen = 1
endWhen = 2
announceWhen = 0
fakeable = FALSE
/datum/round_event/camera_failure/tick()
var/iterations = 1
+1 -1
View File
@@ -13,7 +13,7 @@
/datum/round_event/carp_migration/setup()
startWhen = rand(40, 60)
/datum/round_event/carp_migration/announce()
/datum/round_event/carp_migration/announce(fake)
priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")

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