Merge branch 'master' into upstream-merge-32280
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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;\
|
||||
};\
|
||||
|
||||
|
||||
|
||||
@@ -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;\
|
||||
}
|
||||
@@ -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
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+44
-39
@@ -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
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -154,6 +154,7 @@
|
||||
has_gravity = TRUE
|
||||
noteleport = TRUE
|
||||
hidden = TRUE
|
||||
ambientsounds = REEBE
|
||||
|
||||
/area/reebe/city_of_cogs
|
||||
name = "City of Cogs"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
@@ -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">↕</a>
|
||||
<a href="?src=[REF(src)];setdir=4; flipped=0" title="horizontal">↔</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTH]" title="vertical">↕</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]" title="horizontal">↔</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">↕</a>
|
||||
<a href="?src=[REF(src)];setdir=4; flipped=0" title="horizontal">↔</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTH]" title="vertical">↕</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]" title="horizontal">↔</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=9; flipped=0" title="West to North">╝</a>
|
||||
<a href="?src=[REF(src)];setdir=5; flipped=0" title="North to East">╚</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTHWEST]" title="West to North">╝</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTHEAST]" title="North to East">╚</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=10; flipped=0" title="South to West">╗</a>
|
||||
<a href="?src=[REF(src)];setdir=6; flipped=0" title="East to South">╔</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTHWEST]" title="South to West">╗</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTHEAST]" title="East to South">╔</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">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=4; flipped=0" title="North, West, South">╣</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTH]" title="West, South, East">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]" title="North, West, South">╣</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=2; flipped=0" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=8; flipped=0" title="South, East, North">╠</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTH]" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=[WEST]" title="South, East, North">╠</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">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=4; flipped=0" title="North, West, South">╣</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTH]" title="West, South, East">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]" title="North, West, South">╣</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=2; flipped=0" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=8; flipped=0" title="South, East, North">╠</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTH]" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=[WEST]" title="South, East, North">╠</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=6; flipped=1" title="West, South, East">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=5; flipped=1" title="North, West, South">╣</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTHEAST];flipped=1" title="West, South, East">╦</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTHEAST];flipped=1" title="North, West, South">╣</a>
|
||||
<br />
|
||||
<a href="?src=[REF(src)];setdir=9; flipped=1" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=10; flipped=1" title="South, East, North">╠</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTHWEST];flipped=1" title="East, North, West">╩</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTHWEST];flipped=1" title="South, East, North">╠</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">↑</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]; flipped=0" title="East">→</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTH]; flipped=0" title="South">↓</a>
|
||||
<a href="?src=[REF(src)];setdir=[WEST]; flipped=0" title="West">←</a>
|
||||
<a href="?src=[REF(src)];setdir=[NORTH]" title="North">↑</a>
|
||||
<a href="?src=[REF(src)];setdir=[EAST]" title="East">→</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTH]" title="South">↓</a>
|
||||
<a href="?src=[REF(src)];setdir=[WEST]" title="West">←</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">↕</a>
|
||||
<a href="?src=[REF(src)];setdir=[SOUTH]" title="Pipe">↕</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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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"
|
||||
@@ -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
@@ -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]")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user