This commit is contained in:
Arkatos1
2019-08-12 16:38:33 +02:00
517 changed files with 25918 additions and 8376 deletions
+8 -1
View File
@@ -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)
@@ -248,7 +254,8 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new())
// Ventcrawling
#define VENT_SOUND_DELAY 30
/obj/machinery/atmospherics/relaymove(mob/living/user, direction)
if(!(direction & initialize_directions)) //can't go in a way we aren't connecting to
direction &= initialize_directions
if(!direction || !(direction in cardinal)) //cant go this way.
return
if(buckled_mob == user)
+1 -1
View File
@@ -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()
+54
View File
@@ -0,0 +1,54 @@
#define COLOR_INPUT_DISABLED "#F0F0F0"
#define COLOR_INPUT_ENABLED "#D3B5B5"
#define COLOR_WHITE "#EEEEEE"
#define COLOR_SILVER "#C0C0C0"
#define COLOR_GRAY "#808080"
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
#define COLOR_ALMOST_BLACK "#333333"
#define COLOR_BLACK "#000000"
#define COLOR_RED "#FF0000"
#define COLOR_RED_LIGHT "#FF3333"
#define COLOR_MAROON "#800000"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_OLIVE "#808000"
#define COLOR_LIME "#32CD32"
#define COLOR_GREEN "#008000"
#define COLOR_CYAN "#00FFFF"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_BLUE_LIGHT "#33CCFF"
#define COLOR_NAVY "#000080"
#define COLOR_PINK "#FFC0CB"
#define COLOR_MAGENTA "#FF00FF"
#define COLOR_PURPLE "#800080"
#define COLOR_ORANGE "#FF9900"
#define COLOR_BEIGE "#CEB689"
#define COLOR_BLUE_GRAY "#75A2BB"
#define COLOR_BROWN "#BA9F6D"
#define COLOR_DARK_BROWN "#997C4F"
#define COLOR_DARK_ORANGE "#C3630C"
#define COLOR_GREEN_GRAY "#99BB76"
#define COLOR_RED_GRAY "#B4696A"
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
#define COLOR_PALE_GREEN_GRAY "#B7D993"
#define COLOR_PALE_RED_GRAY "#D59998"
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
#define COLOR_PURPLE_GRAY "#AE8CA8"
//Color defines used by the assembly detailer.
#define COLOR_ASSEMBLY_BLACK "#545454"
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
#define COLOR_ASSEMBLY_RED "#CC4242"
#define COLOR_ASSEMBLY_ORANGE "#E39751"
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
#define COLOR_ASSEMBLY_BROWN "#97670E"
#define COLOR_ASSEMBLY_GOLD "#AA9100"
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
#define COLOR_ASSEMBLY_GURKHA "#999875"
#define COLOR_ASSEMBLY_LGREEN "#789876"
#define COLOR_ASSEMBLY_GREEN "#44843C"
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
#define COLOR_ASSEMBLY_BLUE "#38559E"
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
+20
View File
@@ -70,6 +70,10 @@
#define ATTACK_EFFECT_MECHFIRE "mech_fire"
#define ATTACK_EFFECT_MECHTOXIN "mech_toxin"
#define ATTACK_EFFECT_BOOP "boop" //Honk
//NOTE: INTENT_HOTKEY_* defines are not actual intents!
//they are here to support hotkeys
#define INTENT_HOTKEY_LEFT "left"
#define INTENT_HOTKEY_RIGHT "right"
//Embedded objects
#define EMBEDDED_PAIN_CHANCE 15 //Chance for embedded objects to cause pain (damage user)
@@ -82,6 +86,22 @@
#define EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER 8 //Coefficient of multiplication for the damage the item does when removed without a surgery (this*item.w_class)
#define EMBEDDED_UNSAFE_REMOVAL_TIME 30 //A Time in ticks, total removal time = (this*item.w_class)
// Body Parts
#define BODY_ZONE_HEAD "head"
#define BODY_ZONE_CHEST "chest"
#define BODY_ZONE_L_ARM "l_arm"
#define BODY_ZONE_R_ARM "r_arm"
#define BODY_ZONE_L_LEG "l_leg"
#define BODY_ZONE_R_LEG "r_leg"
#define BODY_ZONE_PRECISE_EYES "eyes"
#define BODY_ZONE_PRECISE_MOUTH "mouth"
#define BODY_ZONE_PRECISE_GROIN "groin"
#define BODY_ZONE_PRECISE_L_HAND "l_hand"
#define BODY_ZONE_PRECISE_R_HAND "r_hand"
#define BODY_ZONE_PRECISE_L_FOOT "l_foot"
#define BODY_ZONE_PRECISE_R_FOOT "r_foot"
//Gun Stuff
#define SAWN_INTACT 0
#define SAWN_OFF 1
+3
View File
@@ -1,6 +1,9 @@
#define ALL ~0 //For convenience.
#define NONE 0
// for /datum/var/datum_flags
#define DF_USE_TAG (1<<0)
//FLAGS BITMASK
#define STOPSPRESSUREDMAGE 1 //This flag is used on the flags variable for SUIT and HEAD items which stop pressure damage. Note that the flag 1 was previous used as ONBACK, so it is possible for some code to use (flags & 1) when checking if something can be put on your back. Replace this code with (inv_flags & SLOT_BACK) if you see it anywhere To successfully stop you taking all pressure damage you must have both a suit and head item with this flag.
#define NODROP 2 // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted.
+1
View File
@@ -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))
+1
View File
@@ -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"
+11 -13
View File
@@ -57,17 +57,6 @@
#define MAX_STACK_AMOUNT_GLASS 50
#define MAX_STACK_AMOUNT_RODS 60
//some 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"
//FONTS:
// Used by Paper and PhotoCopier (and PaperBin once a year).
// Used by PDA's Notekeeper.
@@ -143,7 +132,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
@@ -326,7 +320,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 6
#define SQL_VERSION 8
// Vending machine stuff
#define CAT_NORMAL 1
@@ -404,4 +398,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
+4 -2
View File
@@ -16,6 +16,7 @@
#define CHAT_GHOSTSIGHT 8
#define CHAT_PRAYER 16
#define CHAT_RADIO 32
#define AZERTY 64
#define CHAT_DEBUGLOGS 128
#define CHAT_LOOC 256
#define CHAT_GHOSTRADIO 512
@@ -32,10 +33,11 @@
#define TYPING_ONCE 1048576
#define AMBIENT_OCCLUSION 2097152
#define CHAT_GHOSTPDA 4194304
#define NUMPAD_TARGET 8388608
#define TOGGLES_TOTAL 16777215 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_TOTAL 8388607 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION|CHAT_GHOSTPDA)
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION|CHAT_GHOSTPDA|NUMPAD_TARGET)
// Admin attack logs filter system, see /proc/add_attack_logs and /proc/msg_admin_attack
#define ATKLOG_ALL 0
+5 -1
View File
@@ -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)
+8 -8
View File
@@ -43,7 +43,7 @@
. = "e[.]"
//like clients, which do have gender.
/client/proc/p_they(capitalized, temp_gender)
/client/p_they(capitalized, temp_gender)
if(!temp_gender)
temp_gender = gender
. = "they"
@@ -55,7 +55,7 @@
if(capitalized)
. = capitalize(.)
/client/proc/p_their(capitalized, temp_gender)
/client/p_their(capitalized, temp_gender)
if(!temp_gender)
temp_gender = gender
. = "their"
@@ -67,7 +67,7 @@
if(capitalized)
. = capitalize(.)
/client/proc/p_them(capitalized, temp_gender)
/client/p_them(capitalized, temp_gender)
if(!temp_gender)
temp_gender = gender
. = "them"
@@ -79,35 +79,35 @@
if(capitalized)
. = capitalize(.)
/client/proc/p_have(temp_gender)
/client/p_have(temp_gender)
if(!temp_gender)
temp_gender = gender
. = "has"
if(temp_gender == PLURAL || temp_gender == NEUTER)
. = "have"
/client/proc/p_are(temp_gender)
/client/p_are(temp_gender)
if(!temp_gender)
temp_gender = gender
. = "is"
if(temp_gender == PLURAL || temp_gender == NEUTER)
. = "are"
/client/proc/p_were(temp_gender)
/client/p_were(temp_gender)
if(!temp_gender)
temp_gender = gender
. = "was"
if(temp_gender == PLURAL || temp_gender == NEUTER)
. = "were"
/client/proc/p_do(temp_gender)
/client/p_do(temp_gender)
if(!temp_gender)
temp_gender = gender
. = "does"
if(temp_gender == PLURAL || temp_gender == NEUTER)
. = "do"
/client/proc/p_s(temp_gender)
/client/p_s(temp_gender)
if(!temp_gender)
temp_gender = gender
if(temp_gender != PLURAL && temp_gender != NEUTER)
+9 -2
View File
@@ -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)
+11
View File
@@ -157,6 +157,17 @@
if(degree < 315) return WEST
return NORTH|WEST
/proc/angle2dir_cardinal(angle)
switch(round(angle, 0.1))
if(315.5 to 360, 0 to 45.5)
return NORTH
if(45.6 to 135.5)
return EAST
if(135.6 to 225.5)
return SOUTH
if(225.6 to 315.5)
return WEST
//returns the north-zero clockwise angle in degrees, given a direction
/proc/dir2angle(var/D)
+1 -7
View File
@@ -16,7 +16,7 @@
var/global/next_unique_datum_id = 1
/client/var/tmp/unique_datum_id = null
// /client/var/tmp/unique_datum_id = null
/datum/proc/UID()
if(!unique_datum_id)
@@ -26,12 +26,6 @@ var/global/next_unique_datum_id = 1
tag = tag_backup
return unique_datum_id
/client/proc/UID()
if(!unique_datum_id)
unique_datum_id = "\ref[src]_[next_unique_datum_id++]"
return unique_datum_id
/proc/locateUID(uid)
if(!istext(uid))
return null
+2065 -2065
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -12,6 +12,7 @@ GLOBAL_LIST_INIT(mime_names, file2list("config/names/mime.txt"))
GLOBAL_LIST_INIT(golem_names, file2list("config/names/golem.txt"))
GLOBAL_LIST_INIT(verbs, file2list("config/names/verbs.txt"))
GLOBAL_LIST_INIT(nouns, file2list("config/names/nouns.txt"))
GLOBAL_LIST_INIT(adjectives, file2list("config/names/adjectives.txt"))
GLOBAL_LIST_INIT(dream_strings, file2list("config/names/dreams.txt"))
GLOBAL_LIST_INIT(nightmare_strings, file2list("config/names/nightmares.txt"))
+3 -1
View File
@@ -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
+20 -9
View File
@@ -1,4 +1,3 @@
/obj/screen/movable/action_button
var/datum/action/linked_action
screen_loc = null
@@ -6,18 +5,26 @@
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
moved = 0
if(locked)
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
return TRUE
moved = FALSE
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
return 1
if(usr.next_move >= world.time) // Is this needed ?
return TRUE
if(modifiers["ctrl"])
locked = !locked
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
return TRUE
if(usr.next_click > world.time)
return
usr.next_click = world.time + 1
linked_action.Trigger()
return 1
return TRUE
//Hide/Show Action Buttons ... Button
/obj/screen/movable/action_button/hide_toggle
name = "Hide Buttons"
desc = "Shift-click any button to reset its position. Alt-click to reset all buttons to their default positions."
desc = "Shift-click any button to reset its position, and Control-click it to lock/unlock its position. Alt-click this button to reset all buttons to their default positions."
icon = 'icons/mob/actions/actions.dmi'
icon_state = "bg_default"
var/hidden = 0
@@ -25,9 +32,16 @@
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
if(locked)
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
return TRUE
moved = FALSE
usr.update_action_buttons(TRUE)
return TRUE
if(modifiers["ctrl"])
locked = !locked
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
return TRUE
if(modifiers["alt"])
for(var/V in usr.actions)
var/datum/action/A = V
@@ -69,7 +83,6 @@
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)
@@ -77,7 +90,6 @@
/obj/screen/movable/action_button/MouseExited()
closeToolTip(usr)
/mob/proc/update_action_buttons_icon()
for(var/X in actions)
var/datum/action/A = X
@@ -122,7 +134,6 @@
client.screen += hud_used.hide_actions_toggle
#define AB_MAX_COLUMNS 10
/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty
+35
View File
@@ -177,6 +177,41 @@
desc = "You're severely malnourished. The hunger pains make moving around a chore."
icon_state = "starving"
///Vampire "hunger"
/obj/screen/alert/fat/vampire
name = "Fat"
desc = "You somehow drank too much blood, lardass. Run around the station and lose some weight."
icon_state = "v_fat"
/obj/screen/alert/full/vampire
name = "Full"
desc = "You feel full and satisfied, but you know you will thirst for more blood soon..."
icon_state = "v_full"
/obj/screen/alert/well_fed/vampire
name = "Well Fed"
desc = "You feel quite satisfied, but you could do with a bit more blood."
icon_state = "v_well_fed"
/obj/screen/alert/fed/vampire
name = "Fed"
desc = "You feel moderately satisfied, but a bit more blood wouldn't hurt."
icon_state = "v_fed"
/obj/screen/alert/hungry/vampire
name = "Hungry"
desc = "You currently thirst for blood."
icon_state = "v_hungry"
/obj/screen/alert/starving/vampire
name = "Starving"
desc = "You're severely thirsty. The thirst pains make moving around a chore."
icon_state = "v_starving"
//End of Vampire "hunger"
/obj/screen/alert/hot
name = "Too Hot"
desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit."
+5 -4
View File
@@ -11,6 +11,7 @@
/obj/screen/movable
var/snap2grid = FALSE
var/moved = FALSE
var/locked = TRUE
var/x_off = -16
var/y_off = -16
@@ -20,8 +21,10 @@
/obj/screen/movable/snap
snap2grid = TRUE
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
if(locked) //no! I am locked! begone!
return
var/list/PM = params2list(params)
//No screen-loc information? abort.
@@ -47,7 +50,6 @@
moved = screen_loc
//Debug procs
/client/proc/test_movable_UI()
set category = "Debug"
@@ -67,7 +69,6 @@
screen += M
/client/proc/test_snap_UI()
set category = "Debug"
set name = "Spawn Snap UI Object"
@@ -84,4 +85,4 @@
S.screen_loc = screen_l
screen += S
screen += S
+17 -9
View File
@@ -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
+81
View File
@@ -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
+3 -1
View File
@@ -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
+1 -1
View File
@@ -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
+122
View File
@@ -0,0 +1,122 @@
SUBSYSTEM_DEF(input)
name = "Input"
wait = 1 //SS_TICKER means this runs every tick
init_order = INIT_ORDER_INPUT
flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
var/list/macro_sets
var/list/movement_keys
var/list/alt_movement_keys
/datum/controller/subsystem/input/Initialize()
setup_default_macro_sets()
setup_default_movement_keys()
initialized = TRUE
refresh_client_macro_sets()
return ..()
// This is for when macro sets are eventualy datumized
/datum/controller/subsystem/input/proc/setup_default_macro_sets()
var/list/static/default_macro_sets
if(default_macro_sets)
macro_sets = default_macro_sets
return
default_macro_sets = list(
"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",
"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+O" = "ooc",
),
"old_hotkeys" = list(
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"O" = "ooc",
"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 \[\[*\]\]\"",
),
)
// Because i'm lazy and don't want to type all these out twice
var/list/old_default = default_macro_sets["old_default"]
var/list/static/oldmode_keys = list(
"North", "East", "South", "West",
"Northeast", "Southeast", "Northwest", "Southwest",
"Insert", "Delete", "Ctrl", "Alt",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
)
for(var/i in 1 to oldmode_keys.len)
var/key = oldmode_keys[i]
old_default[key] = "\"KeyDown [key]\""
old_default["[key]+UP"] = "\"KeyUp [key]\""
var/list/static/oldmode_ctrl_override_keys = list(
"W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement
"1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent
"B" = "B", // resist
"E" = "E", // quick equip
"F" = "F", // intent left
"G" = "G", // intent right
"H" = "H", // stop pulling
"Q" = "Q", // drop
"R" = "R", // throw
"X" = "X", // switch hands
"Y" = "Y", // activate item
"Z" = "Z", // activate item
)
for(var/i in 1 to oldmode_ctrl_override_keys.len)
var/key = oldmode_ctrl_override_keys[i]
var/override = oldmode_ctrl_override_keys[key]
old_default["Ctrl+[key]"] = "\"KeyDown [override]\""
old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\""
macro_sets = default_macro_sets
// For initially setting up or resetting to default the movement keys
/datum/controller/subsystem/input/proc/setup_default_movement_keys()
var/static/list/default_movement_keys = list(
"W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
)
var/static/list/azerty_movement_keys = list(
"Z" = NORTH, "Q" = WEST, "S" = SOUTH, "D" = EAST, // WASD
"North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
)
movement_keys = default_movement_keys.Copy()
alt_movement_keys = azerty_movement_keys.Copy()
// Badmins just wanna have fun ♪
/datum/controller/subsystem/input/proc/refresh_client_macro_sets()
var/list/clients = GLOB.clients
for(var/i in 1 to clients.len)
var/client/user = clients[i]
user.set_macros()
/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()
+1 -1
View File
@@ -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 ..()
+18 -16
View File
@@ -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>")
+4 -1
View File
@@ -21,7 +21,7 @@
/client/proc/debug_controller(controller in list("failsafe", "Master", "Ticker", "Air", "Jobs", "Sun", "Radio", "Configuration", "pAI",
"Cameras", "Garbage", "Event", "Alarm", "Nano", "Vote", "Fires",
"Mob", "NPC Pool", "Shuttle", "Timer", "Weather", "Space", "Mob Hunt Server"))
"Mob", "NPC Pool", "Shuttle", "Timer", "Weather", "Space", "Mob Hunt Server","Input"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
@@ -97,5 +97,8 @@
if("Mob Hunt Server")
debug_variables(SSmob_hunt)
feedback_add_details("admin_verb","DMobHuntServer")
if("Input")
debug_variables(SSinput)
feedback_add_details("admin_verb","DInput")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
+2
View File
@@ -43,6 +43,7 @@
M.actions += src
if(M.client)
M.client.screen += button
button.locked = TRUE
M.update_action_buttons()
/datum/action/proc/Remove(mob/M)
@@ -52,6 +53,7 @@
if(M.client)
M.client.screen -= button
button.moved = FALSE //so the button appears in its normal position when given to another owner.
button.locked = FALSE
M.actions -= src
M.update_action_buttons()
+1 -1
View File
@@ -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)
+15
View File
@@ -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)
+1 -1
View File
@@ -5,8 +5,8 @@
var/list/comp_lookup
var/list/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/var_edited = FALSE //Warranty void if seal is broken
var/tmp/unique_datum_id = null
#ifdef TESTING
+5 -5
View File
@@ -3,8 +3,8 @@
/datum/proc/can_vv_get(var_name)
return TRUE
/client/proc/can_vv_get(var_name)
return TRUE
// /client/proc/can_vv_get(var_name)
// return TRUE
/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
@@ -18,7 +18,7 @@
. = TRUE
/client/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited
/client/vv_edit_var(var_name, var_value) //called whenever a var is edited
switch(var_name)
if("vars")
return FALSE
@@ -37,7 +37,7 @@
return debug_variable(var_name, list(), 0, src)
return debug_variable(var_name, vars[var_name], 0, src)
/client/proc/vv_get_var(var_name)
/client/vv_get_var(var_name)
switch(var_name)
if("vars")
return debug_variable(var_name, list(), 0, src)
@@ -57,7 +57,7 @@
.["Delete"] = "?_src_=vars;delete=[UID()]"
. += "---"
/client/proc/vv_get_dropdown()
/client/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;proc_call=[UID()]"
-27
View File
@@ -1,27 +0,0 @@
/datum/hotkey_mode
var/name
var/macro_hotkeys_inactive
var/macro_hotkeys_active
var/mob/my_mob
/datum/hotkey_mode/New(mob)
my_mob = mob
/datum/hotkey_mode/proc/set_winset_values()
winset(my_mob, null, "mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5")
winset(my_mob, null, "hotkey_toggle.command=\".winset \\\"mainwindow.macro != [macro_hotkeys_inactive] ? mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5 : mainwindow.macro=[macro_hotkeys_active] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#f0f0f0\\\"\"")
/datum/hotkey_mode/qwerty
name = "QWERTY"
macro_hotkeys_inactive = "macro"
macro_hotkeys_active = "hotkeymode"
/datum/hotkey_mode/azerty
name = "AZERTY"
macro_hotkeys_inactive = "azertymacro"
macro_hotkeys_active = "azertyhotkeymode"
/datum/hotkey_mode/cyborg
name = "Cyborg"
macro_hotkeys_inactive = "borgmacro"
macro_hotkeys_active = "borghotkeymode"
+7
View File
@@ -141,6 +141,11 @@
..()
popup.add_script("autocomplete.js", 'html/browser/autocomplete.js')
for(var/i=1, i <= choices.len, i++)
var/C = choices[choices[i]]
choices[i] = url_encode(choices[i], TRUE)
choices[choices[i]] = C
/datum/async_input/autocomplete/render_prompt()
return "<label for='input'>[prompt]</label>"
@@ -162,6 +167,8 @@
// Entering an invalid choice is the same as canceling
if(href_list["submit"] in choices)
result = href_list["submit"]
else if(url_encode(href_list["submit"], TRUE) in choices)
result = url_encode(href_list["submit"], TRUE)
close()
return
+2 -1
View File
@@ -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
+1
View File
@@ -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
+121 -1
View File
@@ -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
+1 -1
View File
@@ -1440,7 +1440,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/device_tools/medgun
name = "Medbeam Gun"
desc = "Medical Beam Gun, useful in prolonged firefights."
desc = "Medical Beam Gun, useful in prolonged firefights. DO NOT CROSS THE BEAMS. Crossing beams with another medbeam or attaching two beams to one target will have explosive consequences."
item = /obj/item/gun/medbeam
reference = "MBG"
cost = 15
+1 -1
View File
@@ -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)
+11
View File
@@ -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"
+3 -1
View File
@@ -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
+2 -1
View File
@@ -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
View File
@@ -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)
+44 -20
View File
@@ -68,7 +68,7 @@
if(!(AM.can_be_pulled(src, state, force)))
return FALSE
// If we're pulling something then drop what we're currently pulling and pull this instead.
// if we're pulling something then drop what we're currently pulling and pull this instead.
if(pulling)
if(state == 0)
stop_pulling()
@@ -118,7 +118,9 @@
if(pulling.anchored)
stop_pulling()
return
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
/atom/movable/proc/can_be_pulled(user, grab_state, force)
if(src == user || !isturf(loc))
return FALSE
@@ -141,36 +143,55 @@
. = ..()
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
if(direct & 1)
if(direct & 4)
if(step(src, NORTH))
var/first_step_dir
// The `&& moving_diagonally` checks are so that a forceMove taking
// place due to a Crossed, Bumped, etc. call will interrupt
// the second half of the diagonal movement, or the second attempt
// at a first half if step() fails because we hit something.
if(direct & NORTH)
if(direct & EAST)
if(step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if(step(src, EAST))
else if(moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if(direct & 8)
if(step(src, NORTH))
else if(direct & WEST)
if(step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if(step(src, WEST))
else if(moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if(direct & 2)
if(direct & 4)
if(step(src, SOUTH))
else if(direct & SOUTH)
if(direct & EAST)
if(step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if(step(src, EAST))
else if(moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
else if(direct & 8)
if(step(src, SOUTH))
else if(direct & WEST)
if(step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if(step(src, WEST))
else if(moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
if(moving_diagonally == SECOND_DIAG_STEP)
if(!.)
setDir(first_step_dir)
else if(!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(direct)
moving_diagonally = 0
return
@@ -191,14 +212,14 @@
// Called after a successful Move(). By this point, we've already moved
/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
if (!inertia_moving)
if(!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
return TRUE
// 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().
@@ -214,6 +235,7 @@
/atom/movable/proc/forceMove(atom/destination)
var/turf/old_loc = loc
loc = destination
moving_diagonally = 0
if(old_loc)
old_loc.Exited(src, destination)
@@ -223,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)
@@ -243,7 +267,7 @@
return 1
/atom/movable/proc/onTransitZ(old_z,new_z)
for(var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care.
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
+15 -1
View File
@@ -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 -5
View File
@@ -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)
+1 -1
View File
@@ -388,7 +388,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
+1 -1
View File
@@ -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)
-1
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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
+2 -3
View File
@@ -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
-8
View File
@@ -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)
-1
View File
@@ -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.
+7 -4
View File
@@ -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
+6 -2
View File
@@ -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, ", ")]."
+7
View File
@@ -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))
+17 -9
View File
@@ -297,19 +297,27 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
to_chat(owner, "<span class='warning'>They've got no blood left to give.</span>")
break
if(H.stat < DEAD)
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
bloodusable += blood / 2
if(!issmall(H) || H.ckey)
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
bloodusable += blood / 2
else
blood = min(5, H.blood_volume) // The dead only give 5 blood
bloodtotal += blood
if(!issmall(H) || H.ckey)
blood = min(5, H.blood_volume) // The dead only give 5 blood
bloodtotal += blood
if(old_bloodtotal != bloodtotal)
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
if(!issmall(H) || H.ckey) // not small OR has a ckey, monkeys with ckeys can be sucked, humanized monkeys can be sucked monkeys without ckeys cannot be sucked
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
check_vampire_upgrade()
H.blood_volume = max(H.blood_volume - 25, 0)
if(ishuman(owner))
var/mob/living/carbon/human/V = owner
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
if(issmall(H) && !H.ckey)
to_chat(V, "<span class='notice'><b>Feeding on [H] reduces your hunger, but you get no usable blood from it.</b></span>")
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + 5)
else
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
draining = null
to_chat(owner, "<span class='notice'>You stop draining [H.name] of blood.</span>")
@@ -402,11 +410,11 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
if(!hud.vampire_blood_display)
hud.vampire_blood_display = new /obj/screen()
hud.vampire_blood_display.name = "Usable Blood"
hud.vampire_blood_display.icon_state = "power_display"
hud.vampire_blood_display.icon_state = "blood_display"
hud.vampire_blood_display.screen_loc = "WEST:6,CENTER-1:15"
hud.static_inventory += hud.vampire_blood_display
hud.show_hud(hud.hud_version)
hud.vampire_blood_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#dd66dd'>[bloodusable]</font></div>"
hud.vampire_blood_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#ce0202'>[bloodusable]</font></div>"
handle_vampire_cloak()
if(istype(owner.loc, /turf/space))
check_sun()
+13 -3
View File
@@ -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")
+10
View File
@@ -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)
-1
View File
@@ -7,7 +7,6 @@
required_players = 20
required_enemies = 1
recommended_enemies = 1
free_golems_disabled = TRUE
var/use_huds = 0
var/finished = 0
var/but_wait_theres_more = 0
+19 -18
View File
@@ -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
+33 -2
View File
@@ -160,8 +160,8 @@
title = "Shaft Miner"
flag = MINER
department_flag = SUPPORT
total_positions = 3
spawn_positions = 3
total_positions = 6
spawn_positions = 8
is_supply = 1
supervisors = "the quartermaster"
department_head = list("Head of Personnel")
@@ -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
+1 -1
View File
@@ -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>")
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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
+5 -5
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
@@ -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"])
+1 -3
View File
@@ -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)
+3 -3
View File
@@ -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"]]
+1
View File
@@ -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()
..()
+45 -37
View File
@@ -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)
+1
View File
@@ -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
+2 -1
View File
@@ -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
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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
+4 -5
View File
@@ -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
+139 -58
View File
@@ -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
+1 -1
View File
@@ -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
+1
View File
@@ -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)
+1 -1
View File
@@ -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>")
+27 -22
View File
@@ -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
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
created_window = /obj/structure/window/basic
full_window = /obj/structure/window/full/basic
merge_type = /obj/item/stack/sheet/glass
point_value = 1
/obj/item/stack/sheet/glass/fifty
amount = 50
@@ -90,6 +91,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
created_window = /obj/structure/window/reinforced
full_window = /obj/structure/window/full/reinforced
merge_type = /obj/item/stack/sheet/rglass
point_value = 4
/obj/item/stack/sheet/rglass/cyborg
materials = list()
@@ -113,6 +115,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
origin_tech = "plasmatech=2;materials=2"
created_window = /obj/structure/window/plasmabasic
full_window = /obj/structure/window/full/plasmabasic
point_value = 19
/obj/item/stack/sheet/plasmaglass/New(loc, amount)
recipes = GLOB.pglass_recipes
@@ -154,6 +157,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
created_window = /obj/structure/window/plasmareinforced
full_window = /obj/structure/window/full/plasmareinforced
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0)
point_value = 23
/obj/item/stack/sheet/plasmarglass/New(loc, amount)
recipes = GLOB.prglass_recipes
@@ -144,6 +144,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
origin_tech = "materials=6"
sheettype = "diamond"
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
point_value = 25
/obj/item/stack/sheet/mineral/diamond/New()
..()
@@ -156,6 +157,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
origin_tech = "materials=5"
sheettype = "uranium"
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
point_value = 20
/obj/item/stack/sheet/mineral/uranium/New()
..()
@@ -170,6 +172,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
burn_state = FLAMMABLE
burntime = 5
point_value = 20
/obj/item/stack/sheet/mineral/plasma/New()
..()
@@ -196,6 +199,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
origin_tech = "materials=4"
sheettype = "gold"
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
point_value = 20
/obj/item/stack/sheet/mineral/gold/New()
..()
@@ -208,6 +212,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
origin_tech = "materials=4"
sheettype = "silver"
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
point_value = 20
/obj/item/stack/sheet/mineral/silver/New()
..()
@@ -220,6 +225,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
origin_tech = "materials=4"
sheettype = "bananium"
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
point_value = 50
/obj/item/stack/sheet/mineral/bananium/New(loc, amount=null)
..()
@@ -233,6 +239,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
sheettype = "tranquillite"
materials = list(MAT_TRANQUILLITE=MINERAL_MATERIAL_AMOUNT)
wall_allowed = FALSE //no tranquilite walls in code
point_value = 50
/obj/item/stack/sheet/mineral/tranquillite/New(loc, amount=null)
..()
@@ -253,6 +260,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
throw_range = 3
sheettype = "titanium"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
point_value = 20
var/global/list/datum/stack_recipe/titanium_recipes = list (
new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20),
@@ -282,6 +290,7 @@ var/global/list/datum/stack_recipe/titanium_recipes = list (
throw_range = 3
sheettype = "plastitanium"
materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000)
point_value = 45
var/global/list/datum/stack_recipe/plastitanium_recipes = list (
new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20),
@@ -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),
@@ -105,6 +106,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list(
flags = CONDUCT
origin_tech = "materials=1"
merge_type = /obj/item/stack/sheet/metal
point_value = 2
/obj/item/stack/sheet/metal/cyborg
materials = list()
@@ -151,6 +153,7 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list(
flags = CONDUCT
origin_tech = "materials=2"
merge_type = /obj/item/stack/sheet/plasteel
point_value = 23
/obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null)
recipes = plasteel_recipes
@@ -214,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
@@ -333,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), \
)

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