Merge remote-tracking branch 'upstream/master' into departmental-clothing-vendors

This commit is contained in:
E-MonaRhg
2021-09-11 20:26:54 +02:00
255 changed files with 1654 additions and 676 deletions
+6 -8
View File
@@ -122,7 +122,6 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(M.ckey)
body += "<A href='?_src_=holder;boot2=[M.UID()]'>Kick</A> | "
body += "<A href='?_src_=holder;warn=[M.ckey]'>Warn</A> | "
body += "<A href='?_src_=holder;newban=[M.UID()];dbbanaddckey=[M.ckey]'>Ban</A> | "
body += "<A href='?_src_=holder;jobban2=[M.UID()];dbbanaddckey=[M.ckey]'>Jobban</A> | "
body += "<A href='?_src_=holder;appearanceban=[M.UID()];dbbanaddckey=[M.ckey]'>Appearance Ban</A> | "
@@ -141,14 +140,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "\ <A href='?_src_=holder;sendbacktolobby=[M.UID()]'>Send back to Lobby</A> | "
body += "\ <A href='?_src_=holder;eraseflavortext=[M.UID()]'>Erase Flavor Text</A> | "
body += "\ <A href='?_src_=holder;userandomname=[M.UID()]'>Use Random Name</A> | "
var/muted = M.client.prefs.muted
body += {"<br><b>Mute: </b>
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"#6685f5"]'>IC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"#6685f5"]'>OOC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"#6685f5"]'>PRAY</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"#6685f5"]'>ADMINHELP</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"#6685f5"]'>DEADCHAT</font></a>\]
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"#6685f5"]'>toggle all</font></a>)
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[check_mute(M.client.ckey, MUTE_IC) ? "red" : "#6685f5"]'>IC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[check_mute(M.client.ckey, MUTE_OOC) ? "red" : "#6685f5"]'>OOC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[check_mute(M.client.ckey, MUTE_PRAY) ? "red" : "#6685f5"]'>PRAY</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[check_mute(M.client.ckey, MUTE_ADMINHELP) ? "red" : "#6685f5"]'>ADMINHELP</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[check_mute(M.client.ckey, MUTE_DEADCHAT) ?" red" : "#6685f5"]'>DEADCHAT</font></a>]
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[check_mute(M.client.ckey, MUTE_ALL) ? "red" : "#6685f5"]'>toggle all</font></a>)
"}
var/jumptoeye = ""
-45
View File
@@ -492,51 +492,6 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
log_admin("[key_name(usr)] has turned BB mode [holder.fakekey ? "ON" : "OFF"]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Big Brother Mode")
#define MAX_WARNS 3
#define AUTOBANTIME 10
/client/proc/warn(warned_ckey)
if(!check_rights(R_ADMIN))
return
if(!warned_ckey || !istext(warned_ckey)) return
if(warned_ckey in GLOB.admin_datums)
to_chat(usr, "<font color='red'>Error: warn(): You can't warn admins.</font>")
return
var/datum/preferences/D
var/client/C = GLOB.directory[warned_ckey]
if(C) D = C.prefs
else D = GLOB.preferences_datums[warned_ckey]
if(!D)
to_chat(src, "<font color='red'>Error: warn(): No such ckey found.</font>")
return
if(++D.warns >= MAX_WARNS) //uh ohhhh...you'reee iiiiin trouuuubble O:)
if(C)
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [key_name(C)] resulting in a [AUTOBANTIME] minute ban")
to_chat(C, "<font color='red'><BIG><B>You have been autobanned due to a warning by [ckey].</B></BIG><br>This is a temporary ban, it will be removed in [AUTOBANTIME] minutes.")
qdel(C)
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
AddBan(warned_ckey, D.last_id, "Autobanning due to too many formal warnings", ckey, 1, AUTOBANTIME)
else
if(C)
to_chat(C, "<font color='red'><BIG><B>You have been formally warned by an administrator.</B></BIG><br>Further warnings will result in an autoban.</font>")
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)]. They have [MAX_WARNS-D.warns] strikes remaining.")
log_admin("[key_name(src)] has warned [key_name(C)]. They have [MAX_WARNS-D.warns] strikes remaining.")
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] (DC). They have [MAX_WARNS-D.warns] strikes remaining.")
log_admin("[key_name(src)] has warned [warned_ckey] (DC). They have [MAX_WARNS-D.warns] strikes remaining.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Warning") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
#undef MAX_WARNS
#undef AUTOBANTIME
/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE
set category = "Event"
set name = "Drop Bomb"
+32
View File
@@ -0,0 +1,32 @@
/// Associative list of people who are muted via admin mutes
GLOBAL_LIST_EMPTY(admin_mutes_assoc)
/proc/check_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
return FALSE
if(GLOB.admin_mutes_assoc[ckey] & muteflag)
return TRUE
return FALSE
/proc/toggle_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
if(GLOB.admin_mutes_assoc[ckey] & muteflag)
GLOB.admin_mutes_assoc[ckey] &= ~muteflag
else
GLOB.admin_mutes_assoc[ckey] |= muteflag
/proc/force_add_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
GLOB.admin_mutes_assoc[ckey] |= muteflag
/proc/force_remove_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
GLOB.admin_mutes_assoc[ckey] &= ~muteflag
-3
View File
@@ -446,9 +446,6 @@
alert(usr, "This ban has already been lifted / does not exist.", "Error", "Ok")
unbanpanel()
else if(href_list["warn"])
usr.client.warn(href_list["warn"])
else if(href_list["unbane"])
if(!check_rights(R_BAN)) return
+1 -1
View File
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown", "the", "a", "an", "of"
set name = "Adminhelp"
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>")
return
+2 -2
View File
@@ -58,7 +58,7 @@
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg, type = "PM")
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PM-s (muted).</span>")
return
@@ -212,7 +212,7 @@
return
/client/proc/cmd_admin_discord_pm()
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PMs (muted).</span>")
return
+1
View File
@@ -43,6 +43,7 @@
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
log_mentorsay(msg, src)
mob.create_log(OOC_LOG, "MSAY: [msg]")
if(!msg)
return
+1 -1
View File
@@ -9,7 +9,7 @@
if(!src.mob)
return
if(prefs.muted & MUTE_DEADCHAT)
if(check_mute(ckey, MUTE_DEADCHAT))
to_chat(src, "<span class='warning'>You cannot send DSAY messages (muted).</span>")
return
+16 -2
View File
@@ -1,3 +1,7 @@
#define NUKE_INTACT 0
#define NUKE_CORE_MISSING 1
#define NUKE_MISSING 2
/mob/living/verb/pray(msg as text)
set category = "IC"
set name = "Pray"
@@ -7,7 +11,7 @@
return
if(usr.client)
if(usr.client.prefs.muted & MUTE_PRAY)
if(check_mute(client.ckey, MUTE_PRAY))
to_chat(usr, "<span class='warning'>You cannot pray (muted).</span>")
return
if(client.handle_spam_prevention(msg, MUTE_PRAY, OOC_COOLDOWN))
@@ -72,11 +76,21 @@
/proc/Nuke_request(text , mob/Sender)
var/nuke_code = get_nuke_code()
var/nuke_status = get_nuke_status()
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST: </font>[key_name(Sender)] ([ADMIN_PP(Sender,"PP")]) ([ADMIN_VV(Sender,"VV")]) ([ADMIN_TP(Sender,"TP")]) ([ADMIN_SM(Sender,"SM")]) ([admin_jump_link(Sender)]) ([ADMIN_BSA(Sender,"BSA")]) ([ADMIN_CENTCOM_REPLY(Sender,"RPLY")]):</b> [msg]</span>"
for(var/client/X in GLOB.admins)
if(check_rights(R_EVENT,0,X.mob))
to_chat(X, msg)
to_chat(X, "<span class='adminnotice'><b>The nuke code is [nuke_code].</b></span>")
if(nuke_status == NUKE_MISSING)
to_chat(X, "<span class='userdanger'>The nuclear device is not on station!</span>")
else
to_chat(X, "<b>The nuke code is [nuke_code].</b>")
if(nuke_status == NUKE_CORE_MISSING)
to_chat(X, "<span class='userdanger'>The nuclear device does not have a core, and will not arm!</span>")
if(X.prefs.sound & SOUND_ADMINHELP)
SEND_SOUND(X, sound('sound/effects/adminhelp.ogg'))
#undef NUKE_INTACT
#undef NUKE_CORE_MISSING
#undef NUKE_MISSING
+7 -7
View File
@@ -230,19 +230,19 @@
if(automute)
muteunmute = "auto-muted"
M.client.prefs.muted |= mute_type
force_add_mute(M.client.ckey, mute_type)
log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(M)] from [mute_string]")
message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
to_chat(M, "You have been [muteunmute] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Automute") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
if(M.client.prefs.muted & mute_type)
muteunmute = "unmuted"
M.client.prefs.muted &= ~mute_type
else
toggle_mute(M.client.ckey, mute_type)
if(check_mute(M.client.ckey, mute_type))
muteunmute = "muted"
M.client.prefs.muted |= mute_type
else
muteunmute = "unmuted"
log_admin("[key_name(usr)] has [muteunmute] [key_name(M)] from [mute_string]")
message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
@@ -606,7 +606,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
"Custom" = "Cryptic Message")
var/list/MsgSound = list("Beep" = 'sound/misc/notice2.ogg',
"Enemy Communications Intercepted" = 'sound/AI/intercept2.ogg',
"Enemy Communications Intercepted" = 'sound/AI/intercept.ogg',
"New Command Report Created" = 'sound/AI/commandreport.ogg')
var/type = input(usr, "Pick a type of report to send", "Report Type", "") as anything in MsgType
@@ -25,9 +25,6 @@
H.dna.SetSEState(GLOB.hulkblock, TRUE)
singlemutcheck(H, GLOB.hulkblock, MUTCHK_FORCED)
H.dna.SetSEState(GLOB.xrayblock, TRUE)
singlemutcheck(H, GLOB.xrayblock, MUTCHK_FORCED)
H.dna.SetSEState(GLOB.fireblock, TRUE)
singlemutcheck(H, GLOB.fireblock, MUTCHK_FORCED)
+16 -11
View File
@@ -1,4 +1,3 @@
/obj/effect/nanomob
name = "Nano-Mob Avatar" //will be overridden by the mob datum name value when created
desc = "A wild Nano-Mob appeared! Hit it with your PDA with the game open to attempt to capture it!"
@@ -12,17 +11,29 @@
var/list/clients_encountered = list() //tracks who has already interacted with us, so they can't attempt a second capture
var/image/avatar
/obj/effect/nanomob/New(loc, datum/mob_hunt/new_info)
..()
/obj/effect/nanomob/Initialize(mapload, datum/mob_hunt/new_info)
. = ..()
if(!new_info)
qdel(src)
return
return INITIALIZE_HINT_QDEL
mob_info = new_info
RegisterSignal(mob_info, COMSIG_PARENT_QDELETING, .proc/delete_wrapper)
update_self()
forceMove(mob_info.spawn_point)
if(!mob_info.is_trap)
addtimer(CALLBACK(src, .proc/despawn), mob_info.lifetime)
/obj/effect/nanomob/Destroy()
SSmob_hunt.trap_spawns -= src
SSmob_hunt.normal_spawns -= src
mob_info = null // Can't delete this since multiple players can get the exact same /datum/mob_hunt. (This should be refactored)
clients_encountered.Cut()
QDEL_NULL(avatar)
return ..()
/obj/effect/nanomob/proc/delete_wrapper()
SIGNAL_HANDLER
qdel(src)
/obj/effect/nanomob/proc/update_self()
if(!mob_info)
return
@@ -132,12 +143,6 @@
icon_state = "placeholder"
var/obj/machinery/computer/mob_battle_terminal/my_terminal
/obj/effect/nanomob/battle/New(loc, datum/mob_hunt/new_info)
. = ..()
if(new_info)
mob_info = new_info
update_self()
/obj/effect/nanomob/battle/update_self()
if(!mob_info)
name = "Nano-Mob Battle Avatar"
+1 -1
View File
@@ -215,7 +215,7 @@
var/life_cycles = 0
var/life_cap = 20
anchored = TRUE
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSFENCE
/obj/effect/beam/i_beam/proc/hit()
@@ -71,10 +71,13 @@ Pipelines + Other Objects -> Pipe network
// Icons/overlays/underlays
/obj/machinery/atmospherics/update_icon()
var/turf/T = get_turf(loc)
if(!T || level == 2 || !T.intact)
plane = GAME_PLANE
else
if(T && T.transparent_floor)
plane = FLOOR_PLANE
else
if(!T || level == 2 || !T.intact)
plane = GAME_PLANE
else
plane = FLOOR_PLANE
/obj/machinery/atmospherics/proc/update_pipe_image()
pipe_image = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir) //the 20 puts it above Byond's darkness (not its opacity view)
@@ -95,15 +98,18 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/add_underlay(turf/T, obj/machinery/atmospherics/node, direction, icon_connect_type)
if(node)
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe) && !T.transparent_floor)
//underlays += SSair.icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
if(T.transparent_floor) //we want to keep pipes under transparent floors connected normally
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
/obj/machinery/atmospherics/proc/update_underlays()
if(check_icon_cache())
@@ -166,11 +172,14 @@ Pipelines + Other Objects -> Pipe network
//(De)construction
/obj/machinery/atmospherics/attackby(obj/item/W, mob/user)
var/turf/T = get_turf(src)
if(can_unwrench && istype(W, /obj/item/wrench))
var/turf/T = get_turf(src)
if(T.transparent_floor && istype(src, /obj/machinery/atmospherics/pipe) && layer != GAS_PIPE_VISIBLE_LAYER) //pipes on GAS_PIPE_VISIBLE_LAYER are above the transparent floor and should be interactable
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return
if(level == 1 && isturf(T) && T.intact)
to_chat(user, "<span class='danger'>You must remove the plating first.</span>")
return 1
return
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
@@ -184,14 +193,14 @@ Pipelines + Other Objects -> Pipe network
playsound(src.loc, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if(internal_pressure > 2*ONE_ATMOSPHERE)
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gust of air blows in your face... maybe you should reconsider?</span>")
unsafe_wrenching = TRUE //Oh dear oh dear
if(do_after(user, 40 * W.toolspeed, target = src) && !QDELETED(src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
"<span class='italics'>You hear ratcheting.</span>")
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", "atmos")
for(var/obj/item/clothing/shoes/magboots/usermagboots in user.get_equipped_items())
@@ -206,6 +215,9 @@ Pipelines + Other Objects -> Pipe network
unsafe_pressure_release(user,internal_pressure)
deconstruct(TRUE)
else
if(T.transparent_floor)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return TRUE
return ..()
//Called when an atmospherics object is unwrenched while having a large pressure difference
@@ -240,7 +252,12 @@ Pipelines + Other Objects -> Pipe network
dir = D
initialize_directions = P
var/turf/T = loc
level = T.intact ? 2 : 1
if(!T.transparent_floor)
level = T.intact ? 2 : 1
else
level = 2
plane = GAME_PLANE
layer = GAS_PIPE_VISIBLE_LAYER
add_fingerprint(usr)
if(!SSair.initialized) //If there's no atmos subsystem, we can't really initialize pipenets
SSair.machinery_to_construct.Add(src)
@@ -337,12 +354,15 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/add_underlay_adapter(turf/T, obj/machinery/atmospherics/node, direction, icon_connect_type) //modified from add_underlay, does not make exposed underlays
if(node)
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe) && !T.transparent_floor)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
if(T.transparent_floor) //we want to keep pipes under transparent floors connected normally
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
/obj/machinery/atmospherics/singularity_pull(S, current_size)
if(current_size >= STAGE_FIVE)
@@ -144,7 +144,7 @@
if(!istype(L) || L.buckled)
return
if(L.abiotic())
to_chat(user, "<span class='danger'>Subject cannot have abiotic items on.</span>")
to_chat(user, "<span class='danger'>Subject may not hold anything in their hands.</span>")
return
if(L.has_buckled_mobs()) //mob attached to us
to_chat(user, "<span class='warning'>[L] will not fit into [src] because [L.p_they()] [L.p_have()] a slime latched onto [L.p_their()] head.</span>")
@@ -462,7 +462,7 @@
to_chat(usr, "<span class='danger'>The cryo cell is already occupied!</span>")
return
if(M.abiotic())
to_chat(usr, "<span class='warning'>Subject may not have abiotic items on.</span>")
to_chat(usr, "<span class='warning'>Subject may not hold anything in their hands.</span>")
return
if(!node)
to_chat(usr, "<span class='warning'>The cell is not correctly connected to its pipe network!</span>")
@@ -2,6 +2,7 @@
icon = 'icons/atmos/vent_pump.dmi'
icon_state = "map_vent"
plane = FLOOR_PLANE
layer = GAS_SCRUBBER_LAYER
name = "passive vent"
desc = "A large air vent"
@@ -1,7 +1,7 @@
/obj/machinery/atmospherics/unary/tank
icon = 'icons/atmos/tank.dmi'
icon_state = "air_map"
layer = GAS_PIPE_VISIBLE_LAYER
name = "pressure tank"
desc = "A large vessel containing pressurized gas."
@@ -159,9 +159,9 @@
var/cache_name = state
for(var/D in GLOB.cardinal)
var/image/I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D))
var/image/I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D), layer = GAS_PIPE_HIDDEN_LAYER)
underlays[cache_name + "[D]"] = I
for(var/pipe_color in GLOB.pipe_colors)
I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D))
I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D), layer = GAS_PIPE_HIDDEN_LAYER)
I.color = GLOB.pipe_colors[pipe_color]
underlays[state + "[D]" + "[GLOB.pipe_colors[pipe_color]]"] = I
@@ -79,7 +79,8 @@
break
var/turf/T = get_turf(src) // hide if turf is not intact
if(!istype(T)) return
if(!istype(T) || T.transparent_floor)
return
hide(T.intact)
update_icon()
@@ -57,6 +57,8 @@
node3 = target
break
var/turf/T = src.loc // hide if turf is not intact
if(T.transparent_floor)
return
hide(T.intact)
update_icon()
@@ -165,7 +165,8 @@
break
var/turf/T = src.loc // hide if turf is not intact
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
update_icon()
/obj/machinery/atmospherics/pipe/manifold4w/visible
@@ -46,10 +46,6 @@
if(istype(W, /obj/item/analyzer))
atmosanalyzer_scan(parent.air, user)
return
if(istype(W, /obj/item/painter))
return
return ..()
/obj/machinery/atmospherics/proc/pipeline_expansion()
@@ -68,7 +68,8 @@
break
var/turf/T = loc // hide if turf is not intact
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
update_icon()
/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
@@ -79,8 +79,6 @@
ADD_TRAIT(user, TRAIT_LASEREYES, "ww_wishgranter")
user.dna.SetSEState(GLOB.fireblock, TRUE)
singlemutcheck(user, GLOB.fireblock, MUTCHK_FORCED)
user.dna.SetSEState(GLOB.xrayblock, TRUE)
singlemutcheck(user, GLOB.xrayblock, MUTCHK_FORCED)
if(ishuman(user))
var/mob/living/carbon/human/human = user
if(!isshadowperson(human))
+3 -3
View File
@@ -8,8 +8,8 @@
#define UPLOAD_LIMIT 10485760 //Restricts client uploads to the server to 10MB //Boosted this thing. What's the worst that can happen?
#define MIN_CLIENT_VERSION 513 // Minimum byond major version required to play.
//I would just like the code ready should it ever need to be used.
#define SUGGESTED_CLIENT_VERSION 513 // only integers (e.g: 513, 514) are useful here. This is the part BEFORE the ".", IE 513 out of 513.1542
#define SUGGESTED_CLIENT_BUILD 1542 // only integers (e.g: 1542, 1543) are useful here. This is the part AFTER the ".", IE 1542 out of 513.1542
#define SUGGESTED_CLIENT_VERSION 514 // only integers (e.g: 513, 514) are useful here. This is the part BEFORE the ".", IE 513 out of 513.1542
#define SUGGESTED_CLIENT_BUILD 1566 // only integers (e.g: 1542, 1543) are useful here. This is the part AFTER the ".", IE 1542 out of 513.1542
#define SSD_WARNING_TIMER 30 // cycles, not seconds, so 30=60s
@@ -113,7 +113,7 @@
if(!holder && received_discord_pm < world.time - 6000) // Worse they can do is spam discord for 10 minutes
to_chat(usr, "<span class='warning'>You are no longer able to use this, it's been more then 10 minutes since an admin on Discord has responded to you</span>")
return
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(usr, "<span class='warning'>You cannot use this as your client has been muted from sending messages to the admins on Discord</span>")
return
cmd_admin_discord_pm()
@@ -71,8 +71,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/max_gear_slots = 0
//non-preference stuff
var/warns = 0
var/muted = 0
var/last_ip
var/last_id
@@ -356,3 +356,11 @@
prefs.toggles2 ^= PREFTOGGLE_2_SIMPLE_STAT_PANEL
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_SIMPLE_STAT_PANEL) ? "no longer" : "now"] get detailed information on the status panel.")
/client/verb/toggle_item_outlines()
set name = "Toggle Item Outlines"
set category = "Preferences"
set desc = "Toggles seeing item outlines on hover."
prefs.toggles2 ^= PREFTOGGLE_2_SEE_ITEM_OUTLINES
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles2 & PREFTOGGLE_2_SEE_ITEM_OUTLINES) ? "now" : "no longer"] see item outlines on hover.")
+17 -4
View File
@@ -5,6 +5,13 @@
/datum/event/anomaly/proc/findEventArea()
var/static/list/allowed_areas
var/static/list/existing_areas
if(!existing_areas)
existing_areas = list()
for(var/area/AR in world)
var/turf/picked = safepick(get_area_turfs(AR.type))
if(picked && is_station_level(picked.z))
existing_areas += AR
if(!allowed_areas)
//Places that shouldn't explode
var/list/safe_area_types = typecacheof(list(
@@ -20,10 +27,16 @@
)
//Subtypes from the above that actually should explode.
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
var/list/unsafe_area_subtypes = typecacheof(list(
/area/engine/break_room,
/area/engine/equipmentstorage,
/area/engine/chiefs_office,
/area/engine/controlroom,
/area/engine/mechanic_workshop
))
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(GLOB.all_areas, allowed_areas)
allowed_areas = typecacheof(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(existing_areas, allowed_areas)
if(length(possible_areas))
return pick(possible_areas)
@@ -36,7 +49,7 @@
CRASH("Anomaly: No valid turfs found for [impact_area] - [impact_area.type]")
/datum/event/anomaly/announce()
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_flux.ogg')
/datum/event/anomaly/start()
var/turf/T = pick(get_area_turfs(impact_area))
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/bluespace
/datum/event/anomaly/anomaly_bluespace/announce()
GLOB.event_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_bluespace.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/flux
/datum/event/anomaly/anomaly_flux/announce()
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_flux.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/grav
/datum/event/anomaly/anomaly_grav/announce()
GLOB.event_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_gravity.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/pyro
/datum/event/anomaly/anomaly_pyro/announce()
GLOB.event_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_pyro.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/bhole
/datum/event/anomaly/anomaly_vortex/announce()
GLOB.event_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert", 'sound/AI/anomaly_vortex.ogg')
+2 -2
View File
@@ -21,7 +21,7 @@
SEND_SOUND(M, S)
/datum/event/apc_overload/announce()
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", 'sound/AI/power_overload.ogg')
/datum/event/apc_overload/end()
return TRUE
@@ -33,7 +33,7 @@
/area/turret_protected/ai)
if(announce)
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", 'sound/AI/power_overload.ogg')
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
+7 -7
View File
@@ -20,7 +20,7 @@
SEND_SOUND(M, S)
/datum/event/apc_short/announce()
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", 'sound/AI/power_overload.ogg')
/datum/event/apc_short/end()
return TRUE
@@ -30,7 +30,7 @@
/area/engine/engineering,
/area/engine/supermatter,
/area/turret_protected/ai)
GLOB.event_announcement.Announce("Power failure detected in [station_name()]'s powernet. All APCs have lost power. Gravity systems likely to fail.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Power failure detected in [station_name()]'s powernet. All APCs have lost power. Gravity systems likely to fail.", "Systems Power Failure", 'sound/AI/attention.ogg')
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
var/area/current_area = get_area(A)
@@ -49,7 +49,7 @@
/area/engine/supermatter,
/area/turret_protected/ai)
if(announce)
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", 'sound/AI/power_overload.ogg')
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
for(var/thing in GLOB.apcs)
@@ -76,7 +76,7 @@
/proc/power_restore(announce = TRUE, power_type)
if(power_type == 0) //Power without Repairing
if(announce)
GLOB.event_announcement.Announce("All operational APCs on \the [station_name()] have been fully charged.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All operational APCs on \the [station_name()] have been fully charged.", "Power Systems Nominal", 'sound/AI/power_restore.ogg')
var/affected_apc_count = 0
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
@@ -90,7 +90,7 @@
log_and_message_admins("Power has been restored to [affected_apc_count] APCs.")
if(power_type == 1) //Repair without charging
if(announce)
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired.", "Power Systems Nominal", 'sound/AI/power_restore.ogg')
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
var/area/current_area = get_area(A)
@@ -101,7 +101,7 @@
log_and_message_admins("Power has been restored to all APCs.")
if(power_type == 2) //Repair and Power APCs
if(announce)
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired and recharged. We apologize for the inconvenience.", "Power Systems Optimal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired and recharged. We apologize for the inconvenience.", "Power Systems Optimal", 'sound/AI/power_restore.ogg')
// repair the APCs and recharge them
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
@@ -115,7 +115,7 @@
/proc/power_restore_quick(announce = TRUE)
if(announce)
GLOB.event_announcement.Announce("All SMESs on \the [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All SMESs on \the [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/AI/power_restore.ogg')
// fix all of the SMESs
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(!is_station_level(S.z))
+1 -1
View File
@@ -14,7 +14,7 @@
"You don't want to buy anything? Yeah, well I didn't want to buy your mom either.")
/datum/event/brand_intelligence/announce()
GLOB.event_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert")
GLOB.event_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert", 'sound/AI/brand_intelligence.ogg')
/datum/event/brand_intelligence/start()
for(var/obj/machinery/vending/V in GLOB.machines)
+1 -1
View File
@@ -20,7 +20,7 @@
D.carrier = TRUE
/datum/event/disease_outbreak/announce()
GLOB.event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
GLOB.event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak7.ogg')
for(var/p in GLOB.dead_mob_list)
var/mob/M = p
to_chat(M, "<span class='deadsay'><b>[patient_zero]</b> has been infected with <b>[D.name]</b> ([ghost_follow_link(patient_zero, M)])</span>")
+2 -2
View File
@@ -1,7 +1,7 @@
/datum/event/door_runtime
/datum/event/door_runtime/announce()
GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert")
GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert", 'sound/AI/door_runtimes.ogg')
/datum/event/door_runtime/start()
for(var/obj/machinery/door/D in GLOB.airlocks)
@@ -13,4 +13,4 @@
post_status("alert", "lockdown")
/datum/event/door_runtime/proc/reboot()
GLOB.minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:")
GLOB.minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:", 'sound/AI/door_runtimes_fix.ogg')
+1 -2
View File
@@ -3,7 +3,7 @@
var/lightsoutRange = 25
/datum/event/electrical_storm/announce()
GLOB.event_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
GLOB.event_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert", 'sound/AI/elec_storm.ogg')
/datum/event/electrical_storm/start()
var/list/epicentreList = list()
@@ -26,4 +26,3 @@
var/obj/effect/landmark/epicentre = thing
for(var/obj/machinery/power/apc/apc in range(epicentre, lightsoutRange))
INVOKE_ASYNC(apc, /obj/machinery/power/apc.proc/overload_lighting)
+1 -1
View File
@@ -18,7 +18,7 @@
/datum/event/ion_storm/announce()
if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)))
GLOB.event_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/AI/ionstorm.ogg')
GLOB.event_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/AI/ions.ogg')
/datum/event/ion_storm/start()
//AI laws
+1 -1
View File
@@ -5,4 +5,4 @@
/datum/event/carp_migration/koi/start()
spawn_fish(GLOB.landmarks_list.len)
spawn_fish(rand(4, 6)) //12 to 30 koi, in small groups
+1 -1
View File
@@ -4,7 +4,7 @@
announceWhen = 1
/datum/event/solar_flare/announce()
GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/flare.ogg')
/datum/event/solar_flare/start()
SSweather.run_weather(/datum/weather/solar_flare)
+1 -2
View File
@@ -11,7 +11,7 @@
/datum/event/spider_terror/announce()
if(successSpawn)
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg')
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg', new_sound2 = 'sound/AI/outbreak3.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Terror Spiders")
@@ -61,4 +61,3 @@
successSpawn = TRUE
#undef TS_HIGHPOP_TRIGGER
+1 -1
View File
@@ -5,7 +5,7 @@
var/obj/effect/tear/TE
/datum/event/tear/announce()
GLOB.event_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
/datum/event/tear/start()
var/turf/T = pick(get_area_turfs(impact_area))
+1 -1
View File
@@ -6,7 +6,7 @@
var/list/vents = list()
/datum/event/vent_clog/announce()
GLOB.event_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
GLOB.event_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert", 'sound/AI/scrubbers.ogg')
/datum/event/vent_clog/setup()
endWhen = rand(25, 100)
@@ -180,7 +180,7 @@
/obj/item/reagent_containers/food/snacks/grilledcheese
name = "grilled cheese sandwich"
desc = "Goes great with tomato soup!"
icon_state = "toastedsandwich"
icon_state = "grilledcheese"
filling_color = "#D9BE29"
list_reagents = list("nutriment" = 7, "vitamin" = 1) //why make a regualr sandwhich when you can make grilled cheese, with this nutriment value?
tastes = list("toast" = 1, "grilled cheese" = 1)
@@ -139,8 +139,8 @@
to_chat(user, "<span class='danger'>This is not suitable for [src]!</span>")
return
if(victim.abiotic(1))
to_chat(user, "<span class='danger'>Subject may not have abiotic items on.</span>")
if(victim.abiotic(TRUE))
to_chat(user, "<span class='danger'>Subject may not have anything on their body.</span>")
return
user.visible_message("<span class='danger'>[user] starts to put [victim] into [src]!</span>")
+17
View File
@@ -277,6 +277,13 @@
if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
dat += "<a href='?src=[UID()];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "</div>"
dat += "<div class='line'><h3>Variant</h3></div><div class='statusDisplay'><table>"
dat += "<tr><td width='260px'>[seed.variant ? seed.variant : "None"]</td>"
dat += "<td><a href='?src=[UID()];set_v=1'>Edit</a></td>"
if(seed.variant)
dat += "<td><a href='?src=[UID()];del_v=1'>Remove</a></td>"
dat += "</tr></table></div>"
else
dat += "<br>No sample found.<br><span class='highlight'>Please, insert a plant sample to use this device.</span>"
popup.set_content(dat)
@@ -391,6 +398,16 @@
else if(href_list["abort"])
operation = ""
target = null
else if(href_list["set_v"])
if(!seed)
return
seed.variant_prompt(usr, src)
else if(href_list["del_v"])
if(!seed)
return
seed.variant = null
seed.apply_variant_name()
to_chat(usr, "<span class='notice'>You remove the [seed.plantname]'s variant designation.</span>")
interact(usr)
+2
View File
@@ -42,6 +42,8 @@
seed.prepare_result(src)
transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5 //Makes the resulting produce's sprite larger or smaller based on potency!
add_juice()
if(seed.variant)
name += " \[[seed.variant]]"
/obj/item/reagent_containers/food/snacks/grown/Destroy()
QDEL_NULL(seed)
+6 -2
View File
@@ -344,7 +344,10 @@
/obj/machinery/hydroponics/examine(user)
. = ..()
if(myseed)
. += "<span class='info'>It has <span class='name'>[myseed.plantname]</span> planted.</span>"
if(myseed.variant)
. += "<span class='info'>It has the <span class='name'>[myseed.variant]</span> variant of <span class='name'>[myseed.plantname]</span> planted.</span>"
else
. += "<span class='info'>It has <span class='name'>[myseed.plantname]</span> planted.</span>"
if (dead)
. += "<span class='warning'>It's dead!</span>"
else if (harvest)
@@ -875,7 +878,8 @@
plant_hud_set_status()
adjustWeeds(-10) //Has a side effect of cleaning up those nasty weeds
update_icon()
else if(istype(O, /obj/item/pen) && myseed)
myseed.variant_prompt(user, src)
else
return ..()
+7 -5
View File
@@ -109,6 +109,7 @@
/datum/seed_pile
var/name = ""
var/variant = ""
var/lifespan = 0 //Saved stats
var/endurance = 0
var/maturation = 0
@@ -117,8 +118,9 @@
var/potency = 0
var/amount = 0
/datum/seed_pile/New(name, life, endur, matur, prod, yie, poten, am = 1)
/datum/seed_pile/New(name, variant, life, endur, matur, prod, yie, poten, am = 1)
src.name = name
src.variant = variant
src.lifespan = life
src.endurance = endur
src.maturation = matur
@@ -145,9 +147,9 @@
if (contents.len == 0)
dat += "<font color='red'>No seeds</font>"
else
dat += "<table cellpadding='3' style='text-align:center;'><tr><td>Name</td><td>Lifespan</td><td>Endurance</td><td>Maturation</td><td>Production</td><td>Yield</td><td>Potency</td><td>Stock</td></tr>"
dat += "<table cellpadding='3' style='text-align:center;'><tr><td>Name</td><td>Variant</td><td>Lifespan</td><td>Endurance</td><td>Maturation</td><td>Production</td><td>Yield</td><td>Potency</td><td>Stock</td></tr>"
for (var/datum/seed_pile/O in piles)
dat += "<tr><td>[O.name]</td><td>[O.lifespan]</td><td>[O.endurance]</td><td>[O.maturation]</td>"
dat += "<tr><td>[O.name]</td><td>[O.variant]</td><td>[O.lifespan]</td><td>[O.endurance]</td><td>[O.maturation]</td>"
dat += "<td>[O.production]</td><td>[O.yield]</td><td>[O.potency]</td><td>"
dat += "<a href='byond://?src=[src.UID()];name=[O.name];li=[O.lifespan];en=[O.endurance];ma=[O.maturation];pr=[O.production];yi=[O.yield];pot=[O.potency]'>Vend</a> ([O.amount] left)</td></tr>"
dat += "</table>"
@@ -203,9 +205,9 @@
O.forceMove(src)
. = 1
for (var/datum/seed_pile/N in piles)
if (O.plantname == N.name && O.lifespan == N.lifespan && O.endurance == N.endurance && O.maturation == N.maturation && O.production == N.production && O.yield == N.yield && O.potency == N.potency)
if (O.plantname == N.name && O.variant == N.variant && O.lifespan == N.lifespan && O.endurance == N.endurance && O.maturation == N.maturation && O.production == N.production && O.yield == N.yield && O.potency == N.potency)
++N.amount
return
piles += new /datum/seed_pile(O.plantname, O.lifespan, O.endurance, O.maturation, O.production, O.yield, O.potency)
piles += new /datum/seed_pile(O.plantname, O.variant, O.lifespan, O.endurance, O.maturation, O.production, O.yield, O.potency)
return
+31 -1
View File
@@ -10,6 +10,7 @@
var/plantname = "Plants" // Name of plant when planted.
var/product // A type path. The thing that is created when the plant is harvested.
var/species = "" // Used to update icons. Should match the name in the sprites unless all icon_* are overriden.
var/variant = null // Optional custom name to track modified plants. Can be set with pen or from gene modder.
var/growing_icon = 'icons/obj/hydroponics/growing.dmi' //the file that stores the sprites of the growing plant from this seed.
var/icon_grow // Used to override grow icon (default is "[species]-grow"). You can use one grow icon for multiple closely related plants with it.
@@ -83,6 +84,8 @@
S.potency = potency
S.weed_rate = weed_rate
S.weed_chance = weed_chance
S.variant = variant
S.apply_variant_name()
S.genes = list()
for(var/g in genes)
var/datum/plant_gene/G = g
@@ -317,16 +320,43 @@
return
/obj/item/seeds/attackby(obj/item/O, mob/user, params)
if (istype(O, /obj/item/plant_analyzer))
if(istype(O, /obj/item/plant_analyzer))
to_chat(user, "<span class='info'>*---------*\n This is \a <span class='name'>[src]</span>.</span>")
var/text = get_analyzer_text()
if(text)
to_chat(user, "<span class='notice'>[text]</span>")
return
if(istype(O, /obj/item/pen))
variant_prompt(user)
return
..() // Fallthrough to item/attackby() so that bags can pick seeds up
/obj/item/seeds/proc/variant_prompt(mob/user, obj/item/container = null)
var/prev = variant
var/V = input(user, "Choose variant name:", "Plant Variant Naming", variant) as text|null
if(isnull(V)) // Did the user cancel?
return
if(container && (loc != container)) // Was the seed removed from the container, if there is a container?
return
if(!(container ? container : src).Adjacent(user)) // Is the user next to the seed/container?
return
variant = copytext(sanitize(html_encode(trim(V))), 1, 64) // Sanitization must happen after null check because it converts nulls to empty strings
if(variant == "")
variant = null
if(prev != variant)
to_chat(user, "<span class='notice'>You [variant ? "change" : "remove"] the [plantname]'s variant designation.</span>")
apply_variant_name()
/obj/item/seeds/proc/apply_variant_name()
var/V = variant ? " \[[variant]]" : "" // If we have a non-empty variant add it to the name
var/N = initial(name)
if(copytext(name, 1, 13) == "experimental") // Don't delete 'experimental'
N = "experimental " + N
name = N + V
if(GetComponent(/datum/component/label))
GetComponent(/datum/component/label).apply_label() // Don't delete labels
@@ -14,7 +14,7 @@
do { \
var/timer = start_watch(); \
proc2run ;\
log_debug("\[MAZE] Operation '[opname]' on maze at [##x],[##y],[##z] took [stop_watch(timer)]s"); \
log_debug("\[MAZE] Operation '[opname]' on maze at [x],[y],[z] took [stop_watch(timer)]s"); \
} while (FALSE)
+13 -15
View File
@@ -104,21 +104,7 @@
new /obj/item/toy/katana(src)
if(85 to 86)
new /obj/item/defibrillator/compact(src)
if(87) //1% chance
new /obj/item/weed_extract(src)
if(88)
new /obj/item/organ/internal/brain(src)
if(89)
new /obj/item/organ/internal/brain/xeno(src)
if(90)
new /obj/item/organ/internal/heart(src)
if(91)
new /obj/item/soulstone/anybody(src)
if(92)
new /obj/item/katana(src)
if(93)
new /obj/item/dnainjector/xraymut(src)
if(94)
if(87 to 88)
new /obj/item/storage/backpack/clown(src)
new /obj/item/clothing/under/rank/clown(src)
new /obj/item/clothing/shoes/clown_shoes(src)
@@ -128,6 +114,18 @@
new /obj/item/toy/crayon/rainbow(src)
new /obj/item/reagent_containers/spray/waterflower(src)
new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(src)
if(89) //1% chance
new /obj/item/weed_extract(src)
if(90)
new /obj/item/organ/internal/brain(src)
if(91)
new /obj/item/organ/internal/brain/xeno(src)
if(92)
new /obj/item/organ/internal/heart(src)
if(93)
new /obj/item/soulstone/anybody(src)
if(94)
new /obj/item/katana(src)
if(95)
new /obj/item/clothing/under/mime(src)
new /obj/item/clothing/shoes/black(src)
+1 -1
View File
@@ -19,7 +19,7 @@
log_ghostemote(message, src)
if(src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
if(check_mute(client.ckey, MUTE_DEADCHAT))
to_chat(src, "<span class='warning'>You cannot emote in deadchat (muted).</span>")
return
+1 -1
View File
@@ -112,7 +112,7 @@
O.show_message(message, m_type)
/mob/proc/emote_dead(message)
if(client.prefs.muted & MUTE_DEADCHAT)
if(check_mute(client.ckey, MUTE_DEADCHAT))
to_chat(src, "<span class='warning'>You cannot send deadchat emotes (muted).</span>")
return
@@ -14,10 +14,10 @@
if(silent)
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='warning'>You cannot send IC messages (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_IC))
if(src.client.handle_spam_prevention(message, MUTE_IC))
return
if(stat)
return
+8
View File
@@ -1203,6 +1203,14 @@ so that different stomachs can handle things in different ways VB*/
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_in_dark = max(see_in_dark, 8)
if(HAS_TRAIT(src, TRAIT_MESON_VISION))
sight |= SEE_TURFS
lighting_alpha = min(lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
if(HAS_TRAIT(src, TRAIT_NIGHT_VISION))
see_in_dark = max(see_in_dark, 8)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -446,15 +446,14 @@
SpinAnimation(5,1)
if("spin", "spins")
if(!restrained() && !lying)
if(!incapacitated(ignore_lying = TRUE))
if(prob(5))
spin(30, 1)
message = "<B>[src]</B> spins too much!"
spin(32, 1)
to_chat(src, "<span class='warning'>You spin too much!</span>")
Dizzy(12)
Confused(12)
else
spin(20, 1)
message = "<B>[src]</B> spins!"
if("aflap", "aflaps")
if(!restrained())
@@ -39,7 +39,7 @@ emp_act
if(mind?.martial_art?.deflection_chance) //Some martial arts users can deflect projectiles!
if(!lying && !HAS_TRAIT(src, TRAIT_HULK) && mind.martial_art.try_deflect(src)) //But only if they're not lying down, and hulks can't do it
add_attack_logs(P.firer, src, "hit by [P.type] but got deflected by martial arts '[mind.martial_art]'")
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
visible_message("<span class='danger'>[src] deflects the projectile!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
if(mind.martial_art.reroute_deflection)
P.firer = src
@@ -894,13 +894,21 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(!isnull(H.vision_type.lighting_alpha))
H.lighting_alpha = min(H.vision_type.lighting_alpha, H.lighting_alpha)
if(HAS_TRAIT(src, TRAIT_THERMAL_VISION))
if(HAS_TRAIT(H, TRAIT_MESON_VISION))
H.sight |= SEE_TURFS
H.lighting_alpha = min(H.lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
if(HAS_TRAIT(H, TRAIT_THERMAL_VISION))
H.sight |= (SEE_MOBS)
H.lighting_alpha = min(H.lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
if(HAS_TRAIT(H, TRAIT_XRAY_VISION))
H.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
if(HAS_TRAIT(H, TRAIT_NIGHT_VISION))
H.see_in_dark = max(H.see_in_dark, 8)
H.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
if(H.has_status_effect(STATUS_EFFECT_SUMMONEDGHOST))
H.see_invisible = SEE_INVISIBLE_OBSERVER
@@ -21,7 +21,7 @@
death_message = "gives a short series of shrill beeps, their chassis shuddering before falling limp, nonfunctional."
death_sounds = list('sound/voice/borg_deathsound.ogg') //I've made this a list in the event we add more sounds for dead robots.
species_traits = list(IS_WHITELISTED, NO_BLOOD, NO_CLONESCAN, NO_INTORGANS, NOTRANSSTING)
species_traits = list(IS_WHITELISTED, NO_BLOOD, NO_CLONESCAN, NO_INTORGANS)
inherent_traits = list(TRAIT_VIRUSIMMUNE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_NOGERMS, TRAIT_NODECAY, TRAIT_NOPAIN, TRAIT_GENELESS) //Computers that don't decay? What a lie!
inherent_biotypes = MOB_ROBOTIC | MOB_HUMANOID
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
@@ -5,7 +5,7 @@
dangerous_existence = TRUE //So so much
//language = "Clatter"
species_traits = list(IS_WHITELISTED, NO_BLOOD, NOTRANSSTING, NO_HAIR)
species_traits = list(IS_WHITELISTED, NO_BLOOD, NO_HAIR)
inherent_traits = list(TRAIT_RADIMMUNE, TRAIT_NOHUNGER)
inherent_biotypes = MOB_HUMANOID | MOB_MINERAL
forced_heartattack = TRUE // Plasmamen have no blood, but they should still get heart-attacks
@@ -22,7 +22,7 @@
eyes = "vox_eyes_s"
species_traits = list(NO_CLONESCAN, IS_WHITELISTED, NOTRANSSTING)
species_traits = list(NO_CLONESCAN, IS_WHITELISTED)
inherent_traits = list(TRAIT_NOGERMS, TRAIT_NODECAY)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS //Species-fitted 'em all.
dietflags = DIET_OMNI
+1 -1
View File
@@ -760,7 +760,7 @@
//called when the mob receives a bright flash
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(check_eye_prot() < intensity && (override_blindness_check || !HAS_TRAIT(src, TRAIT_BLIND)))
if(check_eye_prot() < intensity && (override_blindness_check || !HAS_TRAIT(src, TRAIT_BLIND)) && !HAS_TRAIT(src, TRAIT_FLASH_PROTECTION))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
return 1
+3 -3
View File
@@ -110,7 +110,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
/mob/living/say(message, verb = "says", sanitize = TRUE, ignore_speech_problems = FALSE, ignore_atmospherics = FALSE, ignore_languages = FALSE)
if(client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
@@ -297,7 +297,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
/mob/living/emote(act, type, message, force) //emote code is terrible, this is so that anything that isn't already snowflaked to shit can call the parent and handle emoting sanely
if(client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
@@ -352,7 +352,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
/mob/living/proc/whisper_say(list/message_pieces, verb = "whispers")
if(client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='danger'>You cannot speak in IC (Muted).</span>")
return
+14 -11
View File
@@ -212,6 +212,20 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
GLOB.shuttle_caller_list += src
..()
/mob/living/silicon/ai/Destroy()
GLOB.ai_list -= src
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
if(malfhacking)
deltimer(malfhacking)
malfhacking = null
QDEL_NULL(eyeobj) // No AI, no Eye
QDEL_NULL(aiPDA)
QDEL_NULL(aiMulti)
QDEL_NULL(aiRadio)
QDEL_NULL(builtInCamera)
return ..()
/mob/living/silicon/ai/proc/on_mob_init()
to_chat(src, "<B>You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).</B>")
to_chat(src, "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>")
@@ -314,17 +328,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
return TRUE
/mob/living/silicon/ai/Destroy()
GLOB.ai_list -= src
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
QDEL_NULL(eyeobj) // No AI, no Eye
if(malfhacking)
deltimer(malfhacking)
malfhacking = null
malfhack = null
return ..()
/*
The AI Power supply is a dummy object used for powering the AI since only machinery should be using power.
+1 -1
View File
@@ -27,7 +27,7 @@
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/eshuttle_dock.ogg')
qdel(doomsday_device)
if(explosive)
+11 -48
View File
@@ -1147,55 +1147,18 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
cell = null
qdel(src)
#define BORG_CAMERA_BUFFER 30
/mob/living/silicon/robot/Move(a, b, flag)
var/oldLoc = src.loc
#define BORG_CAMERA_BUFFER 3 SECONDS
/mob/living/silicon/robot/Move(atom/newloc, direct, movetime)
var/oldLoc = loc
. = ..()
if(.)
if(src.camera)
if(!updating)
updating = 1
spawn(BORG_CAMERA_BUFFER)
if(camera && oldLoc != src.loc)
GLOB.cameranet.updatePortableCamera(src.camera)
updating = 0
if(module)
if(module.type == /obj/item/robot_module/janitor)
var/turf/tile = loc
if(stat != DEAD && isturf(tile))
var/floor_only = TRUE
for(var/A in tile)
if(istype(A, /obj/effect))
var/obj/effect/E = A
if(E.is_cleanable())
var/obj/effect/decal/cleanable/blood/B = E
if(istype(B) && B.off_floor)
floor_only = FALSE
else
qdel(E)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
else if(istype(A, /mob/living/carbon/human))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
if(floor_only)
tile.clean_blood()
return
if(. && !updating && camera)
updating = TRUE
spawn(BORG_CAMERA_BUFFER)
if(camera && oldLoc != loc)
GLOB.cameranet.updatePortableCamera(camera)
updating = FALSE
#undef BORG_CAMERA_BUFFER
/mob/living/silicon/robot/proc/self_destruct()
@@ -447,6 +447,43 @@
/obj/item/extinguisher/mini
)
/obj/item/robot_module/janitor/Initialize(mapload)
. = ..()
var/mob/living/silicon/robot/R = loc
RegisterSignal(R, COMSIG_MOVABLE_MOVED, .proc/on_cyborg_move)
/**
* Proc called after the janitor cyborg has moved, in order to clean atoms at it's new location.
*
* Arguments:
* * mob/living/silicon/robot/R - The cyborg who moved.
*/
/obj/item/robot_module/janitor/proc/on_cyborg_move(mob/living/silicon/robot/R)
SIGNAL_HANDLER
if(R.stat == DEAD || !isturf(R.loc))
return
var/turf/tile = R.loc
for(var/A in tile)
if(iseffect(A))
var/obj/effect/E = A
if(!E.is_cleanable())
continue
var/obj/effect/decal/cleanable/blood/B = E
if(istype(B) && B.off_floor)
tile.clean_blood()
else
qdel(E)
else if(isitem(A))
var/obj/item/I = A
I.clean_blood()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(!cleaned_human.lying)
continue
cleaned_human.clean_blood()
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
/obj/item/reagent_containers/spray/cyborg_lube
name = "Lube spray"
list_reagents = list("lube" = 250)
@@ -33,27 +33,16 @@
// break_stuff_probability = 2
faction = list("scarybat")
var/mob/living/owner
gold_core_spawnable = HOSTILE_SPAWN
/mob/living/simple_animal/hostile/scarybat/New(loc, mob/living/L as mob)
..()
/mob/living/simple_animal/hostile/scarybat/Initialize(mapload, mob/living/L)
. = ..()
if(istype(L))
owner = L
faction += "\ref[L]"
/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(check_drift = 0)
return ..() //No drifting in space for space carp! //original comments do not steal
/mob/living/simple_animal/hostile/scarybat/Found(atom/A)//This is here as a potential override to pick a specific target if available
if(istype(A) && A == owner)
return 0
return ..()
/mob/living/simple_animal/hostile/scarybat/CanAttack(atom/the_target)//This is here as a potential override to pick a specific target if available
if(istype(the_target) && the_target == owner)
return 0
return ..()
/mob/living/simple_animal/hostile/scarybat/AttackingTarget()
. =..()
var/mob/living/L = .
@@ -31,7 +31,6 @@
move_to_delay = 0
obj_damage = 0
environment_smash = 0
mouse_opacity = MOUSE_OPACITY_OPAQUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
density = FALSE
mob_size = MOB_SIZE_TINY
@@ -51,6 +50,8 @@
var/isqueen = FALSE
var/bee_syndicate = FALSE
var/icon_base = "bee"
var/last_attack = 0
var/opacity_time = 1 MINUTES
var/static/list/bee_icons = list()
var/static/beehometypecache = typecacheof(/obj/structure/beebox)
var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
@@ -162,6 +163,7 @@
else
. = ..()
if(. && isliving(target) && (!client || a_intent == INTENT_HARM))
make_opaque()
var/mob/living/L = target
if(L.reagents)
if(beegent)
@@ -170,6 +172,23 @@
else
L.reagents.add_reagent("spidertoxin", 5)
/mob/living/simple_animal/hostile/poison/bees/proc/make_opaque()
// If a bee attacks someone, make it very easy to hit for a while
last_attack = world.time
mouse_opacity = MOUSE_OPACITY_OPAQUE
/mob/living/simple_animal/hostile/poison/bees/Life(seconds, times_fired)
. = ..()
if(mind || (mouse_opacity == initial(mouse_opacity)))
return
var/diff = world.time - last_attack
if(diff >= opacity_time)
mouse_opacity = initial(mouse_opacity)
/mob/living/simple_animal/hostile/poison/bees/sentience_act()
. = ..()
make_opaque()
/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R)
if(istype(R))
beegent = R
@@ -233,6 +252,7 @@
desc = "She's the queen of bees, BZZ BZZ"
icon_base = "queen"
isqueen = TRUE
mouse_opacity = MOUSE_OPACITY_OPAQUE
//the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
@@ -324,6 +344,7 @@
search_objects = FALSE //these bees don't care about trivial things like plants, especially when there is havoc to sow
bee_syndicate = TRUE
var/list/master_and_friends = list()
mouse_opacity = MOUSE_OPACITY_OPAQUE
/mob/living/simple_animal/hostile/poison/bees/syndi/New()
beegent = GLOB.chemical_reagents_list["facid"] //Prepare to die
@@ -33,7 +33,7 @@
/mob/living/simple_animal/hostile/netherworld/migo/Initialize(mapload)
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/voice/bcreep.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/mpatchedup.ogg', 'sound/voice/mfeelbetter.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heartbeat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/goonstation/effects/screech.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/goonstation/misc/airraid_loop.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/chainsaw.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshots/gunshot_silenced.ogg', 'sound/weapons/gunshots/gunshot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlock_close.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlock_open.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg', 'sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen10.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg') //hahahaha fuck you code divers
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/voice/bcreep.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/mpatchedup.ogg', 'sound/voice/mfeelbetter.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heartbeat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/goonstation/effects/screech.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/goonstation/misc/airraid_loop.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/chainsaw.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshots/gunshot_silenced.ogg', 'sound/weapons/gunshots/gunshot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlock_close.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlock_open.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/alert.ogg', 'sound/ai/radiation.ogg', 'sound/ai/eshuttle_call.ogg', 'sound/ai/eshuttle_dock.ogg', 'sound/ai/eshuttle_recall.ogg', 'sound/ai/aimalf.ogg', 'sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen10.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg') //hahahaha fuck you code divers
/mob/living/simple_animal/hostile/netherworld/migo/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
..()
@@ -19,10 +19,10 @@
if(silent)
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='warning'>You cannot send IC messages (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_IC))
if(src.client.handle_spam_prevention(message, MUTE_IC))
return
if(stat)
return
+13 -9
View File
@@ -1351,17 +1351,21 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
return FALSE //overridden in living.dm
/mob/proc/spin(spintime, speed)
set waitfor = 0
set waitfor = FALSE
if(!spintime || !speed || spintime > 100)
CRASH("Aborted attempted call of /mob/proc/spin with invalid args ([spintime],[speed]) which could have frozen the server.")
var/end_time = world.time + spintime
var/spin_dir = prob(50)
while(world.time <= end_time)
while(spintime >= speed)
sleep(speed)
if(spin_dir)
dir = turn(dir, 90)
else
dir = turn(dir, -90)
switch(dir)
if(NORTH)
setDir(EAST)
if(SOUTH)
setDir(WEST)
if(EAST)
setDir(SOUTH)
if(WEST)
setDir(NORTH)
spintime -= speed
/mob/proc/is_literate()
return FALSE
@@ -1479,7 +1483,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
MA.plane = GAME_PLANE
pic.appearance = MA
flick_overlay(pic, list(client), 10)
GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
/area/chapel
+1 -1
View File
@@ -51,7 +51,7 @@
to_chat(src, "<span class='danger'>Deadchat is globally muted.</span>")
return
if(client.prefs.muted & MUTE_DEADCHAT)
if(check_mute(client.ckey, MUTE_DEADCHAT))
to_chat(src, "<span class='warning'>You cannot talk in deadchat (muted).</span>")
return
+6 -2
View File
@@ -40,11 +40,15 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
/// Target department to send outgoing faxes to
var/destination
/obj/machinery/photocopier/faxmachine/New()
..()
/obj/machinery/photocopier/faxmachine/Initialize(mapload)
. = ..()
GLOB.allfaxes += src
update_network()
/obj/machinery/photocopier/faxmachine/Destroy()
GLOB.allfaxes -= src
return ..()
/obj/machinery/photocopier/faxmachine/proc/update_network()
if(department != "Unknown")
if(!(("[department]" in GLOB.alldepartments) || ("[department]" in GLOB.hidden_departments) || ("[department]" in GLOB.admin_departments) || ("[department]" in GLOB.hidden_admin_departments)))
+30 -9
View File
@@ -28,6 +28,11 @@
disconnect("Program Terminated")
STOP_PROCESSING(SSobj, pda)
/datum/data/pda/app/mob_hunter_game/Destroy()
STOP_PROCESSING(SSobj, pda)
SSmob_hunt.connected_clients -= src
return ..()
/datum/data/pda/app/mob_hunter_game/proc/scan_nearby()
if(!SSmob_hunt || !connected)
return
@@ -74,13 +79,14 @@
return
scan_nearby()
/datum/data/pda/app/mob_hunter_game/proc/register_capture(datum/mob_hunt/captured, wild = 0)
/datum/data/pda/app/mob_hunter_game/proc/register_capture(datum/mob_hunt/captured, wild = FALSE)
if(!captured)
return 0
my_collection.Add(captured)
return FALSE
my_collection += captured
RegisterSignal(captured, COMSIG_PARENT_QDELETING, .proc/remove_mob)
if(wild)
wild_captures++
return 1
return TRUE
/datum/data/pda/app/mob_hunter_game/update_ui(mob/user, list/data)
if(!SSmob_hunt || !(src in SSmob_hunt.connected_clients))
@@ -138,12 +144,27 @@
card.forceMove(get_turf(pda))
remove_mob()
/datum/data/pda/app/mob_hunter_game/proc/remove_mob()
if(!my_collection.len)
/**
* Removes a Nanomob from the [my_collection] list.
*
* The Nanomob that is currently selected in the app ([current_index]) will be removed from the list unless a `mob_override` argument is given, in which case that will be removed instead.
*
* Arguments:
* * mob_override - A specific Nanomob to remove from the list. (Optional)
*/
/datum/data/pda/app/mob_hunter_game/proc/remove_mob(datum/mob_hunt/mob_override = null)
SIGNAL_HANDLER
if(!length(my_collection))
return
my_collection.Remove(my_collection[current_index])
if(current_index > my_collection.len)
current_index = my_collection.len
if(mob_override)
my_collection -= mob_override
else
my_collection -= my_collection[current_index]
var/collection_length = length(my_collection)
if(current_index > collection_length)
current_index = collection_length
/datum/data/pda/app/mob_hunter_game/proc/set_trap()
if(!my_collection.len || !pda || !hacked)
+10 -5
View File
@@ -35,6 +35,7 @@ By design, d1 is the smallest direction and d2 is the highest
icon_state = "0-1"
var/d1 = 0
var/d2 = 1
plane = FLOOR_PLANE
layer = WIRE_LAYER //Just below unary stuff, which is at 2.45 and above pipes, which are at 2.4
color = COLOR_RED
@@ -68,9 +69,11 @@ By design, d1 is the smallest direction and d2 is the highest
d2 = text2num(copytext( icon_state, dash+1 ))
var/turf/T = get_turf(src) // hide if turf is not intact
LAZYADD(GLOB.cable_list, src) //add it to the global cable list
if(T.transparent_floor)
return
if(level == 1)
hide(T.intact)
LAZYADD(GLOB.cable_list, src) //add it to the global cable list
/obj/structure/cable/Destroy() // called when a cable is deleted
if(powernet)
@@ -162,7 +165,8 @@ By design, d1 is the smallest direction and d2 is the highest
//
/obj/structure/cable/attackby(obj/item/W, mob/user)
var/turf/T = get_turf(src)
if(T.intact)
if(T.transparent_floor || T.intact)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return
else if(istype(W, /obj/item/stack/cable_coil))
@@ -204,7 +208,8 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/wirecutter_act(mob/user, obj/item/I)
. = TRUE
var/turf/T = get_turf(src)
if(T.intact)
if(T.transparent_floor || T.intact)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
return
@@ -703,7 +708,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe/cable_restrain
var/turf/T = get_turf(C)
if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
if(!isturf(T) || T.intact || T.transparent_floor) // sanity checks, also stop use interacting with T-scanner revealed cable
return
if(get_dist(C, user) > 1) // make sure it's close enough
@@ -719,7 +724,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe/cable_restrain
// one end of the clicked cable is pointing towards us
if(C.d1 == dirn || C.d2 == dirn)
if(U.intact) // can't place a cable if the floor is complete
if(U.intact || U.transparent_floor) // can't place a cable if the floor is complete
to_chat(user, "<span class='warning'>You can't lay cable there unless the floor tiles are removed!</span>")
return
else
+7 -1
View File
@@ -284,6 +284,12 @@
charge = 0
update_icon()
/obj/item/stock_parts/cell/bluespace/charging
name = "self-charging bluespace power cell"
desc = "An experimental, self-charging, transdimensional power cell."
origin_tech = "powerstorage=10;bluespace=10"
self_recharge = TRUE
/obj/item/stock_parts/cell/infinite
name = "infinite-capacity power cell!"
icon_state = "icell"
@@ -294,7 +300,7 @@
chargerate = 30000
/obj/item/stock_parts/cell/infinite/use()
return 1
return TRUE
/obj/item/stock_parts/cell/infinite/abductor
name = "void core"
-2
View File
@@ -352,8 +352,6 @@
overlays += "[icon_state]_broken"
else
overlays += icon_screen
if(cdir > -1)
overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))
/obj/machinery/power/solar_control/attack_ai(mob/user as mob)
add_hiddenprint(user)
@@ -221,7 +221,7 @@
return
var/mob/living/carbon/human/H = user
var/immune = istype(H.glasses, /obj/item/clothing/glasses/meson)
if(!immune && (get_dist(user, src) < HALLUCINATION_RANGE(power)))
if(!immune && !HAS_TRAIT(H, TRAIT_MESON_VISION) && (get_dist(user, src) < HALLUCINATION_RANGE(power)))
. += "<span class='danger'>You get headaches just from looking at it.</span>"
/obj/machinery/power/supermatter_crystal/detailed_examine()
@@ -537,7 +537,7 @@
//Makes em go mad and accumulate rads.
for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them.
if(!istype(l.glasses, /obj/item/clothing/glasses/meson))
if(!istype(l.glasses, /obj/item/clothing/glasses/meson) && !HAS_TRAIT(l, TRAIT_MESON_VISION))
var/D = sqrt(1 / max(1, get_dist(l, src)))
l.hallucination += power * hallucination_power * D
l.hallucination = clamp(l.hallucination, 0, 200)
+2
View File
@@ -15,6 +15,8 @@
/obj/machinery/power/terminal/Initialize(mapload)
. = ..()
var/turf/T = get_turf(src)
if(T.transparent_floor)
return
if(level == 1)
hide(T.intact)
+1 -1
View File
@@ -53,7 +53,7 @@
fire_sound = 'sound/magic/staff_door.ogg'
/obj/item/gun/magic/staff/slipping
name = "wand of slipping"
name = "staff of slipping"
desc = "An artefact that spits... bananas?"
ammo_type = /obj/item/ammo_casing/magic/slipping
icon_state = "staffofslipping"
+2 -2
View File
@@ -51,7 +51,7 @@
user.visible_message("<span class='danger'>[user] zaps [user.p_them()]self with [src].</span>")
playsound(user, fire_sound, 50, 1)
user.create_attack_log("<b>[key_name(user)]</b> zapped [user.p_them()]self with a <b>[src]</b>")
add_attack_logs(null, user, "zapped [user.p_them()]self with a [src]", ATKLOG_ALL)
add_attack_logs(user, user, "zapped [user.p_them()]self with a [src]", ATKLOG_ALL)
/////////////////////////////////////
//WAND OF DEATH
@@ -182,7 +182,7 @@
desc = "This wand shoots... banana peels?"
fire_sound = 'sound/items/bikehorn.ogg'
ammo_type = /obj/item/ammo_casing/magic/slipping
icon_state = "staffofslipping"
icon_state = "wandofslipping"
max_charges = 5 //5, 4, 3, 2
/obj/item/gun/magic/wand/slipping/zap_self(mob/living/user)
+1 -1
View File
@@ -81,7 +81,7 @@
if(!istype(user_turf))
return 0
var/obj/dummy = new(user_turf)
dummy.pass_flags |= PASSTABLE & PASSGLASS & PASSGRILLE //Grille/Glass so it can be used through common windows
dummy.pass_flags |= PASSTABLE & PASSGLASS & PASSGRILLE & PASSFENCE //Grille/Glass so it can be used through common windows
for(var/turf/turf in getline(user_turf,target))
if(turf.density)
qdel(dummy)
+2 -2
View File
@@ -142,8 +142,8 @@
/obj/item/projectile/beam/immolator/on_hit(atom/target, blocked = 0)
. = ..()
if(istype(target, /mob/living/carbon))
var/mob/living/carbon/M = target
if(isliving(target))
var/mob/living/M = target
M.adjust_fire_stacks(1)
M.IgniteMob()
+1 -1
View File
@@ -275,7 +275,7 @@
return
M.create_attack_log("<font color='orange'>[key_name(M)] became [new_mob.real_name].</font>")
add_attack_logs(null, M, "became [new_mob.real_name]", ATKLOG_ALL)
add_attack_logs(M, M, "became [new_mob.real_name]", ATKLOG_ALL)
new_mob.a_intent = INTENT_HARM
if(M.mind)
@@ -915,8 +915,8 @@
name = "Gimlet"
id = "gimlet"
result = "gimlet"
required_reagents = list("gin" = 1, "limejuice" = 1)
result_amount = 2
required_reagents = list("gin" = 1, "limejuice" = 1, "sugar" = 1)
result_amount = 3
mix_sound = 'sound/goonstation/misc/drinkfizz.ogg'
/datum/chemical_reaction/sidecar
+12 -3
View File
@@ -691,6 +691,7 @@
armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
damage_deflection = 10
flags_2 = RAD_PROTECT_CONTENTS_2 | RAD_NO_CONTAMINATE_2
plane = FLOOR_PLANE
layer = DISPOSAL_PIPE_LAYER // slightly lower than wires and other pipes
var/base_icon_state // initial icon state on map
@@ -757,6 +758,9 @@
// update the icon_state to reflect hidden status
/obj/structure/disposalpipe/proc/update()
var/turf/T = get_turf(src)
if(T.transparent_floor)
update_icon()
return
hide(T.intact && !istype(T, /turf/space)) // space never hides pipes
update_icon()
@@ -889,15 +893,20 @@
/obj/structure/disposalpipe/attackby(obj/item/I, mob/user, params)
var/turf/T = get_turf(src)
if(T.intact)
return // prevent interaction with T-scanner revealed pipes
if(T.intact || T.transparent_floor)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return // prevent interaction with T-scanner revealed pipes and pipes under glass
add_fingerprint(user)
/obj/structure/disposalpipe/welder_act(mob/user, obj/item/I)
. = TRUE
var/turf/T = get_turf(src)
if(!I.tool_use_check(user, 0))
return
if(T.transparent_floor)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return
WELDER_ATTEMPT_SLICING_MESSAGE
if(!I.use_tool(src, user, 30, volume = I.tool_volume))
return
@@ -1201,7 +1210,7 @@
return
var/turf/T = src.loc
if(T.intact)
if(T.intact || T.transparent_floor)
return // prevent interaction with T-scanner revealed pipes
src.add_fingerprint(user)
+17 -15
View File
@@ -11,19 +11,17 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
container_type = OPENCONTAINER
categories = list(
"AI Modules",
"Computer Boards",
"Engineering Machinery",
"Exosuit Modules",
"Hydroponics Machinery",
"Medical Machinery",
"Misc. Machinery",
"Research Machinery",
"Subspace Telecomms",
"Teleportation Machinery"
)
reagents = new()
"AI Modules",
"Computer Boards",
"Engineering Machinery",
"Exosuit Modules",
"Hydroponics Machinery",
"Medical Machinery",
"Misc. Machinery",
"Research Machinery",
"Subspace Telecomms",
"Teleportation Machinery"
)
/obj/machinery/r_n_d/circuit_imprinter/New()
..()
@@ -33,8 +31,8 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
component_parts += new /obj/item/stock_parts/manipulator(null)
component_parts += new /obj/item/reagent_containers/glass/beaker(null)
component_parts += new /obj/item/reagent_containers/glass/beaker(null)
create_reagents()
RefreshParts()
reagents.my_atom = src
/obj/machinery/r_n_d/circuit_imprinter/upgraded/New()
..()
@@ -45,7 +43,11 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
component_parts += new /obj/item/reagent_containers/glass/beaker/large(null)
component_parts += new /obj/item/reagent_containers/glass/beaker/large(null)
RefreshParts()
reagents.my_atom = src
/obj/machinery/r_n_d/circuit_imprinter/Destroy()
if(linked_console)
linked_console.linked_imprinter = null
return ..()
/obj/machinery/r_n_d/circuit_imprinter/RefreshParts()
reagents.maximum_volume = 0
@@ -72,6 +72,16 @@
build_path = /obj/item/defibrillator
category = list("Medical")
/datum/design/compact_defib
name = "Compact Defibrillator"
desc = "A belt-mounted defibrillator for rapid deployment."
id = "compact_defib"
req_tech = list("materials" = 7, "biotech" = 7, "powerstorage" = 6)
build_type = PROTOLATHE
materials = list(MAT_METAL = 10000, MAT_GLASS = 4000, MAT_SILVER = 2000)
build_path = /obj/item/defibrillator/compact
category = list("Medical")
/datum/design/defib_mount
name = "Defibrillator Wall Mount"
desc = "A wall mount for defibrillator units."
@@ -29,6 +29,11 @@ Note: Must be placed within 3 tiles of the R&D Console
component_parts += new /obj/item/stock_parts/micro_laser/ultra(null)
RefreshParts()
/obj/machinery/r_n_d/destructive_analyzer/Destroy()
if(linked_console)
linked_console.linked_destroy = null
return ..()
/obj/machinery/r_n_d/destructive_analyzer/RefreshParts()
var/T = 0
for(var/obj/item/stock_parts/S in component_parts)
+4 -2
View File
@@ -60,14 +60,16 @@ GLOBAL_LIST_EMPTY(message_servers)
var/active = TRUE
var/decryptkey = "password"
/obj/machinery/message_server/New()
/obj/machinery/message_server/Initialize(mapload)
. = ..()
GLOB.message_servers += src
decryptkey = GenerateKey()
send_pda_message("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.")
..()
/obj/machinery/message_server/Destroy()
GLOB.message_servers -= src
QDEL_LIST(pda_msgs)
QDEL_LIST(rc_msgs)
return ..()
/obj/machinery/message_server/process()
+15 -16
View File
@@ -14,19 +14,16 @@ Note: Must be placed west/left of and R&D console to function.
container_type = OPENCONTAINER
categories = list(
"Bluespace",
"Equipment",
"Janitorial",
"Medical",
"Mining",
"Miscellaneous",
"Power",
"Stock Parts",
"Weapons"
)
reagents = new()
"Bluespace",
"Equipment",
"Janitorial",
"Medical",
"Mining",
"Miscellaneous",
"Power",
"Stock Parts",
"Weapons"
)
/obj/machinery/r_n_d/protolathe/New()
..()
@@ -38,10 +35,9 @@ Note: Must be placed west/left of and R&D console to function.
component_parts += new /obj/item/stock_parts/manipulator(null)
component_parts += new /obj/item/reagent_containers/glass/beaker/large(null)
component_parts += new /obj/item/reagent_containers/glass/beaker/large(null)
create_reagents()
RefreshParts()
reagents.my_atom = src
/obj/machinery/r_n_d/protolathe/upgraded/New()
..()
component_parts = list()
@@ -54,7 +50,10 @@ Note: Must be placed west/left of and R&D console to function.
component_parts += new /obj/item/reagent_containers/glass/beaker/large(null)
RefreshParts()
reagents.my_atom = src
/obj/machinery/r_n_d/protolathe/Destroy()
if(linked_console)
linked_console.linked_lathe = null
return ..()
/obj/machinery/r_n_d/protolathe/RefreshParts()
var/T = 0
+14
View File
@@ -176,6 +176,20 @@ won't update every console in existence) but it's more of a hassle to do. Also,
SyncRDevices()
/obj/machinery/computer/rdconsole/Destroy()
QDEL_NULL(files)
QDEL_NULL(t_disk)
QDEL_NULL(d_disk)
QDEL_LIST(matching_designs)
if(linked_destroy)
linked_destroy.linked_console = null
linked_destroy = null
if(linked_lathe)
linked_lathe.linked_console = null
linked_lathe = null
if(linked_imprinter)
linked_imprinter.linked_console = null
linked_imprinter = null
if(wait_message_timer)
deltimer(wait_message_timer)
wait_message_timer = 0
+11 -6
View File
@@ -32,12 +32,17 @@
wires["Black"] = 0
wires["White"] = 0
var/list/w = list("Red","Blue","Green","Yellow","Black","White")
src.hack_wire = pick(w)
w -= src.hack_wire
src.shock_wire = pick(w)
w -= src.shock_wire
src.disable_wire = pick(w)
w -= src.disable_wire
hack_wire = pick_n_take(w)
shock_wire = pick_n_take(w)
disable_wire = pick_n_take(w)
/obj/machinery/r_n_d/Destroy()
if(loaded_item)
loaded_item.forceMove(get_turf(src))
loaded_item = null
linked_console = null
materials = null
return ..()
/obj/machinery/r_n_d/attack_hand(mob/user as mob)
if(shocked)
+2 -2
View File
@@ -340,7 +340,7 @@
/obj/item/organ/internal/cyberimp/arm/surgery,
/obj/item/organ/internal/cyberimp/chest/nutriment
)
belt = /obj/item/defibrillator/compact/loaded
belt = /obj/item/defibrillator/compact/advanced/loaded
l_pocket = /obj/item/reagent_containers/hypospray/safety/ert
r_pocket = /obj/item/melee/classic_baton/telescopic
@@ -369,7 +369,7 @@
mask = /obj/item/clothing/mask/gas/sechailer/swat
suit_store = /obj/item/gun/energy/gun/blueshield/pdw9
belt = /obj/item/defibrillator/compact/loaded
belt = /obj/item/defibrillator/compact/advanced/loaded
l_pocket = /obj/item/reagent_containers/hypospray/combat/nanites
r_pocket = /obj/item/reagent_containers/hypospray/autoinjector
@@ -33,7 +33,7 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
switch(level)
if(SEC_LEVEL_GREEN)
GLOB.security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
GLOB.security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.", 'sound/AI/green.ogg')
GLOB.security_level = SEC_LEVEL_GREEN
post_status("alert", "outline")
@@ -45,9 +45,9 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
if(SEC_LEVEL_BLUE)
if(GLOB.security_level < SEC_LEVEL_BLUE)
GLOB.security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
GLOB.security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.", 'sound/AI/blue.ogg')
else
GLOB.security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
GLOB.security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.", 'sound/AI/blue.ogg')
GLOB.security_level = SEC_LEVEL_BLUE
post_status("alert", "outline")
@@ -59,9 +59,9 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
if(SEC_LEVEL_RED)
if(GLOB.security_level < SEC_LEVEL_RED)
GLOB.security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
GLOB.security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!", 'sound/AI/red.ogg')
else
GLOB.security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
GLOB.security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!", 'sound/AI/red.ogg')
GLOB.security_level = SEC_LEVEL_RED
var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in GLOB.airlocks
@@ -77,7 +77,7 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
if(SEC_LEVEL_GAMMA)
GLOB.security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location.", "Attention! Gamma security level activated!", sound('sound/effects/new_siren.ogg'))
GLOB.security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location.", "Attention! Gamma security level activated!", 'sound/effects/new_siren.ogg', new_sound2 = 'sound/AI/gamma.ogg')
GLOB.security_level = SEC_LEVEL_GAMMA
if(GLOB.security_level < SEC_LEVEL_RED)
@@ -95,7 +95,7 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
FA.update_icon()
if(SEC_LEVEL_EPSILON)
GLOB.security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!", new_sound = sound('sound/effects/purge_siren.ogg'))
GLOB.security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!", 'sound/effects/purge_siren.ogg', new_sound2 = 'sound/AI/epsilon.ogg')
GLOB.security_level = SEC_LEVEL_EPSILON
post_status("alert", "epsilonalert")
@@ -106,7 +106,7 @@ GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/secur
FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
if(SEC_LEVEL_DELTA)
GLOB.security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!", new_sound = sound('sound/effects/deltaalarm.ogg'))
GLOB.security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!", 'sound/effects/deltaalarm.ogg', new_sound2 = 'sound/AI/delta.ogg')
GLOB.security_level = SEC_LEVEL_DELTA
post_status("alert", "deltaalert")
+14 -7
View File
@@ -86,12 +86,15 @@
travelDir = 0
var/sound_played = 0 //If the launch sound has been sent to all players on the shuttle itself
var/datum/announcement/priority/emergency_shuttle_docked = new(0, new_sound = sound('sound/AI/shuttledock.ogg'))
var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg'))
var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg'))
var/datum/announcement/priority/emergency_shuttle_docked = new(0, new_sound = sound('sound/AI/eshuttle_dock.ogg'))
var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/eshuttle_call.ogg'))
var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/eshuttle_recall.ogg'))
var/canRecall = TRUE //no bad condom, do not recall the crew transfer shuttle!
var/datum/announcement/priority/crew_shuttle_called = new(0, new_sound = sound('sound/AI/cshuttle.ogg'))
var/datum/announcement/priority/crew_shuttle_docked = new(0, new_sound = sound('sound/AI/cshuttle_dock.ogg'))
/obj/docking_port/mobile/emergency/register()
if(!..())
@@ -146,9 +149,10 @@
SSshuttle.emergencyLastCallLoc = signalOrigin
else
SSshuttle.emergencyLastCallLoc = null
emergency_shuttle_called.Announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]")
if(canRecall)
emergency_shuttle_called.Announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]")
else
crew_shuttle_called.Announce("The crew transfer shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason]")
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
if(!canRecall)
@@ -230,7 +234,10 @@
return
mode = SHUTTLE_DOCKED
timer = world.time
emergency_shuttle_docked.Announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.")
if(canRecall)
emergency_shuttle_docked.Announce("The emergency shuttle has docked with the station. You have [timeLeft(600)] minutes to board the emergency shuttle.")
else
crew_shuttle_docked.Announce("The crew transfer shuttle has docked with the station. You have [timeLeft(600)] minutes to board the crew transfer shuttle.")
/*
//Gangs only have one attempt left if the shuttle has docked with the station to prevent suffering from dominator delays

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