Merge branch 'master' into revenant_TK

This commit is contained in:
Artur
2021-01-20 18:27:11 +02:00
414 changed files with 6097 additions and 2811 deletions
@@ -69,7 +69,7 @@ GLOBAL_LIST_EMPTY(actionspeed_modification_cache)
return TRUE
remove_actionspeed_modifier(existing, FALSE)
if(length(actionspeed_modification))
BINARY_INSERT(type_or_datum.id, actionspeed_modification, datum/actionspeed_modifier, type_or_datum, priority, COMPARE_VALUE)
BINARY_INSERT(type_or_datum.id, actionspeed_modification, /datum/actionspeed_modifier, type_or_datum, priority, COMPARE_VALUE)
LAZYSET(actionspeed_modification, type_or_datum.id, type_or_datum)
if(update)
update_actionspeed()
+8
View File
@@ -226,6 +226,14 @@
key_cache[key] = 0
return .
/proc/restore_stickybans()
for (var/banned_ckey in GLOB.stickybanadmintexts)
world.SetConfig("ban", banned_ckey, GLOB.stickybanadmintexts[banned_ckey])
GLOB.stickybanadminexemptions = list()
GLOB.stickybanadmintexts = list()
if (GLOB.stickbanadminexemptiontimerid)
deltimer(GLOB.stickbanadminexemptiontimerid)
GLOB.stickbanadminexemptiontimerid = null
#undef STICKYBAN_MAX_MATCHES
#undef STICKYBAN_MAX_EXISTING_USER_MATCHES
+7 -9
View File
@@ -52,11 +52,9 @@
edit_emitter(user)
/obj/effect/sound_emitter/AltClick(mob/user)
. = ..()
if(check_rights_for(user.client, R_SOUNDS))
activate(user)
to_chat(user, "<span class='notice'>Sound emitter activated.</span>")
return TRUE
to_chat(user, "<span class='notice'>Sound emitter activated.</span>", confidential = TRUE)
/obj/effect/sound_emitter/proc/edit_emitter(mob/user)
var/dat = ""
@@ -84,20 +82,20 @@
if(!new_label)
return
maptext = new_label
to_chat(user, "<span class='notice'>Label set to [maptext].</span>")
to_chat(user, "<span class='notice'>Label set to [maptext].</span>", confidential = TRUE)
if(href_list["edit_sound_file"])
var/new_file = input(user, "Choose a sound file.", "Sound Emitter") as null|sound
if(!new_file)
return
sound_file = new_file
to_chat(user, "<span class='notice'>New sound file set to [sound_file].</span>")
to_chat(user, "<span class='notice'>New sound file set to [sound_file].</span>", confidential = TRUE)
if(href_list["edit_volume"])
var/new_volume = input(user, "Choose a volume.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_volume))
return
new_volume = clamp(new_volume, 0, 100)
sound_volume = new_volume
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>")
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>", confidential = TRUE)
if(href_list["edit_mode"])
var/new_mode
var/mode_list = list("Local (normal sound)" = SOUND_EMITTER_LOCAL, "Direct (not affected by environment/location)" = SOUND_EMITTER_DIRECT)
@@ -105,7 +103,7 @@
if(!new_mode)
return
motus_operandi = mode_list[new_mode]
to_chat(user, "<span class='notice'>Mode set to [motus_operandi].</span>")
to_chat(user, "<span class='notice'>Mode set to [motus_operandi].</span>", confidential = TRUE)
if(href_list["edit_range"])
var/new_range
var/range_list = list("Radius (all mobs within a radius)" = SOUND_EMITTER_RADIUS, "Z-Level (all mobs on the same z)" = SOUND_EMITTER_ZLEVEL, "Global (all players)" = SOUND_EMITTER_GLOBAL)
@@ -113,14 +111,14 @@
if(!new_range)
return
emitter_range = range_list[new_range]
to_chat(user, "<span class='notice'>Range set to [emitter_range].</span>")
to_chat(user, "<span class='notice'>Range set to [emitter_range].</span>", confidential = TRUE)
if(href_list["edit_radius"])
var/new_radius = input(user, "Choose a radius.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_radius))
return
new_radius = clamp(new_radius, 0, 127)
play_radius = new_radius
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>")
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>", confidential = TRUE)
if(href_list["play"])
activate(user)
edit_emitter(user) //Refresh the UI to see our changes
+318 -55
View File
@@ -7,7 +7,7 @@
if ("add")
var/list/ban = list()
var/ckey
ban["admin"] = usr.key
ban["admin"] = usr.ckey
ban["type"] = list("sticky")
ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
@@ -21,7 +21,8 @@
ban["ckey"] = ckey
if (get_stickyban_from_ckey(ckey))
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>")
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>", confidential = TRUE)
return
if (data["reason"])
ban["message"] = data["reason"]
@@ -31,7 +32,26 @@
return
ban["message"] = "[reason]"
if(SSdbcore.Connect()) // todo: second wave
// var/datum/db_query/query_create_stickyban = SSdbcore.NewQuery({"
// INSERT INTO [format_table_name("stickyban")] (ckey, reason, banning_admin)
// VALUES (:ckey, :message, :banning_admin)
// "}, list("ckey" = ckey, "message" = ban["message"], "banning_admin" = usr.ckey))
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("stickyban")] (ckey, reason, banning_admin)
VALUES ([ckey], [ban["message"]], [usr.ckey])
"})
if (query_create_stickyban.warn_execute())
ban["fromdb"] = TRUE
qdel(query_create_stickyban)
world.SetConfig("ban",ckey,list2stickyban(ban))
ban = stickyban2list(list2stickyban(ban))
ban["matches_this_round"] = list()
ban["existing_user_matches_this_round"] = list()
ban["admin_matches_this_round"] = list()
ban["pending_matches_this_round"] = list()
SSstickyban.cache[ckey] = ban
log_admin_private("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]</span>")
@@ -43,14 +63,29 @@
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
return
if (!get_stickyban_from_ckey(ckey))
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
world.SetConfig("ban",ckey, null)
SSstickyban.cache -= ckey
if (SSdbcore.Connect())
// SSdbcore.QuerySelect(list(
// SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban")] WHERE ckey = :ckey", list("ckey" = ckey)),
// SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = :ckey", list("ckey" = ckey)),
// SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_cid")] WHERE stickyban = :ckey", list("ckey" = ckey)),
// SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ip")] WHERE stickyban = :ckey", list("ckey" = ckey))
// ), warn = TRUE, qdel = TRUE)
SSdbcore.QuerySelect(list(
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban")] WHERE ckey = [ckey]"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = [ckey]"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_cid")] WHERE stickyban = [ckey]"),
SSdbcore.NewQuery("DELETE FROM [format_table_name("stickyban_matched_ip")] WHERE stickyban = [ckey]")
), warn = TRUE, qdel = TRUE)
log_admin_private("[key_name(usr)] removed [ckey]'s stickyban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] removed [ckey]'s stickyban</span>")
@@ -64,42 +99,45 @@
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/found = 0
//we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
for (var/key in ban["keys"])
if (ckey(key) == alt)
found = 1
break
if (!found)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>", confidential = TRUE)
return
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them, Use \[E] to exempt them","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
found = 0
for (var/key in ban["keys"])
if (ckey(key) == alt)
ban["keys"] -= key
found = 1
break
key = LAZYACCESS(ban["keys"], alt)
if (!found)
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>")
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>", confidential = TRUE)
return
LAZYREMOVE(ban["keys"], alt)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
// var/datum/db_query/query_remove_stickyban_alt = SSdbcore.NewQuery(
// "DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = :ckey AND matched_ckey = :alt",
// list("ckey" = ckey, "alt" = alt)
// )
var/datum/DBQuery/query_remove_stickyban_alt = SSdbcore.NewQuery(
"DELETE FROM [format_table_name("stickyban_matched_ckey")] WHERE stickyban = [ckey] AND matched_ckey = [alt]"
)
query_remove_stickyban_alt.warn_execute()
qdel(query_remove_stickyban_alt)
log_admin_private("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban</span>")
@@ -109,7 +147,7 @@
var/ckey = data["ckey"]
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/oldreason = ban["message"]
var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
@@ -118,28 +156,203 @@
//we have to do this again incase something changed while we waited for input
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
ban["message"] = "[reason]"
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
// var/datum/db_query/query_edit_stickyban = SSdbcore.NewQuery(
// "UPDATE [format_table_name("stickyban")] SET reason = :reason WHERE ckey = :ckey",
// list("reason" = reason, "ckey" = ckey)
// )
var/datum/DBQuery/query_edit_stickyban = SSdbcore.NewQuery(
"UPDATE [format_table_name("stickyban")] SET reason = [reason] WHERE ckey = [ckey]"
)
query_edit_stickyban.warn_execute()
qdel(query_edit_stickyban)
log_admin_private("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]</span>")
if ("exempt")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (!data["alt"])
return
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>", confidential = TRUE)
return
if (alert("Are you sure you want to exempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s link to [ckey]'s sticky ban disappeared.</span>", confidential = TRUE)
return
LAZYREMOVE(ban["keys"], alt)
key["exempt"] = TRUE
LAZYSET(ban["whitelist"], alt, key)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
// var/datum/db_query/query_exempt_stickyban_alt = SSdbcore.NewQuery(
// "UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 1 WHERE stickyban = :ckey AND matched_ckey = :alt",
// list("ckey" = ckey, "alt" = alt)
// )
var/datum/DBQuery/query_exempt_stickyban_alt = SSdbcore.NewQuery(
"UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 1 WHERE stickyban = [ckey] AND matched_ckey = [alt]"
)
query_exempt_stickyban_alt.warn_execute()
qdel(query_exempt_stickyban_alt)
log_admin_private("[key_name(usr)] has exempted [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has exempted [alt] from [ckey]'s sticky ban</span>")
if ("unexempt")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (!data["alt"])
return
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/key = LAZYACCESS(ban["whitelist"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not exempt from [ckey]'s sticky ban!</span>", confidential = TRUE)
return
if (alert("Are you sure you want to unexempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
return
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
key = LAZYACCESS(ban["whitelist"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s exemption from [ckey]'s sticky ban disappeared.</span>", confidential = TRUE)
return
LAZYREMOVE(ban["whitelist"], alt)
key["exempt"] = FALSE
LAZYSET(ban["keys"], alt, key)
world.SetConfig("ban",ckey,list2stickyban(ban))
SSstickyban.cache[ckey] = ban
if (SSdbcore.Connect())
// var/datum/db_query/query_unexempt_stickyban_alt = SSdbcore.NewQuery(
// "UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 0 WHERE stickyban = :ckey AND matched_ckey = :alt",
// list("ckey" = ckey, "alt" = alt)
// )
var/datum/DBQuery/query_unexempt_stickyban_alt = SSdbcore.NewQuery(
"UPDATE [format_table_name("stickyban_matched_ckey")] SET exempt = 0 WHERE stickyban = [ckey] AND matched_ckey = [alt]"
)
query_unexempt_stickyban_alt.warn_execute()
qdel(query_unexempt_stickyban_alt)
log_admin_private("[key_name(usr)] has unexempted [alt] from [ckey]'s sticky ban")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has unexempted [alt] from [ckey]'s sticky ban</span>")
if ("timeout")
if (!data["ckey"])
return
if (!SSdbcore.Connect())
to_chat(usr, "<span class='adminnotice'>No database connection!</span>", confidential = TRUE)
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to put [ckey]'s stickyban on timeout until next round (or removed)?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
ban["timeout"] = TRUE
world.SetConfig("ban", ckey, null)
var/cachedban = SSstickyban.cache[ckey]
if (cachedban)
cachedban["timeout"] = TRUE
log_admin_private("[key_name(usr)] has put [ckey]'s sticky ban on timeout.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has put [ckey]'s sticky ban on timeout.</span>")
if ("untimeout")
if (!data["ckey"])
return
if (!SSdbcore.Connect())
to_chat(usr, "<span class='adminnotice'>No database connection!</span>", confidential = TRUE)
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to lift the timeout on [ckey]'s stickyban?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
var/cachedban = SSstickyban.cache[ckey]
if (cachedban)
cachedban["timeout"] = FALSE
if (!ban)
if (!cachedban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
ban = cachedban
ban["timeout"] = FALSE
world.SetConfig("ban",ckey,list2stickyban(ban))
log_admin_private("[key_name(usr)] has taken [ckey]'s sticky ban off of timeout.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has taken [ckey]'s sticky ban off of timeout.</span>")
if ("revert")
if (!data["ckey"])
return
var/ckey = data["ckey"]
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start?","Are you sure","Yes","No") == "No")
if (alert("Are you sure you want to revert the sticky ban on [ckey] to its state at round start (or last edit)?","Are you sure","Yes","No") == "No")
return
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/cached_ban = SSstickyban.cache[ckey]
if (!cached_ban)
to_chat(usr, "<span class='adminnotice'>Error: No cached sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No cached sticky ban for [ckey] found!</span>", confidential = TRUE)
world.SetConfig("ban",ckey,null)
log_admin_private("[key_name(usr)] has reverted [ckey]'s sticky ban to its state at round start.")
@@ -150,14 +363,22 @@
world.SetConfig("ban",ckey,list2stickyban(cached_ban))
/datum/admins/proc/stickyban_gethtml(ckey, ban)
. = {"
/datum/admins/proc/stickyban_gethtml(ckey)
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
return
var/timeout
if (SSdbcore.Connect())
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=[(ban["timeout"] ? "untimeout" : "timeout")]&ckey=[ckey]'>\[[(ban["timeout"] ? "untimeout" : "timeout" )]\]</a>"
else
timeout = "<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>"
. = list({"
<a href='?_src_=holder;[HrefToken()];stickyban=remove&ckey=[ckey]'>\[-\]</a>
<a href='?_src_=holder;[HrefToken()];stickyban=revert&ckey=[ckey]'>\[revert\]</a>
[timeout]
<b>[ckey]</b>
<br />"
[ban["message"]] <b><a href='?_src_=holder;[HrefToken()];stickyban=edit&ckey=[ckey]'>\[Edit\]</a></b><br />
"}
"})
if (ban["admin"])
. += "[ban["admin"]]<br />"
else
@@ -166,19 +387,24 @@
for (var/key in ban["keys"])
if (ckey(key) == ckey)
continue
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]</li>"
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=exempt&ckey=[ckey]&alt=[ckey(key)]'>\[E\]</a></li>"
for (var/key in ban["whitelist"])
if (ckey(key) == ckey)
continue
. += "<li><a href='?_src_=holder;[HrefToken()];stickyban=remove_alt&ckey=[ckey]&alt=[ckey(key)]'>\[-\]</a>[key]<a href='?_src_=holder;[HrefToken()];stickyban=unexempt&ckey=[ckey]&alt=[ckey(key)]'>\[UE\]</a></li>"
. += "</ol>\n"
/datum/admins/proc/stickyban_show()
if(!check_rights(R_BAN))
return
var/list/bans = sortList(world.GetConfig("ban"))
var/banhtml = ""
var/list/bans = sticky_banned_ckeys()
var/list/banhtml = list()
for(var/key in bans)
var/ckey = ckey(key)
var/ban = stickyban2list(world.GetConfig("ban",key))
banhtml += "<br /><hr />\n"
banhtml += stickyban_gethtml(ckey,ban)
banhtml += stickyban_gethtml(ckey)
var/html = {"
<head>
@@ -186,22 +412,49 @@
</head>
<body>
<h2>All Sticky Bans:</h2> <a href='?_src_=holder;[HrefToken()];stickyban=add'>\[+\]</a><br>
[banhtml]
[banhtml.Join("")]
</body>
"}
usr << browse(html,"window=stickybans;size=700x400")
/proc/get_stickyban_from_ckey(var/ckey)
/proc/sticky_banned_ckeys()
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
if (SSstickyban.dbcacheexpire < world.time)
SSstickyban.Populatedbcache()
if (SSstickyban.dbcacheexpire)
return SSstickyban.dbcache.Copy()
return sortList(world.GetConfig("ban"))
/proc/get_stickyban_from_ckey(ckey)
. = list()
if (!ckey)
return null
ckey = ckey(ckey)
. = null
for (var/key in world.GetConfig("ban"))
if (ckey(key) == ckey)
. = stickyban2list(world.GetConfig("ban",key))
break
if (SSdbcore.Connect() || length(SSstickyban.dbcache))
if (SSstickyban.dbcacheexpire < world.time)
SSstickyban.Populatedbcache()
if (SSstickyban.dbcacheexpire)
. = SSstickyban.dbcache[ckey]
//reset the cache incase its a newer ban (but only if we didn't update the cache recently)
if (!. && SSstickyban.dbcacheexpire != world.time+STICKYBAN_DB_CACHE_TIME)
SSstickyban.dbcacheexpire = 1
SSstickyban.Populatedbcache()
. = SSstickyban.dbcache[ckey]
if (.)
var/list/cachedban = SSstickyban.cache["[ckey]"]
if (cachedban)
.["timeout"] = cachedban["timeout"]
/proc/stickyban2list(var/ban)
.["fromdb"] = TRUE
return
. = stickyban2list(world.GetConfig("ban", ckey)) || stickyban2list(world.GetConfig("ban", ckey(ckey))) || list()
if (!length(.))
return null
/proc/stickyban2list(ban, strictdb = TRUE)
if (!ban)
return null
. = params2list(ban)
@@ -212,30 +465,40 @@
var/ckey = ckey(key)
ckeys[ckey] = ckey //to make searching faster.
.["keys"] = ckeys
if (.["whitelist"])
var/keys = splittext(.["whitelist"], ",")
var/ckeys = list()
for (var/key in keys)
var/ckey = ckey(key)
ckeys[ckey] = ckey //to make searching faster.
.["whitelist"] = ckeys
.["type"] = splittext(.["type"], ",")
.["IP"] = splittext(.["IP"], ",")
.["computer_id"] = splittext(.["computer_id"], ",")
. -= "fromdb"
/proc/list2stickyban(var/list/ban)
/proc/list2stickyban(list/ban)
if (!ban || !islist(ban))
return null
. = ban.Copy()
if (.["keys"])
.["keys"] = jointext(.["keys"], ",")
if (.["IP"])
.["IP"] = jointext(.["IP"], ",")
if (.["computer_id"])
.["computer_id"] = jointext(.["computer_id"], ",")
if (.["whitelist"])
.["whitelist"] = jointext(.["whitelist"], ",")
if (.["type"])
.["type"] = jointext(.["type"], ",")
//internal tracking only, shouldn't be stored
. -= "reverting"
. -= "matches_this_round"
. -= "existing_user_matches_this_round"
. -= "admin_matches_this_round"
. -= "matches_this_round"
. -= "reverting"
. -= "pending_matches_this_round"
//storing these can sometimes cause sticky bans to start matching everybody
// and isn't even needed for sticky ban matching, as the hub tracks these separately
. -= "IP"
. -= "computer_id"
. = list2params(.)
+1 -1
View File
@@ -782,7 +782,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(temp.vars.Find(v))
temp.vars[v] = SDQL_expression(d, set_list[sets])
else
temp.vv_edit_var(v, SDQL_expression(d, set_list[sets]))
temp.vv_edit_var(v, SDQL_expression(d, set_list[sets]), TRUE)
break
if(temp.vars.Find(v) && (istype(temp.vars[v], /datum) || istype(temp.vars[v], /client)))
temp = temp.vars[v]
+16
View File
@@ -158,3 +158,19 @@
else
to_chat(src, "Failed to move mob to a valid location.", confidential = TRUE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/// Proc to hook user-enacted teleporting behavior and keep logging of the event.
/atom/movable/proc/admin_teleport(atom/new_location, message = TRUE)
if(isnull(new_location))
log_admin("[key_name(usr)] teleported [key_name(src)] to nullspace")
moveToNullspace()
else
log_admin("[key_name(usr)] teleported [key_name(src)] to [AREACOORD(loc)]")
forceMove(new_location)
/mob/admin_teleport(atom/new_location, message = TRUE)
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(src)] to [isnull(new_location) ? "nullspace" : ADMIN_VERBOSEJMP(loc)]"
if(message)
message_admins(msg)
admin_ticket_log(src, msg)
return ..()
+4 -6
View File
@@ -4,12 +4,10 @@
if(!check_rights(R_SOUNDS))
return
var/freq = 1
var/vol = input(usr, "What volume would you like the sound to play at?",, 100) as null|num
if(!vol)
return
var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num
if(!freq)
freq = 1
vol = clamp(vol, 1, 100)
var/sound/admin_sound = new()
@@ -18,14 +16,14 @@
admin_sound.channel = CHANNEL_ADMIN
admin_sound.frequency = freq
admin_sound.wait = 1
admin_sound.repeat = 0
admin_sound.repeat = FALSE
admin_sound.status = SOUND_STREAM
admin_sound.volume = vol
var/res = alert(usr, "Show the title of this song to the players?",, "Yes","No", "Cancel")
switch(res)
if("Yes")
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>", confidential = TRUE)
if("Cancel")
return
@@ -49,7 +47,7 @@
log_admin("[key_name(src)] played a local sound [S]")
message_admins("[key_name_admin(src)] played a local sound [S]")
playsound(get_turf(src.mob), S, 50, 0, 0)
playsound(get_turf(src.mob), S, 50, FALSE, FALSE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Local Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/play_web_sound()
@@ -104,7 +104,7 @@
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE)
if (D.vv_edit_var(variable, initial(D.vars[variable]), TRUE) != FALSE)
accepted++
else
rejected++
@@ -135,7 +135,7 @@
for(var/V in varsvars)
new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]")
if (D.vv_edit_var(variable, new_value) != FALSE)
if (D.vv_edit_var(variable, new_value, TRUE) != FALSE)
accepted++
else
rejected++
@@ -161,7 +161,7 @@
if(many && !new_value)
new_value = new type()
if (D.vv_edit_var(variable, new_value) != FALSE)
if (D.vv_edit_var(variable, new_value, TRUE) != FALSE)
accepted++
else
rejected++
@@ -176,7 +176,7 @@
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, new_value) != FALSE)
if (D.vv_edit_var(variable, new_value, TRUE) != FALSE)
accepted++
else
rejected++
@@ -109,7 +109,7 @@ GLOBAL_LIST_EMPTY(deletion_failures)
set name = "Find References"
set src in world
find_references(FALSE)
find_references_legacy(FALSE)
/datum/proc/find_references_legacy(skip_alert)
@@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(deletion_failures)
qdel(src, TRUE) //force a qdel
if(!running_find_references)
find_references(TRUE)
find_references_legacy(TRUE)
/datum/verb/qdel_then_if_fail_find_references()
@@ -38,7 +38,7 @@
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_ROBELESS]'>Robeless</A><BR>"
dat += "<I>Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.</I><BR>"
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_MARTIAL]'>Martial Artist</a><BR>"
dat += "<I>Your apprentice is training in ancient martial arts. They know the Plasmafist and Nuclear Fist.</I><BR>"
dat += "<I>Your apprentice is training in ancient martial arts. They know an Inner Mantra and the Nuclear Fist technique.</I><BR>"
user << browse(dat, "window=radio")
onclose(user, "radio")
return
@@ -69,6 +69,7 @@ GLOBAL_LIST_INIT(abductor_gear, subtypesof(/datum/abductor_gear))
build_path = /obj/item/abductor_machine_beacon/chem_dispenser
category = "Advanced Gear"
/*
/datum/abductor_gear/shrink_ray
name = "Shrink Ray Blaster"
description = "This is a piece of frightening alien tech that enhances the magnetic pull of atoms in a localized space to temporarily make an object shrink. \
@@ -77,3 +78,4 @@ GLOBAL_LIST_INIT(abductor_gear, subtypesof(/datum/abductor_gear))
cost = 2
build_path = /obj/item/gun/energy/shrink_ray
category = "Advanced Gear"
*/
@@ -13,8 +13,9 @@
var/nightime_duration = 900 //15 Minutes
/obj/effect/sunlight/Initialize()
countdown()
hud_tick()
. = ..()
INVOKE_ASYNC(src, .proc/countdown)
INVOKE_ASYNC(src, .proc/hud_tick)
/obj/effect/sunlight/proc/countdown()
set waitfor = FALSE
@@ -90,7 +90,7 @@
/datum/antagonist/vassal/greet()
to_chat(owner, "<span class='userdanger'>You are now the mortal servant of [master.owner.current], a bloodsucking vampire!</span>")
to_chat(owner, "<span class='boldannounce'>The power of [master.owner.current.p_their()] immortal blood compells you to obey [master.owner.current.p_them()] in all things, even offering your own life to prolong theirs.<br>\
You are not required to obey any other Bloodsucker, for only [master.owner.current] is your master. The laws of Nanotransen do not apply to you now; only your vampiric master's word must be obeyed.<span>")
You are not required to obey any other Bloodsucker, for only [master.owner.current] is your master. The laws of Nanotrasen do not apply to you now; only your vampiric master's word must be obeyed.<span>")
// Effects...
owner.current.playsound_local(null, 'sound/magic/mutate.ogg', 100, FALSE, pressure_affected = FALSE)
//owner.store_memory("You became the mortal servant of [master.owner.current], a bloodsucking vampire!")
@@ -213,7 +213,7 @@
if(canrespec)
to_chat(owner.current, "<span class='notice'>We have removed our evolutions from this form, and are now ready to readapt.</span>")
reset_powers()
playsound(get_turf(owner.current), 'sound/effects/lingreadapt.ogg', 75, TRUE, 5, soundenvwet = 0)
playsound(get_turf(owner.current), 'sound/effects/lingreadapt.ogg', 75, TRUE, 5)
canrespec = 0
SSblackbox.record_feedback("tally", "changeling_power_purchase", 1, "Readapt")
return 1
@@ -29,7 +29,7 @@
for(var/obj/machinery/light/L in range(4, user))
L.on = 1
L.break_light_tube()
playsound(get_turf(user), 'sound/effects/lingscreech.ogg', 75, TRUE, 5, soundenvwet = 0)
playsound(get_turf(user), 'sound/effects/lingscreech.ogg', 75, TRUE, 5)
return TRUE
/obj/effect/proc_holder/changeling/dissonant_shriek
@@ -49,5 +49,5 @@
L.on = 1
L.break_light_tube()
empulse_using_range(get_turf(user), 8, TRUE)
playsound(get_turf(user), 'sound/effects/lingempscreech.ogg', 75, TRUE, 5, soundenvwet = 0)
playsound(get_turf(user), 'sound/effects/lingempscreech.ogg', 75, TRUE, 5)
return TRUE
@@ -22,7 +22,7 @@
for(var/mob/M in GLOB.player_list)
if(M.z == z)
if(get_dist(src, M) >= 7)
M.playsound_local(src, 'sound/magic/blink.ogg', 10, FALSE, falloff = 10)
M.playsound_local(src, 'sound/magic/blink.ogg', 10, FALSE)
else
M.playsound_local(src, 'sound/magic/blink.ogg', 50, FALSE)
@@ -348,9 +348,9 @@
L.dust()
else if(L.health > min_drain_health)
if(!GLOB.ratvar_awakens && L.stat == CONSCIOUS)
vitality_drained = L.adjustToxLoss(1, forced = TRUE)
vitality_drained = L.adjustToxLoss(1, forced = TRUE, toxins_type = TOX_OMNI)
else
vitality_drained = L.adjustToxLoss(1.5, forced = TRUE)
vitality_drained = L.adjustToxLoss(1.5, forced = TRUE, toxins_type = TOX_OMNI)
if(vitality_drained)
GLOB.clockwork_vitality += vitality_drained
else
@@ -115,7 +115,7 @@
if(totaldamage)
L.heal_overall_damage(brutedamage, burndamage, only_organic = FALSE) //Maybe a machine god shouldn't murder augmented followers instead of healing them
L.adjustOxyLoss(-oxydamage)
L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE)
L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE, toxins_type = TOX_OMNI)
clockwork_say(ranged_ability_user, text2ratvar("[has_holy_water ? "Heal tainted" : "Mend wounded"] flesh!"))
log_combat(ranged_ability_user, L, "healed with Sentinel's Compromise")
L.visible_message("<span class='warning'>A blue light washes over [L], [has_holy_water ? "causing [L.p_them()] to briefly glow as it mends" : " mending"] [L.p_their()] bruises and burns!</span>", \
@@ -15,3 +15,5 @@
audible_message("<i>*click*</i>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
activate()
. = ..()
@@ -8,7 +8,7 @@
alpha = 75
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/mech/Crossed(atom/movable/AM)
. = ..()
if(!istype(AM,/obj/mecha/))
return
@@ -21,3 +21,5 @@
if(isliving(AM) && opacity)
var/mob/living/L = AM
L.adjust_fire_stacks(-1) //It's wet!
return
. = ..()
+3 -3
View File
@@ -717,9 +717,9 @@
uses = 0
ratio *= -1
H.adjustOxyLoss((overall_damage*ratio) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((overall_damage*ratio) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((overall_damage*ratio) * (H.getFireLoss() / overall_damage), 0)
H.adjustBruteLoss((overall_damage*ratio) * (H.getBruteLoss() / overall_damage), 0)
H.adjustToxLoss((overall_damage*ratio) * (H.getToxLoss() / overall_damage), 0, toxins_type = TOX_OMNI)
H.adjustFireLoss((overall_damage*ratio) * (H.getFireLoss() / overall_damage), 0, only_organic = FALSE)
H.adjustBruteLoss((overall_damage*ratio) * (H.getBruteLoss() / overall_damage), 0, only_organic = FALSE)
H.updatehealth()
playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25)
new /obj/effect/temp_visual/cult/sparks(get_turf(H))
@@ -214,8 +214,8 @@
if(L.health != L.maxHealth)
new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
if(ishuman(L))
L.adjustBruteLoss(-1, 0)
L.adjustFireLoss(-1, 0)
L.adjustBruteLoss(-1, 0, only_organic = FALSE)
L.adjustFireLoss(-1, 0, only_organic = FALSE)
L.updatehealth()
if(isshade(L) || isconstruct(L))
var/mob/living/simple_animal/M = L
@@ -189,6 +189,10 @@
name = "Mutate"
spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate
/datum/spellbook_entry/mantra
name = "Inner Mantra"
spell_type = /obj/effect/proc_holder/spell/self/mantra
/datum/spellbook_entry/jaunt
name = "Ethereal Jaunt"
spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt
+2 -2
View File
@@ -181,8 +181,8 @@
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
if(APPRENTICE_MARTIAL)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null))
H.put_in_hands(new /obj/item/book/granter/martial/plasma_fist(H))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned mystical martial abilities. You are also able to use the Nuclear Fist at will.")
owner.AddSpell(new /obj/effect/proc_holder/spell/self/mantra(null))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned to control your Inner Mantra. You are also able to use the Nuclear Fist at will.")
/datum/antagonist/wizard/apprentice/create_objectives()
var/datum/objective/protect/new_objective = new /datum/objective/protect
+1
View File
@@ -123,6 +123,7 @@ obj/item/dildo/flared/huge
desc = "THIS THING IS HUGE!"
dildo_size = 4
force = 10
hitsound = 'sound/weapons/klonk.ogg'
obj/item/dildo/custom
name = "customizable dildo"
+1
View File
@@ -62,6 +62,7 @@
master.update_icon()
/obj/item/assembly_holder/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(a_left)
a_left.Crossed(AM)
if(a_right)
@@ -1,5 +1,5 @@
/// Process asset cache client topic calls for "asset_cache_confirm_arrival=[INT]"
/// Process asset cache client topic calls for `"asset_cache_confirm_arrival=[INT]"`
/client/proc/asset_cache_confirm_arrival(job_id)
var/asset_cache_job = round(text2num(job_id))
//because we skip the limiter, we have to make sure this is a valid arrival and not somebody tricking us into letting them append to a list without limit.
@@ -10,7 +10,7 @@
return asset_cache_job || TRUE
/// Process asset cache client topic calls for "asset_cache_preload_data=[HTML+JSON_STRING]
/// Process asset cache client topic calls for `"asset_cache_preload_data=[HTML+JSON_STRING]"`
/client/proc/asset_cache_preload_data(data)
var/json = data
var/list/preloaded_assets = json_decode(json)
+58 -5
View File
@@ -47,8 +47,9 @@
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif'
// "borg_mon.gif" = 'icons/program_icons/borg_mon.gif',
// "robotact.gif" = 'icons/program_icons/robotact.gif'
)
/datum/asset/simple/radar_assets
@@ -156,7 +157,6 @@
)
/datum/asset/simple/namespaced/fontawesome
legacy = TRUE
assets = list(
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
@@ -248,6 +248,10 @@
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
"ascension" = 'icons/UI_Icons/Achievements/Misc/ascension.png',
"ashascend" = 'icons/UI_Icons/Achievements/Misc/ashascend.png',
"fleshascend" = 'icons/UI_Icons/Achievements/Misc/fleshascend.png',
"rustascend" = 'icons/UI_Icons/Achievements/Misc/rustascend.png',
"voidascend" = 'icons/UI_Icons/Achievements/Misc/voidascend.png',
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
"assistant" = 'icons/UI_Icons/Achievements/Mafia/assistant.png',
"changeling" = 'icons/UI_Icons/Achievements/Mafia/changeling.png',
@@ -288,7 +292,7 @@
)
/datum/asset/spritesheet/simple/pills
name ="pills"
name = "pills"
assets = list(
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
@@ -313,7 +317,28 @@
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
)
/*
/datum/asset/spritesheet/simple/condiments
name = "condiments"
assets = list(
CONDIMASTER_STYLE_FALLBACK = 'icons/UI_Icons/Condiments/emptycondiment.png',
"enzyme" = 'icons/UI_Icons/Condiments/enzyme.png',
"flour" = 'icons/UI_Icons/Condiments/flour.png',
"mayonnaise" = 'icons/UI_Icons/Condiments/mayonnaise.png',
"milk" = 'icons/UI_Icons/Condiments/milk.png',
"blackpepper" = 'icons/UI_Icons/Condiments/peppermillsmall.png',
"rice" = 'icons/UI_Icons/Condiments/rice.png',
"sodiumchloride" = 'icons/UI_Icons/Condiments/saltshakersmall.png',
"soymilk" = 'icons/UI_Icons/Condiments/soymilk.png',
"soysauce" = 'icons/UI_Icons/Condiments/soysauce.png',
"sugar" = 'icons/UI_Icons/Condiments/sugar.png',
"ketchup" = 'icons/UI_Icons/Condiments/ketchup.png',
"capsaicin" = 'icons/UI_Icons/Condiments/hotsauce.png',
"frostoil" = 'icons/UI_Icons/Condiments/coldsauce.png',
"bbqsauce" = 'icons/UI_Icons/Condiments/bbqsauce.png',
"cornoil" = 'icons/UI_Icons/Condiments/oliveoil.png',
)
*/
//this exists purely to avoid meta by pre-loading all language icons.
/datum/asset/language/register()
for(var/path in typesof(/datum/language))
@@ -484,3 +509,31 @@
/datum/asset/spritesheet/mafia/register()
InsertAll("", 'icons/obj/mafia.dmi')
..()
/datum/asset/simple/portraits
var/tab = "use subtypes of this please"
assets = list()
/datum/asset/simple/portraits/New()
if(!SSpersistence.paintings || !SSpersistence.paintings[tab] || !length(SSpersistence.paintings[tab]))
return
for(var/p in SSpersistence.paintings[tab])
var/list/portrait = p
var/png = "data/paintings/[tab]/[portrait["md5"]].png"
if(fexists(png))
assets[portrait["title"]] = png
..() //this is where it registers all these assets we added to the list
/datum/asset/simple/portraits/library
tab = "library"
/datum/asset/simple/portraits/library_secure
tab = "library_secure"
/datum/asset/simple/portraits/library_private
tab = "library_private"
/datum/asset/simple/safe
assets = list(
"safe_dial.png" = 'html/safe_dial.png'
)
+2 -2
View File
@@ -24,7 +24,7 @@ Call .get_url_mappings() to get an associated list with the urls your assets can
See the documentation for `/datum/asset_transport` for the backend api the asset datums utilize.
The global variable `SSassets.transport` contains the currently configured transport.
The global variable `SSassets.transport` contains the currently configured transport.
@@ -32,6 +32,6 @@ The global variable `SSassets.transport` contains the currently configured trans
Because byond browse() calls use non-blocking queues, if your code uses output() (which bypasses all of these queues) to invoke javascript functions you will need to first have the javascript announce to the server it has loaded before trying to invoke js functions.
To make your code work with any CDNs configured by the server, you must make sure assets are referenced from the url returned by `get_url_mappings()` or by asset_transport's `get_asset_url()`. (TGUI also has helpers for this.) If this can not be easily done, you can bypass the cdn using legacy assets, see the simple asset datum for details.
To make your code work with any CDNs configured by the server, you must make sure assets are referenced from the url returned by `get_url_mappings()` or by asset_transport's `get_asset_url()`. (TGUI also has helpers for this.) If this can not be easily done, you can bypass the cdn using legacy assets, see the simple asset datum for details.
CSS files that use url() can be made to use the CDN without needing to rewrite all url() calls in code by using the namespaced helper datum. See the documentation for `/datum/asset/simple/namespaced` for details.
@@ -49,6 +49,7 @@
SSair.add_to_active(T)
return ..()
/// Function for Extools Atmos
/turf/proc/update_air_ref()
/////////////////GAS MIXTURE PROCS///////////////////
+90 -60
View File
@@ -7,6 +7,8 @@
#define AMMO_DROP_LIFETIME 300
#define CTF_REQUIRED_PLAYERS 4
/obj/item/ctf
name = "banner"
icon = 'icons/obj/items_and_weapons.dmi'
@@ -16,13 +18,13 @@
righthand_file = 'icons/mob/inhands/equipment/banners_righthand.dmi'
desc = "A banner with Nanotrasen's logo on it."
slowdown = 2
item_flags = SLOWS_WHILE_IN_HAND
throw_speed = 0
throw_range = 1
force = 200
armour_penetration = 1000
resistance_flags = INDESTRUCTIBLE
anchored = TRUE
item_flags = SLOWS_WHILE_IN_HAND
var/team = WHITE_TEAM
var/reset_cooldown = 0
var/anyonecanpickup = TRUE
@@ -53,12 +55,13 @@
to_chat(M, "<span class='userdanger'>\The [src] has been returned to base!</span>")
STOP_PROCESSING(SSobj, src)
/obj/item/ctf/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/ctf/on_attack_hand(mob/living/user)
if(!is_ctf_target(user) && !anyonecanpickup)
to_chat(user, "Non players shouldn't be moving the flag!")
to_chat(user, "<span class='warning'>Non-players shouldn't be moving the flag!</span>")
return
if(team in user.faction)
to_chat(user, "You can't move your own flag!")
to_chat(user, "<span class='warning'>You can't move your own flag!</span>")
return
if(loc == user)
if(!user.dropItemToGround(src))
@@ -68,7 +71,7 @@
if(!user.put_in_active_hand(src))
dropped(user)
return
user.anchored = TRUE
user.set_anchored(TRUE)
user.status_flags &= ~CANPUSH
for(var/mob/M in GLOB.player_list)
var/area/mob_area = get_area(M)
@@ -79,7 +82,7 @@
/obj/item/ctf/dropped(mob/user)
..()
user.anchored = FALSE
user.set_anchored(FALSE)
user.status_flags |= CANPUSH
reset_cooldown = world.time + 200 //20 seconds
START_PROCESSING(SSobj, src)
@@ -172,20 +175,20 @@
GLOB.poi_list.Remove(src)
..()
/obj/machinery/capture_the_flag/process()
/obj/machinery/capture_the_flag/process(delta_time)
for(var/i in spawned_mobs)
if(!i)
spawned_mobs -= i
continue
// Anyone in crit, automatically reap
var/mob/living/M = i
if(M.InCritical() || M.stat == DEAD)
ctf_dust_old(M)
var/mob/living/living_participant = i
if(living_participant.InCritical() || living_participant.stat == DEAD)
ctf_dust_old(living_participant)
else
// The changes that you've been hit with no shield but not
// instantly critted are low, but have some healing.
M.adjustBruteLoss(-5)
M.adjustFireLoss(-5)
living_participant.adjustBruteLoss(-2.5 * delta_time)
living_participant.adjustFireLoss(-2.5 * delta_time)
/obj/machinery/capture_the_flag/red
name = "Red CTF Controller"
@@ -212,6 +215,10 @@
toggle_all_ctf(user)
return
// if(!(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME))
// to_chat(user, "<span class='warning'>CTF has been temporarily disabled by admins.</span>")
// return
people_who_want_to_play |= user.ckey
var/num = people_who_want_to_play.len
var/remaining = CTF_REQUIRED_PLAYERS - num
@@ -227,7 +234,7 @@
return
if(user.ckey in team_members)
if(user.ckey in recently_dead_ckeys)
to_chat(user, "It must be more than [DisplayTimeText(respawn_cooldown)] from your last death to respawn!")
to_chat(user, "<span class='warning'>It must be more than [DisplayTimeText(respawn_cooldown)] from your last death to respawn!</span>")
return
var/client/new_team_member = user.client
if(user.mind && user.mind.current)
@@ -239,10 +246,10 @@
if(CTF == src || CTF.ctf_enabled == FALSE)
continue
if(user.ckey in CTF.team_members)
to_chat(user, "No switching teams while the round is going!")
to_chat(user, "<span class='warning'>No switching teams while the round is going!</span>")
return
if(CTF.team_members.len < src.team_members.len)
to_chat(user, "[src.team] has more team members than [CTF.team]. Try joining [CTF.team] team to even things up.")
to_chat(user, "<span class='warning'>[src.team] has more team members than [CTF.team]! Try joining [CTF.team] team to even things up.</span>")
return
team_members |= user.ckey
var/client/new_team_member = user.client
@@ -258,7 +265,7 @@
addtimer(CALLBACK(src, .proc/clear_cooldown, body.ckey), respawn_cooldown, TIMER_UNIQUE)
body.dust()
/obj/machinery/capture_the_flag/proc/clear_cooldown(var/ckey)
/obj/machinery/capture_the_flag/proc/clear_cooldown(ckey)
recently_dead_ckeys -= ckey
/obj/machinery/capture_the_flag/proc/spawn_team_member(client/new_team_member)
@@ -270,7 +277,7 @@
M.equipOutfit(ctf_gear)
M.dna.species.punchdamagehigh = 25
M.dna.species.punchdamagelow = 25
M.AddElement(/datum/element/ghost_role_eligibility)
M.AddElement(/datum/element/ghost_role_eligibility) //??
spawned_mobs += M
/obj/machinery/capture_the_flag/Topic(href, href_list)
@@ -293,14 +300,15 @@
victory()
/obj/machinery/capture_the_flag/proc/victory()
for(var/mob/M in GLOB.mob_list)
var/area/mob_area = get_area(M)
for(var/mob/_competitor in GLOB.mob_living_list)
var/mob/living/competitor = _competitor
var/area/mob_area = get_area(competitor)
if(istype(mob_area, /area/ctf))
to_chat(M, "<span class='narsie [team_span]'>[team] team wins!</span>")
to_chat(M, "<span class='userdanger'>Teams have been cleared. Click on the machines to vote to begin another round.</span>")
for(var/obj/item/ctf/W in M)
M.dropItemToGround(W)
M.dust()
to_chat(competitor, "<span class='narsie [team_span]'>[team] team wins!</span>")
to_chat(competitor, "<span class='userdanger'>Teams have been cleared. Click on the machines to vote to begin another round.</span>")
for(var/obj/item/ctf/W in competitor)
competitor.dropItemToGround(W)
competitor.dust()
for(var/obj/machinery/control_point/control in GLOB.machines)
control.icon_state = "dominator"
control.controlling = null
@@ -328,7 +336,7 @@
dead_barricades.Cut()
notify_ghosts("[name] has been activated!", enter_link="<a href=?src=[REF(src)];join=1>(Click to join the [team] team!)</a> or click on the controller directly!", source = src, action=NOTIFY_ATTACK)
notify_ghosts("[name] has been activated!", enter_link="<a href=?src=[REF(src)];join=1>(Click to join the [team] team!)</a> or click on the controller directly!", source = src, action=NOTIFY_ATTACK, header = "CTF has been activated")
if(!arena_reset)
reset_the_arena()
@@ -355,10 +363,10 @@
ctf_enabled = FALSE
arena_reset = FALSE
var/area/A = get_area(src)
for(var/i in GLOB.mob_list)
var/mob/M = i
if((get_area(A) == A) && (M.ckey in team_members))
M.dust()
for(var/_competitor in GLOB.mob_living_list)
var/mob/living/competitor = _competitor
if((get_area(A) == A) && (competitor.ckey in team_members))
competitor.dust()
team_members.Cut()
spawned_mobs.Cut()
recently_dead_ckeys.Cut()
@@ -375,18 +383,18 @@
CTF.ctf_gear = initial(ctf_gear)
CTF.respawn_cooldown = DEFAULT_RESPAWN
/proc/ctf_floor_vanish(atom/target)
if(isturf(target.loc))
qdel(target)
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf
desc = "This looks like it could really hurt in melee."
force = 75
mag_type = /obj/item/ammo_box/magazine/m50/ctf
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped(mob/user)
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped()
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/obj/item/ammo_box/magazine/m50/ctf
ammo_type = /obj/item/ammo_casing/a50/ctf
@@ -400,6 +408,7 @@
/obj/item/projectile/bullet/ctf/prehit(atom/target)
if(is_ctf_target(target))
damage = 60
return //PROJECTILE_PIERCE_NONE /// hey uhh don't hit anyone behind them
. = ..()
/obj/item/gun/ballistic/automatic/laser/ctf
@@ -407,16 +416,24 @@
desc = "This looks like it could really hurt in melee."
force = 50
/obj/item/gun/ballistic/automatic/laser/ctf/dropped(mob/user)
/obj/item/gun/ballistic/automatic/laser/ctf/dropped()
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/gun/ballistic/automatic/laser/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/obj/item/ammo_box/magazine/recharge/ctf
ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
/obj/item/ammo_box/magazine/recharge/ctf/dropped(mob/user)
/obj/item/ammo_box/magazine/recharge/ctf/dropped()
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/ammo_box/magazine/recharge/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/obj/item/ammo_casing/caseless/laser/ctf
projectile_type = /obj/item/projectile/beam/ctf
@@ -428,15 +445,16 @@
/obj/item/projectile/beam/ctf/prehit(atom/target)
if(is_ctf_target(target))
damage = 150
return //PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them
. = ..()
/proc/is_ctf_target(atom/target)
. = FALSE
if(istype(target, /obj/structure/barricade/security/ctf))
. = TRUE
if(isliving(target))
var/mob/living/H = target
if((RED_TEAM in H.faction) || (BLUE_TEAM in H.faction))
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/shielded/ctf))
. = TRUE
// RED TEAM GUNS
@@ -482,7 +500,11 @@
/obj/item/claymore/ctf/dropped(mob/user)
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/claymore/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
/datum/outfit/ctf
name = "CTF"
@@ -491,27 +513,28 @@
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf
toggle_helmet = FALSE // see the whites of their eyes
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/tackler/combat
gloves = /obj/item/clothing/gloves/combat
id = /obj/item/card/id/away
belt = /obj/item/gun/ballistic/automatic/pistol/deagle/ctf
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf
back = /obj/item/claymore/ctf
/datum/outfit/ctf/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
/datum/outfit/ctf/post_equip(mob/living/carbon/human/H, visualsOnly=FALSE)
if(visualsOnly)
return
var/list/no_drops = list()
var/obj/item/card/id/W = H.wear_id
no_drops += W
W.registered_name = H.real_name
W.update_label(W.registered_name, W.assignment)
W.update_label()
// The shielded hardsuit is already TRAIT_NODROP
no_drops += H.get_item_by_slot(SLOT_GLOVES)
no_drops += H.get_item_by_slot(SLOT_SHOES)
no_drops += H.get_item_by_slot(SLOT_W_UNIFORM)
no_drops += H.get_item_by_slot(SLOT_EARS)
no_drops += H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
no_drops += H.get_item_by_slot(ITEM_SLOT_GLOVES)
no_drops += H.get_item_by_slot(ITEM_SLOT_FEET)
no_drops += H.get_item_by_slot(ITEM_SLOT_ICLOTHING)
no_drops += H.get_item_by_slot(ITEM_SLOT_EARS)
for(var/i in no_drops)
var/obj/item/I = i
ADD_TRAIT(I, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT)
@@ -525,6 +548,7 @@
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/red
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red
id = /obj/item/card/id/syndicate_command //it's red
/datum/outfit/ctf/red/instagib
r_hand = /obj/item/gun/energy/laser/instakill/red
@@ -535,12 +559,13 @@
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/blue
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue
id = /obj/item/card/id/centcom //it's blue
/datum/outfit/ctf/blue/instagib
r_hand = /obj/item/gun/energy/laser/instakill/blue
shoes = /obj/item/clothing/shoes/jackboots/fast
/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H)
..()
var/obj/item/radio/R = H.ears
R.set_frequency(FREQ_CTF_RED)
@@ -548,7 +573,7 @@
R.independent = TRUE
H.dna.species.stunmod = 0
/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H)
..()
var/obj/item/radio/R = H.ears
R.set_frequency(FREQ_CTF_BLUE)
@@ -595,6 +620,10 @@
/obj/structure/barricade/security/ctf/make_debris()
new /obj/effect/ctf/dead_barricade(get_turf(src))
/obj/structure/table/reinforced/ctf
resistance_flags = INDESTRUCTIBLE
flags_1 = NODECONSTRUCT_1
/obj/effect/ctf
density = FALSE
anchored = TRUE
@@ -617,10 +646,11 @@
QDEL_IN(src, AMMO_DROP_LIFETIME)
/obj/effect/ctf/ammo/Crossed(atom/movable/AM)
. = ..()
reload(AM)
/obj/effect/ctf/ammo/Bump(atom/movable/AM)
reload(AM)
/obj/effect/ctf/ammo/Bump(atom/A)
reload(A)
/obj/effect/ctf/ammo/Bumped(atom/movable/AM)
reload(AM)
@@ -636,7 +666,7 @@
qdel(G)
O.equip(M)
to_chat(M, "<span class='notice'>Ammunition reloaded!</span>")
playsound(get_turf(M), 'sound/weapons/shotgunpump.ogg', 50, 1, -1)
playsound(get_turf(M), 'sound/weapons/shotgunpump.ogg', 50, TRUE, -1)
qdel(src)
break
@@ -667,18 +697,18 @@
resistance_flags = INDESTRUCTIBLE
var/obj/machinery/capture_the_flag/controlling
var/team = "none"
var/point_rate = 1
var/point_rate = 0.5
/obj/machinery/control_point/process()
/obj/machinery/control_point/process(delta_time)
if(controlling)
controlling.control_points += point_rate
controlling.control_points += point_rate * delta_time
if(controlling.control_points >= controlling.control_points_to_win)
controlling.victory()
/obj/machinery/control_point/attackby(mob/user, params)
capture(user)
/obj/machinery/control_point/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/control_point/on_attack_hand(mob/user)
capture(user)
/obj/machinery/control_point/proc/capture(mob/user)
+1 -1
View File
@@ -66,7 +66,7 @@
/obj/effect/mob_spawn/Initialize(mapload)
. = ..()
if(instant || (roundstart && (mapload || (SSticker && SSticker.current_state > GAME_STATE_SETTING_UP))))
create()
INVOKE_ASYNC(src, .proc/create)
else if(ghost_usable)
GLOB.poi_list |= src
LAZYADD(GLOB.mob_spawners[job_description ? job_description : name], src)
@@ -196,7 +196,7 @@
/obj/item/dice/d20/fate/proc/effect(var/mob/living/carbon/human/user,roll)
if(!reusable)
used = 1
visible_message("<span class='userdanger'>The die flare briefly.</span>")
visible_message("<span class='userdanger'>The die flares briefly.</span>")
switch(roll)
if(1)
//Dust
@@ -132,6 +132,7 @@
var/triggered = 0
/obj/effect/meatgrinder/Crossed(atom/movable/AM)
. = ..()
Bumped(AM)
/obj/effect/meatgrinder/Bumped(atom/movable/AM)
+1 -1
View File
@@ -38,7 +38,7 @@
var/path = "sound/chatter/[phomeme]_[length].ogg"
playsound(loc, path,
vol = 40, vary = 0, extrarange = 3, falloff = FALSE)
vol = 40, vary = 0, extrarange = 3)
sleep((length + 1) * chatter_get_sleep_multiplier(phomeme))
+1
View File
@@ -31,6 +31,7 @@
var/datum/preferences/prefs = null
var/last_turn = 0
var/move_delay = 0
var/last_move = 0
var/area = null
/// Last time we Click()ed. No clicking twice in one tick!
+4 -2
View File
@@ -147,6 +147,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/client/proc/handle_statpanel_click(list/href_list)
var/atom/target = locate(href_list["statpanel_item_target"])
if(!target)
return
Click(target, target.loc, null, "[href_list["statpanel_item_shiftclick"]?"shift=1;":null][href_list["statpanel_item_ctrlclick"]?"ctrl=1;":null]&alt=[href_list["statpanel_item_altclick"]?"alt=1;":null]", FALSE, "statpanel")
/client/proc/is_content_unlocked()
@@ -496,7 +498,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.directory -= ckey
log_access("Logout: [key_name(src)]")
GLOB.ahelp_tickets.ClientLogout(src)
// SSserver_maint.UpdateHubStatus()
SSserver_maint.UpdateHubStatus()
if(credits)
QDEL_LIST(credits)
if(holder)
@@ -642,7 +644,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
query_log_connection.Execute()
qdel(query_log_connection)
// SSserver_maint.UpdateHubStatus()
SSserver_maint.UpdateHubStatus()
if(new_player)
player_age = -1
@@ -36,7 +36,7 @@
/obj/item/clothing/gloves/fingerless/pugilist/equipped(mob/user, slot)
. = ..()
if(current_equipped_slot == SLOT_GLOVES)
if(slot == SLOT_GLOVES)
use_buffs(user, TRUE)
wornonce = TRUE
@@ -510,12 +510,12 @@ Contains:
name = "paramedic EVA suit"
icon_state = "paramedic-eva"
item_state = "paramedic-eva"
desc = "A deep blue space suit decorated with red and white crosses to indicate that the wearer is trained emergency medical personnel."
desc = "A deep blue space suit decorated with medical insignia to indicate that the wearer is trained emergency medical personnel."
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/roller)
/obj/item/clothing/head/helmet/space/eva/paramedic
name = "paramedic EVA helmet"
desc = "A deep blue space helmet with a large red cross on the faceplate to designate the wearer as trained emergency medical personnel."
desc = "A deep blue space helmet decorated with medical insignia to designate the wearer as trained emergency medical personnel."
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
+6 -1
View File
@@ -55,7 +55,7 @@
/obj/item/clothing/suit/toggle/labcoat/virologist
name = "virologist labcoat"
desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
desc = "A suit that protects against minor chemical spills. Has a green stripe on the shoulder."
icon_state = "labcoat_vir"
/obj/item/clothing/suit/toggle/labcoat/science
@@ -63,6 +63,11 @@
desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox"
/obj/item/clothing/suit/toggle/labcoat/roboticist
name = "roboticist labcoat"
desc = "More like an eccentric coat than a labcoat. Helps pass off bloodstains as part of the aesthetic. Comes with red shoulder pads."
icon_state = "labcoat_robo"
// Departmental Jackets
/obj/item/clothing/suit/toggle/labcoat/depjacket
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
+10
View File
@@ -58,6 +58,12 @@
RemoveHood()
/obj/item/clothing/suit/hooded/proc/ToggleHood()
if(!hood)
to_chat(loc, "<span class='warning'>[src] seems to be missing its hood..</span>")
return
if(atom_colours)
hood.atom_colours = atom_colours.Copy()
hood.update_atom_colour()
if(!suittoggled)
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
@@ -191,7 +197,11 @@
if(!helmettype)
return
if(!helmet)
to_chat(H, "<span class='warning'>[src] seems to be missing its helmet..</span>")
return
if(atom_colours)
helmet.atom_colours = atom_colours.Copy()
helmet.update_atom_colour()
if(!suittoggled)
if(ishuman(src.loc))
if(H.wear_suit != src)
+1 -1
View File
@@ -92,7 +92,7 @@
log_admin_private("[key_name(usr)] cancelled event [name].")
SSblackbox.record_feedback("tally", "event_admin_cancelled", 1, typepath)
/datum/round_event_control/proc/runEvent()
/datum/round_event_control/proc/runEvent(random = FALSE)
var/datum/round_event/E = new typepath()
E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
E.control = src
+1
View File
@@ -340,6 +340,7 @@
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/spacevine/Crossed(atom/movable/AM)
. = ..()
if(!isliving(AM))
return
for(var/datum/spacevine_mutation/SM in mutations)
+1 -1
View File
@@ -99,7 +99,7 @@
new reward(get_turf(src))
/mob/living/carbon/human/dummy/travelling_trader/Initialize()
..()
. = ..() // return a hint you fuck
add_atom_colour("#570d6b", FIXED_COLOUR_PRIORITY) //make them purple (otherworldly!)
set_light(1, -0.7, "#AAD84B")
ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood
+8 -6
View File
@@ -16,7 +16,7 @@
if(!F.check_variables() && !override_checks)
QDEL_NULL(F)
if(start_field && (F || override_checks))
F.Initialize()
F.begin_field()
return F
/datum/proximity_monitor/advanced
@@ -78,11 +78,11 @@
/datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T)
/datum/proximity_monitor/advanced/New()
/datum/proximity_monitor/advanced/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
if(requires_processing)
START_PROCESSING(SSfields, src)
/datum/proximity_monitor/advanced/proc/Initialize()
/datum/proximity_monitor/advanced/proc/begin_field()
setup_field()
post_setup_field()
@@ -154,7 +154,7 @@
var/atom/_host = host
var/atom/new_host_loc = _host.loc
if(last_host_loc != new_host_loc)
recalculate_field()
INVOKE_ASYNC(src, .proc/recalculate_field)
/datum/proximity_monitor/advanced/proc/post_setup_field()
@@ -302,7 +302,7 @@
/obj/item/multitool/field_debug/attack_self(mob/user)
operating = !operating
to_chat(user, "You turn [src] [operating? "on":"off"].")
to_chat(user, "<span class='notice'>You turn [src] [operating? "on":"off"].</span>")
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
if(!istype(current) && operating)
@@ -312,13 +312,15 @@
else if(!operating)
QDEL_NULL(current)
/obj/item/multitool/field_debug/dropped(mob/user)
/obj/item/multitool/field_debug/dropped()
. = ..()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
/obj/item/multitool/field_debug/proc/on_mob_move()
SIGNAL_HANDLER
check_turf(get_turf(src))
/obj/item/multitool/field_debug/process()
+13 -8
View File
@@ -33,7 +33,7 @@
if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune.
immune[G] = TRUE
if(start)
timestop()
INVOKE_ASYNC(src, .proc/timestop)
/obj/effect/timestop/Destroy()
qdel(chronofield)
@@ -42,7 +42,7 @@
/obj/effect/timestop/proc/timestop()
target = get_turf(src)
playsound(src, 'sound/magic/timeparadox2.ogg', 75, 1, -1)
playsound(src, 'sound/magic/timeparadox2.ogg', 75, TRUE, -1)
chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy))
QDEL_IN(src, duration)
@@ -112,6 +112,8 @@
unfreeze_turf(T)
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_atom(atom/movable/A)
SIGNAL_HANDLER
if(A.throwing)
unfreeze_throwing(A)
if(isliving(A))
@@ -128,12 +130,14 @@
frozen_things -= A
global_frozen_atoms -= A
/datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/mecha/M)
M.completely_disabled = TRUE
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/mecha/M)
M.completely_disabled = FALSE
/datum/proximity_monitor/advanced/timestop/proc/freeze_throwing(atom/movable/AM)
var/datum/thrownthing/T = AM.throwing
T.paused = TRUE
@@ -160,7 +164,7 @@
/datum/proximity_monitor/advanced/timestop/process()
for(var/i in frozen_mobs)
var/mob/living/m = i
m.Stun(20, 1, 1)
m.Stun(20, ignore_canstun = TRUE)
/datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T)
for(var/i in T.contents)
@@ -168,6 +172,7 @@
freeze_turf(T)
return ..()
/datum/proximity_monitor/advanced/timestop/proc/freeze_projectile(obj/item/projectile/P)
P.paused = TRUE
@@ -176,18 +181,18 @@
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
frozen_mobs += L
L.Stun(20, 1, 1)
L.Stun(20, ignore_canstun = TRUE)
ADD_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT)
walk(L, 0) //stops them mid pathing even if they're stunimmune
if(isanimal(L))
var/mob/living/simple_animal/S = L
S.toggle_ai(AI_OFF)
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.LoseTarget()
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.LoseTarget()
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L)
L.AdjustStun(-20, 1, 1)
L.AdjustStun(-20, ignore_canstun = TRUE)
REMOVE_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT)
frozen_mobs -= L
if(isanimal(L))
+4 -2
View File
@@ -24,11 +24,12 @@
desc = "Get off my turf!"
/obj/effect/abstract/proximity_checker/advanced/field_turf/CanPass(atom/movable/AM, turf/target)
. = ..()
if(parent)
return parent.field_turf_canpass(AM, src, target)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_turf/Crossed(atom/movable/AM)
. = ..()
if(parent)
return parent.field_turf_crossed(AM, src)
return TRUE
@@ -48,11 +49,12 @@
desc = "Edgy description here."
/obj/effect/abstract/proximity_checker/advanced/field_edge/CanPass(atom/movable/AM, turf/target)
. = ..()
if(parent)
return parent.field_edge_canpass(AM, src, target)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_edge/Crossed(atom/movable/AM)
. = ..()
if(parent)
return parent.field_edge_crossed(AM, src)
return TRUE
+3 -1
View File
@@ -139,10 +139,11 @@ GLOBAL_LIST_INIT(hallucination_list, list(
Show()
/obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir)
. = ..()
Show()
/obj/effect/hallucination/simple/Destroy()
if(target && target.client)
if(target?.client)
target.client.images.Remove(current_image)
active = FALSE
return ..()
@@ -1093,6 +1094,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
target.client.images += image
/obj/effect/hallucination/danger/lava/Crossed(atom/movable/AM)
. = ..()
if(AM == target)
target.adjustStaminaLoss(20)
new /datum/hallucination/fire(target)
@@ -596,7 +596,7 @@
name = "Buzz Fuzz"
desc = "The sister drink of Shambler's Juice! Uses real honey, making it a sweet tooth's dream drink. The slogan reads ''A Hive of Flavour'', there's also a label about how it is adddicting."
icon_state = "honeysoda_can"
list_reagents = list(/datum/reagent/consumable/buzz_fuzz = 25, /datum/reagent/consumable/honey = 5)
list_reagents = list(/datum/reagent/consumable/buzz_fuzz = 30)
foodtype = SUGAR | JUNKFOOD
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull
@@ -117,7 +117,7 @@
/obj/item/weldingtool = 3,
/obj/item/wirecutters = 2,
/obj/item/wrench = 4,
/obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 1,
/obj/item/weaponcrafting/receiver = 1,
/obj/item/geiger_counter = 3,
/obj/item/reagent_containers/food/snacks/grown/citrus/orange = 5,
/obj/item/assembly/infra = 1,
+16 -19
View File
@@ -50,16 +50,18 @@
var/cached_z
/// I'm busy, don't move.
var/busy = FALSE
var/static/blacklisted_items = typecacheof(list(
/obj/effect,
/obj/belly,
/obj/mafia_game_board,
/obj/docking_port,
/obj/shapeshift_holder,
/obj/screen))
/obj/effect,
/obj/belly,
/obj/mafia_game_board,
/obj/docking_port,
/obj/shapeshift_holder,
/obj/screen
))
/mob/living/simple_animal/jacq/Initialize()
..()
. = ..() //fuck you jacq, return a hint you shit
cached_z = z
poof()
@@ -158,23 +160,18 @@
return FALSE
/mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C)
var/gender = "lamb"
if(C)
if(C.gender == MALE)
gender = "laddie"
if(C.gender == FEMALE)
gender = "lassie"
return gender
. = "lamb"
switch(C)
if(MALE)
. = "laddie"
if(FEMALE)
. = "lassie"
//Ye wee bugger, gerrout of it. Ye've nae tae enjoy reading the code fer mae secrets like.
/mob/living/simple_animal/jacq/proc/chit_chat(mob/living/carbon/C)
//Very important
var/gender = gender_check(C)
if(C)
if(C.gender == MALE)
gender = "laddie"
if(C.gender == FEMALE)
gender = "lassie"
// it physicaly cannot fail*. Why is there a fucking dupe
if(!progression["[C.real_name]"] || !(progression["[C.real_name]"] & JACQ_HELLO))
visible_message("<b>[src]</b> smiles ominously at [C], <span class='spooky'>\"Well halo there [gender]! Ah'm Jacqueline, tae great Pumpqueen, great tae meet ye.\"</span>")
@@ -82,5 +82,5 @@
var/sound/music_played = sound(soundfile)
for(var/i in hearing_mobs)
var/mob/M = i
M.playsound_local(source, null, volume * using_instrument.volume_multiplier, falloff = 5, S = music_played)
M.playsound_local(source, null, volume * using_instrument.volume_multiplier, S = music_played)
// Could do environment and echo later but not for now
@@ -578,6 +578,7 @@
return FALSE
/obj/item/electronic_assembly/Moved(oldLoc, dir)
. = ..()
for(var/I in assembly_components)
var/obj/item/integrated_circuit/IC = I
IC.ext_moved(oldLoc, dir)
+1 -1
View File
@@ -187,7 +187,7 @@
/datum/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels.
if(H && GLOB.announcement_systems.len)
//timer because these should come after the captain announcement
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/addtimer, CALLBACK(pick(GLOB.announcement_systems), /obj/machinery/announcement_system/proc/announce, "NEWHEAD", H.real_name, H.job, channels), 1))
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/_addtimer, CALLBACK(pick(GLOB.announcement_systems), /obj/machinery/announcement_system/proc/announce, "NEWHEAD", H.real_name, H.job, channels), 1))
//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1
/datum/job/proc/player_old_enough(client/C)
+1 -1
View File
@@ -32,7 +32,7 @@
l_pocket = /obj/item/pda/roboticist
ears = /obj/item/radio/headset/headset_sci
uniform = /obj/item/clothing/under/rank/rnd/roboticist
suit = /obj/item/clothing/suit/toggle/labcoat
suit = /obj/item/clothing/suit/toggle/labcoat/roboticist
backpack = /obj/item/storage/backpack/science
satchel = /obj/item/storage/backpack/satchel/tox
+5 -5
View File
@@ -135,7 +135,7 @@
var/curr_z = text2num(dmmRegex.group[5])
if(curr_z < z_lower || curr_z > z_upper)
continue
var/curr_x = text2num(dmmRegex.group[3])
var/curr_y = text2num(dmmRegex.group[4])
@@ -171,7 +171,7 @@
if(width > right_width)
for(var/i in 1 to lines)
gridLines[i] = copytext(gridLines[i], 1, key_len * right_width)
// during the actual load we're starting at the top and working our way down
gridSet.ycrd += lines - 1
@@ -300,14 +300,14 @@
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
T.AfterChange(CHANGETURF_IGNORE_AIR)
if(did_expand)
world.refresh_atmos_grid()
#ifdef TESTING
if(turfsSkipped)
testing("Skipped loading [turfsSkipped] default turfs")
#endif
if(did_expand)
world.refresh_atmos_grid()
return TRUE
/datum/parsed_map/proc/build_cache(no_changeturf, bad_paths=null)
@@ -1104,7 +1104,7 @@
if(1)
new /obj/item/mayhem(src)
if(2)
new /obj/item/gun/ballistic/revolver/doublebarrel/super(src)
new /obj/item/book/granter/spell/asura(src)
if(3)
new /obj/item/guardiancreator(src)
@@ -1187,6 +1187,13 @@
unique_reskin = null
sawn_off = TRUE
/obj/item/book/granter/spell/asura
spell = /obj/effect/proc_holder/spell/self/asura
spellname = "asuras wrath"
icon_state = "bookasura"
desc = "This crimson novel emanates rage incarnate."
remarks = list("Kaio-What?", "It can only be sustained for a short time...", "It's like a massive upsurge of energy...", "Takes a heavy toll on the user's body...?", "Extra arms not included...", "There's stronger levels? Why aren't they in the book...")
//Colossus
/obj/structure/closet/crate/necropolis/colossus
name = "colossus chest"
+5 -3
View File
@@ -8,6 +8,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
throwforce = 0
/mob/dead/Initialize()
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
@@ -68,14 +69,15 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set desc= "Jump to the other server"
if(mob_transforming)
return
var/list/csa = CONFIG_GET(keyed_list/cross_server)
var/list/our_id = CONFIG_GET(string/cross_comms_name)
var/list/csa = CONFIG_GET(keyed_list/cross_server) - our_id
var/pick
switch(csa.len)
if(0)
remove_verb(src, /mob/dead/proc/server_hop)
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
if(1)
pick = csa[0]
pick = csa[1]
else
pick = input(src, "Pick a server to jump to", "Server Hop") as null|anything in csa
@@ -100,7 +102,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
C << link("[addr]?server_hop=[key]")
C << link("[addr]")
/mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister
if (registered_z != new_z)
@@ -243,6 +243,10 @@
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_fluff/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/insect_fluff/punished
name = "Burnt Off"
icon_state = "punished"
@@ -271,6 +275,10 @@
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_fluff/featherymoth
name = "Feathery Moth"
icon_state = "featherymoth"
/datum/sprite_accessory/insect_fluff/firewatch
name = "Firewatch"
icon_state = "firewatch"
@@ -291,18 +299,22 @@
name = "Moon Fly"
icon_state = "moonfly"
/datum/sprite_accessory/insect_fluff/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_fluff/plain
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/insect_fluff/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/insect_fluff/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_fluff/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_fluff/ragged
name = "Ragged"
icon_state = "ragged"
@@ -311,6 +323,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/insect_fluff/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/insect_fluff/royal
name = "Royal"
icon_state = "royal"
@@ -58,9 +58,7 @@
dimension_y = 34
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/deco_wings/atlas
name = "Atlas"
icon_state = "atlas"
//nonmoth wings
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
@@ -70,18 +68,76 @@
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/deco_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/deco_wings/bee2
name = "Small Bee"
icon_state = "beewings"
/datum/sprite_accessory/deco_wings/dragon
name = "Dragon"
icon_state = "dragon"
/datum/sprite_accessory/deco_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
/datum/sprite_accessory/deco_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/deco_wings/feathery
/datum/sprite_accessory/deco_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/deco_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
/datum/sprite_accessory/deco_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
/datum/sprite_accessory/deco_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
/datum/sprite_accessory/deco_wings/roboticwing
name = "Robotic"
icon_state = "drago"
/datum/sprite_accessory/deco_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
/datum/sprite_accessory/deco_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
/datum/sprite_accessory/deco_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
/datum/sprite_accessory/deco_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
//moth wings
/datum/sprite_accessory/deco_wings/atlas
name = "Atlas"
icon_state = "atlas"
/datum/sprite_accessory/deco_wings/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/deco_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/deco_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
/datum/sprite_accessory/deco_wings/firewatch
name = "Firewatch"
icon_state = "firewatch"
@@ -90,6 +146,10 @@
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/deco_wings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/deco_wings/lovers
name = "Lovers"
icon_state = "lovers"
@@ -106,10 +166,18 @@
name = "Moon Fly"
icon_state = "moonfly"
/datum/sprite_accessory/deco_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/deco_wings/plain
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/deco_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/deco_wings/poison
name = "Poison"
icon_state = "poison"
@@ -126,6 +194,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/deco_wings/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/deco_wings/royal
name = "Royal"
icon_state = "royal"
@@ -138,18 +210,10 @@
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/deco_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/deco_wings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
/datum/sprite_accessory/deco_wings/jungle
name = "Jungle"
icon_state = "jungle"
//INSECT WINGS
/datum/sprite_accessory/insect_wings
@@ -157,6 +221,69 @@
color_src = WINGCOLOR
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
//non insect wings
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
icon_state = "bat"
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/insect_wings/bee2
name = "Small Bee"
icon_state = "beewings"
/datum/sprite_accessory/insect_wings/dragon
name = "Dragon"
icon_state = "dragon"
/datum/sprite_accessory/insect_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
/datum/sprite_accessory/insect_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/insect_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/insect_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
/datum/sprite_accessory/insect_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
/datum/sprite_accessory/insect_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
/datum/sprite_accessory/insect_wings/roboticwing
name = "Robotic"
icon_state = "drago"
/datum/sprite_accessory/insect_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
/datum/sprite_accessory/insect_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
/datum/sprite_accessory/insect_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
/datum/sprite_accessory/insect_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
//moth wings
/datum/sprite_accessory/insect_wings/none
name = "None"
icon_state = "none"
@@ -166,25 +293,17 @@
name = "Atlas"
icon_state = "atlas"
/datum/sprite_accessory/insect_wings/bat
name = "Bat"
icon_state = "bat"
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/insect_wings/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/insect_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/insect_wings/feathery
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/insect_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
/datum/sprite_accessory/insect_wings/firewatch
name = "Firewatch"
@@ -222,6 +341,10 @@
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/insect_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/insect_wings/poison
name = "Poison"
icon_state = "poison"
@@ -238,6 +361,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/insect_wings/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/insect_wings/royal
name = "Royal"
icon_state = "royal"
@@ -265,45 +392,25 @@
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_markings/reddish
name = "Reddish"
icon_state = "reddish"
/datum/sprite_accessory/insect_markings/royal
name = "Royal"
icon_state = "royal"
/datum/sprite_accessory/insect_markings/gothic
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/insect_markings/whitefly
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/insect_markings/lovers
name = "Lovers"
icon_state = "lovers"
/datum/sprite_accessory/insect_markings/punished
name = "Punished"
icon_state = "punished"
/datum/sprite_accessory/insect_markings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_markings/firewatch
name = "Firewatch"
icon_state = "firewatch"
/datum/sprite_accessory/insect_markings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_markings/gothic
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/insect_markings/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_markings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/insect_markings/ragged
name = "Ragged"
icon_state = "ragged"
/datum/sprite_accessory/insect_markings/lovers
name = "Lovers"
icon_state = "lovers"
/datum/sprite_accessory/insect_markings/moonfly
name = "Moon Fly"
@@ -313,10 +420,42 @@
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_markings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/insect_markings/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_markings/punished
name = "Punished"
icon_state = "punished"
/datum/sprite_accessory/insect_markings/ragged
name = "Ragged"
icon_state = "ragged"
/datum/sprite_accessory/insect_markings/reddish
name = "Reddish"
icon_state = "reddish"
/datum/sprite_accessory/insect_markings/royal
name = "Royal"
icon_state = "royal"
/datum/sprite_accessory/insect_markings/whitefly
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/insect_markings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
//DONATOR WINGS
/datum/sprite_accessory/deco_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
//ckeys_allowed = list("liquidfirefly","seiga") //At request.
/datum/sprite_accessory/insect_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
//ckeys_allowed = list("liquidfirefly","seiga") //At request.
@@ -91,8 +91,8 @@
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
. = ..()
HasProximity(target)
return
/obj/item/clothing/mask/facehugger/on_found(mob/finder)
if(stat == CONSCIOUS)
@@ -304,10 +304,16 @@
emote("wag")
else if(check_zone(M.zone_selected) == BODY_ZONE_R_ARM || check_zone(M.zone_selected) == BODY_ZONE_L_ARM)
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] shakes your hand.</span>")
if((pulling == M) && (grab_state == GRAB_PASSIVE))
M.visible_message( \
"<span class='notice'>[M] squeezes [src]'s hand.</span>", \
"<span class='notice'>You squeeze [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] squeezes your hand.</span>")
else
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] shakes your hand.</span>")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
@@ -62,8 +62,8 @@
amount += BP.burn_dam
return amount
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
//In both these procs, only_organic / only_robotic are only used for healing, not for damaging. For now at least.
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL))
return FALSE
if(!forced && (status_flags & GODMODE))
@@ -71,10 +71,10 @@
if(amount > 0)
take_overall_damage(amount, 0, 0, updating_health)
else
heal_overall_damage(abs(amount), 0, 0, FALSE, TRUE, updating_health)
heal_overall_damage(abs(amount), 0, 0, only_robotic, only_organic, updating_health)
return amount
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) //Vamps don't heal naturally.
return FALSE
if(!forced && (status_flags & GODMODE))
@@ -82,7 +82,7 @@
if(amount > 0)
take_overall_damage(0, amount, 0, updating_health)
else
heal_overall_damage(0, abs(amount), 0, FALSE, TRUE, updating_health)
heal_overall_damage(0, abs(amount), 0, only_robotic, only_organic, updating_health)
return amount
@@ -80,10 +80,11 @@
if("shortlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 5 SECONDS)
to_chat(src, "<span class='warning'>Error - Limb control subsystem partially shutdown, rebooting.</span>")
if("shortblind")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
become_blind(CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), 5 SECONDS)
to_chat(src, "<span class='warning'>Visual receptor shutdown detected - Initiating reboot.</span>")
if("shortstun")
@@ -105,10 +106,11 @@
if("longlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 25 SECONDS)
to_chat(src, "<span class='warning'>Fatal error in limb control subsystem - rebooting.</span>")
if("blindmutedeaf")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
become_blind(CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), (rand(10, 25)) SECONDS)
ADD_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_hearing), (rand(15, 35)) SECONDS)
@@ -140,6 +142,7 @@
/mob/living/carbon/proc/reenable_limb(disabled_limb)
REMOVE_TRAIT(src, disabled_limb, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
to_chat(src, "<span class='notice'>Limb control subsystem successfully rebooted.</span>")
/mob/living/carbon/proc/reenable_hearing()
@@ -147,7 +150,7 @@
to_chat(src, "<span class='notice'>Hearing restored.</span>")
/mob/living/carbon/proc/reenable_vision()
REMOVE_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
cure_blind(CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Visual receptors back online.</span>")
/mob/living/carbon/proc/reenable_speech()
@@ -3,7 +3,7 @@
real_name = "Unknown"
icon = 'icons/mob/human.dmi'
icon_state = "caucasian_m"
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE
SET_APPEARANCE_FLAGS(KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE)
/mob/living/carbon/human/Initialize()
add_verb(src, /mob/living/proc/mob_sleep)
@@ -1028,7 +1028,7 @@
return
stop_pulling()
riding_datum.handle_vehicle_layer()
riding_datum.handle_vehicle_layer(dir)
riding_datum.fireman_carrying = fireman
. = ..(target, force, check_loc)
@@ -411,15 +411,18 @@
if(isrobotic(src))
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
severity *= 0.5
var/do_not_stun = FALSE
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
severity *= 0.5 //Robotpeople take less limb damage, but instead suffer system corruption (see carbon emp_act)
do_not_stun = TRUE
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.is_robotic_limb())
if(!informed)
to_chat(src, "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>")
informed = TRUE
L.receive_damage(0,severity/10)
Stun(severity*2)
if(!do_not_stun) //Tiny bit better than checking for the trait another six times in succession
Stun(severity*2)
/mob/living/carbon/human/acid_act(acidpwr, acid_volume, bodyzone_hit)
var/list/damaged = list()
@@ -9,11 +9,6 @@
return
return considering
/mob/living/carbon/human/movement_delay()
. = ..()
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
. -= 1.5
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
return 0
@@ -4,7 +4,7 @@
override_bp_icon = 'icons/mob/arachnid_parts.dmi'
say_mod = "chitters"
default_color = "00FF00"
species_traits = list(LIPS, NOEYES, NO_UNDERWEAR)
species_traits = list(LIPS, NOEYES, NO_UNDERWEAR, HAS_FLESH, HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain")
attack_verb = "slash"
@@ -94,7 +94,7 @@
name = "Xenobiological Slime Entity"
id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH)
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 150
@@ -404,7 +404,7 @@
id = SPECIES_SLIME_HYBRID
limbs_id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "legs" = "Plantigrade")
say_mod = "says"
@@ -4,7 +4,7 @@
id = SPECIES_LIZARD
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutanttongue = /obj/item/organ/tongue/lizard
mutanttail = /obj/item/organ/tail/lizard
@@ -48,7 +48,7 @@
name = "Ash Walker"
id = SPECIES_ASHWALKER
limbs_id = SPECIES_LIZARD
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,CAN_SCAR,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
mutantlungs = /obj/item/organ/lungs/ashwalker
mutanteyes = /obj/item/organ/eyes/night_vision
@@ -68,7 +68,7 @@
/datum/species/pod/pseudo_weak
name = "Anthromorphic Plant"
id = SPECIES_POD_WEAK
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS,CAN_SCAR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
limbs_id = SPECIES_POD
light_nutrition_gain_factor = 3
@@ -4,7 +4,7 @@
id = SPECIES_XENOHYBRID
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade","deco_wings"= "None")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
+8
View File
@@ -594,10 +594,18 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
drunkenness = max(drunkenness - (drunkenness * 0.04), 0)
if(drunkenness >= 6)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk)
if(prob(25))
slurring += 2
jitteriness = max(jitteriness - 3, 0)
// throw_alert("drunk", /atom/movable/screen/alert/drunk)
if(HAS_TRAIT(src, TRAIT_DRUNK_HEALING))
adjustBruteLoss(-0.12, FALSE)
adjustFireLoss(-0.06, FALSE)
sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
else
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "drunk")
clear_alert("drunk")
sound_environment_override = SOUND_ENVIRONMENT_NONE
if(mind && (mind.assigned_role == "Scientist" || mind.assigned_role == "Research Director"))
if(SSresearch.science_tech)
@@ -8,10 +8,12 @@
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
else
clear_fullscreen("high")
clear_alert("high")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "high")
sound_environment_override = SOUND_ENVIRONMENT_NONE
/mob/living/carbon/set_drugginess(amount)
druggy = max(amount, 0)
+4 -2
View File
@@ -141,7 +141,8 @@
/mob/living/proc/getBruteLoss()
return bruteloss
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
//only_robotic and only_organic arg only relevant for carbons
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = clamp((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
@@ -215,7 +216,8 @@
/mob/living/proc/getFireLoss()
return fireloss
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
//only_robotic and only_organic arg only relevant for carbons
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && (status_flags & GODMODE))
return FALSE
fireloss = clamp((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
@@ -101,6 +101,7 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
dirt_buildup()
+3 -3
View File
@@ -911,10 +911,10 @@
if(!istype(apc) || QDELETED(apc) || apc.stat & BROKEN)
to_chat(src, "<span class='danger'>Hack aborted. The designated APC no longer exists on the power network.</span>")
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, TRUE, ignore_walls = FALSE)
else if(apc.aidisabled)
to_chat(src, "<span class='danger'>Hack aborted. \The [apc] is no longer responding to our systems.</span>")
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, TRUE, ignore_walls = FALSE)
else
malf_picker.processing_time += 10
@@ -923,7 +923,7 @@
apc.locked = TRUE
apc.coverlocked = TRUE
playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/ding.ogg', 50, TRUE, ignore_walls = FALSE)
to_chat(src, "Hack complete. \The [apc] is now under your exclusive control.")
apc.update_icon()
@@ -426,6 +426,10 @@
//Misc
.["Cyborg - Misc (dog - blade)"] = process_holoform_icon_filter(icon('modular_citadel/icons/mob/widerobot.dmi', "blade"), HOLOFORM_FILTER_PAI, FALSE)
// Gorillas
.["Gorilla (standing)"] = process_holoform_icon_filter(icon('icons/mob/gorilla.dmi', "standing"), HOLOFORM_FILTER_PAI, FALSE)
.["Gorilla (crawling)"] = process_holoform_icon_filter(icon('icons/mob/gorilla.dmi', "crawling"), HOLOFORM_FILTER_PAI, FALSE)
/mob/living/silicon/pai/proc/default_chassis_pixel_offsets_x()
. = list()
//Engi
@@ -81,10 +81,10 @@
to_chat(src, "<span class='userdanger'>The impact degrades your holochassis!</span>")
return amount
/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
return take_holo_damage(amount)
/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
return take_holo_damage(amount)
/mob/living/silicon/pai/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
@@ -7,13 +7,13 @@
updatehealth()
return amount
/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BRUTE])
. = adjustHealth(amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BURN])
@@ -37,23 +37,25 @@
return
..()
/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM)
if(ismob(AM))
if(isliving(AM))
var/mob/living/A = AM
if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING))
if(prob(squish_chance))
A.visible_message("<span class='notice'>[A] squashed [src].</span>", "<span class='notice'>You squashed [src].</span>")
adjustBruteLoss(1) //kills a normal cockroach
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
else
if(isstructure(AM))
/mob/living/simple_animal/cockroach/Crossed(atom/movable/AM)
. = ..()
if(isliving(AM))
var/mob/living/A = AM
if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING))
if(HAS_TRAIT(A, TRAIT_PACIFISM))
A.visible_message("<span class='notice'>[A] carefully steps over [src].</span>", "<span class='notice'>You carefully step over [src] to avoid hurting it.</span>")
return
if(prob(squish_chance))
AM.visible_message("<span class='notice'>[src] was crushed under [AM].</span>")
adjustBruteLoss(1)
A.visible_message("<span class='notice'>[A] squashed [src].</span>", "<span class='notice'>You squashed [src].</span>")
adjustBruteLoss(1) //kills a normal cockroach
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
else if(isstructure(AM))
if(prob(squish_chance))
AM.visible_message("<span class='notice'>[src] is crushed under [AM].</span>")
adjustBruteLoss(1)
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
/mob/living/simple_animal/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach.
return
@@ -263,7 +263,7 @@
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,user,1)
INVOKE_ASYNC(item_to_add, /obj/item.proc/afterattack, src, user, 1)
return
if(inventory_head)
@@ -271,13 +271,15 @@
to_chat(user, "<span class='warning'>You can't put more than one hat on [src]!</span>")
return
if(!item_to_add)
user.visible_message("[user] pets [src].","<span class='notice'>You rest your hand on [src]'s head for a moment.</span>")
user.visible_message("<span class='notice'>[user] pets [src].</span>", "<span class='notice'>You rest your hand on [src]'s head for a moment.</span>")
if(flags_1 & HOLOGRAM_1)
return
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, src, /datum/mood_event/pet_animal, src)
return
if(user && !user.temporarilyRemoveItemFromInventory(item_to_add))
to_chat(user, "<span class='warning'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!</span>")
return 0
return
var/valid = FALSE
if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/head))
@@ -287,11 +289,11 @@
if(valid)
if(health <= 0)
to_chat(user, "<span class ='notice'>There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].</span>")
to_chat(user, "<span class='notice'>There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].</span>")
else if(user)
user.visible_message("[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.",
"<span class='notice'>You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.</span>",
"<span class='italics'>You hear a friendly-sounding bark.</span>")
user.visible_message("<span class='notice'>[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.</span>",
"<span class='notice'>You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.</span>",
"<span class='hear'>You hear a friendly-sounding bark.</span>")
item_to_add.forceMove(src)
src.inventory_head = item_to_add
update_corgi_fluff()
@@ -361,7 +363,7 @@
icon_state = "old_corgi"
icon_living = "old_corgi"
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
desc = "At a ripe old age of [record_age], Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
RemoveElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/mob_holder, "old_corgi")
@@ -110,6 +110,7 @@
/obj/effect/snare/Crossed(AM as mob|obj)
. = ..()
if(isliving(AM) && spawner && spawner.summoner && AM != spawner && !spawner.hasmatchingsummoner(AM))
to_chat(spawner.summoner, "<span class='danger'><B>[AM] has crossed surveillance snare, [name].</span></B>")
var/list/guardians = spawner.summoner.hasparasites()
@@ -94,16 +94,17 @@
consume_bait()
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait()
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in oview(src, 9)
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in oview(src, 9)
if(!diamonds && !bait)
return
var/list/L = list()
for(var/obj/O in view(src, 9))
L += O
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in L
if(diamonds)
var/distanced = 0
distanced = get_dist(loc,diamonds.loc)
if(distanced <= 1 && diamonds)
qdel(diamonds)
src.visible_message("<span class='notice'>[src] consumes [diamonds], and it disappears! ...At least, you think.</span>")
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in L
if(bait)
var/distanceb = 0
distanceb = get_dist(loc,bait.loc)
@@ -219,6 +219,9 @@
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner)
. = ..()
INVOKE_ASYNC(src, .proc/createpatch)
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/proc/createpatch()
var/tentacle_locs = spiral_range_turfs(1, get_turf(src))
for(var/T in tentacle_locs)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
@@ -42,7 +42,8 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/nugget = 5)
/mob/living/simple_animal/hostile/retaliate/frog/Crossed(AM as mob|obj)
. = ..()
if(!stat && isliving(AM))
var/mob/living/L = AM
if(L.mob_size > MOB_SIZE_TINY)
playsound(src, stepped_sound, 50, 1)
playsound(src, stepped_sound, 50, TRUE)
@@ -1189,4 +1189,4 @@
icon_state = "mtoo-flap"
icon_living = "mtoo-flap"
icon_dead = "mtoo-dead"
icon_sit = "mtoo_sit"
icon_sit = "mtoo_sit"
@@ -225,7 +225,7 @@
. += "Power Level: [powerlevel]"
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced)
amount = -abs(amount)
return ..() //Heals them
+3
View File
@@ -177,3 +177,6 @@
var/list/ability_actions
/// ability = list(data). see __DEFINES/mobs/innate_abilities.dm
var/list/ability_properties
///Override for sound_environments. If this is set the user will always hear a specific type of reverb (Instead of the area defined reverb)
var/sound_environment_override = SOUND_ENVIRONMENT_NONE
+4
View File
@@ -73,6 +73,7 @@
return FALSE
//We are now going to move
var/add_delay = mob.movement_delay()
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? 2 : 1 ) ), FALSE) // set it now in case of pulled objects
if(old_move_delay + (add_delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
move_delay = old_move_delay
else
@@ -95,6 +96,7 @@
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
add_delay *= 2
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay), FALSE)
move_delay += add_delay
if(.) // If mob is null here, we deserve the runtime
if(mob.throwing)
@@ -104,6 +106,8 @@
if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM))
L.setDir(turn(L.dir, 180))
last_move = world.time
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay)
/// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement.
@@ -27,7 +27,7 @@
// user?.mind?.adjust_experience(/datum/skill/gaming, 1)
if(boss_hp <= 0)
heads_up = "You have crushed [boss_name]! Rejoice!"
playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
game_active = FALSE
program_icon_state = "arcade_off"
if(istype(computer))
@@ -37,7 +37,7 @@
sleep(10)
else if(player_hp <= 0 || player_mp <= 0)
heads_up = "You have been defeated... how will the station survive?"
playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
game_active = FALSE
program_icon_state = "arcade_off"
if(istype(computer))
@@ -57,17 +57,17 @@
return
if (boss_mp <= 5)
heads_up = "[boss_mpamt] magic power has been stolen from you!"
playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3)
player_mp -= boss_mpamt
boss_mp += boss_mpamt
else if(boss_mp > 5 && boss_hp <12)
heads_up = "[boss_name] heals for [bossheal] health!"
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
boss_hp += bossheal
boss_mp -= boss_mpamt
else
heads_up = "[boss_name] attacks you for [boss_attackamt] damage!"
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
player_hp -= boss_attackamt
pause_state = FALSE
@@ -106,7 +106,7 @@
attackamt = rand(2,6)// + rand(0, gamerSkill)
pause_state = TRUE
heads_up = "You attack for [attackamt] damage."
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
boss_hp -= attackamt
sleep(10)
game_check()
@@ -123,7 +123,7 @@
healcost = rand(1, maxPointCost)
pause_state = TRUE
heads_up = "You heal for [healamt] damage."
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
player_hp += healamt
player_mp -= healcost
sleep(10)
@@ -136,7 +136,7 @@
rechargeamt = rand(4,7)// + rand(0, gamerSkill)
pause_state = TRUE
heads_up = "You regain [rechargeamt] magic power."
playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10)
playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
player_mp += rechargeamt
sleep(10)
game_check()
@@ -153,7 +153,7 @@
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
if(ticket_count >= 1)
new /obj/item/stack/arcadeticket((get_turf(computer)), 1)
to_chat(usr, "<span class='notice'>[src] dispenses a ticket!</span>")
to_chat(usr, "<span class='notice'>[computer] dispenses a ticket!</span>")
ticket_count -= 1
printer.stored_paper -= 1
else
+16 -4
View File
@@ -96,7 +96,7 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
return TRUE
remove_movespeed_modifier(existing, FALSE)
if(length(movespeed_modification))
BINARY_INSERT(type_or_datum.id, movespeed_modification, datum/movespeed_modifier, type_or_datum, priority, COMPARE_VALUE)
BINARY_INSERT(type_or_datum.id, movespeed_modification, /datum/movespeed_modifier, type_or_datum, priority, COMPARE_VALUE)
LAZYSET(movespeed_modification, type_or_datum.id, type_or_datum)
if(update)
update_movespeed()
@@ -217,13 +217,25 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
else
continue
. = M.apply_multiplicative(., src)
var/old = cached_multiplicative_slowdown // CITAEDL EDIT - To make things a bit less jarring, when in situations where
// your delay decreases, "give" the delay back to the client
cached_multiplicative_slowdown = .
var/diff = old - cached_multiplicative_slowdown
if((diff > 0) && client)
if(!client)
return
var/diff = (client.last_move - client.move_delay) - cached_multiplicative_slowdown
if(diff > 0)
if(client.move_delay > world.time + 1.5)
client.move_delay -= diff
var/timeleft = world.time - client.move_delay
var/elapsed = world.time - client.last_move
var/glide_size_current = glide_size
if((timeleft <= 0) || (elapsed > 20))
set_glide_size(16, TRUE)
return
var/pixels_moved = glide_size_current * elapsed * (1 / world.tick_lag)
// calculate glidesize needed to move to the next tile within timeleft deciseconds
var/ticks_allowed = timeleft / world.tick_lag
var/pixels_per_tick = pixels_moved / ticks_allowed
set_glide_size(pixels_per_tick * GLOB.glide_size_multiplier, TRUE)
/// Get the move speed modifiers list of the mob
/mob/proc/get_movespeed_modifiers()
+5
View File
@@ -62,6 +62,11 @@
var/mod = CONFIG_GET(number/movedelay/walk_delay)
multiplicative_slowdown = isnum(mod)? mod : initial(multiplicative_slowdown)
/datum/movespeed_modifier/config_wak_run/walk/apply_multiplicative(existing, mob/target)
. = ..()
if(HAS_TRAIT(target, TRAIT_SPEEDY_STEP))
. -= 1.25
/datum/movespeed_modifier/config_walk_run/run/sync()
var/mod = CONFIG_GET(number/movedelay/run_delay)
multiplicative_slowdown = isnum(mod)? mod : initial(multiplicative_slowdown)
+2 -1
View File
@@ -150,7 +150,8 @@
H.DefaultCombatKnockdown(40)
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
else if(filled)
victim.adjustStaminaLoss(1)
if(iscarbon(victim))
victim.adjustStaminaLoss(1)
playsound(src, "water_wade", 20, TRUE)
return ..()
@@ -56,12 +56,14 @@
else
..()
/obj/machinery/field/containment/Crossed(mob/mover)
if(isliving(mover))
shock(mover)
/obj/machinery/field/containment/Crossed(atom/movable/AM)
. = ..()
if(isliving(AM))
shock(AM)
if(ismachinery(AM) || isstructure(AM) || ismecha(AM))
bump_field(AM)
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
/obj/machinery/field/containment/proc/set_master(master1,master2)
if(!master1 || !master2)
@@ -44,6 +44,7 @@
movement_range = 0
/obj/effect/accelerated_particle/Crossed(atom/A)
. = ..()
if(isliving(A))
toxmob(A)
@@ -348,11 +348,11 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/proc/alarm()
switch(get_status())
if(SUPERMATTER_DELAMINATING)
playsound(src, 'sound/misc/bloblarm.ogg', 100)
playsound(src, 'sound/misc/bloblarm.ogg', 100, FALSE, 40, 30, falloff_distance = 10)
if(SUPERMATTER_EMERGENCY)
playsound(src, 'sound/machines/engine_alert1.ogg', 100)
playsound(src, 'sound/machines/engine_alert1.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
if(SUPERMATTER_DANGER)
playsound(src, 'sound/machines/engine_alert2.ogg', 100)
playsound(src, 'sound/machines/engine_alert2.ogg', 100, FALSE, 30, 30, falloff_distance = 10)
if(SUPERMATTER_WARNING)
playsound(src, 'sound/machines/terminal_alert.ogg', 75)
+17 -2
View File
@@ -18,6 +18,8 @@
item_flags = NEEDS_PERMIT
attack_verb = list("struck", "hit", "bashed")
attack_speed = CLICK_CD_RANGE
var/ranged_attack_speed = CLICK_CD_RANGE
var/melee_attack_speed = CLICK_CD_MELEE
var/fire_sound = "gunshot"
var/suppressed = null //whether or not a message is displayed when fired
@@ -159,7 +161,7 @@
user.UseStaminaBuffer(safe_cost)
if(suppressed)
playsound(user, fire_sound, 10, 1)
playsound(user, fire_sound, 10, TRUE, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0)
else
playsound(user, fire_sound, 50, 1)
if(message)
@@ -174,12 +176,25 @@
for(var/obj/O in contents)
O.emp_act(severity)
/obj/item/gun/attack(mob/living/M, mob/user)
. = ..()
if(!(. & DISCARD_LAST_ACTION))
user.DelayNextAction(melee_attack_speed)
/obj/item/gun/attack_obj(obj/O, mob/user)
. = ..()
if(!(. & DISCARD_LAST_ACTION))
user.DelayNextAction(melee_attack_speed)
/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params)
. = ..()
if(user && !CheckAttackCooldown(user, target))
if(user && !CheckAttackCooldown(user, target, TRUE))
return
process_afterattack(target, user, flag, params)
/obj/item/gun/CheckAttackCooldown(mob/user, atom/target, shooting = FALSE)
return user.CheckActionCooldown(shooting? ranged_attack_speed : attack_speed, clickdelay_from_next_action, clickdelay_mod_bypass, clickdelay_ignores_next_action)
/obj/item/gun/proc/process_afterattack(atom/target, mob/living/user, flag, params)
if(!target)
return
@@ -373,7 +373,6 @@
sawn_off = TRUE
slot_flags = ITEM_SLOT_BELT
/obj/item/gun/ballistic/revolver/reverse //Fires directly at its user... unless the user is a clown, of course.
clumsy_check = 0

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