mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 23:53:47 +01:00
Merge branch 'master' into wizard-mmi-fix
This commit is contained in:
@@ -231,6 +231,12 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
|
||||
var/turf/T = loc
|
||||
level = T.intact ? 2 : 1
|
||||
add_fingerprint(usr)
|
||||
if(!SSair.initialized) //If there's no atmos subsystem, we can't really initialize pipenets
|
||||
SSair.machinery_to_construct.Add(src)
|
||||
return
|
||||
initialize_atmos_network()
|
||||
|
||||
/obj/machinery/atmospherics/proc/initialize_atmos_network()
|
||||
atmos_init()
|
||||
var/list/nodes = pipeline_expansion()
|
||||
for(var/obj/machinery/atmospherics/A in nodes)
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
T.to_be_destroyed = 0
|
||||
T.max_fire_temperature_sustained = 0
|
||||
|
||||
/obj/effect/hotspot/Crossed(mob/living/L)
|
||||
/obj/effect/hotspot/Crossed(mob/living/L, oldloc)
|
||||
..()
|
||||
if(isliving(L))
|
||||
L.fire_act()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define TARGET_INVALID_UNREACHABLE 5
|
||||
#define TARGET_INVALID_GOLEM 6
|
||||
#define TARGET_INVALID_EVENT 7
|
||||
#define TARGET_INVALID_IS_TARGET 8
|
||||
|
||||
//gamemode istype helpers
|
||||
#define GAMEMODE_IS_BLOB (SSticker && istype(SSticker.mode, /datum/game_mode/blob))
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#define DATA_HUD_ABDUCTOR 18
|
||||
#define ANTAG_HUD_DEVIL 19
|
||||
#define ANTAG_HUD_EVENTMISC 20
|
||||
#define ANTAG_HUD_BLOB 21
|
||||
|
||||
// Notification action types
|
||||
#define NOTIFY_JUMP "jump"
|
||||
|
||||
+94
-2
@@ -57,6 +57,89 @@
|
||||
#define MAX_STACK_AMOUNT_GLASS 50
|
||||
#define MAX_STACK_AMOUNT_RODS 60
|
||||
|
||||
//Colors
|
||||
#define COLOR_RED "#FF0000"
|
||||
#define COLOR_GREEN "#00FF00"
|
||||
#define COLOR_BLUE "#0000FF"
|
||||
#define COLOR_CYAN "#00FFFF"
|
||||
#define COLOR_PINK "#FF00FF"
|
||||
#define COLOR_YELLOW "#FFFF00"
|
||||
#define COLOR_ORANGE "#FF9900"
|
||||
#define COLOR_WHITE "#FFFFFF"
|
||||
#define COLOR_GRAY "#808080"
|
||||
#define COLOR_BLACK "#000000"
|
||||
#define COLOR_NAVY_BLUE "#000080"
|
||||
#define COLOR_LIGHT_GREEN "#008000"
|
||||
#define COLOR_DARK_GRAY "#404040"
|
||||
#define COLOR_MAROON "#800000"
|
||||
#define COLOR_PURPLE "#800080"
|
||||
#define COLOR_VIOLET "#9933ff"
|
||||
#define COLOR_OLIVE "#808000"
|
||||
#define COLOR_BROWN_ORANGE "#824b28"
|
||||
#define COLOR_DARK_ORANGE "#b95a00"
|
||||
#define COLOR_GRAY40 "#666666"
|
||||
#define COLOR_GRAY20 "#333333"
|
||||
#define COLOR_GRAY15 "#151515"
|
||||
#define COLOR_SEDONA "#cc6600"
|
||||
#define COLOR_DARK_BROWN "#917448"
|
||||
#define COLOR_DEEP_SKY_BLUE "#00e1ff"
|
||||
#define COLOR_LIME "#00ff00"
|
||||
#define COLOR_TEAL "#33cccc"
|
||||
#define COLOR_PALE_PINK "#bf89ba"
|
||||
#define COLOR_YELLOW_GRAY "#c9a344"
|
||||
#define COLOR_PALE_YELLOW "#c1bb7a"
|
||||
#define COLOR_WARM_YELLOW "#b3863c"
|
||||
#define COLOR_RED_GRAY "#aa5f61"
|
||||
#define COLOR_BROWN "#b19664"
|
||||
#define COLOR_GREEN_GRAY "#8daf6a"
|
||||
#define COLOR_DARK_GREEN_GRAY "#54654c"
|
||||
#define COLOR_BLUE_GRAY "#6a97b0"
|
||||
#define COLOR_DARK_BLUE_GRAY "#3e4855"
|
||||
#define COLOR_SUN "#ec8b2f"
|
||||
#define COLOR_PURPLE_GRAY "#a2819e"
|
||||
#define COLOR_BLUE_LIGHT "#33ccff"
|
||||
#define COLOR_RED_LIGHT "#ff3333"
|
||||
#define COLOR_BEIGE "#ceb689"
|
||||
#define COLOR_BABY_BLUE "#89cff0"
|
||||
#define COLOR_PALE_GREEN_GRAY "#aed18b"
|
||||
#define COLOR_PALE_RED_GRAY "#cc9090"
|
||||
#define COLOR_PALE_PURPLE_GRAY "#bda2ba"
|
||||
#define COLOR_PALE_BLUE_GRAY "#8bbbd5"
|
||||
#define COLOR_LUMINOL "#66ffff"
|
||||
#define COLOR_SILVER "#c0c0c0"
|
||||
#define COLOR_GRAY80 "#cccccc"
|
||||
#define COLOR_OFF_WHITE "#eeeeee"
|
||||
#define COLOR_GOLD "#6d6133"
|
||||
#define COLOR_NT_RED "#9d2300"
|
||||
#define COLOR_BOTTLE_GREEN "#1f6b4f"
|
||||
#define COLOR_PALE_BTL_GREEN "#57967f"
|
||||
#define COLOR_GUNMETAL "#545c68"
|
||||
#define COLOR_WALL_GUNMETAL "#353a42"
|
||||
#define COLOR_STEEL "#a8b0b2"
|
||||
#define COLOR_MUZZLE_FLASH "#ffffb2"
|
||||
#define COLOR_CHESTNUT "#996633"
|
||||
#define COLOR_BEASTY_BROWN "#663300"
|
||||
#define COLOR_WHEAT "#ffff99"
|
||||
#define COLOR_CYAN_BLUE "#3366cc"
|
||||
#define COLOR_LIGHT_CYAN "#66ccff"
|
||||
#define COLOR_PAKISTAN_GREEN "#006600"
|
||||
#define COLOR_HULL "#436b8e"
|
||||
#define COLOR_AMBER "#ffbf00"
|
||||
#define COLOR_COMMAND_BLUE "#46698c"
|
||||
#define COLOR_SKY_BLUE "#5ca1cc"
|
||||
#define COLOR_PALE_ORANGE "#b88a3b"
|
||||
#define COLOR_CIVIE_GREEN "#b7f27d"
|
||||
#define COLOR_TITANIUM "#d1e6e3"
|
||||
#define COLOR_DARK_GUNMETAL "#4c535b"
|
||||
#define COLOR_BRONZE "#8c7853"
|
||||
#define COLOR_BRASS "#b99d71"
|
||||
#define COLOR_INDIGO "#4b0082"
|
||||
#define COLOR_ALUMINIUM "#bbbbbb"
|
||||
#define COLOR_CRYSTAL "#00c8a5"
|
||||
#define COLOR_ASTEROID_ROCK "#735555"
|
||||
#define COLOR_NULLGLASS "#ff6088"
|
||||
#define COLOR_DIAMOND "#d8d4ea"
|
||||
|
||||
//FONTS:
|
||||
// Used by Paper and PhotoCopier (and PaperBin once a year).
|
||||
// Used by PDA's Notekeeper.
|
||||
@@ -132,7 +215,12 @@
|
||||
for(type in view(range, dview_mob))
|
||||
#define END_FOR_DVIEW dview_mob.loc = null
|
||||
|
||||
//Turf locational stuff
|
||||
#define get_turf(A) (get_step(A, 0))
|
||||
#define NORTH_OF_TURF(T) locate(T.x, T.y + 1, T.z)
|
||||
#define EAST_OF_TURF(T) locate(T.x + 1, T.y, T.z)
|
||||
#define SOUTH_OF_TURF(T) locate(T.x, T.y - 1, T.z)
|
||||
#define WEST_OF_TURF(T) locate(T.x - 1, T.y, T.z)
|
||||
|
||||
#define MIN_SUPPLIED_LAW_NUMBER 15
|
||||
#define MAX_SUPPLIED_LAW_NUMBER 50
|
||||
@@ -315,7 +403,7 @@
|
||||
#define INVESTIGATE_BOMB "bombs"
|
||||
|
||||
// The SQL version required by this version of the code
|
||||
#define SQL_VERSION 7
|
||||
#define SQL_VERSION 8
|
||||
|
||||
// Vending machine stuff
|
||||
#define CAT_NORMAL 1
|
||||
@@ -393,4 +481,8 @@
|
||||
#define SENSOR_COORDS 3
|
||||
|
||||
// Cult summon possibilities
|
||||
#define SUMMON_POSSIBILITIES 3
|
||||
#define SUMMON_POSSIBILITIES 3
|
||||
|
||||
#define DICE_NOT_RIGGED 1
|
||||
#define DICE_BASICALLY_RIGGED 2
|
||||
#define DICE_TOTALLY_RIGGED 3
|
||||
@@ -19,6 +19,12 @@
|
||||
return A
|
||||
return 0
|
||||
|
||||
/proc/get_location_name(atom/X, format_text = FALSE)
|
||||
var/area/A = isarea(X) ? X : get_area(X)
|
||||
if(!A)
|
||||
return null
|
||||
return format_text ? format_text(A.name) : A.name
|
||||
|
||||
/proc/get_areas_in_range(dist=0, atom/center=usr)
|
||||
if(!dist)
|
||||
var/turf/T = get_turf(center)
|
||||
|
||||
@@ -298,8 +298,12 @@ This is always put in the attack log.
|
||||
loglevel = ATKLOG_FEW
|
||||
else if(istype(user) && !user.ckey && !target.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL
|
||||
loglevel = ATKLOG_ALL
|
||||
else if(!target.ckey) // Attacks by players on NPCs are only shown to admins with ATKLOG_ALL or ATKLOG_ALMOSTALL
|
||||
else if(!user.ckey || !target.ckey) // Player v NPC combat is de-prioritized.
|
||||
loglevel = ATKLOG_ALMOSTALL
|
||||
else
|
||||
var/area/A = get_area(target)
|
||||
if(A && A.hide_attacklogs)
|
||||
loglevel = ATKLOG_ALMOSTALL
|
||||
|
||||
msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]", loglevel)
|
||||
|
||||
|
||||
+46
-2
@@ -28,6 +28,11 @@
|
||||
/*
|
||||
* Text sanitization
|
||||
*/
|
||||
// Can be used almost the same way as normal input for text
|
||||
/proc/clean_input(Message, Title, Default, mob/user=usr)
|
||||
var/txt = input(user, Message, Title, Default) as text | null
|
||||
if(txt)
|
||||
return html_encode(txt)
|
||||
|
||||
//Simply removes < and > and limits the length of the message
|
||||
/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN)
|
||||
@@ -125,8 +130,10 @@
|
||||
|
||||
//Filters out undesirable characters from names
|
||||
/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN)
|
||||
// Decode so that names with characters like < are still rejected. Will be encoded again at the end
|
||||
t_in = html_decode(t_in)
|
||||
if(!t_in || length(t_in) > max_length)
|
||||
return //Rejects the input if it is null or if it is longer then the max length allowed
|
||||
return //Rejects the input if it is null or if it is longer than the max length allowed
|
||||
|
||||
var/number_of_alphanumeric = 0
|
||||
var/last_char_group = 0
|
||||
@@ -185,7 +192,7 @@
|
||||
for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names
|
||||
if(cmptext(t_out,bad_name)) return //(not case sensitive)
|
||||
|
||||
return t_out
|
||||
return html_encode(t_out)
|
||||
|
||||
//checks text for html tags
|
||||
//if tag is not in whitelist (var/list/paper_tag_whitelist in global.dm)
|
||||
@@ -538,6 +545,43 @@ proc/checkhtml(var/t)
|
||||
text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN)
|
||||
return text
|
||||
|
||||
/proc/convert_pencode_arg(text, tag, arg)
|
||||
arg = sanitize_simple(html_encode(arg), list("''"="","\""="", "?"=""))
|
||||
// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-4---css-escape-and-strictly-validate-before-inserting-untrusted-data-into-html-style-property-values
|
||||
var/list/style_attacks = list("javascript:", "expression", "byond:", "file:")
|
||||
|
||||
for(var/style_attack in style_attacks)
|
||||
if(findtext(arg, style_attack))
|
||||
// Do not attempt to render dangerous things
|
||||
return text
|
||||
|
||||
if(tag == "class")
|
||||
return "<span class='[arg]'>"
|
||||
|
||||
if(tag == "style")
|
||||
return "<span style='[arg]'>"
|
||||
|
||||
if(tag == "img")
|
||||
var/list/img_props = splittext(arg, ";")
|
||||
if(img_props.len == 3)
|
||||
return "<img src='[img_props[1]]' width='[img_props[2]]' height='[img_props[3]]'>"
|
||||
if(img_props.len == 2)
|
||||
return "<img src='[img_props[1]]' width='[img_props[2]]'>"
|
||||
return "<img src='[arg]'>"
|
||||
|
||||
return text
|
||||
|
||||
/proc/admin_pencode_to_html()
|
||||
var/text = pencode_to_html(arglist(args))
|
||||
var/regex/R = new(@"\[(.*?) (.*?)\]", "ge")
|
||||
text = R.Replace(text, /proc/convert_pencode_arg)
|
||||
|
||||
text = replacetext(text, "\[/class\]", "</span>")
|
||||
text = replacetext(text, "\[/style\]", "</span>")
|
||||
text = replacetext(text, "\[/img\]", "</img>")
|
||||
|
||||
return text
|
||||
|
||||
/proc/html_to_pencode(text)
|
||||
text = replacetext(text, "<BR>", "\n")
|
||||
text = replacetext(text, "<center>", "\[center\]")
|
||||
|
||||
@@ -88,4 +88,6 @@ var/copier_items_printed_logged = FALSE
|
||||
|
||||
GLOBAL_VAR(map_name) // Self explanatory
|
||||
|
||||
var/global/datum/datacore/data_core = null // Station datacore, manifest, etc
|
||||
var/global/datum/datacore/data_core = null // Station datacore, manifest, etc
|
||||
|
||||
GLOBAL_VAR_INIT(panic_bunker_enabled, 0) // Is the panic bunker enabled
|
||||
@@ -107,14 +107,20 @@
|
||||
#define ui_healthdoll "EAST-1:28,CENTER-1:15"
|
||||
#define ui_health "EAST-1:28,CENTER:17"
|
||||
#define ui_internal "EAST-1:28,CENTER+1:19"
|
||||
//borgs
|
||||
|
||||
//borgs
|
||||
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
|
||||
|
||||
//aliens
|
||||
#define ui_alien_health "EAST-1:28,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
|
||||
|
||||
|
||||
//constructs
|
||||
#define ui_construct_pull "EAST-1:28,SOUTH+1:10" //above the zone_sel icon
|
||||
#define ui_construct_health "EAST,CENTER:15" //same height as humans, hugging the right border
|
||||
|
||||
//slimes
|
||||
#define ui_slime_health "EAST,CENTER:15" //same as borgs, constructs and humans
|
||||
|
||||
//Pop-up inventory
|
||||
#define ui_shoes "WEST+1:8,SOUTH:5"
|
||||
|
||||
|
||||
@@ -2,6 +2,25 @@
|
||||
var/datum/action/linked_action
|
||||
screen_loc = null
|
||||
|
||||
/obj/screen/movable/action_button/MouseDrop(over_object)
|
||||
if((istype(over_object, /obj/screen/movable/action_button) && !istype(over_object, /obj/screen/movable/action_button/hide_toggle)))
|
||||
if(locked)
|
||||
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
closeToolTip(usr)
|
||||
return
|
||||
var/obj/screen/movable/action_button/B = over_object
|
||||
var/list/actions = usr.actions
|
||||
actions.Swap(actions.Find(linked_action), actions.Find(B.linked_action))
|
||||
moved = FALSE
|
||||
B.moved = FALSE
|
||||
closeToolTip(usr)
|
||||
usr.update_action_buttons()
|
||||
else if(istype(over_object, /obj/screen/movable/action_button/hide_toggle))
|
||||
closeToolTip(usr)
|
||||
else
|
||||
closeToolTip(usr)
|
||||
return ..()
|
||||
|
||||
/obj/screen/movable/action_button/Click(location,control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
@@ -29,6 +48,13 @@
|
||||
icon_state = "bg_default"
|
||||
var/hidden = 0
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/MouseDrop(over_object)
|
||||
if(istype(over_object, /obj/screen/movable/action_button))
|
||||
closeToolTip(usr)
|
||||
else
|
||||
closeToolTip(usr)
|
||||
return ..()
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
@@ -83,9 +109,9 @@
|
||||
var/image/img = image(icon, src, hidden ? "show" : "hide")
|
||||
overlays += img
|
||||
|
||||
/obj/screen/movable/action_button/MouseEntered(location,control,params)
|
||||
openToolTip(usr,src,params,title = name,content = desc)
|
||||
|
||||
/obj/screen/movable/action_button/MouseEntered(location, control, params)
|
||||
if(!QDELETED(src))
|
||||
openToolTip(usr, src, params, title = name, content = desc)
|
||||
|
||||
/obj/screen/movable/action_button/MouseExited()
|
||||
closeToolTip(usr)
|
||||
|
||||
@@ -256,4 +256,10 @@
|
||||
//Add multicamera camera
|
||||
using = new /obj/screen/ai/add_multicam()
|
||||
using.screen_loc = ui_ai_add_multicam
|
||||
static_inventory += using
|
||||
static_inventory += using
|
||||
|
||||
//Intent
|
||||
using = new /obj/screen/act_intent/robot/AI()
|
||||
using.icon_state = mymob.a_intent
|
||||
static_inventory += using
|
||||
action_intent = using
|
||||
@@ -95,6 +95,9 @@
|
||||
icon = 'icons/mob/screen_robot.dmi'
|
||||
screen_loc = ui_borg_intents
|
||||
|
||||
/obj/screen/act_intent/robot/AI
|
||||
screen_loc = "EAST-1:32,SOUTH:70"
|
||||
|
||||
/obj/screen/mov_intent
|
||||
name = "run/walk toggle"
|
||||
icon_state = "running"
|
||||
@@ -453,6 +456,12 @@
|
||||
/obj/screen/healths/corgi
|
||||
icon = 'icons/mob/screen_corgi.dmi'
|
||||
|
||||
/obj/screen/healths/slime
|
||||
icon = 'icons/mob/screen_slime.dmi'
|
||||
icon_state = "slime_health0"
|
||||
screen_loc = ui_slime_health
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/obj/screen/healths/guardian
|
||||
name = "summoner health"
|
||||
icon = 'icons/mob/guardian.dmi'
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/mob/living/carbon/slime/create_mob_hud()
|
||||
if(client && !hud_used)
|
||||
hud_used = new /datum/hud/slime(src)
|
||||
|
||||
/mob/living/simple_animal/slime/create_mob_hud()
|
||||
if(client && !hud_used)
|
||||
hud_used = new /datum/hud/slime(src)
|
||||
|
||||
/datum/hud/slime/New(mob/owner)
|
||||
..()
|
||||
mymob.healths = new /obj/screen/healths/slime()
|
||||
infodisplay += mymob.healths
|
||||
|
||||
mymob.pullin = new /obj/screen/pull()
|
||||
mymob.pullin.icon = 'icons/mob/screen_slime.dmi'
|
||||
mymob.pullin.update_icon(mymob)
|
||||
mymob.pullin.screen_loc = ui_construct_pull
|
||||
hotkeybuttons += mymob.pullin
|
||||
@@ -72,11 +72,15 @@
|
||||
var/assistantlimit = 0 //enables assistant limiting
|
||||
var/assistantratio = 2 //how many assistants to security members
|
||||
|
||||
// The AFK subsystem will not be activated if any of the below config values are equal or less than 0
|
||||
var/warn_afk_minimum = 0 // How long till you get a warning while being AFK
|
||||
var/auto_cryo_afk = 0 // How long till you get put into cryo when you're AFK
|
||||
var/auto_despawn_afk = 0 // How long till you actually despawn in cryo when you're AFK (Not ssd so not automatic)
|
||||
|
||||
var/auto_cryo_ssd_mins = 0
|
||||
var/ssd_warning = 0
|
||||
|
||||
var/prob_free_golems = 75 //chance for free golems spawners to appear roundstart
|
||||
var/unrestricted_free_golems = FALSE //if true, free golems can appear on all roundtypes
|
||||
|
||||
var/list_afk_minimum = 5 // How long people have to be AFK before it's listed on the "List AFK players" verb
|
||||
|
||||
var/traitor_objectives_amount = 2
|
||||
var/shadowling_max_age = 0
|
||||
@@ -305,20 +309,24 @@
|
||||
if("jobs_have_minimal_access")
|
||||
config.jobs_have_minimal_access = 1
|
||||
|
||||
if("prob_free_golems")
|
||||
config.prob_free_golems = text2num(value)
|
||||
|
||||
if("unrestricted_free_golems")
|
||||
config.unrestricted_free_golems = TRUE
|
||||
|
||||
if("shadowling_max_age")
|
||||
config.shadowling_max_age = text2num(value)
|
||||
|
||||
if("warn_afk_minimum")
|
||||
config.warn_afk_minimum = text2num(value)
|
||||
if("auto_cryo_afk")
|
||||
config.auto_cryo_afk = text2num(value)
|
||||
if("auto_despawn_afk")
|
||||
config.auto_despawn_afk = text2num(value)
|
||||
|
||||
if("auto_cryo_ssd_mins")
|
||||
config.auto_cryo_ssd_mins = text2num(value)
|
||||
if("ssd_warning")
|
||||
config.ssd_warning = 1
|
||||
|
||||
if("list_afk_minimum")
|
||||
config.list_afk_minimum = text2num(value)
|
||||
|
||||
if("ipintel_email")
|
||||
if(value != "ch@nge.me")
|
||||
config.ipintel_email = value
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#define AFK_WARNED 1
|
||||
#define AFK_CRYOD 2
|
||||
|
||||
SUBSYSTEM_DEF(afk)
|
||||
name = "AFK Watcher"
|
||||
wait = 300
|
||||
flags = SS_BACKGROUND
|
||||
var/list/afk_players = list() // Associative list. ckey as key and AFK state as value
|
||||
|
||||
|
||||
/datum/controller/subsystem/afk/Initialize()
|
||||
if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0)
|
||||
flags |= SS_NO_FIRE
|
||||
|
||||
/datum/controller/subsystem/afk/fire()
|
||||
var/list/toRemove = list()
|
||||
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
|
||||
if(!H.ckey) // Useless non ckey creatures
|
||||
continue
|
||||
|
||||
var/turf/T
|
||||
// Only players and players with the AFK watch enabled
|
||||
// No dead, unconcious, restrained, people without jobs, people on other Z levels than the station or antags
|
||||
if(!H.client || !H.client.prefs.afk_watch || !H.mind || \
|
||||
H.stat || H.restrained() || !H.job || H.mind.special_role || \
|
||||
!is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization
|
||||
if(afk_players[H.ckey])
|
||||
toRemove += H.ckey
|
||||
continue
|
||||
|
||||
var/mins_afk = round(H.client.inactivity / 600)
|
||||
if(mins_afk < config.warn_afk_minimum)
|
||||
if(afk_players[H.ckey])
|
||||
toRemove += H.ckey
|
||||
continue
|
||||
|
||||
if(!afk_players[H.ckey])
|
||||
afk_players[H.ckey] = AFK_WARNED
|
||||
warn(H, "<span class='danger'>You are AFK for [mins_afk] minutes. You will be cryod after [config.auto_cryo_afk] total minutes and fully despawned after [config.auto_despawn_afk] total minutes. Please move or click in game if you want to avoid being despawned.</span>")
|
||||
else
|
||||
var/area/A = T.loc // Turfs loc is the area
|
||||
if(afk_players[H.ckey] == AFK_WARNED)
|
||||
if(mins_afk >= config.auto_cryo_afk && A.can_get_auto_cryod)
|
||||
if(A.fast_despawn)
|
||||
toRemove += H.ckey
|
||||
warn(H, "<span class='danger'>You are have been despawned after being AFK for [mins_afk] minutes. You have been despawned instantly due to you being in a secure area.</span>")
|
||||
msg_admins(H, mins_afk, T, "forcefully despawned", "AFK in a fast despawn area")
|
||||
force_cryo_human(H)
|
||||
else if(cryo_ssd(H))
|
||||
afk_players[H.ckey] = AFK_CRYOD
|
||||
msg_admins(H, mins_afk, T, "put into cryostorage")
|
||||
warn(H, "<span class='danger'>You are AFK for [mins_afk] minutes and have been moved to cryostorage. After being AFK for [config.auto_despawn_afk] total minutes you will be fully despawned. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.</span>")
|
||||
|
||||
else if(mins_afk >= config.auto_despawn_afk)
|
||||
var/obj/machinery/cryopod/P = H.loc
|
||||
msg_admins(H, mins_afk, T, "forcefully despawned")
|
||||
warn(H, "<span class='danger'>You are have been despawned after being AFK for [mins_afk] minutes.</span>")
|
||||
toRemove += H.ckey
|
||||
P.despawn_occupant()
|
||||
|
||||
removeFromWatchList(toRemove)
|
||||
|
||||
/datum/controller/subsystem/afk/proc/warn(mob/living/carbon/human/H, text)
|
||||
to_chat(H, text)
|
||||
SEND_SOUND(H, 'sound/effects/adminhelp.ogg')
|
||||
if(H.client)
|
||||
window_flash(H.client)
|
||||
|
||||
/datum/controller/subsystem/afk/proc/msg_admins(mob/living/carbon/human/H, mins_afk, turf/location, action, info)
|
||||
log_admin("[key_name(H)] has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]")
|
||||
message_admins("[key_name_admin(H)] at ([get_area(location).name] [ADMIN_JMP(location)]) has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]")
|
||||
|
||||
/datum/controller/subsystem/afk/proc/removeFromWatchList(list/toRemove)
|
||||
for(var/C in toRemove)
|
||||
for(var/i in 1 to afk_players.len)
|
||||
if(afk_players[i] == C)
|
||||
afk_players.Cut(i, i + 1)
|
||||
break
|
||||
|
||||
#undef AFK_WARNED
|
||||
#undef AFK_CRYOD
|
||||
@@ -30,6 +30,7 @@ SUBSYSTEM_DEF(air)
|
||||
var/list/networks = list()
|
||||
var/list/atmos_machinery = list()
|
||||
var/list/pipe_init_dirs_cache = list()
|
||||
var/list/machinery_to_construct = list()
|
||||
|
||||
|
||||
|
||||
@@ -67,9 +68,10 @@ SUBSYSTEM_DEF(air)
|
||||
setup_allturfs()
|
||||
setup_atmos_machinery(GLOB.machines)
|
||||
setup_pipenets(GLOB.machines)
|
||||
for(var/obj/machinery/atmospherics/A in machinery_to_construct)
|
||||
A.initialize_atmos_network()
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/air/fire(resumed = 0)
|
||||
var/timer = TICK_USAGE_REAL
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ SUBSYSTEM_DEF(events)
|
||||
else if(href_list["back"])
|
||||
selected_event_container = null
|
||||
else if(href_list["set_name"])
|
||||
var/name = input("Enter event name.", "Set Name") as text|null
|
||||
var/name = clean_input("Enter event name.", "Set Name")
|
||||
if(name)
|
||||
var/datum/event_meta/EM = locate(href_list["set_name"])
|
||||
EM.name = name
|
||||
|
||||
@@ -33,25 +33,22 @@ SUBSYSTEM_DEF(input)
|
||||
"default" = list(
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"F3" = "say",
|
||||
"T" = ".say",
|
||||
"M" = ".me",
|
||||
"Back" = "\".winset \\\"input.focus=true input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
),
|
||||
"old_default" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"",
|
||||
"Ctrl+T" = "say",
|
||||
"Ctrl+T" = ".say",
|
||||
"Ctrl+O" = "ooc",
|
||||
"F3" = "say",
|
||||
),
|
||||
"old_hotkeys" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"F3" = "say",
|
||||
"T" = ".say",
|
||||
"M" = ".me",
|
||||
"Back" = "\".winset \\\"input.focus=true input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
@@ -118,6 +115,8 @@ SUBSYSTEM_DEF(input)
|
||||
|
||||
/datum/controller/subsystem/input/fire()
|
||||
var/list/clients = GLOB.clients // Let's sing the list cache song
|
||||
if(listclearnulls(clients)) // clear nulls before we run keyloop
|
||||
log_world("Found a null in clients list!")
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/C = clients[i]
|
||||
C.keyLoop()
|
||||
|
||||
@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
|
||||
for(var/i = 1, i <= num_extra_space, i++)
|
||||
var/zlev = space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED)
|
||||
var/zlev = space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED, traits = list(REACHABLE))
|
||||
seedRuins(list(zlev), rand(0, 3), /area/space, space_ruins_templates)
|
||||
|
||||
// Setup the Z-level linkage
|
||||
|
||||
@@ -8,7 +8,7 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
|
||||
name = "Mentor Tickets"
|
||||
ticket_system_name = "Mentor Tickets"
|
||||
ticket_name = "Mentor Ticket"
|
||||
span_text = "<span class='mentorhelp'>"
|
||||
span_class = "mentorhelp"
|
||||
close_rights = R_MENTOR | R_ADMIN
|
||||
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
|
||||
@@ -17,5 +17,5 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets
|
||||
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
|
||||
close_messages = list("<font color='red' size='3'><b>- [ticket_name] Closed -</b></font>",
|
||||
"<span class='boldmessage'>Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.</span>",
|
||||
"[span_text]Your [ticket_name] has now been closed.</span>")
|
||||
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
|
||||
return ..()
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
SUBSYSTEM_DEF(tickets)
|
||||
name = "Admin Tickets"
|
||||
var/span_text = "<span class='adminticket'>"
|
||||
var/span_class = "adminticket"
|
||||
var/ticket_system_name = "Admin Tickets"
|
||||
var/ticket_name = "Admin Ticket"
|
||||
var/close_rights = R_ADMIN
|
||||
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
/datum/controller/subsystem/tickets/Initialize()
|
||||
close_messages = list("<font color='red' size='4'><b>- [ticket_name] Rejected! -</b></font>",
|
||||
"<span class='boldmessage'>Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.</span>",
|
||||
"[span_text]Your [ticket_name] has now been closed.</span>")
|
||||
"<span class='[span_class]'>Your [ticket_name] has now been closed.</span>")
|
||||
LAZYINITLIST(allTickets)
|
||||
return ..()
|
||||
|
||||
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/report
|
||||
for(var/num in stales)
|
||||
report += "[num], "
|
||||
message_staff("[span_text]Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
|
||||
message_staff("<span class='[span_class]'>Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
|
||||
|
||||
/datum/controller/subsystem/tickets/stat_entry()
|
||||
..("Tickets: [LAZYLEN(allTickets)]")
|
||||
@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/datum/ticket/existingTicket = checkForOpenTicket(C)
|
||||
if(existingTicket)
|
||||
existingTicket.setCooldownPeriod()
|
||||
to_chat(C.mob, "[span_text]Your [ticket_name] #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.</span>")
|
||||
to_chat(C.mob, "<span class='[span_class]'>Your [ticket_name] #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.</span>")
|
||||
return
|
||||
|
||||
if(!title)
|
||||
@@ -93,7 +93,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
T.mobControlled = C.mob
|
||||
|
||||
//Inform the user that they have opened a ticket
|
||||
to_chat(C, "[span_text]You have opened [ticket_name] number #[(getTicketCounter() - 1)]! Please be patient and we will help you soon!</span>")
|
||||
to_chat(C, "<span class='[span_class]'>You have opened [ticket_name] number #[(getTicketCounter() - 1)]! Please be patient and we will help you soon!</span>")
|
||||
|
||||
//Set ticket state with key N to open
|
||||
/datum/controller/subsystem/tickets/proc/openTicket(N)
|
||||
@@ -138,8 +138,10 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/datum/ticket/T = allTickets[N]
|
||||
return T.clientName
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/assignStaffToTicket(client/C, var/N)
|
||||
/datum/controller/subsystem/tickets/proc/assignStaffToTicket(client/C, N)
|
||||
var/datum/ticket/T = allTickets[N]
|
||||
if(T.staffAssigned != null && T.staffAssigned != C && alert("Ticket is already assigned to [T.staffAssigned.ckey]. Are you sure you want to take it?","Take ticket","No","Yes") != "Yes")
|
||||
return FALSE
|
||||
T.assignStaff(C)
|
||||
return TRUE
|
||||
|
||||
@@ -158,7 +160,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
var/ticketState // State of the ticket, open, closed, resolved etc
|
||||
var/timeUntilStale // When the ticket goes stale
|
||||
var/ticketCooldown // Cooldown before allowing the user to open another ticket.
|
||||
var/staffAssigned // Staff member who has assigned themselves to this ticket
|
||||
var/client/staffAssigned // Staff member who has assigned themselves to this ticket
|
||||
|
||||
/datum/ticket/New(tit, cont, num)
|
||||
title = tit
|
||||
@@ -367,15 +369,15 @@ UI STUFF
|
||||
if(href_list["resolve"])
|
||||
var/indexNum = text2num(href_list["resolve"])
|
||||
if(resolveTicket(indexNum))
|
||||
message_staff("[span_text][usr.client] / ([usr]) resolved [ticket_name] number [indexNum]</span>")
|
||||
to_chat_safe(returnClient(indexNum), "[span_text]Your [ticket_name] has now been resolved.</span>")
|
||||
message_staff("<span class='[span_class]'>[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]</span>")
|
||||
to_chat_safe(returnClient(indexNum), "<span class='[span_class]'>Your [ticket_name] has now been resolved.</span>")
|
||||
showUI(usr)
|
||||
|
||||
if(href_list["detailresolve"])
|
||||
var/indexNum = text2num(href_list["detailresolve"])
|
||||
if(resolveTicket(indexNum))
|
||||
message_staff("[span_text][usr.client] / ([usr]) resolved [ticket_name] number [indexNum]</span>")
|
||||
to_chat_safe(returnClient(indexNum), "[span_text]Your [ticket_name] has now been resolved.</span>")
|
||||
message_staff("<span class='[span_class]'>[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]</span>")
|
||||
to_chat_safe(returnClient(indexNum), "<span class='[span_class]'>Your [ticket_name] has now been resolved.</span>")
|
||||
showDetailUI(usr, indexNum)
|
||||
|
||||
if(href_list["detailclose"])
|
||||
@@ -386,7 +388,7 @@ UI STUFF
|
||||
if(alert("Are you sure? This will send a negative message.",,"Yes","No") != "Yes")
|
||||
return
|
||||
if(closeTicket(indexNum))
|
||||
message_staff("[span_text][usr.client] / ([usr]) closed [ticket_name] number [indexNum]</span>")
|
||||
message_staff("<span class='[span_class]'>[usr.client] / ([usr]) closed [ticket_name] number [indexNum]</span>")
|
||||
to_chat_safe(returnClient(indexNum), close_messages)
|
||||
showDetailUI(usr, indexNum)
|
||||
|
||||
@@ -394,7 +396,7 @@ UI STUFF
|
||||
if(href_list["detailreopen"])
|
||||
var/indexNum = text2num(href_list["detailreopen"])
|
||||
if(openTicket(indexNum))
|
||||
message_staff("[span_text][usr.client] / ([usr]) re-opened [ticket_name] number [indexNum]</span>")
|
||||
message_staff("<span class='[span_class]'>[usr.client] / ([usr]) re-opened [ticket_name] number [indexNum]</span>")
|
||||
showDetailUI(usr, indexNum)
|
||||
|
||||
if(href_list["assignstaff"])
|
||||
@@ -404,8 +406,8 @@ UI STUFF
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/takeTicket(var/index)
|
||||
if(assignStaffToTicket(usr.client, index))
|
||||
if(span_text == "<span class='mentorhelp'>")
|
||||
message_staff("[span_text][usr.client] / ([usr]) has taken [ticket_name] number [index]</span>")
|
||||
if(span_class == "mentorhelp")
|
||||
message_staff("<span class='[span_class]'>[usr.client] / ([usr]) has taken [ticket_name] number [index]</span>")
|
||||
else
|
||||
message_staff("<span class='admin_channel'>[usr.client] / ([usr]) has taken [ticket_name] number [index]</span>", TRUE)
|
||||
to_chat_safe(returnClient(index), "[span_text]Your [ticket_name] is being handled by [usr.client].</span>")
|
||||
to_chat_safe(returnClient(index), "<span class='[span_class]'>Your [ticket_name] is being handled by [usr.client].</span>")
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/ebeam/deadly/Crossed(atom/A)
|
||||
/obj/effect/ebeam/deadly/Crossed(atom/A, oldloc)
|
||||
..()
|
||||
A.ex_act(1)
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/datum/component/waddling
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
/datum/component/waddling/Initialize()
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
|
||||
|
||||
/datum/component/waddling/proc/Waddle()
|
||||
var/mob/living/L = parent
|
||||
if(L.incapacitated() || L.lying)
|
||||
return
|
||||
animate(L, pixel_z = 4, time = 0)
|
||||
animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
|
||||
animate(pixel_z = 0, transform = matrix(), time = 0)
|
||||
@@ -100,15 +100,20 @@
|
||||
height = 400
|
||||
immediate_submit = TRUE
|
||||
|
||||
/datum/async_input/ranked/New()
|
||||
..()
|
||||
popup.add_script("rankedInput.js", 'html/browser/rankedInput.js')
|
||||
popup.add_head_content("<title>Drag and drop or use the buttons to reorder</title>")
|
||||
|
||||
/datum/async_input/ranked/render_choices()
|
||||
var/dat = "<div>"
|
||||
dat += "<table style='margin: auto; text-align: left;'>"
|
||||
dat += "<table id='choices' uid=[UID()] style='margin: auto; text-align: left;'>"
|
||||
for(var/i = 1, i <= choices.len, i++)
|
||||
var/choice = choices[i]
|
||||
dat += "<tr>"
|
||||
dat += "<td>[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)]</td>"
|
||||
dat += "<td>[button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)]</td>"
|
||||
dat += "<td>[i]. [choice]</td>"
|
||||
dat += "<td style='cursor: move;' index='[i]' ondrop='drop(event)' ondragover='allowDrop(event)' draggable='true' ondragstart='drag(event)'>[i]. [choice]</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "</div>"
|
||||
@@ -131,6 +136,15 @@
|
||||
show()
|
||||
return
|
||||
|
||||
if(href_list["cut"] && href_list["insert"])
|
||||
var/cut = text2num(href_list["cut"])
|
||||
var/insert = text2num(href_list["insert"])
|
||||
var/choice = choices[cut]
|
||||
choices.Cut(cut, cut + 1)
|
||||
choices.Insert(insert, choice)
|
||||
show()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/datum/async_input/autocomplete
|
||||
|
||||
+2
-1
@@ -22,7 +22,8 @@ var/datum/atom_hud/huds = list( \
|
||||
ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(),\
|
||||
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),\
|
||||
ANTAG_HUD_DEVIL = new/datum/atom_hud/antag/hidden(),\
|
||||
ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden()\
|
||||
ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),\
|
||||
ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()\
|
||||
)
|
||||
|
||||
/datum/atom_hud
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
var/list/kills = list()
|
||||
var/list/datum/objective/objectives = list()
|
||||
var/list/datum/objective/special_verbs = list()
|
||||
var/list/targets = list()
|
||||
|
||||
var/has_been_rev = 0//Tracks if this mind has been a rev or not
|
||||
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
Comes with a rustic wooden bar and suicidal bartender."
|
||||
suffix = "lavaland_biodome_beach.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/cube
|
||||
name = "The Wishgranter Cube"
|
||||
id = "wishgranter-cube"
|
||||
description = "Nothing good can come from this. Learn from their mistakes and turn around."
|
||||
suffix = "lavaland_surface_cube.dmm"
|
||||
cost = 10
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/seed_vault
|
||||
name = "Seed Vault"
|
||||
id = "seed-vault"
|
||||
@@ -38,6 +46,15 @@ datum/map_template/ruin/lavaland/ash_walker
|
||||
cost = 20
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/free_golem
|
||||
name = "Free Golem Ship"
|
||||
id = "golem-ship"
|
||||
description = "Lumbering humanoids, made out of precious metals, move inside this ship. They frequently leave to mine more minerals, which they somehow turn into more of them. \
|
||||
Seem very intent on research and individual liberty, and also geology based naming?"
|
||||
cost = 20
|
||||
suffix = "lavaland_surface_golem_ship.dmm"
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/animal_hospital
|
||||
name = "Animal Hospital"
|
||||
id = "animal-hospital"
|
||||
@@ -46,6 +63,49 @@ datum/map_template/ruin/lavaland/ash_walker
|
||||
suffix = "lavaland_surface_animal_hospital.dmm"
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin
|
||||
cost = 10
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin/envy
|
||||
name = "Ruin of Envy"
|
||||
id = "envy"
|
||||
description = "When you get what they have, then you'll finally be happy."
|
||||
suffix = "lavaland_surface_envy.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin/gluttony
|
||||
name = "Ruin of Gluttony"
|
||||
id = "gluttony"
|
||||
description = "If you eat enough, then eating will be all that you do."
|
||||
suffix = "lavaland_surface_gluttony.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin/greed
|
||||
name = "Ruin of Greed"
|
||||
id = "greed"
|
||||
description = "Sure you don't need magical powers, but you WANT them, and that's what's important."
|
||||
suffix = "lavaland_surface_greed.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin/pride
|
||||
name = "Ruin of Pride"
|
||||
id = "pride"
|
||||
description = "Wormhole lifebelts are for LOSERS, who you are better than."
|
||||
suffix = "lavaland_surface_pride.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/sin/sloth
|
||||
name = "Ruin of Sloth"
|
||||
id = "sloth"
|
||||
description = "..."
|
||||
suffix = "lavaland_surface_sloth.dmm"
|
||||
cost = 0
|
||||
|
||||
/datum/map_template/ruin/lavaland/ratvar
|
||||
name = "Dead God"
|
||||
id = "ratvar"
|
||||
description = "Ratvars final resting place."
|
||||
suffix = "lavaland_surface_dead_ratvar.dmm"
|
||||
cost = 0
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/hierophant
|
||||
name = "Hierophant's Arena"
|
||||
id = "hierophant"
|
||||
@@ -70,6 +130,51 @@ datum/map_template/ruin/lavaland/ash_walker
|
||||
name = "Blood-Drunk Miner (Hunter)"
|
||||
suffix = "lavaland_surface_blooddrunk3.dmm"
|
||||
|
||||
/datum/map_template/ruin/lavaland/ufo_crash
|
||||
name = "UFO Crash"
|
||||
id = "ufo-crash"
|
||||
description = "Turns out that keeping your abductees unconscious is really important. Who knew?"
|
||||
suffix = "lavaland_surface_ufo_crash.dmm"
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/xeno_nest
|
||||
name = "Xenomorph Nest"
|
||||
id = "xeno-nest"
|
||||
description = "These xenomorphs got bored of horrifically slaughtering people on space stations, and have settled down on a nice lava filled hellscape to focus on what's really important in life. \
|
||||
Quality memes."
|
||||
suffix = "lavaland_surface_xeno_nest.dmm"
|
||||
cost = 20
|
||||
|
||||
/datum/map_template/ruin/lavaland/fountain
|
||||
name = "Fountain Hall"
|
||||
id = "fountain"
|
||||
description = "The fountain has a warning on the side. DANGER: May have undeclared side effects that only become obvious when implemented."
|
||||
suffix = "lavaland_surface_fountain_hall.dmm"
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/survivalcapsule
|
||||
name = "Survival Capsule Ruins"
|
||||
id = "survivalcapsule"
|
||||
description = "What was once sanctuary to the common miner, is now their tomb."
|
||||
suffix = "lavaland_surface_survivalpod.dmm"
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/pizza
|
||||
name = "Ruined Pizza Party"
|
||||
id = "pizza"
|
||||
description = "Little Timmy's birthday pizza-bash took a turn for the worse when a bluespace anomaly passed by."
|
||||
suffix = "lavaland_surface_pizzaparty.dmm"
|
||||
allow_duplicates = FALSE
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/cultaltar
|
||||
name = "Summoning Ritual"
|
||||
id = "cultaltar"
|
||||
description = "A place of vile worship, the scrawling of blood in the middle glowing eerily. A demonic laugh echoes throughout the caverns"
|
||||
suffix = "lavaland_surface_cultaltar.dmm"
|
||||
allow_duplicates = FALSE
|
||||
cost = 10
|
||||
|
||||
/datum/map_template/ruin/lavaland/hermit
|
||||
name = "Makeshift Shelter"
|
||||
id = "hermitcave"
|
||||
@@ -84,4 +189,19 @@ datum/map_template/ruin/lavaland/ash_walker
|
||||
description = "A Syndicate shuttle had an unfortunate stowaway..."
|
||||
suffix = "lavaland_surface_swarmer_crash.dmm"
|
||||
allow_duplicates = FALSE
|
||||
cost = 20
|
||||
cost = 20
|
||||
|
||||
/datum/map_template/ruin/lavaland/miningripley
|
||||
name = "Ripley"
|
||||
id = "ripley"
|
||||
description = "A heavily-damaged mining ripley, property of a very unfortunate miner. You might have to do a bit of work to fix this thing up."
|
||||
suffix = "lavaland_surface_random_ripley.dmm"
|
||||
allow_duplicates = FALSE
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/puzzle
|
||||
name = "Ancient Puzzle"
|
||||
id = "puzzle"
|
||||
description = "Mystery to be solved."
|
||||
suffix = "lavaland_surface_puzzle.dmm"
|
||||
cost = 5
|
||||
@@ -1107,10 +1107,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
cost = 2
|
||||
|
||||
/datum/uplink_item/stealthy_tools/thermal
|
||||
name = "Thermal Imaging Glasses"
|
||||
desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
|
||||
name = "Thermal Chameleon Glasses"
|
||||
desc = "These glasses are thermals with Syndicate chameleon technology built into them. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
|
||||
reference = "THIG"
|
||||
item = /obj/item/clothing/glasses/thermal/syndi
|
||||
item = /obj/item/clothing/glasses/chameleon/thermal
|
||||
cost = 6
|
||||
|
||||
/datum/uplink_item/stealthy_tools/traitor_belt
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
receivers -= M
|
||||
garbled_receivers |= M
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M.client && M.stat == DEAD)
|
||||
if(M.client && M.stat == DEAD && !isnewplayer(M))
|
||||
receivers |= M
|
||||
|
||||
return list(receivers, garbled_receivers)
|
||||
|
||||
@@ -50,6 +50,7 @@ var/list/ghostteleportlocs = list()
|
||||
icon_state = "start"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
hide_attacklogs = TRUE
|
||||
|
||||
|
||||
/area/adminconstruction
|
||||
@@ -57,6 +58,7 @@ var/list/ghostteleportlocs = list()
|
||||
icon_state = "start"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
hide_attacklogs = TRUE
|
||||
|
||||
/area/space
|
||||
icon_state = "space"
|
||||
@@ -522,6 +524,7 @@ var/list/ghostteleportlocs = list()
|
||||
icon_state = "thunder"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
hide_attacklogs = TRUE
|
||||
|
||||
|
||||
/area/tdome/arena_source
|
||||
@@ -1400,10 +1403,12 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper Prison Wing"
|
||||
icon_state = "sec_prison_perma"
|
||||
fast_despawn = TRUE
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/prison
|
||||
name = "\improper Prison Wing"
|
||||
icon_state = "sec_prison"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/prison/prison_break()
|
||||
for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
|
||||
@@ -1432,14 +1437,17 @@ var/list/ghostteleportlocs = list()
|
||||
/area/security/execution
|
||||
name = "\improper Execution"
|
||||
icon_state = "execution"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/processing
|
||||
name = "\improper Prisoner Processing"
|
||||
icon_state = "prisonerprocessing"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/interrogation
|
||||
name = "\improper Interrogation"
|
||||
icon_state = "interrogation"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/seceqstorage
|
||||
name = "\improper Security Equipment Storage"
|
||||
@@ -1456,6 +1464,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/security/interrogationobs
|
||||
name = "\improper Interrogation Observation"
|
||||
icon_state = "security"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/evidence
|
||||
name = "\improper Evidence Room"
|
||||
@@ -1464,6 +1473,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/security/prisonlockers
|
||||
name = "\improper Prisoner Lockers"
|
||||
icon_state = "sec_prison_lockers"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/medbay
|
||||
name = "\improper Security Medbay"
|
||||
@@ -1472,6 +1482,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/security/prisonershuttle
|
||||
name = "\improper Security Prisoner Shuttle"
|
||||
icon_state = "security"
|
||||
can_get_auto_cryod = FALSE
|
||||
|
||||
/area/security/warden
|
||||
name = "\improper Warden's Office"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
var/static_equip
|
||||
var/static_light = FALSE
|
||||
var/static_environ
|
||||
|
||||
|
||||
var/has_gravity = TRUE
|
||||
var/list/apc = list()
|
||||
var/no_air = null
|
||||
@@ -64,6 +64,8 @@
|
||||
'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
|
||||
|
||||
var/fast_despawn = FALSE
|
||||
var/can_get_auto_cryod = TRUE
|
||||
var/hide_attacklogs = FALSE // For areas such as thunderdome, lavaland syndiebase, etc which generate a lot of spammy attacklogs. Reduces log priority.
|
||||
|
||||
/area/Initialize(mapload)
|
||||
GLOB.all_areas += src
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
icon_state = "dk_yellow"
|
||||
|
||||
/area/ruin/powered/golem_ship
|
||||
name = "Free Golem Ship"
|
||||
name = "Free Golem Landing"
|
||||
icon_state = "dk_yellow"
|
||||
|
||||
/area/ruin/powered/greed
|
||||
@@ -37,6 +37,7 @@
|
||||
icon_state = "dk_yellow"
|
||||
ambientsounds = list('sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg')
|
||||
report_alerts = FALSE
|
||||
hide_attacklogs = TRUE
|
||||
|
||||
/area/ruin/unpowered/syndicate_lava_base/engineering
|
||||
name = "Syndicate Lavaland Engineering"
|
||||
|
||||
+1
-1
@@ -361,7 +361,7 @@
|
||||
fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key)
|
||||
fingerprintslast = H.ckey
|
||||
return 0
|
||||
if(!( fingerprints ))
|
||||
if(!fingerprints)
|
||||
if(fingerprintslast != H.ckey)
|
||||
//Add the list if it does not exist.
|
||||
if(!fingerprintshidden)
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
|
||||
// Previously known as HasEntered()
|
||||
// This is automatically called when something enters your square
|
||||
/atom/movable/Crossed(atom/movable/AM)
|
||||
/atom/movable/Crossed(atom/movable/AM, oldloc)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
|
||||
|
||||
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
|
||||
@@ -245,7 +245,9 @@
|
||||
if(destination)
|
||||
destination.Entered(src)
|
||||
for(var/atom/movable/AM in destination)
|
||||
AM.Crossed(src)
|
||||
if(AM == src)
|
||||
continue
|
||||
AM.Crossed(src, old_loc)
|
||||
var/turf/oldturf = get_turf(old_loc)
|
||||
var/turf/destturf = get_turf(destination)
|
||||
var/old_z = (oldturf ? oldturf.z : null)
|
||||
|
||||
+15
-1
@@ -437,4 +437,18 @@ var/global/list/bad_blocks[0]
|
||||
var/datum/species/S = data["species"]
|
||||
species = new S
|
||||
b_type = data["b_type"]
|
||||
real_name = data["real_name"]
|
||||
real_name = data["real_name"]
|
||||
|
||||
/datum/dna/proc/transfer_identity(mob/living/carbon/human/destination)
|
||||
if(!istype(destination))
|
||||
return
|
||||
|
||||
// We manually set the species to ensure all proper species change procs are called.
|
||||
destination.set_species(species.type, retain_damage = TRUE)
|
||||
var/datum/dna/new_dna = Clone()
|
||||
new_dna.species = destination.dna.species
|
||||
destination.dna = new_dna
|
||||
destination.dna.species.handle_dna(destination) // Handle DNA has to be re-called as the DNA was changed.
|
||||
|
||||
destination.UpdateAppearance()
|
||||
domutcheck(destination, null, MUTCHK_FORCED)
|
||||
|
||||
@@ -14,7 +14,6 @@ var/list/blob_nodes = list()
|
||||
required_enemies = 1
|
||||
recommended_enemies = 1
|
||||
restricted_jobs = list("Cyborg", "AI")
|
||||
free_golems_disabled = TRUE
|
||||
|
||||
var/declared = 0
|
||||
var/burst = 0
|
||||
@@ -43,9 +42,11 @@ var/list/blob_nodes = list()
|
||||
for(var/j = 0, j < cores_to_spawn, j++)
|
||||
if(!possible_blobs.len)
|
||||
break
|
||||
|
||||
var/datum/mind/blob = pick(possible_blobs)
|
||||
infected_crew += blob
|
||||
blob.special_role = SPECIAL_ROLE_BLOB
|
||||
update_blob_icons_added(blob)
|
||||
blob.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(blob)] has been selected as a Blob")
|
||||
possible_blobs -= blob
|
||||
@@ -67,8 +68,11 @@ var/list/blob_nodes = list()
|
||||
var/datum/mind/blobmind = blob.mind
|
||||
if(!istype(blobmind))
|
||||
return 0
|
||||
|
||||
infected_crew += blobmind
|
||||
blobmind.special_role = SPECIAL_ROLE_BLOB
|
||||
update_blob_icons_added(blobmind)
|
||||
|
||||
log_game("[key_name(blob)] has been selected as a Blob")
|
||||
greet_blob(blobmind)
|
||||
to_chat(blob, "<span class='userdanger'>You feel very tired and bloated! You don't have long before you burst!</span>")
|
||||
@@ -186,16 +190,21 @@ var/list/blob_nodes = list()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/blob/proc/stage(var/stage)
|
||||
|
||||
switch(stage)
|
||||
if(0)
|
||||
send_intercept(1)
|
||||
declared = 1
|
||||
|
||||
if(1)
|
||||
event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
|
||||
|
||||
if(2)
|
||||
send_intercept(2)
|
||||
|
||||
return
|
||||
/datum/game_mode/proc/update_blob_icons_added(datum/mind/mob_mind)
|
||||
var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB]
|
||||
antaghud.join_hud(mob_mind.current)
|
||||
set_antag_hud(mob_mind.current, "hudblob")
|
||||
|
||||
/datum/game_mode/proc/update_blob_icons_removed(datum/mind/mob_mind)
|
||||
var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB]
|
||||
antaghud.leave_hud(mob_mind.current)
|
||||
set_antag_hud(mob_mind.current, null)
|
||||
@@ -25,7 +25,8 @@
|
||||
if(blob_nodes.len)
|
||||
var/list/nodes = list()
|
||||
for(var/i = 1; i <= blob_nodes.len; i++)
|
||||
nodes["Blob Node #[i]"] = blob_nodes[i]
|
||||
var/obj/structure/blob/node/B = blob_nodes[i]
|
||||
nodes["Blob Node #[i] ([get_location_name(B)])"] = B
|
||||
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
|
||||
var/obj/structure/blob/node/chosen_node = nodes[node_name]
|
||||
if(chosen_node)
|
||||
@@ -388,7 +389,7 @@
|
||||
set name = "Blob Broadcast"
|
||||
set desc = "Speak with your blob spores and blobbernauts as your mouthpieces. This action is free."
|
||||
|
||||
var/speak_text = input(usr, "What would you like to say with your minions?", "Blob Broadcast", null) as text
|
||||
var/speak_text = clean_input("What would you like to say with your minions?", "Blob Broadcast", null)
|
||||
|
||||
if(!speak_text)
|
||||
return
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
take_damage(Proj.damage, Proj.damage_type)
|
||||
return 0
|
||||
|
||||
/obj/structure/blob/Crossed(var/mob/living/L)
|
||||
/obj/structure/blob/Crossed(var/mob/living/L, oldloc)
|
||||
..()
|
||||
L.blob_act(src)
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ var/global/list/all_cults = list()
|
||||
required_players = 30
|
||||
required_enemies = 3
|
||||
recommended_enemies = 4
|
||||
free_golems_disabled = TRUE
|
||||
|
||||
var/datum/mind/sacrifice_target = null
|
||||
var/finished = 0
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(iscultist(M))
|
||||
to_chat(M, my_message)
|
||||
else if(M in GLOB.dead_mob_list)
|
||||
else if((M in GLOB.dead_mob_list) && !isnewplayer(M))
|
||||
to_chat(M, "<span class='cultspeech'> <a href='?src=[M.UID()];follow=[user.UID()]'>(F)</a> [my_message] </span>")
|
||||
|
||||
log_say("(CULT) [message]", user)
|
||||
|
||||
@@ -271,7 +271,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list(
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/gateway/Crossed(AM as mob|obj)
|
||||
/obj/effect/gateway/Crossed(AM as mob|obj, oldloc)
|
||||
spawn(0)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -494,9 +494,8 @@ var/list/teleport_runes = list()
|
||||
|
||||
/obj/effect/rune/narsie/New()
|
||||
..()
|
||||
cultist_name = "Summon [SSticker.cultdat.entity_name]"
|
||||
cultist_desc = "tears apart dimensional barriers, calling forth [SSticker.cultdat.entity_title3]. Requires 9 invokers."
|
||||
|
||||
cultist_name = "Summon [SSticker.cultdat ? SSticker.cultdat.entity_name : "your god"]"
|
||||
cultist_desc = "tears apart dimensional barriers, calling forth [SSticker.cultdat ? SSticker.cultdat.entity_title3 : "your god"]. Requires 9 invokers."
|
||||
|
||||
/obj/effect/rune/narsie/check_icon()
|
||||
return
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/obj/item/paper/talisman
|
||||
icon = 'icons/obj/paper.dmi'
|
||||
icon_state = "paper_talisman"
|
||||
var/cultist_name = "talisman"
|
||||
var/cultist_desc = "A basic talisman. It serves no purpose."
|
||||
@@ -7,6 +8,9 @@
|
||||
var/uses = 1
|
||||
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
|
||||
|
||||
/obj/item/paper/talisman/update_icon()//overriding this so the update_icon doesn't turn them into normal looking paper
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_UPDATE_ICON)
|
||||
|
||||
/obj/item/paper/talisman/examine(mob/user)
|
||||
if(iscultist(user) || user.stat == DEAD)
|
||||
to_chat(user, "<b>Name:</b> [cultist_name]")
|
||||
@@ -49,6 +53,7 @@
|
||||
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
|
||||
/obj/item/paper/talisman/supply
|
||||
cultist_name = "Supply Talisman"
|
||||
icon_state = "supply"
|
||||
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
|
||||
invocation = null
|
||||
uses = 3
|
||||
@@ -117,6 +122,7 @@
|
||||
//Rite of Translocation: Same as rune
|
||||
/obj/item/paper/talisman/teleport
|
||||
cultist_name = "Talisman of Teleportation"
|
||||
icon_state = "teleport"
|
||||
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
health_cost = 5
|
||||
@@ -159,6 +165,7 @@
|
||||
|
||||
/obj/item/paper/talisman/summon_tome
|
||||
cultist_name = "Talisman of Tome Summoning"
|
||||
icon_state = "tome"
|
||||
cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of a cult."
|
||||
invocation = "N'ath reth sh'yro eth d'raggathnor!"
|
||||
health_cost = 1
|
||||
@@ -173,6 +180,7 @@
|
||||
|
||||
/obj/item/paper/talisman/true_sight
|
||||
cultist_name = "Talisman of Veiling"
|
||||
icon_state = "veil"
|
||||
cultist_desc = "A multi-use talisman that hides nearby runes. On its second use, will reveal nearby runes."
|
||||
invocation = "Kla'atu barada nikt'o!"
|
||||
health_cost = 1
|
||||
@@ -197,6 +205,7 @@
|
||||
//Rite of False Truths: Same as rune
|
||||
/obj/item/paper/talisman/make_runes_fake
|
||||
cultist_name = "Talisman of Disguising"
|
||||
icon_state = "disguising"
|
||||
cultist_desc = "A talisman that will make nearby runes appear fake."
|
||||
invocation = "By'o nar'nar!"
|
||||
|
||||
@@ -212,6 +221,7 @@
|
||||
//Rite of Disruption: Weaker than rune
|
||||
/obj/item/paper/talisman/emp
|
||||
cultist_name = "Talisman of Electromagnetic Pulse"
|
||||
icon_state = "emp"
|
||||
cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
|
||||
invocation = "Ta'gh fara'qha fel d'amar det!"
|
||||
health_cost = 5
|
||||
@@ -226,6 +236,7 @@
|
||||
//Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time
|
||||
/obj/item/paper/talisman/stun
|
||||
cultist_name = "Talisman of Stunning"
|
||||
icon_state = "stunning"
|
||||
cultist_desc = "A talisman that will stun and inhibit speech on a single target. To use, attack target directly."
|
||||
invocation = "Dream sign:Evil sealing talisman!"
|
||||
health_cost = 10
|
||||
@@ -271,6 +282,7 @@
|
||||
//Rite of Arming: Equips cultist armor on the user, where available
|
||||
/obj/item/paper/talisman/armor
|
||||
cultist_name = "Talisman of Arming"
|
||||
icon_state = "arming"
|
||||
cultist_desc = "A talisman that will equip the invoker with cultist equipment if there is a slot to equip it to."
|
||||
invocation = "N'ath reth sh'yro eth draggathnor!"
|
||||
|
||||
@@ -301,6 +313,7 @@
|
||||
//Talisman of Horrors: Breaks the mind of the victim with nightmarish hallucinations
|
||||
/obj/item/paper/talisman/horror
|
||||
cultist_name = "Talisman of Horrors"
|
||||
icon_state = "horror"
|
||||
cultist_desc = "A talisman that will break the mind of the victim with nightmarish hallucinations."
|
||||
invocation = "Lo'Nab Na'Dm!"
|
||||
|
||||
@@ -316,6 +329,7 @@
|
||||
//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets.
|
||||
/obj/item/paper/talisman/construction
|
||||
cultist_name = "Talisman of Construction"
|
||||
icon_state = "construction"
|
||||
cultist_desc = "Use this talisman on at least twenty-five metal sheets to create an empty construct shell or on plasteel to make runed metal"
|
||||
invocation = "Ethra p'ni dedol!"
|
||||
uses = 25
|
||||
@@ -360,6 +374,7 @@
|
||||
//Talisman of Shackling: Applies special cuffs directly from the talisman
|
||||
/obj/item/paper/talisman/shackle
|
||||
cultist_name = "Talisman of Shackling"
|
||||
icon_state = "shackling"
|
||||
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
|
||||
invocation = "In'totum Lig'abis!"
|
||||
uses = 4
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
var/recommended_enemies = 0
|
||||
var/newscaster_announcements = null
|
||||
var/ert_disabled = 0
|
||||
var/free_golems_disabled = FALSE
|
||||
var/uplink_welcome = "Syndicate Uplink Console:"
|
||||
var/uplink_uses = 20
|
||||
|
||||
@@ -81,7 +80,6 @@
|
||||
// feedback_set_details("revision","[revdata.revision]")
|
||||
feedback_set_details("server_ip","[world.internet_address]:[world.port]")
|
||||
generate_station_goals()
|
||||
check_free_golems()
|
||||
start_state = new /datum/station_state()
|
||||
start_state.count()
|
||||
return 1
|
||||
@@ -513,12 +511,6 @@ proc/display_roundstart_logout_report()
|
||||
var/datum/station_goal/G = V
|
||||
G.print_result()
|
||||
|
||||
/datum/game_mode/proc/check_free_golems() //check config and gamemode for free golems setting and run the prob to check if the round will have free golems spawned or not
|
||||
if((config.unrestricted_free_golems || !free_golems_disabled) && prob(config.prob_free_golems))
|
||||
for(var/obj/effect/landmark/free_golem_spawn/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc))
|
||||
new /obj/effect/mob_spawn/human/golem/adamantine(L.loc)
|
||||
|
||||
/datum/game_mode/proc/update_eventmisc_icons_added(datum/mind/mob_mind)
|
||||
var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_EVENTMISC]
|
||||
antaghud.join_hud(mob_mind.current)
|
||||
|
||||
@@ -545,7 +545,7 @@
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
health = 10
|
||||
|
||||
/obj/structure/swarmer/trap/Crossed(var/atom/movable/AM)
|
||||
/obj/structure/swarmer/trap/Crossed(var/atom/movable/AM, oldloc)
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
do_teleport(M, M, 10)
|
||||
new /obj/effect/temp_visual/guardian/phase/out(get_turf(M))
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
|
||||
/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj, oldloc)
|
||||
..()
|
||||
collision_ignite(AM)
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
invisibility = 1
|
||||
|
||||
|
||||
/obj/item/effect/snare/Crossed(AM as mob|obj)
|
||||
/obj/item/effect/snare/Crossed(AM as mob|obj, oldloc)
|
||||
if(isliving(AM))
|
||||
var/turf/snare_loc = get_turf(loc)
|
||||
if(spawner)
|
||||
|
||||
@@ -12,7 +12,6 @@ proc/issyndicate(mob/living/M as mob)
|
||||
required_players = 30 // 30 players - 5 players to be the nuke ops = 25 players remaining
|
||||
required_enemies = 5
|
||||
recommended_enemies = 5
|
||||
free_golems_disabled = TRUE
|
||||
|
||||
var/const/agents_possible = 5 //If we ever need more syndicate agents.
|
||||
|
||||
|
||||
@@ -165,10 +165,13 @@
|
||||
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in item_names
|
||||
if(!targetitem)
|
||||
return
|
||||
var/list/obj/item/target_candidates = get_all_of_type(item_paths[targetitem], subtypes = TRUE)
|
||||
for(var/obj/item/candidate in target_candidates)
|
||||
if(!is_admin_level(candidate.loc.z))
|
||||
target = candidate
|
||||
|
||||
var/list/target_candidates = get_all_of_type(item_paths[targetitem], subtypes = TRUE)
|
||||
for(var/obj/item/candidate in target_candidates)
|
||||
if(!is_admin_level((get_turf(candidate)).z))
|
||||
target = candidate
|
||||
break
|
||||
|
||||
if(!target)
|
||||
to_chat(usr, "<span class='warning'>Failed to locate [targetitem]!</span>")
|
||||
return
|
||||
|
||||
@@ -25,6 +25,8 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
|
||||
/datum/objective/proc/is_invalid_target(datum/mind/possible_target)
|
||||
if(possible_target == owner)
|
||||
return TARGET_INVALID_IS_OWNER
|
||||
if(possible_target in owner.targets)
|
||||
return TARGET_INVALID_IS_TARGET
|
||||
if(!ishuman(possible_target.current))
|
||||
return TARGET_INVALID_NOT_HUMAN
|
||||
if(!possible_target.current.stat == DEAD)
|
||||
@@ -52,7 +54,6 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
|
||||
if(possible_targets.len > 0)
|
||||
target = pick(possible_targets)
|
||||
|
||||
|
||||
/datum/objective/assassinate
|
||||
martyr_compatible = 1
|
||||
|
||||
@@ -361,9 +362,12 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
|
||||
var/datum/theft_objective/O = new thefttype
|
||||
if(owner.assigned_role in O.protected_jobs)
|
||||
continue
|
||||
if(O in owner.targets)
|
||||
continue
|
||||
if(O.flags & 2)
|
||||
continue
|
||||
steal_target=O
|
||||
steal_target = O
|
||||
|
||||
explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. "
|
||||
if(islist(O.protected_jobs) && O.protected_jobs.len)
|
||||
explanation_text += "It may also be in the possession of the [jointext(O.protected_jobs, ", ")]."
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
yandere_one.owner = traitor
|
||||
traitor.objectives += yandere_one
|
||||
yandere_one.find_target()
|
||||
traitor.targets += yandere_one.target
|
||||
objective_count++
|
||||
var/datum/objective/maroon/yandere_two = new
|
||||
yandere_two.owner = traitor
|
||||
@@ -99,6 +100,7 @@
|
||||
kill_objective.owner = traitor
|
||||
kill_objective.find_target()
|
||||
traitor.objectives += kill_objective
|
||||
traitor.targets += kill_objective.target
|
||||
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = traitor
|
||||
@@ -124,26 +126,31 @@
|
||||
destroy_objective.owner = traitor
|
||||
destroy_objective.find_target()
|
||||
traitor.objectives += destroy_objective
|
||||
traitor.targets += destroy_objective.target
|
||||
else if(prob(5))
|
||||
var/datum/objective/debrain/debrain_objective = new
|
||||
debrain_objective.owner = traitor
|
||||
debrain_objective.find_target()
|
||||
traitor.objectives += debrain_objective
|
||||
traitor.targets += debrain_objective.target
|
||||
else if(prob(30))
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = traitor
|
||||
maroon_objective.find_target()
|
||||
traitor.objectives += maroon_objective
|
||||
traitor.targets += maroon_objective.target
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = traitor
|
||||
kill_objective.find_target()
|
||||
traitor.objectives += kill_objective
|
||||
traitor.targets += kill_objective.target
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = traitor
|
||||
steal_objective.find_target()
|
||||
traitor.objectives += steal_objective
|
||||
traitor.targets += steal_objective.steal_target
|
||||
|
||||
if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
|
||||
if(!(locate(/datum/objective/hijack) in traitor.objectives))
|
||||
|
||||
@@ -261,8 +261,10 @@
|
||||
for(var/mob/living/carbon/C in hearers(4))
|
||||
if(C == user)
|
||||
continue
|
||||
if(ishuman(C) && (C:l_ear || C:r_ear) && istype((C:l_ear || C:r_ear), /obj/item/clothing/ears/earmuffs))
|
||||
continue
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs))
|
||||
continue
|
||||
if(!affects(C))
|
||||
continue
|
||||
to_chat(C, "<span class='warning'><font size='3'><b>You hear a ear piercing shriek and your senses dull!</font></b></span>")
|
||||
@@ -347,8 +349,16 @@
|
||||
SSticker.mode.vampire_enthralled.Add(H.mind)
|
||||
SSticker.mode.vampire_enthralled[H.mind] = user.mind
|
||||
H.mind.special_role = SPECIAL_ROLE_VAMPIRE_THRALL
|
||||
to_chat(H, "<span class='danger'>You have been Enthralled by [user]. Follow [user.p_their()] every command.</span>")
|
||||
|
||||
var/datum/objective/protect/serve_objective = new
|
||||
serve_objective.owner = user.mind
|
||||
serve_objective.target = H.mind
|
||||
serve_objective.explanation_text = "You have been Enthralled by [user]. Follow [user.p_their()] every command."
|
||||
H.mind.objectives += serve_objective
|
||||
|
||||
to_chat(H, "<span class='biggerdanger'>You have been Enthralled by [user]. Follow [user.p_their()] every command.</span>")
|
||||
to_chat(user, "<span class='warning'>You have successfully Enthralled [H]. <i>If [H.p_they()] refuse[H.p_s()] to do as you say just adminhelp.</i></span>")
|
||||
H.Stun(2)
|
||||
add_attack_logs(user, H, "Vampire-thralled")
|
||||
|
||||
|
||||
|
||||
@@ -906,3 +906,13 @@
|
||||
spellname = "sacred flame"
|
||||
icon_state ="booksacredflame"
|
||||
desc = "Become one with the flames that burn within... and invite others to do so as well."
|
||||
|
||||
/obj/item/spellbook/oneuse/random
|
||||
icon_state = "random_book"
|
||||
|
||||
/obj/item/spellbook/oneuse/random/initialize()
|
||||
. = ..()
|
||||
var/static/banned_spells = list(/obj/item/spellbook/oneuse/mime, /obj/item/spellbook/oneuse/mime/fingergun, /obj/item/spellbook/oneuse/mime/fingergun/fake, /obj/item/spellbook/oneuse/mime/greaterwall)
|
||||
var/real_type = pick(subtypesof(/obj/item/spellbook/oneuse) - banned_spells)
|
||||
new real_type(loc)
|
||||
qdel(src)
|
||||
@@ -7,8 +7,8 @@
|
||||
required_players = 20
|
||||
required_enemies = 1
|
||||
recommended_enemies = 1
|
||||
free_golems_disabled = TRUE
|
||||
var/use_huds = 1
|
||||
|
||||
var/finished = 0
|
||||
var/but_wait_theres_more = 0
|
||||
|
||||
|
||||
+19
-18
@@ -601,28 +601,29 @@ proc/get_all_job_icons() //For all existing HUD icons
|
||||
return GLOB.joblist + list("Prisoner")
|
||||
|
||||
/obj/proc/GetJobName() //Used in secHUD icon generation
|
||||
var/obj/item/card/id/I
|
||||
var/assignmentName = "Unknown"
|
||||
var/rankName = "Unknown"
|
||||
if(istype(src, /obj/item/pda))
|
||||
var/obj/item/pda/P = src
|
||||
I = P.id
|
||||
assignmentName = P.ownjob
|
||||
rankName = P.ownrank
|
||||
else if(istype(src, /obj/item/card/id))
|
||||
I = src
|
||||
var/obj/item/card/id/I = src
|
||||
assignmentName = I.assignment
|
||||
rankName = I.rank
|
||||
|
||||
|
||||
if(I)
|
||||
var/job_icons = get_all_job_icons()
|
||||
var/centcom = get_all_centcom_jobs()
|
||||
var/job_icons = get_all_job_icons()
|
||||
var/centcom = get_all_centcom_jobs()
|
||||
|
||||
if(I.assignment in centcom) //Return with the NT logo if it is a Centcom job
|
||||
return "Centcom"
|
||||
if(I.rank in centcom)
|
||||
return "Centcom"
|
||||
|
||||
if(I.assignment in job_icons) //Check if the job has a hud icon
|
||||
return I.assignment
|
||||
if(I.rank in job_icons)
|
||||
return I.rank
|
||||
|
||||
else
|
||||
return
|
||||
if(assignmentName in centcom) //Return with the NT logo if it is a Centcom job
|
||||
return "Centcom"
|
||||
if(rankName in centcom)
|
||||
return "Centcom"
|
||||
|
||||
if(assignmentName in job_icons) //Check if the job has a hud icon
|
||||
return assignmentName
|
||||
if(rankName in job_icons)
|
||||
return rankName
|
||||
|
||||
return "Unknown" //Return unknown if none of the above apply
|
||||
|
||||
@@ -193,7 +193,38 @@
|
||||
backpack = /obj/item/storage/backpack/explorer
|
||||
satchel = /obj/item/storage/backpack/explorer
|
||||
|
||||
/datum/outfit/job/mining/equipped
|
||||
name = "Shaft Miner"
|
||||
|
||||
suit = /obj/item/clothing/suit/hooded/explorer
|
||||
mask = /obj/item/clothing/mask/gas/explorer
|
||||
glasses = /obj/item/clothing/glasses/meson
|
||||
suit_store = /obj/item/tank/emergency_oxygen
|
||||
internals_slot = slot_s_store
|
||||
backpack_contents = list(
|
||||
/obj/item/flashlight/seclite=1,\
|
||||
/obj/item/kitchen/knife/combat/survival=1,
|
||||
/obj/item/mining_voucher=1,
|
||||
/obj/item/t_scanner/adv_mining_scanner/lesser=1,
|
||||
/obj/item/gun/energy/kinetic_accelerator=1,\
|
||||
/obj/item/stack/marker_beacon/ten=1
|
||||
)
|
||||
|
||||
backpack = /obj/item/storage/backpack/explorer
|
||||
satchel = /obj/item/storage/backpack/explorer
|
||||
|
||||
/datum/outfit/job/miner/equipped/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
..()
|
||||
if(visualsOnly)
|
||||
return
|
||||
if(istype(H.wear_suit, /obj/item/clothing/suit/hooded))
|
||||
var/obj/item/clothing/suit/hooded/S = H.wear_suit
|
||||
S.ToggleHood()
|
||||
|
||||
/datum/outfit/job/miner/equipped/hardsuit
|
||||
name = "Shaft Miner (Equipment + Hardsuit)"
|
||||
suit = /obj/item/clothing/suit/space/hardsuit/mining
|
||||
mask = /obj/item/clothing/mask/breath
|
||||
|
||||
//Griff //BS12 EDIT
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
icon_state = "table2-idle"
|
||||
return 0
|
||||
|
||||
/obj/machinery/optable/Crossed(atom/movable/AM)
|
||||
/obj/machinery/optable/Crossed(atom/movable/AM, oldloc)
|
||||
. = ..()
|
||||
if(iscarbon(AM) && LAZYLEN(injected_reagents))
|
||||
to_chat(AM, "<span class='danger'>You feel a series of tiny pricks!</span>")
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
return O:id_tag in sensors
|
||||
|
||||
/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, link/context)
|
||||
sensors[O:id_tag] = reject_bad_name(input(user, "Choose a sensor label:", "Sensor Label") as text|null, allow_numbers=1)
|
||||
sensors[O:id_tag] = reject_bad_name(clean_input(user, "Choose a sensor label:", "Sensor Label"), allow_numbers=1)
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/general_air_control/large_tank_control
|
||||
|
||||
@@ -334,9 +334,6 @@
|
||||
/obj/item/circuitboard/white_ship
|
||||
name = "circuit Board (White Ship)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship
|
||||
/obj/item/circuitboard/golem_ship
|
||||
name = "circuit Board (Golem Ship)"
|
||||
build_path = /obj/machinery/computer/shuttle/golem_ship
|
||||
/obj/item/circuitboard/shuttle/syndicate
|
||||
name = "circuit board (Syndicate Shuttle)"
|
||||
build_path = /obj/machinery/computer/shuttle/syndicate
|
||||
@@ -346,7 +343,9 @@
|
||||
/obj/item/circuitboard/shuttle/syndicate/drop_pod
|
||||
name = "circuit board (Syndicate Drop Pod)"
|
||||
build_path = /obj/machinery/computer/shuttle/syndicate/drop_pod
|
||||
|
||||
/obj/item/circuitboard/shuttle/golem_ship
|
||||
name = "circuit Board (Golem Ship)"
|
||||
build_path = /obj/machinery/computer/shuttle/golem_ship
|
||||
|
||||
/obj/item/circuitboard/HolodeckControl
|
||||
name = "Circuit board (Holodeck Control)"
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
message_cooldown = 0
|
||||
|
||||
if("callshuttle")
|
||||
var/input = input(usr, "Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
|
||||
var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
|
||||
if(!input || ..() || !is_authenticated(usr))
|
||||
SSnanoui.update_uis(src)
|
||||
return
|
||||
@@ -217,11 +217,11 @@
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg1")
|
||||
stat_msg1 = input("Line 1", "Enter Message Text", stat_msg1) as text|null
|
||||
stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1)
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg2")
|
||||
stat_msg2 = input("Line 2", "Enter Message Text", stat_msg2) as text|null
|
||||
stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2)
|
||||
setMenuState(usr,COMM_SCREEN_STAT)
|
||||
|
||||
if("nukerequest")
|
||||
|
||||
@@ -466,7 +466,7 @@
|
||||
active2.fields["comments"] -= active2.fields["comments"][index]
|
||||
|
||||
if(href_list["search"])
|
||||
var/t1 = input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text
|
||||
var/t1 = clean_input("Search String: (Name, DNA, or ID)", "Med. records", null, null)
|
||||
if(!t1 || ..())
|
||||
return 1
|
||||
active1 = null
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
auth = 0
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
var/dkey = trim(clean_input("Please enter the decryption key."))
|
||||
if(dkey && dkey != "")
|
||||
if(src.linkedServer.decryptkey == dkey)
|
||||
auth = 1
|
||||
@@ -332,7 +332,7 @@
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
var/dkey = trim(clean_input("Please enter the decryption key."))
|
||||
if(dkey && dkey != "")
|
||||
if(src.linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
@@ -395,7 +395,7 @@
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = input(usr, "Please enter the sender's name.") as text|null
|
||||
customsender = clean_input("Please enter the sender's name.")
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
@@ -414,11 +414,11 @@
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = input(usr, "Please enter the sender's job.") as text|null
|
||||
customjob = clean_input("Please enter the sender's job.")
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = input(usr, "Please enter your message.") as text|null
|
||||
custommessage = clean_input("Please enter your message.")
|
||||
custommessage = sanitize(copytext(custommessage, 1, MAX_MESSAGE_LEN))
|
||||
|
||||
//Send message
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
switch(href_list["field"])
|
||||
if("name")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/t1 = reject_bad_name(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
|
||||
var/t1 = reject_bad_name(clean_input("Please input name:", "Secure. records", active1.fields["name"], null))
|
||||
if(!t1 || !length(trim(t1)) || ..() || active1 != a1)
|
||||
return 1
|
||||
active1.fields["name"] = t1
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
switch(href_list["field"])
|
||||
if("name")
|
||||
if(istype(active1, /datum/data/record))
|
||||
var/t1 = reject_bad_name(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
|
||||
var/t1 = reject_bad_name(clean_input("Please input name:", "Secure. records", active1.fields["name"], null))
|
||||
if(!t1 || !length(trim(t1)) || incapable || active1 != a1)
|
||||
return 1
|
||||
active1.fields["name"] = t1
|
||||
|
||||
@@ -311,6 +311,7 @@ About the new airlock wires panel:
|
||||
/obj/machinery/door/airlock/update_icon(state=0, override=0)
|
||||
if(operating && !override)
|
||||
return
|
||||
check_unres()
|
||||
icon_state = density ? "closed" : "open"
|
||||
switch(state)
|
||||
if(0)
|
||||
@@ -333,7 +334,6 @@ About the new airlock wires panel:
|
||||
var/image/sparks_overlay
|
||||
var/image/note_overlay
|
||||
var/notetype = note_type()
|
||||
|
||||
switch(state)
|
||||
if(AIRLOCK_CLOSED)
|
||||
frame_overlay = get_airlock_overlay("closed", icon)
|
||||
@@ -621,6 +621,31 @@ About the new airlock wires panel:
|
||||
if(user)
|
||||
attack_ai(user)
|
||||
|
||||
/obj/machinery/door/airlock/proc/check_unres() //unrestricted sides. This overlay indicates which directions the player can access even without an ID
|
||||
if(hasPower() && unres_sides)
|
||||
if(unres_sides & NORTH)
|
||||
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_n") //layer=src.layer+1
|
||||
I.pixel_y = 32
|
||||
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
|
||||
add_overlay(I)
|
||||
if(unres_sides & SOUTH)
|
||||
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_s") //layer=src.layer+1
|
||||
I.pixel_y = -32
|
||||
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
|
||||
add_overlay(I)
|
||||
if(unres_sides & EAST)
|
||||
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_e") //layer=src.layer+1
|
||||
I.pixel_x = 32
|
||||
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
|
||||
add_overlay(I)
|
||||
if(unres_sides & WEST)
|
||||
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_w") //layer=src.layer+1
|
||||
I.pixel_x = -32
|
||||
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
|
||||
add_overlay(I)
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(isElectrified() && density && istype(mover, /obj/item))
|
||||
var/obj/item/I = mover
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
var/list/conf_access = null
|
||||
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
|
||||
var/const/max_brain_damage = 60 // Maximum brain damage a mob can have until it can't use the electronics
|
||||
var/unres_sides = 0
|
||||
var/unres_direction = null
|
||||
|
||||
/obj/item/airlock_electronics/attack_self(mob/user)
|
||||
if(!ishuman(user) && !isrobot(user))
|
||||
@@ -23,14 +25,22 @@
|
||||
return
|
||||
|
||||
var/t1 = text("<B>Access control</B><br>\n")
|
||||
t1 += "<hr>"
|
||||
t1 += "<B> Unrestricted Access Settings</B><br>"
|
||||
|
||||
var/list/Directions = list("North","South",,"East",,,,"West")
|
||||
for(var/direction in cardinal)
|
||||
if (unres_direction && unres_direction == direction)
|
||||
t1 += "<a style='color: red' href='?src=[UID()];unres_direction=[direction]'>[Directions[direction]]</a><br>"
|
||||
else
|
||||
t1 += "<a href='?src=[UID()];unres_direction=[direction]'>[Directions[direction]]</a><br>"
|
||||
|
||||
t1 += "<hr>"
|
||||
t1 += "Access requirement is set to "
|
||||
t1 += one_access ? "<a style='color: green' href='?src=[UID()];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=[UID()];one_access=1'>ALL</a><hr>"
|
||||
|
||||
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=[UID()];access=all'>All</a><br>"
|
||||
|
||||
t1 += "<br>"
|
||||
|
||||
var/list/accesses = get_all_accesses()
|
||||
for(var/acc in accesses)
|
||||
var/aname = get_access_desc(acc)
|
||||
@@ -64,6 +74,14 @@
|
||||
|
||||
if(href_list["access"])
|
||||
toggle_access(href_list["access"])
|
||||
|
||||
if(href_list["unres_direction"])
|
||||
unres_direction = text2num(href_list["unres_direction"])
|
||||
if (unres_sides == unres_direction)
|
||||
unres_sides = 0
|
||||
unres_direction = null
|
||||
else
|
||||
unres_sides = unres_direction
|
||||
|
||||
attack_self(usr)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/real_explosion_block //ignore this, just use explosion_block
|
||||
var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors
|
||||
var/emergency = FALSE
|
||||
|
||||
var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access
|
||||
//Multi-tile doors
|
||||
var/width = 1
|
||||
|
||||
@@ -55,6 +55,10 @@
|
||||
..()
|
||||
update_dir()
|
||||
|
||||
/obj/machinery/door/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/proc/update_dir()
|
||||
if(width > 1)
|
||||
if(dir in list(EAST, WEST))
|
||||
@@ -175,10 +179,15 @@
|
||||
/obj/machinery/door/allowed(mob/M)
|
||||
if(emergency)
|
||||
return TRUE
|
||||
if(unrestricted_side(M))
|
||||
return TRUE
|
||||
if(!requiresID())
|
||||
return FALSE // Intentional. machinery/door/requiresID() always == 1. airlocks, however, == 0 if ID scan is disabled. Yes, this var is poorly named.
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
|
||||
return get_dir(src, M) & unres_sides
|
||||
|
||||
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
|
||||
return
|
||||
|
||||
|
||||
@@ -76,6 +76,21 @@
|
||||
name = "Airlock Controller"
|
||||
tag_secure = 1
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Initialize(mapload, given_id_tag, given_frequency, given_tag_exterior_door, given_tag_interior_door, given_tag_airpump, given_tag_chamber_sensor)
|
||||
if(given_id_tag)
|
||||
id_tag = given_id_tag
|
||||
if(given_frequency)
|
||||
set_frequency(given_frequency)
|
||||
if(given_tag_exterior_door)
|
||||
tag_exterior_door = given_tag_exterior_door
|
||||
if(given_tag_interior_door)
|
||||
tag_interior_door = given_tag_interior_door
|
||||
if(given_tag_airpump)
|
||||
tag_airpump = given_tag_airpump
|
||||
if(given_tag_chamber_sensor)
|
||||
tag_chamber_sensor = given_tag_chamber_sensor
|
||||
..()
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
@@ -129,7 +144,6 @@
|
||||
name = "Access Controller"
|
||||
tag_secure = 1
|
||||
|
||||
|
||||
/obj/machinery/embedded_controller/radio/airlock/access_controller/update_icon()
|
||||
if(on && program)
|
||||
if(program.memory["processing"])
|
||||
|
||||
@@ -553,9 +553,7 @@ Class Procs:
|
||||
threatcount += 2
|
||||
|
||||
if(check_records || check_arrest)
|
||||
var/perpname = perp.name
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
var/perpname = perp.get_visible_name(TRUE)
|
||||
|
||||
var/datum/data/record/R = find_security_record("name", perpname)
|
||||
if(check_records && !R)
|
||||
|
||||
@@ -409,10 +409,10 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
|
||||
// if(href_list["table"] && href_list["table"] in tables)
|
||||
// if(requires_unlock[href_list["table"]] && !source.unlocked)
|
||||
// return
|
||||
// var/new_key = input(user, "Provide a key for the new row.", "New Row") as text|null
|
||||
// var/new_key = clean_input(user, "Provide a key for the new row.", "New Row")
|
||||
// if(!new_key)
|
||||
// return
|
||||
// var/new_value = input(user, "Provide a new value for the key [new_key]", "New Row") as text|null
|
||||
// var/new_value = clean_input(user, "Provide a new value for the key [new_key]", "New Row")
|
||||
// if(new_value == null)
|
||||
// return
|
||||
// if(word_blacklist.Find(new_value)) //uh oh, they tried to be naughty
|
||||
@@ -439,7 +439,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
|
||||
if(href_list["array"] && href_list["array"] in arrays)
|
||||
if(requires_unlock[href_list["array"]] && !source.unlocked)
|
||||
return
|
||||
var/new_value = input(user, "Provide a value for the new index.", "New Index") as text|null
|
||||
var/new_value = clean_input(user, "Provide a value for the new index.", "New Index")
|
||||
if(new_value == null)
|
||||
return
|
||||
var/list/array = vars[href_list["array"]]
|
||||
|
||||
@@ -1083,6 +1083,7 @@
|
||||
premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_robustgold = 1,
|
||||
/obj/item/lighter/zippo = 3)
|
||||
prices = list()
|
||||
|
||||
/obj/machinery/vending/cigarette/New()
|
||||
..()
|
||||
@@ -1131,7 +1132,6 @@
|
||||
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
|
||||
icon_state = "wallmed"
|
||||
icon_deny = "wallmed-deny"
|
||||
req_access = list(access_medical)
|
||||
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
|
||||
products = list(/obj/item/stack/medical/bruise_pack = 2, /obj/item/stack/medical/ointment = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4, /obj/item/healthanalyzer = 1)
|
||||
contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4, /obj/item/reagent_containers/syringe/antiviral = 4, /obj/item/reagent_containers/food/pill/tox = 1)
|
||||
@@ -1142,7 +1142,6 @@
|
||||
desc = "Wall-mounted Medical Equipment dispenser."
|
||||
icon_state = "wallmed"
|
||||
icon_deny = "wallmed-deny"
|
||||
req_access = list(access_medical)
|
||||
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
|
||||
products = list(/obj/item/reagent_containers/hypospray/autoinjector = 5, /obj/item/reagent_containers/syringe/charcoal = 3, /obj/item/stack/medical/bruise_pack = 3,
|
||||
/obj/item/stack/medical/ointment = 3, /obj/item/healthanalyzer = 3)
|
||||
|
||||
@@ -13,26 +13,28 @@
|
||||
|
||||
/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
|
||||
if(.)
|
||||
return
|
||||
return ..()
|
||||
|
||||
if(charges <= 0)
|
||||
to_chat(user, "The Wish Granter lies silent.")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>The Wish Granter lies silent.</span>")
|
||||
return TRUE
|
||||
|
||||
else if(!ishuman(user))
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
to_chat(user, "<span class='warning'>You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's..</span>")
|
||||
return
|
||||
|
||||
else if(is_special_character(user))
|
||||
to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.")
|
||||
to_chat(user, "<span class='warning'>Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.</span>")
|
||||
|
||||
else if(!insisting)
|
||||
to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?")
|
||||
to_chat(user, "<span class='warning'>Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?</span>")
|
||||
insisting = TRUE
|
||||
|
||||
else
|
||||
to_chat(user, "You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.")
|
||||
to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.")
|
||||
to_chat(user, "<span class='notice'>You speak. [pick("I want the station to disappear", "Humanity is corrupt, mankind must be destroyed", "I want to be rich", "I want to rule the world", "I want immortality.")]. The Wish Granter answers.</span>")
|
||||
to_chat(user, "<span class='notice'>Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.</span>")
|
||||
|
||||
charges--
|
||||
insisting = FALSE
|
||||
@@ -46,37 +48,43 @@
|
||||
var/list/types = list()
|
||||
|
||||
/obj/machinery/wish_granter/super/attack_hand(mob/living/carbon/user)
|
||||
. = ..()
|
||||
|
||||
if(.)
|
||||
return ..()
|
||||
|
||||
if(!ishuman(user))
|
||||
to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.")
|
||||
return
|
||||
else if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, "Syndicate"))
|
||||
to_chat(user, "Something instinctual makes you pull away.")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.</warning>")
|
||||
return TRUE
|
||||
|
||||
if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, "Syndicate"))
|
||||
to_chat(user, "<span class='warning'>Something instinctual makes you pull away.</span>")
|
||||
return TRUE
|
||||
|
||||
to_chat(user, "<span class='notice'>Your touch makes the Wish Granter stir. Are you really sure you want to do this?</span>")
|
||||
|
||||
for(var/supname in GLOB.all_superheroes)
|
||||
types += supname
|
||||
|
||||
var/wish
|
||||
if(types.len == 1)
|
||||
wish = pick(types)
|
||||
else
|
||||
|
||||
to_chat(user, "Your touch makes the Wish Granter stir. Are you really sure you want to do this?")
|
||||
|
||||
for(var/supname in GLOB.all_superheroes)
|
||||
types += supname
|
||||
|
||||
var/wish
|
||||
if(types.len == 1)
|
||||
wish = pick(types)
|
||||
else
|
||||
wish = input("You want to become...","Wish") as null|anything in types
|
||||
wish = input("You want to become...", "Wish") as null|anything in types
|
||||
|
||||
if(!src || !wish || user.stat == DEAD || (get_dist(src, user) > 4)) //another check after the input to check if someone already used it, closed it, or if they're dead, or if they ran off
|
||||
return
|
||||
if(!wish || user.stat == DEAD || (get_dist(src, user) > 4)) // Another check after the input to check if someone already used it, closed it, or if they're dead, or if they ran off.
|
||||
return
|
||||
|
||||
var/datum/superheroes/S = GLOB.all_superheroes[wish]
|
||||
if(S.activated)
|
||||
to_chat(user,"<span class='warning'>There can only be one! Pick something else!</span>")
|
||||
return
|
||||
var/datum/superheroes/S = GLOB.all_superheroes[wish]
|
||||
if(S.activated)
|
||||
to_chat(user,"<span class='warning'>There can only be one! Pick something else!</span>")
|
||||
return
|
||||
|
||||
S.create(user)
|
||||
S.activated = TRUE //sets this superhero as taken so we don't have duplicates
|
||||
playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
|
||||
visible_message("<span class='notice'>The wishgranter fades into mist..</span>")
|
||||
add_attack_logs(null, user, "Became [GLOB.all_superheroes[wish]]")
|
||||
notify_ghosts("[GLOB.all_superheroes[wish]] has appeared in [get_area(user)].", source = user)
|
||||
qdel(src)
|
||||
S.create(user)
|
||||
S.activated = TRUE //sets this superhero as taken so we don't have duplicates
|
||||
|
||||
playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
|
||||
visible_message("<span class='notice'>The wishgranter fades into mist..</span>")
|
||||
add_attack_logs(null, user, "Became [GLOB.all_superheroes[wish]]")
|
||||
notify_ghosts("[GLOB.all_superheroes[wish]] has appeared in [get_area(user)].", source = user)
|
||||
qdel(src)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
infra_luminosity = 15 //byond implementation is bugged.
|
||||
force = 5
|
||||
armor = list(melee = 20, bullet = 10, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming.
|
||||
var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
|
||||
var/can_move = 0 // time of next allowed movement
|
||||
var/mob/living/carbon/occupant = null
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
|
||||
/obj/mecha/working/New()
|
||||
..()
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
if(!ruin_mecha)
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
|
||||
@@ -88,7 +88,7 @@ var/global/list/image/splatter_cache = list()
|
||||
return TRUE
|
||||
|
||||
//Add "bloodiness" of this blood's type, to the human's shoes
|
||||
/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O)
|
||||
/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O, oldloc)
|
||||
if(!off_floor && ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
|
||||
|
||||
@@ -29,7 +29,7 @@ var/global/list/image/fluidtrack_cache = list()
|
||||
blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
|
||||
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O, oldloc)
|
||||
if(ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
|
||||
@@ -345,7 +345,7 @@ steam.start() -- spawns the effect
|
||||
return 1
|
||||
|
||||
|
||||
/obj/effect/effect/bad_smoke/Crossed(mob/living/carbon/M as mob )
|
||||
/obj/effect/effect/bad_smoke/Crossed(mob/living/carbon/M as mob, oldloc)
|
||||
..()
|
||||
if(istype(M, /mob/living/carbon))
|
||||
if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT))
|
||||
@@ -569,7 +569,7 @@ steam.start() -- spawns the effect
|
||||
M.coughedtime = 0
|
||||
return
|
||||
|
||||
/obj/effect/effect/sleep_smoke/Crossed(mob/living/carbon/M as mob )
|
||||
/obj/effect/effect/sleep_smoke/Crossed(mob/living/carbon/M as mob, oldloc)
|
||||
..()
|
||||
if(istype(M, /mob/living/carbon))
|
||||
if(M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT))
|
||||
@@ -672,7 +672,7 @@ steam.start() -- spawns the effect
|
||||
R.updatehealth()
|
||||
return
|
||||
|
||||
/obj/effect/effect/mustard_gas/Crossed(mob/living/carbon/human/R as mob )
|
||||
/obj/effect/effect/mustard_gas/Crossed(mob/living/carbon/human/R as mob, oldloc)
|
||||
..()
|
||||
if(istype(R, /mob/living/carbon/human))
|
||||
if(R.internal != null && usr.wear_mask && (R.wear_mask.flags & AIRTIGHT) && R.wear_suit != null && !istype(R.wear_suit, /obj/item/clothing/suit/storage/labcoat) && !istype(R.wear_suit, /obj/item/clothing/suit/straight_jacket) && !istype(R.wear_suit, /obj/item/clothing/suit/straight_jacket && !istype(R.wear_suit, /obj/item/clothing/suit/armor)))
|
||||
@@ -984,7 +984,7 @@ steam.start() -- spawns the effect
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/structure/foam/Crossed(var/atom/movable/AM)
|
||||
/obj/structure/foam/Crossed(var/atom/movable/AM, oldloc)
|
||||
if(metal)
|
||||
return
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
spawn(5)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/particle_effect/foam/Crossed(atom/movable/AM)
|
||||
/obj/effect/particle_effect/foam/Crossed(atom/movable/AM, oldloc)
|
||||
if(metal)
|
||||
return
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
steps--
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/Crossed(mob/living/M)
|
||||
/obj/effect/particle_effect/smoke/Crossed(mob/living/M, oldloc)
|
||||
if(!istype(M))
|
||||
return
|
||||
smoke_mob(M)
|
||||
@@ -207,4 +207,4 @@
|
||||
return 1
|
||||
|
||||
/datum/effect_system/smoke_spread/sleeping
|
||||
effect_type = /obj/effect/particle_effect/smoke/sleeping
|
||||
effect_type = /obj/effect/particle_effect/smoke/sleeping
|
||||
|
||||
@@ -67,6 +67,23 @@
|
||||
/obj/effect/mapping_helpers/no_lava
|
||||
icon_state = "no_lava"
|
||||
|
||||
/obj/effect/mapping_helpers/airlock
|
||||
layer = DOOR_HELPER_LAYER
|
||||
|
||||
/obj/effect/mapping_helpers/airlock/unres
|
||||
name = "airlock unresctricted side helper"
|
||||
icon_state = "airlock_unres_helper"
|
||||
|
||||
/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
|
||||
if(!mapload)
|
||||
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
||||
return
|
||||
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in src.loc
|
||||
if(airlock)
|
||||
airlock.unres_sides ^= dir
|
||||
else
|
||||
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
||||
..()
|
||||
/obj/effect/mapping_helpers/no_lava/New()
|
||||
var/turf/T = get_turf(src)
|
||||
T.flags |= NO_LAVA_GEN
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/obj/effect/mine/proc/mineEffect(mob/living/victim)
|
||||
to_chat(victim, "<span class='danger'>*click*</span>")
|
||||
|
||||
/obj/effect/mine/Crossed(AM as mob|obj)
|
||||
/obj/effect/mine/Crossed(AM as mob|obj, oldloc)
|
||||
if(!isliving(AM))
|
||||
return
|
||||
var/mob/living/M = AM
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
desc = "Looks unstable. Best to test it with the clown."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "portal"
|
||||
density = TRUE
|
||||
unacidable = TRUE
|
||||
anchored = TRUE
|
||||
|
||||
@@ -17,9 +16,6 @@
|
||||
var/can_multitool_to_remove = FALSE
|
||||
var/ignore_tele_proof_area_setting = FALSE
|
||||
|
||||
/obj/effect/portal/Bumped(mob/M as mob|obj)
|
||||
teleport(M)
|
||||
|
||||
/obj/effect/portal/New(loc, turf/target, creator = null, lifespan = 300)
|
||||
..()
|
||||
|
||||
@@ -49,10 +45,13 @@
|
||||
/obj/effect/portal/singularity_act()
|
||||
return
|
||||
|
||||
/obj/effect/portal/Crossed(atom/movable/AM)
|
||||
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
|
||||
if(isobserver(AM))
|
||||
return ..()
|
||||
|
||||
if(target && (get_turf(oldloc) == get_turf(target)))
|
||||
return ..()
|
||||
|
||||
if(!teleport(AM))
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
Spawners for mappers. Just plonk one down of the desired size and it will place the machinery for you. The red arrow things indicate where the chamber is.
|
||||
This spawner places pipe leading up to the interior door, you will need to finish it off yourself with a connector, canister, and pipe connecting the two. It also assumes you already put in wall and floor.
|
||||
*/
|
||||
|
||||
#define HALF_X round((tiles_in_x_direction - 1) * 0.5) //These are required so that the airlock can be in the middle of the chamber wall
|
||||
#define HALF_Y round((tiles_in_y_direction - 1) * 0.5)
|
||||
#define CHAMBER_LONG 1
|
||||
#define CHAMBER_SQUARE 2
|
||||
#define CHAMBER_BIGGER 3
|
||||
#define DOOR_NORMAL_PLACEMENT 1
|
||||
#define DOOR_FLIPPED_PLACEMENT 2
|
||||
|
||||
#define AIRPUMP_TAG "[id_to_link]_pump"
|
||||
#define SENSOR_TAG "[id_to_link]_sensor"
|
||||
#define OUTER_DOOR_TAG "[id_to_link]_outer"
|
||||
#define INNER_DOOR_TAG "[id_to_link]_inner"
|
||||
|
||||
/obj/effect/spawner/airlock
|
||||
name = "1 by 1 airlock spawner (interior north, exterior south)"
|
||||
desc = "If you can see this, there's probably a missing airlock here. Better tell an admin and report this on the github."
|
||||
icon = 'icons/obj/airlock_spawner.dmi'
|
||||
icon_state = "1x1_N_to_S"
|
||||
layer = SPLASHSCREEN_PLANE //So we absolutely always appear above everything else. We delete ourself after spawning so this is fine
|
||||
var/interior_direction = NORTH //This is also the direction the spawner will send the pipe
|
||||
var/exterior_direction = SOUTH
|
||||
var/opposite_interior_direction //We're checking these often enough for them to merit their own vars
|
||||
var/interior_direction_cw
|
||||
var/interior_direction_ccw
|
||||
var/north_or_south_interior //Used a bit everywhere for locational stuff
|
||||
var/north_or_south_exterior //Likewise
|
||||
var/tiles_in_x_direction = 1
|
||||
var/tiles_in_y_direction = 1
|
||||
var/id_to_link
|
||||
var/radio_frequency = 1379
|
||||
var/required_access = list(access_external_airlocks)
|
||||
var/door_name = "external access"
|
||||
var/door_type = /obj/machinery/door/airlock/external/glass
|
||||
var/one_door_interior //For square airlocks, if you set this then a) only one door will spawn, and b) you can choose if the door should go opposite to how it normally goes. Please use the define
|
||||
var/one_door_exterior //See above
|
||||
|
||||
/obj/effect/spawner/airlock/Initialize()
|
||||
..()
|
||||
forceMove(locate(x + 1, y + 1, z)) //Needs to move because our icon_state implies we are one turf to the northeast, when we're not
|
||||
opposite_interior_direction = turn(interior_direction, 180) //Do it this way (instead of setting it directly) to avoid code mishaps
|
||||
interior_direction_cw = turn(interior_direction, 90)
|
||||
interior_direction_ccw = turn(interior_direction, 270)
|
||||
if(interior_direction == NORTH || interior_direction == SOUTH)
|
||||
north_or_south_interior = TRUE
|
||||
if(exterior_direction == NORTH || exterior_direction == SOUTH)
|
||||
north_or_south_exterior = TRUE
|
||||
id_to_link = "[UID()]" //We want unique IDs, this will give us a unique ID
|
||||
var/turf/turf_interior = get_airlock_location(interior_direction)
|
||||
var/turf/turf_exterior = get_airlock_location(exterior_direction)
|
||||
handle_door_creation(turf_interior, TRUE, one_door_interior)
|
||||
handle_door_creation(turf_exterior, FALSE, one_door_exterior)
|
||||
handle_pipes_creation(turf_interior)
|
||||
handle_control_placement()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spawner/airlock/proc/get_airlock_location(desired_direction) //Finds a turf to place an airlock and returns it, this turf will be in the middle of the relevant wall
|
||||
var/turf/T
|
||||
switch(desired_direction)
|
||||
if(NORTH)
|
||||
T = locate(x + HALF_X, y + tiles_in_y_direction, z)
|
||||
if(SOUTH)
|
||||
T = locate(x + HALF_X, y - 1, z)
|
||||
if(EAST)
|
||||
T = locate(x + tiles_in_x_direction, y + HALF_Y, z)
|
||||
if(WEST)
|
||||
T = locate(x - 1, y + HALF_Y, z)
|
||||
return T
|
||||
|
||||
/obj/effect/spawner/airlock/proc/handle_door_creation(turf/T, is_this_an_interior_airlock, one_door_only) //Creates a door (or two) and also creates a button
|
||||
var/obj/machinery/door/airlock/A
|
||||
if(one_door_only != DOOR_FLIPPED_PLACEMENT)
|
||||
A = new door_type(T)
|
||||
handle_door_stuff(A, is_this_an_interior_airlock)
|
||||
var/obj/machinery/access_button/the_button = spawn_button(T, is_this_an_interior_airlock ? interior_direction : exterior_direction)
|
||||
if(one_door_only == DOOR_NORMAL_PLACEMENT) //We only need one door, we are done
|
||||
return
|
||||
if(!(tiles_in_x_direction % 2) && (is_this_an_interior_airlock && north_or_south_interior || !is_this_an_interior_airlock && north_or_south_exterior)) //Handle extra airlock for aesthetics
|
||||
A = new door_type(get_step(T, EAST))
|
||||
handle_door_stuff(A, is_this_an_interior_airlock)
|
||||
if(one_door_only == DOOR_FLIPPED_PLACEMENT)
|
||||
the_button.forceMove(get_step(the_button, EAST))
|
||||
else if(!(tiles_in_y_direction % 2) && (is_this_an_interior_airlock && !north_or_south_interior || !is_this_an_interior_airlock && !north_or_south_exterior)) //Handle extra airlock for aesthetics
|
||||
A = new door_type(get_step(T, NORTH))
|
||||
handle_door_stuff(A, is_this_an_interior_airlock)
|
||||
if(one_door_only == DOOR_FLIPPED_PLACEMENT)
|
||||
the_button.forceMove(get_step(the_button, NORTH))
|
||||
|
||||
/obj/effect/spawner/airlock/proc/handle_door_stuff(obj/machinery/door/airlock/A, is_this_an_interior_airlock) //This sets up the door vars correctly and then locks it before first use
|
||||
A.set_frequency(radio_frequency)
|
||||
A.id_tag = is_this_an_interior_airlock ? INNER_DOOR_TAG : OUTER_DOOR_TAG
|
||||
A.req_access = required_access
|
||||
A.name = door_name
|
||||
A.lock()
|
||||
|
||||
/obj/effect/spawner/airlock/proc/spawn_button(turf/T, some_direction)
|
||||
var/obj/machinery/access_button/the_button = new(T)
|
||||
the_button.master_tag = id_to_link
|
||||
the_button.set_frequency(radio_frequency)
|
||||
switch(some_direction)
|
||||
if(NORTH)
|
||||
the_button.pixel_x -= 25
|
||||
the_button.pixel_y = 7
|
||||
if(EAST)
|
||||
the_button.pixel_x = 7
|
||||
the_button.pixel_y = -25
|
||||
if(SOUTH)
|
||||
the_button.pixel_x -= 25
|
||||
the_button.pixel_y -= 7
|
||||
if(WEST)
|
||||
the_button.pixel_x -= 7
|
||||
the_button.pixel_y -= 25
|
||||
the_button.req_access = required_access
|
||||
return the_button
|
||||
|
||||
/obj/effect/spawner/airlock/proc/handle_control_placement() //Stick the sensor and controller on the same bit of wall, this will ONLY be unsuitable if airlocks are on both the south and west turfs
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/machinery/airlock_sensor/AS = new(T)
|
||||
var/obj/machinery/embedded_controller/radio/airlock/airlock_controller/AC = new(T, id_to_link, radio_frequency, OUTER_DOOR_TAG, INNER_DOOR_TAG, AIRPUMP_TAG, SENSOR_TAG)
|
||||
AC.req_access = required_access
|
||||
AS.id_tag = SENSOR_TAG
|
||||
AS.set_frequency(radio_frequency)
|
||||
if(interior_direction != WEST && exterior_direction != WEST) //If west wall is free, place stuff there
|
||||
AC.pixel_x -= 25
|
||||
AC.pixel_y += 9
|
||||
AS.pixel_x -= 25
|
||||
AS.pixel_y -= 9
|
||||
else if(interior_direction != SOUTH && exterior_direction != SOUTH) //If south wall is free, place stuff there
|
||||
AC.pixel_x += 9
|
||||
AC.pixel_y -= 25
|
||||
AS.pixel_x -= 9
|
||||
AS.pixel_y -= 25
|
||||
else //Send them over to the other side of the chamber
|
||||
T = locate(x + tiles_in_x_direction - 1, y + tiles_in_y_direction - 1, z)
|
||||
AC.forceMove(T)
|
||||
AS.forceMove(T)
|
||||
AC.pixel_x += 25
|
||||
AC.pixel_y += 9
|
||||
AS.pixel_x += 25
|
||||
AS.pixel_y -= 9
|
||||
|
||||
/obj/effect/spawner/airlock/proc/handle_pipes_creation(turf/T) //This places all required piping down, then properly initializes it. T is the turf that the interior airlock occupies
|
||||
var/turf/below_T = get_step(T, opposite_interior_direction)
|
||||
|
||||
var/two_way_pipe = interior_direction | opposite_interior_direction
|
||||
var/chamber_shape //This determines the layout of the chamber and therefore how many vents should be present
|
||||
if(tiles_in_x_direction == 2 && tiles_in_y_direction == 2)
|
||||
chamber_shape = CHAMBER_SQUARE
|
||||
else if(tiles_in_x_direction > 1 && tiles_in_y_direction > 1)
|
||||
chamber_shape = CHAMBER_BIGGER
|
||||
else
|
||||
chamber_shape = CHAMBER_LONG
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/pipe/simple/visible, T, interior_direction, two_way_pipe)
|
||||
switch(chamber_shape)
|
||||
if(CHAMBER_LONG) //Easy enough, place a single vent
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
|
||||
below_T,
|
||||
interior_direction)
|
||||
if(CHAMBER_SQUARE) //We need a T-manifold and two vents for this
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold/visible,
|
||||
below_T,
|
||||
north_or_south_interior ? WEST : SOUTH,
|
||||
NORTH | EAST | (north_or_south_interior ? SOUTH : WEST))
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
|
||||
get_step(below_T, opposite_interior_direction),
|
||||
interior_direction)
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
|
||||
north_or_south_interior ? EAST_OF_TURF(below_T) : NORTH_OF_TURF(below_T),
|
||||
turn(interior_direction, interior_direction == SOUTH || interior_direction == EAST ? -90 : 90))
|
||||
if(CHAMBER_BIGGER) //We need a central column of manifolds and a vent either side of each manifold
|
||||
var/depth = north_or_south_interior ? tiles_in_y_direction : tiles_in_x_direction
|
||||
var/turf/put_thing_here = below_T
|
||||
for(var/i in 1 to depth)
|
||||
if(i != depth)//We're placing more pipe later, so we need a 4-way manifold
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold4w/visible, put_thing_here, interior_direction, NORTH | EAST | SOUTH | WEST)
|
||||
else //We stop here, so place a T-manifold down
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/pipe/manifold/visible,
|
||||
put_thing_here,
|
||||
opposite_interior_direction,
|
||||
interior_direction_cw | interior_direction | interior_direction_ccw)
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
|
||||
get_step(put_thing_here, interior_direction_cw),
|
||||
interior_direction_ccw)
|
||||
pipe_creation_helper(/obj/machinery/atmospherics/unary/vent_pump/high_volume,
|
||||
get_step(put_thing_here, interior_direction_ccw),
|
||||
interior_direction_cw)
|
||||
put_thing_here = get_step(put_thing_here, opposite_interior_direction) //Now move the turf we're generating stuff from 1 forward
|
||||
|
||||
/obj/effect/spawner/airlock/proc/pipe_creation_helper(path, location, direction, initialization_directions) //Create some kind of atmospherics machinery and initialize it properly
|
||||
var/obj/machinery/atmospherics/A = new path(location)
|
||||
A.dir = direction
|
||||
A.on_construction(A.dir, initialization_directions ? initialization_directions : A.dir)
|
||||
if(istype(A, /obj/machinery/atmospherics/unary/vent_pump/high_volume))
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/high_volume/created_pump = A
|
||||
created_pump.id_tag = AIRPUMP_TAG
|
||||
created_pump.set_frequency(radio_frequency)
|
||||
|
||||
|
||||
//Premade airlocks for mappers, probably won't need all of these but whatever
|
||||
/obj/effect/spawner/airlock/s_to_n
|
||||
name = "1 by 1 airlock spawner (interior south, exterior north)"
|
||||
icon_state = "1x1_S_to_N"
|
||||
interior_direction = SOUTH
|
||||
exterior_direction = NORTH
|
||||
/obj/effect/spawner/airlock/e_to_w
|
||||
name = "1 by 1 airlock spawner (interior east, exterior west)"
|
||||
icon_state = "1x1_E_to_W"
|
||||
interior_direction = EAST
|
||||
exterior_direction = WEST
|
||||
/obj/effect/spawner/airlock/w_to_e
|
||||
name = "1 by 1 airlock spawner (interior west, exterior east)"
|
||||
icon_state = "1x1_W_to_E"
|
||||
interior_direction = WEST
|
||||
exterior_direction = EAST
|
||||
|
||||
/obj/effect/spawner/airlock/long //Long and thin
|
||||
name = "long airlock spawner (interior north, exterior south)"
|
||||
icon_state = "1x2_N_to_S"
|
||||
tiles_in_y_direction = 2
|
||||
/obj/effect/spawner/airlock/s_to_n/long
|
||||
name = "long airlock spawner (interior south, exterior north)"
|
||||
icon_state = "1x2_S_to_N"
|
||||
tiles_in_y_direction = 2
|
||||
/obj/effect/spawner/airlock/e_to_w/long
|
||||
name = "long airlock spawner (interior east, exterior west)"
|
||||
icon_state = "1x2_E_to_W"
|
||||
tiles_in_x_direction = 2
|
||||
/obj/effect/spawner/airlock/w_to_e/long
|
||||
name = "long airlock spawner (interior west, exterior east)"
|
||||
icon_state = "1x2_W_to_E"
|
||||
tiles_in_x_direction = 2
|
||||
|
||||
/obj/effect/spawner/airlock/long/square //Square
|
||||
name = "square airlock spawner (interior north, exterior south)"
|
||||
icon_state = "2x2_N_to_S"
|
||||
tiles_in_x_direction = 2
|
||||
/obj/effect/spawner/airlock/s_to_n/long/square
|
||||
name = "square airlock spawner (interior south, exterior north)"
|
||||
icon_state = "2x2_S_to_N"
|
||||
tiles_in_x_direction = 2
|
||||
/obj/effect/spawner/airlock/e_to_w/long/square
|
||||
name = "square airlock spawner (interior east, exterior west)"
|
||||
icon_state = "2x2_E_to_W"
|
||||
tiles_in_y_direction = 2
|
||||
/obj/effect/spawner/airlock/w_to_e/long/square
|
||||
name = "square airlock spawner (interior west, exterior east)"
|
||||
icon_state = "2x2_W_to_E"
|
||||
tiles_in_y_direction = 2
|
||||
/obj/effect/spawner/airlock/long/square/e_to_s
|
||||
name = "square airlock spawner (interior east, exterior south)"
|
||||
icon_state = "2x2_E_to_S"
|
||||
interior_direction = EAST
|
||||
exterior_direction = SOUTH
|
||||
|
||||
/obj/effect/spawner/airlock/long/square/wide
|
||||
name = "rectangular airlock spawner (interior north, exterior south)"
|
||||
icon_state = "3x2_N_to_S"
|
||||
tiles_in_x_direction = 3
|
||||
/obj/effect/spawner/airlock/s_to_n/long/square/wide
|
||||
name = "rectangular airlock spawner (interior south, exterior north)"
|
||||
icon_state = "3x2_S_to_N"
|
||||
tiles_in_x_direction = 3
|
||||
/obj/effect/spawner/airlock/e_to_w/long/square/wide
|
||||
name = "rectangular airlock spawner (interior east, exterior west)"
|
||||
icon_state = "3x2_E_to_W"
|
||||
tiles_in_y_direction = 3
|
||||
/obj/effect/spawner/airlock/w_to_e/long/square/wide
|
||||
name = "rectangular airlock spawner (interior west, exterior east)"
|
||||
icon_state = "3x2_W_to_E"
|
||||
tiles_in_y_direction = 3
|
||||
|
||||
/obj/effect/spawner/airlock/long/square/three
|
||||
name = "3 by 3 square airlock spawner (interior north, exterior south)"
|
||||
icon_state = "3x3_N_to_S"
|
||||
interior_direction = NORTH
|
||||
exterior_direction = SOUTH
|
||||
tiles_in_x_direction = 3
|
||||
tiles_in_y_direction = 3
|
||||
|
||||
/obj/effect/spawner/airlock/e_to_w/arrivals
|
||||
required_access = null
|
||||
|
||||
/obj/effect/spawner/airlock/engineer
|
||||
required_access = list(access_engine)
|
||||
door_name = "engineering external access"
|
||||
/obj/effect/spawner/airlock/e_to_w/engineer
|
||||
required_access = list(access_engine)
|
||||
door_name = "engineering external access"
|
||||
/obj/effect/spawner/airlock/s_to_n/engineer
|
||||
required_access = list(access_engine)
|
||||
door_name = "engineering external access"
|
||||
/obj/effect/spawner/airlock/long/engineer
|
||||
required_access = list(access_engine)
|
||||
door_name = "engineering external access"
|
||||
/obj/effect/spawner/airlock/long/square/engine
|
||||
required_access = list(access_engine)
|
||||
door_name = "engine external access"
|
||||
icon_state = "2x2_N_to_S_leftdoors"
|
||||
door_type = /obj/machinery/door/airlock/external
|
||||
one_door_interior = DOOR_NORMAL_PLACEMENT
|
||||
one_door_exterior = DOOR_NORMAL_PLACEMENT
|
||||
/obj/effect/spawner/airlock/long/square/engine/reversed
|
||||
icon_state = "2x2_N_to_S_rightdoors"
|
||||
one_door_interior = DOOR_FLIPPED_PLACEMENT
|
||||
one_door_exterior = DOOR_FLIPPED_PLACEMENT
|
||||
|
||||
/obj/effect/spawner/airlock/w_to_e/long/square/wide/mining
|
||||
door_name = "mining external access"
|
||||
required_access = list(access_mining)
|
||||
/obj/effect/spawner/airlock/long/square/wide/mining
|
||||
door_name = "mining external access"
|
||||
required_access = list(access_mining)
|
||||
|
||||
/obj/effect/spawner/airlock/e_to_w/minisat
|
||||
door_name = "minisat external access"
|
||||
required_access = list(access_minisat)
|
||||
/obj/effect/spawner/airlock/long/square/e_to_s/telecoms
|
||||
door_name = "telecoms external access"
|
||||
required_access = list(access_tcomsat, access_external_airlocks)
|
||||
door_type = /obj/machinery/door/airlock/external
|
||||
|
||||
/obj/effect/spawner/airlock/long/square/three/syndicate
|
||||
name = "3 by 3 square airlock spawner (interior west, exterior north)"
|
||||
icon_state = "3x3_W_to_N"
|
||||
interior_direction = WEST
|
||||
exterior_direction = NORTH
|
||||
door_name = "ship external access"
|
||||
req_access = list(access_syndicate)
|
||||
door_type = /obj/machinery/door/airlock/external
|
||||
|
||||
#undef HALF_X
|
||||
#undef HALF_Y
|
||||
#undef CHAMBER_LONG
|
||||
#undef CHAMBER_SQUARE
|
||||
#undef CHAMBER_BIGGER
|
||||
#undef DOOR_NORMAL_PLACEMENT
|
||||
#undef DOOR_FLIPPED_PLACEMENT
|
||||
#undef AIRPUMP_TAG
|
||||
#undef SENSOR_TAG
|
||||
#undef OUTER_DOOR_TAG
|
||||
#undef INNER_DOOR_TAG
|
||||
@@ -1,23 +1,43 @@
|
||||
/* Simple object type, calls a proc when "stepped" on by something */
|
||||
|
||||
/obj/effect/step_trigger
|
||||
var/affect_ghosts = 0
|
||||
var/stopper = 1 // stops throwers
|
||||
invisibility = 101 // nope cant see this shit
|
||||
anchored = 1
|
||||
var/affect_ghosts = FALSE
|
||||
var/stopper = TRUE // stops throwers
|
||||
var/mobs_only = FALSE
|
||||
invisibility = INVISIBILITY_ABSTRACT // nope cant see this shit
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/step_trigger/proc/Trigger(var/atom/movable/A)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/obj/effect/step_trigger/Crossed(H as mob|obj)
|
||||
..()
|
||||
/obj/effect/step_trigger/Crossed(var/H, oldloc)
|
||||
. = ..()
|
||||
if(!H)
|
||||
return
|
||||
if(istype(H, /mob/dead/observer) && !affect_ghosts)
|
||||
if(isobserver(H) && !affect_ghosts)
|
||||
return
|
||||
if(!ismob(H) && mobs_only)
|
||||
return
|
||||
Trigger(H)
|
||||
|
||||
/obj/effect/step_trigger/singularity_act()
|
||||
return
|
||||
|
||||
/obj/effect/step_trigger/singularity_pull()
|
||||
return
|
||||
|
||||
/* Sends a message to mob when triggered*/
|
||||
|
||||
/obj/effect/step_trigger/message
|
||||
var/message //the message to give to the mob
|
||||
var/once = 1
|
||||
mobs_only = TRUE
|
||||
|
||||
/obj/effect/step_trigger/message/Trigger(mob/M)
|
||||
if(M.client)
|
||||
to_chat(M, "<span class='info'>[message]</span>")
|
||||
if(once)
|
||||
qdel(src)
|
||||
|
||||
/* Tosses things in a certain direction */
|
||||
|
||||
@@ -30,57 +50,57 @@
|
||||
var/nostop = 0 // if 1: will only be stopped by teleporters
|
||||
var/list/affecting = list()
|
||||
|
||||
Trigger(var/atom/A)
|
||||
if(!A || !istype(A, /atom/movable))
|
||||
/obj/effect/step_trigger/thrower/Trigger(atom/A)
|
||||
if(!A || !ismovableatom(A))
|
||||
return
|
||||
var/atom/movable/AM = A
|
||||
var/curtiles = 0
|
||||
var/stopthrow = 0
|
||||
for(var/obj/effect/step_trigger/thrower/T in orange(2, src))
|
||||
if(AM in T.affecting)
|
||||
return
|
||||
var/atom/movable/AM = A
|
||||
var/curtiles = 0
|
||||
var/stopthrow = 0
|
||||
for(var/obj/effect/step_trigger/thrower/T in orange(2, src))
|
||||
if(AM in T.affecting)
|
||||
return
|
||||
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(immobilize)
|
||||
M.canmove = 0
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
if(immobilize)
|
||||
M.canmove = FALSE
|
||||
|
||||
affecting.Add(AM)
|
||||
while(AM && !stopthrow)
|
||||
if(tiles)
|
||||
if(curtiles >= tiles)
|
||||
break
|
||||
if(AM.z != src.z)
|
||||
affecting.Add(AM)
|
||||
while(AM && !stopthrow)
|
||||
if(tiles)
|
||||
if(curtiles >= tiles)
|
||||
break
|
||||
if(AM.z != src.z)
|
||||
break
|
||||
|
||||
curtiles++
|
||||
curtiles++
|
||||
|
||||
sleep(speed)
|
||||
sleep(speed)
|
||||
|
||||
// Calculate if we should stop the process
|
||||
if(!nostop)
|
||||
for(var/obj/effect/step_trigger/T in get_step(AM, direction))
|
||||
if(T.stopper && T != src)
|
||||
stopthrow = 1
|
||||
else
|
||||
for(var/obj/effect/step_trigger/teleporter/T in get_step(AM, direction))
|
||||
if(T.stopper)
|
||||
stopthrow = 1
|
||||
// Calculate if we should stop the process
|
||||
if(!nostop)
|
||||
for(var/obj/effect/step_trigger/T in get_step(AM, direction))
|
||||
if(T.stopper && T != src)
|
||||
stopthrow = 1
|
||||
else
|
||||
for(var/obj/effect/step_trigger/teleporter/T in get_step(AM, direction))
|
||||
if(T.stopper)
|
||||
stopthrow = 1
|
||||
|
||||
if(AM)
|
||||
var/predir = AM.dir
|
||||
step(AM, direction)
|
||||
if(!facedir)
|
||||
AM.dir = predir
|
||||
if(AM)
|
||||
var/predir = AM.dir
|
||||
step(AM, direction)
|
||||
if(!facedir)
|
||||
AM.setDir(predir)
|
||||
|
||||
|
||||
|
||||
affecting.Remove(AM)
|
||||
affecting.Remove(AM)
|
||||
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(immobilize)
|
||||
M.canmove = 1
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
if(immobilize)
|
||||
M.canmove = TRUE
|
||||
|
||||
/* Stops things thrown by a thrower, doesn't do anything */
|
||||
|
||||
@@ -93,12 +113,11 @@
|
||||
var/teleport_y = 0
|
||||
var/teleport_z = 0
|
||||
|
||||
Trigger(var/atom/movable/A)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
/obj/effect/step_trigger/teleporter/Trigger(atom/movable/A)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
|
||||
A.x = teleport_x
|
||||
A.y = teleport_y
|
||||
A.z = teleport_z
|
||||
var/turf/T = locate(teleport_x, teleport_y, teleport_z)
|
||||
A.forceMove(T)
|
||||
|
||||
/* Random teleporter, teleports atoms to locations ranging from teleport_x - teleport_x_offset, etc */
|
||||
|
||||
@@ -107,11 +126,73 @@
|
||||
var/teleport_y_offset = 0
|
||||
var/teleport_z_offset = 0
|
||||
|
||||
Trigger(var/atom/movable/A)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
if(teleport_x_offset && teleport_y_offset && teleport_z_offset)
|
||||
/obj/effect/step_trigger/teleporter/random/Trigger(atom/movable/A)
|
||||
if(teleport_x && teleport_y && teleport_z)
|
||||
if(teleport_x_offset && teleport_y_offset && teleport_z_offset)
|
||||
|
||||
A.x = rand(teleport_x, teleport_x_offset)
|
||||
A.y = rand(teleport_y, teleport_y_offset)
|
||||
A.z = rand(teleport_z, teleport_z_offset)
|
||||
var/turf/T = locate(rand(teleport_x, teleport_x_offset), rand(teleport_y, teleport_y_offset), rand(teleport_z, teleport_z_offset))
|
||||
if (T)
|
||||
A.forceMove(T)
|
||||
|
||||
/* Fancy teleporter, creates sparks and smokes when used */
|
||||
|
||||
/obj/effect/step_trigger/teleport_fancy
|
||||
var/locationx
|
||||
var/locationy
|
||||
var/uses = 1 //0 for infinite uses
|
||||
var/entersparks = 0
|
||||
var/exitsparks = 0
|
||||
var/entersmoke = 0
|
||||
var/exitsmoke = 0
|
||||
|
||||
/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M)
|
||||
var/dest = locate(locationx, locationy, z)
|
||||
M.Move(dest)
|
||||
|
||||
if(entersparks)
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(4, 1, src)
|
||||
s.start()
|
||||
if(exitsparks)
|
||||
var/datum/effect_system/spark_spread/s = new
|
||||
s.set_up(4, 1, dest)
|
||||
s.start()
|
||||
|
||||
if(entersmoke)
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(4, 1, src, 0)
|
||||
s.start()
|
||||
if(exitsmoke)
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(4, 1, dest, 0)
|
||||
s.start()
|
||||
|
||||
uses--
|
||||
if(uses == 0)
|
||||
qdel(src)
|
||||
|
||||
/* Simple sound player, Mapper friendly! */
|
||||
|
||||
/obj/effect/step_trigger/sound_effect
|
||||
var/sound //eg. path to the sound, inside '' eg: 'growl.ogg'
|
||||
var/volume = 100
|
||||
var/freq_vary = 1 //Should the frequency of the sound vary?
|
||||
var/extra_range = 0 // eg World.view = 7, extra_range = 1, 7+1 = 8, 8 turfs radius
|
||||
var/happens_once = 0
|
||||
var/triggerer_only = 0 //Whether the triggerer is the only person who hears this
|
||||
|
||||
|
||||
/obj/effect/step_trigger/sound_effect/Trigger(atom/movable/A)
|
||||
var/turf/T = get_turf(A)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
if(triggerer_only && ismob(A))
|
||||
var/mob/B = A
|
||||
B.playsound_local(T, sound, volume, freq_vary)
|
||||
else
|
||||
playsound(T, sound, volume, freq_vary, extra_range)
|
||||
|
||||
if(happens_once)
|
||||
qdel(src)
|
||||
@@ -6,6 +6,10 @@
|
||||
randomdir = 0
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/door
|
||||
icon_state = "ratvardoorglow"
|
||||
layer = CLOSED_DOOR_LAYER //above closed doors
|
||||
|
||||
/obj/effect/temp_visual/ratvar/door/window
|
||||
icon_state = "ratvarwindoorglow"
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
@@ -16,9 +20,27 @@
|
||||
/obj/effect/temp_visual/ratvar/beam/grille
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/beam/itemconsume
|
||||
layer = HIGH_OBJ_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/beam/falsewall
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/beam/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/wall
|
||||
icon_state = "ratvarwallglow"
|
||||
|
||||
/obj/effect/temp_visual/ratvar/wall/false
|
||||
layer = OBJ_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/floor
|
||||
icon_state = "ratvarfloorglow"
|
||||
|
||||
/obj/effect/temp_visual/ratvar/floor/catwalk
|
||||
layer = LATTICE_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/window
|
||||
icon_state = "ratvarwindowglow"
|
||||
layer = ABOVE_OBJ_LAYER
|
||||
@@ -26,6 +48,10 @@
|
||||
/obj/effect/temp_visual/ratvar/window/single
|
||||
icon_state = "ratvarwindowglow_s"
|
||||
|
||||
/obj/effect/temp_visual/ratvar/gear
|
||||
icon_state = "ratvargearglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
/obj/effect/temp_visual/ratvar/grille
|
||||
icon_state = "ratvargrilleglow"
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
@@ -578,7 +578,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
|
||||
/obj/item/proc/is_equivalent(obj/item/I)
|
||||
return I == src
|
||||
|
||||
/obj/item/Crossed(atom/movable/AM)
|
||||
/obj/item/Crossed(atom/movable/AM, oldloc)
|
||||
. = ..()
|
||||
if(prob(trip_chance) && ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
/obj/item/storage/pill_bottle/happy
|
||||
name = "Happy pills"
|
||||
desc = "Highly illegal drug. When you want to see the rainbow."
|
||||
wrapper_color = COLOR_PINK
|
||||
|
||||
/obj/item/storage/pill_bottle/happy/New()
|
||||
..()
|
||||
@@ -18,6 +19,7 @@
|
||||
/obj/item/storage/pill_bottle/zoom
|
||||
name = "Zoom pills"
|
||||
desc = "Highly illegal drug. Trade brain for speed."
|
||||
wrapper_color = COLOR_BLUE
|
||||
|
||||
/obj/item/storage/pill_bottle/zoom/New()
|
||||
..()
|
||||
@@ -49,15 +51,12 @@
|
||||
adulterants--
|
||||
reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_adulterants"), 3)
|
||||
|
||||
|
||||
|
||||
/obj/item/storage/pill_bottle/random_drug_bottle
|
||||
name = "pill bottle (???)"
|
||||
desc = "Huh."
|
||||
allow_wrap = FALSE
|
||||
|
||||
/obj/item/storage/pill_bottle/random_drug_bottle/New()
|
||||
..()
|
||||
for(var/i in 1 to 5)
|
||||
new /obj/item/reagent_containers/food/pill/random_drugs(src)
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
to_chat(user, "<span class='danger'>[D]'s ID scan is disabled!</span>")
|
||||
return
|
||||
if(D.check_access(src.ID))
|
||||
D.add_hiddenprint(user)
|
||||
switch(mode)
|
||||
if(WAND_OPEN)
|
||||
if(D.density)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
/obj/item/voice_changer/proc/set_voice(mob/user)
|
||||
var/chosen_voice = input(user, "What voice would you like to mimic? Leave this empty to use the voice on your ID card.", "Set Voice Changer", voice) as text
|
||||
var/chosen_voice = clean_input("What voice would you like to mimic? Leave this empty to use the voice on your ID card.", "Set Voice Changer", voice, user)
|
||||
if(!chosen_voice)
|
||||
voice = null
|
||||
to_chat(user, "<span class='notice'>You are now mimicking the voice on your ID card.</span>")
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
/obj/item/storage/pill_bottle/random_meds
|
||||
name = "unlabelled pillbottle"
|
||||
desc = "The sheer recklessness of this bottle's existence astounds you."
|
||||
allow_wrap = FALSE
|
||||
var/labelled = FALSE
|
||||
|
||||
/obj/item/storage/pill_bottle/random_meds/New()
|
||||
|
||||
@@ -195,8 +195,6 @@
|
||||
heal_burn = 25
|
||||
|
||||
//Medical Herbs//
|
||||
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/comfrey
|
||||
name = "\improper Comfrey leaf"
|
||||
singular_name = "Comfrey leaf"
|
||||
@@ -217,48 +215,55 @@
|
||||
color = "#4CC5C7"
|
||||
heal_burn = 12
|
||||
|
||||
|
||||
//Splints//
|
||||
|
||||
|
||||
// Splints
|
||||
/obj/item/stack/medical/splint
|
||||
name = "medical splints"
|
||||
singular_name = "medical splint"
|
||||
icon_state = "splint"
|
||||
unique_handling = 1
|
||||
unique_handling = TRUE
|
||||
self_delay = 100
|
||||
var/other_delay = 0
|
||||
|
||||
/obj/item/stack/medical/splint/attack(mob/living/M, mob/user)
|
||||
if(..())
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
var/limb = affecting.name
|
||||
|
||||
if(!(affecting.limb_name in list("l_arm", "r_arm", "l_hand", "r_hand", "l_leg", "r_leg", "l_foot", "r_foot")))
|
||||
to_chat(user, "<span class='danger'>You can't apply a splint there!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(affecting.status & ORGAN_SPLINTED)
|
||||
to_chat(user, "<span class='danger'>[H]'s [limb] is already splinted!</span>")
|
||||
if(alert(user, "Would you like to remove the splint from [H]'s [limb]?", "Removing.", "Yes", "No") == "Yes")
|
||||
if(alert(user, "Would you like to remove the splint from [H]'s [limb]?", "Splint removal.", "Yes", "No") == "Yes")
|
||||
affecting.status &= ~ORGAN_SPLINTED
|
||||
H.handle_splints()
|
||||
to_chat(user, "<span class='notice'>You remove the splint from [H]'s [limb].</span>")
|
||||
return
|
||||
if(M == user)
|
||||
user.visible_message("<span class='notice'>[user] starts to apply [src] to [user.p_their()] [limb].</span>", \
|
||||
"<span class='notice'>You start to apply [src] to your [limb].</span>", \
|
||||
"<span class='notice'>You hear something being wrapped.</span>")
|
||||
if(!do_mob(user, H, self_delay))
|
||||
return
|
||||
else
|
||||
user.visible_message("<span class='green'>[user] applies [src] to [H]'s [limb].</span>", \
|
||||
"<span class='green'>You apply [src] to [H]'s [limb].</span>", \
|
||||
"<span class='green'>You hear something being wrapped.</span>")
|
||||
return TRUE
|
||||
|
||||
if((M == user && self_delay > 0) || (M != user && other_delay > 0))
|
||||
user.visible_message("<span class='notice'>[user] starts to apply [src] to [H]'s [limb].</span>", \
|
||||
"<span class='notice'>You start to apply [src] to [H]'s [limb].</span>", \
|
||||
"<span class='notice'>You hear something being wrapped.</span>")
|
||||
|
||||
if(M == user && !do_mob(user, H, self_delay))
|
||||
return TRUE
|
||||
else if(!do_mob(user, H, other_delay))
|
||||
return TRUE
|
||||
|
||||
user.visible_message("<span class='notice'>[user] applies [src] to [H]'s [limb].</span>", \
|
||||
"<span class='notice'>You apply [src] to [H]'s [limb].</span>")
|
||||
|
||||
affecting.status |= ORGAN_SPLINTED
|
||||
affecting.splinted_count = H.step_count
|
||||
H.handle_splints()
|
||||
|
||||
use(1)
|
||||
|
||||
/obj/item/stack/medical/splint/tribal
|
||||
name = "tribal splints"
|
||||
icon_state = "tribal_splint"
|
||||
other_delay = 50
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
var/global/list/datum/stack_recipe/metal_recipes = list(
|
||||
new /datum/stack_recipe("stool", /obj/structure/chair/stool, one_per_turf = 1, on_floor = 1),
|
||||
new /datum/stack_recipe("chair", /obj/structure/chair, one_per_turf = 1, on_floor = 1),
|
||||
new /datum/stack_recipe("shuttle seat", /obj/structure/chair/comfy/shuttle, 2, one_per_turf = 1, on_floor = 1),
|
||||
new /datum/stack_recipe("sofa (middle)", /obj/structure/chair/sofa, one_per_turf = 1, on_floor = 1),
|
||||
new /datum/stack_recipe("sofa (left)", /obj/structure/chair/sofa/left, one_per_turf = 1, on_floor = 1),
|
||||
new /datum/stack_recipe("sofa (right)", /obj/structure/chair/sofa/right, one_per_turf = 1, on_floor = 1),
|
||||
@@ -216,6 +217,8 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \
|
||||
null, \
|
||||
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1), \
|
||||
new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \
|
||||
null, \
|
||||
new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 3), \
|
||||
)
|
||||
|
||||
/obj/item/stack/sheet/cloth
|
||||
@@ -335,10 +338,13 @@ var/global/list/datum/stack_recipe/cult = list ( \
|
||||
* Brass
|
||||
*/
|
||||
var/global/list/datum/stack_recipe/brass_recipes = list (\
|
||||
new/datum/stack_recipe("wall gear", /obj/structure/clockwork/wall_gear, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
null,
|
||||
new/datum/stack_recipe/window("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, on_floor = TRUE, window_checks = TRUE), \
|
||||
null,
|
||||
new/datum/stack_recipe/window("directional brass window", /obj/structure/window/reinforced/clockwork, time = 0, on_floor = TRUE, window_checks = TRUE), \
|
||||
new/datum/stack_recipe/window("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
|
||||
new/datum/stack_recipe("brass chair", /obj/structure/chair/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
if(S.merge_type == merge_type)
|
||||
merge(S)
|
||||
|
||||
/obj/item/stack/Crossed(obj/O)
|
||||
/obj/item/stack/Crossed(obj/O, oldloc)
|
||||
if(amount >= max_amount || ismob(loc)) // Prevents unnecessary call. Also prevents merging stack automatically in a mob's inventory
|
||||
return
|
||||
if(istype(O, merge_type) && !O.throwing)
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
origin_tech = null
|
||||
attack_verb = list("attacked", "struck", "hit")
|
||||
brightness_on = 0
|
||||
sharp_when_wielded = FALSE // It's a toy
|
||||
|
||||
/obj/item/twohanded/dualsaber/toy/hit_reaction()
|
||||
return 0
|
||||
@@ -283,7 +284,7 @@
|
||||
..()
|
||||
pop_burst()
|
||||
|
||||
/obj/item/toy/snappop/Crossed(H as mob|obj)
|
||||
/obj/item/toy/snappop/Crossed(H as mob|obj, oldloc)
|
||||
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
|
||||
var/mob/living/carbon/M = H
|
||||
if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
icon = 'icons/obj/dice.dmi'
|
||||
icon_state = "dicebag"
|
||||
can_hold = list(/obj/item/dice)
|
||||
allow_wrap = FALSE
|
||||
|
||||
/obj/item/storage/pill_bottle/dice/New()
|
||||
..()
|
||||
@@ -25,20 +26,34 @@
|
||||
if(special_die == "100")
|
||||
new /obj/item/dice/d100(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/dice/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (OXYLOSS)
|
||||
|
||||
/obj/item/dice //depreciated d6, use /obj/item/dice/d6 if you actually want a d6
|
||||
name = "die"
|
||||
desc = "A die with six sides. Basic and servicable."
|
||||
icon = 'icons/obj/dice.dmi'
|
||||
icon_state = "d6"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
var/sides = 6
|
||||
var/result = null
|
||||
var/list/special_faces = list() //entries should match up to sides var if used
|
||||
|
||||
/obj/item/dice/New()
|
||||
result = rand(1, sides)
|
||||
var/rigged = DICE_NOT_RIGGED
|
||||
var/rigged_value
|
||||
|
||||
/obj/item/dice/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!result)
|
||||
result = roll(sides)
|
||||
update_icon()
|
||||
|
||||
/obj/item/dice/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (OXYLOSS)
|
||||
|
||||
/obj/item/dice/d1
|
||||
name = "d1"
|
||||
desc = "A die with one side. Deterministic!"
|
||||
@@ -117,11 +132,19 @@
|
||||
. = ..()
|
||||
|
||||
/obj/item/dice/proc/diceroll(mob/user)
|
||||
result = rand(1, sides)
|
||||
var/fake_result = rand(1, sides)//Daredevil isn't as good as he used to be
|
||||
result = roll(sides)
|
||||
if(rigged != DICE_NOT_RIGGED && result != rigged_value)
|
||||
if(rigged == DICE_BASICALLY_RIGGED && prob(Clamp(1/(sides - 1) * 100, 25, 80)))
|
||||
result = rigged_value
|
||||
else if(rigged == DICE_TOTALLY_RIGGED)
|
||||
result = rigged_value
|
||||
|
||||
. = result
|
||||
|
||||
var/fake_result = roll(sides)//Daredevil isn't as good as he used to be
|
||||
var/comment = ""
|
||||
if(sides == 20 && result == 20)
|
||||
comment = "Nat 20!"
|
||||
comment = "NAT 20!"
|
||||
else if(sides == 20 && result == 1)
|
||||
comment = "Ouch, bad luck."
|
||||
update_icon()
|
||||
@@ -130,16 +153,18 @@
|
||||
if(special_faces.len == sides)
|
||||
result = special_faces[result]
|
||||
if(user != null) //Dice was rolled in someone's hand
|
||||
user.visible_message("<span class='notice'>[user] has thrown [src]. It lands on [result]. [comment]</span>", \
|
||||
user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
|
||||
"<span class='notice'>You throw [src]. It lands on [result]. [comment]</span>", \
|
||||
"<span class='italics'>You hear [src] rolling, it sounds like a [fake_result].</span>")
|
||||
else if(!throwing) //Dice was thrown and is coming to rest
|
||||
else if(!src.throwing) //Dice was thrown and is coming to rest
|
||||
visible_message("<span class='notice'>[src] rolls to a stop, landing on [result]. [comment]</span>")
|
||||
|
||||
/obj/item/dice/d20/e20/diceroll(mob/user as mob, thrown)
|
||||
if(triggered)
|
||||
return
|
||||
..()
|
||||
|
||||
. = ..()
|
||||
|
||||
if(result == 1)
|
||||
to_chat(user, "<span class='danger'>Rocks fall, you die.</span>")
|
||||
user.gib()
|
||||
@@ -166,7 +191,7 @@
|
||||
|
||||
/obj/item/dice/update_icon()
|
||||
overlays.Cut()
|
||||
overlays += "[src.icon_state][src.result]"
|
||||
overlays += "[icon_state][result]"
|
||||
|
||||
/obj/item/storage/box/dice
|
||||
name = "Box of dice"
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
/obj/item/grenade/plastic/receive_signal()
|
||||
prime()
|
||||
|
||||
/obj/item/grenade/plastic/Crossed(atom/movable/AM)
|
||||
/obj/item/grenade/plastic/Crossed(atom/movable/AM, oldloc)
|
||||
if(nadeassembly)
|
||||
nadeassembly.Crossed(AM)
|
||||
nadeassembly.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/grenade/plastic/on_found(mob/finder)
|
||||
if(nadeassembly)
|
||||
|
||||
@@ -239,9 +239,9 @@
|
||||
if(nadeassembly)
|
||||
nadeassembly.process_movement()
|
||||
|
||||
/obj/item/grenade/chem_grenade/Crossed(atom/movable/AM)
|
||||
/obj/item/grenade/chem_grenade/Crossed(atom/movable/AM, oldloc)
|
||||
if(nadeassembly)
|
||||
nadeassembly.Crossed(AM)
|
||||
nadeassembly.Crossed(AM, oldloc)
|
||||
|
||||
/obj/item/grenade/chem_grenade/on_found(mob/finder)
|
||||
if(nadeassembly)
|
||||
@@ -289,7 +289,7 @@
|
||||
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
|
||||
var/turf/T = get_turf(src)
|
||||
var/area/A = get_area(T)
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)][ADMIN_QUE(M,"(?)")] ([admin_jump_link(M)]) and last touched by [key_name_admin(last)][ADMIN_QUE(last,"(?)")] ([admin_jump_link(last)]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>. [contained]")
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)] and last touched by [key_name_admin(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>. [contained]")
|
||||
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z]) [contained]")
|
||||
|
||||
update_mob()
|
||||
@@ -419,7 +419,7 @@
|
||||
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
|
||||
var/turf/T = get_turf(src)
|
||||
var/area/A = get_area(T)
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)][ADMIN_QUE(M,"(?)")] ([ADMIN_FLW(M,"FLW")]) and last touched by [key_name_admin(last)][ADMIN_QUE(last,"(?)")] ([ADMIN_FLW(last,"FLW")]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>.")
|
||||
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)] and last touched by [key_name_admin(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>.")
|
||||
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
|
||||
else
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time)
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj)
|
||||
/obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj, oldloc)
|
||||
if(armed && isturf(src.loc))
|
||||
if( (iscarbon(AM) || isanimal(AM)) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/hostile/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator))
|
||||
var/mob/living/L = AM
|
||||
@@ -193,6 +193,6 @@
|
||||
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom)
|
||||
if(iscarbon(hit_atom))
|
||||
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
|
||||
B.Crossed(hit_atom)
|
||||
B.Crossed(hit_atom, null)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/shard/Crossed(AM as mob|obj)
|
||||
/obj/item/shard/Crossed(AM as mob|obj, oldloc)
|
||||
if(isliving(AM))
|
||||
var/mob/living/M = AM
|
||||
if(M.incorporeal_move || M.flying || M.throwing)//you are incorporal or flying or being thrown ..no shard stepping!
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user