Merge branch 'master' into Dispencer-UI-change
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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(.)
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -174,7 +174,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
//is_bwoink is TRUE if this ticket was started by an admin PM
|
||||
/datum/admin_help/New(msg, client/C, is_bwoink)
|
||||
//clean the input msg
|
||||
msg = sanitize(copytext_char(msg,1,MAX_MESSAGE_LEN))
|
||||
msg = copytext_char(msg,1,MAX_MESSAGE_LEN)
|
||||
if(!msg || !C || !C.mob)
|
||||
qdel(src)
|
||||
return
|
||||
@@ -263,7 +263,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
//message from the initiator without a target, all admins will see this
|
||||
//won't bug irc
|
||||
/datum/admin_help/proc/MessageNoRecipient(msg)
|
||||
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
|
||||
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
|
||||
var/ref_src = "[REF(src)]"
|
||||
//Message to be sent to all admins
|
||||
var/admin_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> <span class='linkify'>[keywords_lookup(msg)]</span></span>"
|
||||
@@ -523,7 +523,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
return
|
||||
|
||||
msg = trim(msg)
|
||||
msg = sanitize(trim(msg))
|
||||
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -113,7 +113,6 @@
|
||||
to_chat(src, "<span class='danger'>Error: Use the admin IRC/Discord channel, nerd.</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
|
||||
else
|
||||
//get message text, limit it's length.and clean/escape html
|
||||
if(!msg)
|
||||
@@ -128,11 +127,16 @@
|
||||
else
|
||||
if(holder)
|
||||
to_chat(src, "<span class='danger'>Error: Admin-PM: Client not found.</span>", confidential = TRUE)
|
||||
to_chat(src, "<span class='danger'><b>Message not sent:</b></span><br>[msg]", confidential = TRUE)
|
||||
to_chat(src, "<span class='danger'><b>Message not sent:</b></span><br>[sanitize(msg)]", confidential = TRUE)
|
||||
if(recipient_ticket)
|
||||
recipient_ticket.AddInteraction("<b>No client found, message not sent:</b><br>[msg]")
|
||||
return
|
||||
else
|
||||
//clean the message if it's not sent by a high-rank admin
|
||||
if(!check_rights(R_SERVER|R_DEBUG,0)||external)//no sending html to the poor bots
|
||||
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return
|
||||
current_ticket.MessageNoRecipient(msg)
|
||||
return
|
||||
|
||||
@@ -141,7 +145,7 @@
|
||||
to_chat(src, "<span class='danger'>Error: Admin-PM: You are unable to use admin PM-s (muted).</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
if (src.handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
return
|
||||
|
||||
//clean the message if it's not sent by a high-rank admin
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
|
||||
/obj/item/organ/heart/gland/ventcrawling/activate()
|
||||
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
|
||||
owner.ventcrawler = VENTCRAWLER_ALWAYS
|
||||
owner.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
|
||||
|
||||
@@ -277,3 +277,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob)
|
||||
if(!B)
|
||||
mind.add_antag_datum(/datum/antagonist/blob)
|
||||
|
||||
//the same but it's forced to be allowed by default as cameras usually don't allow emoting
|
||||
/mob/camera/blob/emote(act, m_type=1, message = null, intentional = FALSE, forced = TRUE)
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -165,14 +165,16 @@
|
||||
/datum/clockwork_rite/treat_wounds/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target)
|
||||
if(!target)
|
||||
return FALSE
|
||||
if(!target.all_wounds.len)
|
||||
if(!target.all_wounds || !target.all_wounds.len)
|
||||
to_chat(invoker, "<span class='inathneq_small'>This one does not require mending.</span>")
|
||||
return FALSE
|
||||
.= ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
target.adjustToxLoss(10 * target.all_wounds.len)
|
||||
QDEL_LIST(target.all_wounds)
|
||||
for(var/i in target.all_wounds)
|
||||
var/datum/wound/mended = i
|
||||
mended.remove_wound()
|
||||
to_chat(target, "<span class='warning'>You feel your wounds heal, but are overcome with deep nausea.</span>")
|
||||
new /obj/effect/temp_visual/ratvar/sigil/vitality(T)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
. = ..()
|
||||
desc = initial(desc)
|
||||
|
||||
obj/item/shield/riot/ratvarian/proc/calc_bash_mult()
|
||||
/obj/item/shield/riot/ratvarian/proc/calc_bash_mult()
|
||||
var/bash_mult = 0
|
||||
if(!dam_absorbed)
|
||||
return 1
|
||||
|
||||
@@ -203,10 +203,10 @@
|
||||
to_chat(user, "<span class='warning'>You need to hold the slab in your active hand to recite scripture!</span>")
|
||||
return FALSE
|
||||
var/initial_tier = initial(scripture.tier)
|
||||
if(initial_tier == SCRIPTURE_PERIPHERAL)
|
||||
if(initial_tier == SCRIPTURE_PERIPHERAL && !issilicon(user)) //Silicons use peripheral scripture & cannot open the slab.
|
||||
to_chat(user, "<span class='warning'>Nice try using href exploits</span>")
|
||||
return
|
||||
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
|
||||
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier] &&!issilicon(user)) //silicons can't choose their spells, so lets allow them to always cast their assigned ones.
|
||||
to_chat(user, "<span class='warning'>That scripture is not unlocked, and cannot be recited!</span>")
|
||||
return FALSE
|
||||
var/datum/clockwork_scripture/scripture_to_recite = new scripture
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@
|
||||
transform = matrix() * 2
|
||||
animate(src, transform = matrix() * 0.5, time = 30, flags = ANIMATION_END_NOW)
|
||||
|
||||
obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
if(!purpose_fulfilled)
|
||||
var/area/gate_area = get_area(src)
|
||||
|
||||
@@ -15,3 +15,5 @@
|
||||
audible_message("<i>*click*</i>")
|
||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
|
||||
activate()
|
||||
|
||||
. = ..()
|
||||
|
||||
+1
-1
@@ -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
|
||||
. = ..()
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
gender = NEUTER
|
||||
health = 350
|
||||
maxHealth = 350
|
||||
ventcrawler = VENTCRAWLER_NONE
|
||||
density = TRUE
|
||||
pass_flags = 0
|
||||
sight = (SEE_TURFS | SEE_OBJS)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
var/give_equipment = TRUE
|
||||
var/list/researched_knowledge = list()
|
||||
var/total_sacrifices = 0
|
||||
var/list/sac_targetted = list() //Which targets did living hearts give them, but they did not sac?
|
||||
var/list/actually_sacced = list() //Which targets did they actually sac?
|
||||
var/ascended = FALSE
|
||||
|
||||
/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin)
|
||||
@@ -175,6 +177,17 @@
|
||||
knowledge_message += "[EK.name]"
|
||||
parts += knowledge_message.Join(", ")
|
||||
|
||||
parts += "<b>Targets assigned by living hearts, but not sacrificed:</b>"
|
||||
if(!sac_targetted.len)
|
||||
parts += "None."
|
||||
else
|
||||
parts += sac_targetted.Join(",")
|
||||
parts += "<b>Sacrifices performed:</b>"
|
||||
if(!actually_sacced.len)
|
||||
parts += "<span class='redtext'>None!</span>"
|
||||
else
|
||||
parts += actually_sacced.Join(",")
|
||||
|
||||
return parts.Join("<br>")
|
||||
////////////////
|
||||
// Knowledge //
|
||||
@@ -213,6 +226,23 @@
|
||||
if(ascended)
|
||||
. += 20
|
||||
|
||||
/datum/antagonist/heretic/antag_panel()
|
||||
var/list/parts = list()
|
||||
parts += ..()
|
||||
parts += "<b>Targets currently assigned by living hearts (Can give a false negative if they stole someone elses living heart):</b>"
|
||||
if(!sac_targetted.len)
|
||||
parts += "None."
|
||||
else
|
||||
parts += sac_targetted.Join(",")
|
||||
parts += "<b>Targets actually sacrificed:</b>"
|
||||
if(!actually_sacced.len)
|
||||
parts += "None."
|
||||
else
|
||||
parts += actually_sacced.Join(",")
|
||||
|
||||
return (parts.Join("<br>") + "<br>")
|
||||
|
||||
|
||||
////////////////
|
||||
// Objectives //
|
||||
////////////////
|
||||
|
||||
@@ -6,6 +6,17 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///Target
|
||||
var/mob/living/carbon/human/target
|
||||
var/datum/antagonist/heretic/sac_targetter //The heretic who used this to acquire the current target - gets cleared when target gets sacrificed.
|
||||
|
||||
/obj/item/living_heart/Initialize()
|
||||
. = ..()
|
||||
GLOB.living_heart_cache.Add(src) //Add is better than +=.
|
||||
|
||||
/obj/item/living_heart/Destroy()
|
||||
GLOB.living_heart_cache.Remove(src)
|
||||
if(sac_targetter && target)
|
||||
sac_targetter.sac_targetted.Remove(target.real_name)
|
||||
return ..()
|
||||
|
||||
/obj/item/living_heart/attack_self(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/**
|
||||
* #Eldritch Knwoledge
|
||||
* #Eldritch Knowledge
|
||||
*
|
||||
* Datum that makes eldritch cultist interesting.
|
||||
*
|
||||
@@ -252,6 +252,10 @@
|
||||
LH.target = null
|
||||
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
|
||||
EC.actually_sacced.Add(H.real_name)
|
||||
if(LH.sac_targetter)
|
||||
LH.sac_targetter.sac_targetted.Remove(H.real_name)
|
||||
LH.sac_targetter = null
|
||||
EC.total_sacrifices++
|
||||
for(var/X in carbon_user.get_all_gear())
|
||||
if(!istype(X,/obj/item/forbidden_book))
|
||||
@@ -265,8 +269,14 @@
|
||||
var/datum/objective/A = new
|
||||
A.owner = user.mind
|
||||
var/list/targets = list()
|
||||
var/list/target_blacklist = list()
|
||||
for(var/obj/item/living_heart/CLH in GLOB.living_heart_cache)
|
||||
if(!CLH || !CLH.target || !CLH.target.mind)
|
||||
continue
|
||||
target_blacklist.Add(CLH.target.mind)
|
||||
|
||||
for(var/i in 0 to 3)
|
||||
var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code
|
||||
var/datum/mind/targeted = A.find_target(blacklist = target_blacklist)//easy way, i dont feel like copy pasting that entire block of code
|
||||
if(!targeted)
|
||||
break
|
||||
targets[targeted.current.real_name] = targeted.current
|
||||
@@ -274,9 +284,24 @@
|
||||
|
||||
if(!LH.target && targets.len)
|
||||
LH.target = pick(targets) //Tsk tsk, you can and will get another target if you want it or not.
|
||||
|
||||
if(LH.target)
|
||||
target_blacklist = list()
|
||||
for(var/obj/item/living_heart/CLH in (GLOB.living_heart_cache - LH)) //Recreate blacklist, excluding ourselves.
|
||||
if(!CLH || !CLH.target || !CLH.target.mind)
|
||||
continue
|
||||
target_blacklist.Add(CLH.target.mind)
|
||||
if(LH.target.mind in target_blacklist) //Someone was faster, or you tried to cheese the system.
|
||||
to_chat(user, "<span class='warning'>It seems you were too slow, and your target of choice has already been selected by another living heart!</span>")
|
||||
LH.target = null
|
||||
|
||||
qdel(A)
|
||||
if(LH.target)
|
||||
to_chat(user,"<span class='warning'>Your new target has been selected, go and sacrifice [LH.target.real_name]!</span>")
|
||||
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
LH.sac_targetter = EC
|
||||
EC.sac_targetted.Add(LH.target.real_name)
|
||||
|
||||
else
|
||||
to_chat(user,"<span class='warning'>target could not be found for living heart.</span>")
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
stop_automated_movement = 1
|
||||
status_flags = CANPUSH
|
||||
pass_flags = PASSTABLE
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxHealth = 150
|
||||
@@ -53,6 +52,10 @@
|
||||
You can attack any item or dead creature to consume it - creatures will fully restore your health. \
|
||||
Finally, you can restore yourself to your original form while morphed by shift-clicking yourself.</b>"
|
||||
|
||||
/mob/living/simple_animal/hostile/morph/Initialize()
|
||||
. = ..()
|
||||
src.AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
|
||||
|
||||
/mob/living/simple_animal/hostile/morph/examine(mob/user)
|
||||
if(morphed)
|
||||
. = form.examine(user)
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
var/list/drained_mobs = list() //Cannot harvest the same mob twice
|
||||
var/perfectsouls = 0 //How many perfect, regen-cap increasing souls the revenant has. //TODO, add objective for getting a perfect soul(s?)
|
||||
var/generated_objectives_and_spells = FALSE
|
||||
var/telekinesis_cooldown
|
||||
|
||||
/mob/living/simple_animal/revenant/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -93,13 +94,16 @@
|
||||
|
||||
/mob/living/simple_animal/revenant/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='deadsay'><span class='big bold'>You are a revenant.</span></span>")
|
||||
to_chat(src, "<b>Your formerly mundane spirit has been infused with alien energies and empowered into a revenant.</b>")
|
||||
to_chat(src, "<b>You are not dead, not alive, but somewhere in between. You are capable of limited interaction with both worlds.</b>")
|
||||
to_chat(src, "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>")
|
||||
to_chat(src, "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>")
|
||||
to_chat(src, "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>")
|
||||
to_chat(src, "<b>Be sure to read <a href=\"https://tgstation13.org/wiki/Revenant\">the wiki page</a> to learn more.</b>")
|
||||
var/revenant_greet
|
||||
revenant_greet += "<span class='deadsay'><span class='big bold'>You are a revenant.</span></span>"
|
||||
revenant_greet += "<b>Your formerly mundane spirit has been infused with alien energies and empowered into a revenant.</b>"
|
||||
revenant_greet += "<b>You are not dead, not alive, but somewhere in between. You are capable of limited interaction with both worlds.</b>"
|
||||
revenant_greet += "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>"
|
||||
revenant_greet += "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>"
|
||||
revenant_greet += "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>"
|
||||
revenant_greet += "<b>Be sure to read <a href=\"https://tgstation13.org/wiki/Revenant\">the wiki page</a> to learn more.</b>"
|
||||
revenant_greet += "<b>You are also able to telekinetically throw objects by clickdragging them.</b>"
|
||||
to_chat(src, revenant_greet)
|
||||
if(!generated_objectives_and_spells)
|
||||
generated_objectives_and_spells = TRUE
|
||||
mind.assigned_role = ROLE_REVENANT
|
||||
@@ -317,6 +321,12 @@
|
||||
to_chat(src, "<span class='revenminor'>Lost [essence_amt]E[source ? " from [source]":""].</span>")
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/telekinesis_cooldown_end()
|
||||
if(!telekinesis_cooldown)
|
||||
CRASH("telekinesis_cooldown_end ran when telekinesis_cooldown on [src] was false")
|
||||
else
|
||||
telekinesis_cooldown = FALSE
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/death_reset()
|
||||
revealed = FALSE
|
||||
unreveal_time = 0
|
||||
@@ -431,6 +441,38 @@
|
||||
qdel(revenant)
|
||||
..()
|
||||
|
||||
/proc/RevenantThrow(over, mob/user, obj/item/throwable)
|
||||
var/mob/living/simple_animal/revenant/spooker = user
|
||||
if(!istype(throwable))
|
||||
return
|
||||
if(!throwable.anchored && !spooker.telekinesis_cooldown && spooker.essence > 20)
|
||||
if(7 < get_dist(throwable, spooker))
|
||||
return
|
||||
if(3 >= get_dist(throwable, spooker))
|
||||
spooker.stun(10)
|
||||
spooker.reveal(25)
|
||||
else
|
||||
spooker.stun(20)
|
||||
spooker.reveal(50)
|
||||
spooker.change_essence_amount(-20, FALSE, "telekinesis")
|
||||
spooker.telekinesis_cooldown = TRUE
|
||||
throwable.float(TRUE, TRUE)
|
||||
sleep(20)
|
||||
throwable.DoRevenantThrowEffects(over)
|
||||
throwable.throw_at(over, 10, 2)
|
||||
ADD_TRAIT(throwable, TRAIT_SPOOKY_THROW, "revenant")
|
||||
log_combat(throwable, over, "spooky telekinesised at", throwable)
|
||||
var/obj/effect/temp_visual/telekinesis/T = new(get_turf(throwable))
|
||||
T.color = "#8715b4"
|
||||
addtimer(CALLBACK(spooker, /mob/living/simple_animal/revenant.proc/telekinesis_cooldown_end), 50)
|
||||
sleep(5)
|
||||
throwable.float(FALSE, TRUE)
|
||||
|
||||
|
||||
//Use this for effects you want to happen when a revenant throws stuff, check the TRAIT_SPOOKY_THROW if you want to know if its still being thrown
|
||||
/obj/item/proc/DoRevenantThrowEffects(atom/target)
|
||||
return TRUE
|
||||
|
||||
//objectives
|
||||
/datum/objective/revenant
|
||||
var/targetAmount = 100
|
||||
|
||||
@@ -93,7 +93,6 @@
|
||||
AIStatus = AI_OFF
|
||||
pass_flags = PASSTABLE
|
||||
mob_size = MOB_SIZE_TINY
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/beam/disabler
|
||||
ranged_cooldown_time = 20
|
||||
@@ -112,6 +111,7 @@
|
||||
remove_verb(src, /mob/living/verb/pulled)
|
||||
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
|
||||
diag_hud.add_to_hud(src)
|
||||
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/med_hud_set_health()
|
||||
var/image/holder = hud_list[DIAG_HUD]
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
var/list/to_generate = list(
|
||||
CONTRACT_PAYOUT_LARGE,
|
||||
CONTRACT_PAYOUT_MEDIUM,
|
||||
CONTRACT_PAYOUT_SMALL,
|
||||
CONTRACT_PAYOUT_MEDIUM,
|
||||
CONTRACT_PAYOUT_SMALL,
|
||||
CONTRACT_PAYOUT_SMALL,
|
||||
CONTRACT_PAYOUT_SMALL
|
||||
|
||||
@@ -103,29 +103,29 @@
|
||||
name = "knotted dildo"
|
||||
attack_verb = list("penetrated", "knotted", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/human
|
||||
/obj/item/dildo/human
|
||||
dildo_shape = "human"
|
||||
name = "human dildo"
|
||||
attack_verb = list("penetrated", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/plain
|
||||
/obj/item/dildo/plain
|
||||
dildo_shape = "plain"
|
||||
name = "plain dildo"
|
||||
attack_verb = list("penetrated", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/flared
|
||||
/obj/item/dildo/flared
|
||||
dildo_shape = "flared"
|
||||
name = "flared dildo"
|
||||
attack_verb = list("penetrated", "slapped", "neighed", "gaped", "prolapsed", "inseminated")
|
||||
|
||||
obj/item/dildo/flared/huge
|
||||
/obj/item/dildo/flared/huge
|
||||
name = "literal horse cock"
|
||||
desc = "THIS THING IS HUGE!"
|
||||
dildo_size = 4
|
||||
force = 10
|
||||
hitsound = 'sound/weapons/klonk.ogg'
|
||||
|
||||
obj/item/dildo/custom
|
||||
/obj/item/dildo/custom
|
||||
name = "customizable dildo"
|
||||
desc = "Thanks to significant advances in synthetic nanomaterials, this dildo is capable of taking on many different forms to fit the user's preferences! Pricy!"
|
||||
can_customize = TRUE
|
||||
@@ -136,9 +136,9 @@ obj/item/dildo/custom
|
||||
// Suicide acts, by request
|
||||
|
||||
/obj/item/dildo/proc/manual_suicide(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] finally finishes deepthroating the [src], and their life.</span>")
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
user.visible_message("<span class='suicide'>[user] finally finishes deepthroating the [src], and their life.</span>")
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
|
||||
/obj/item/dildo/suicide_act(mob/living/user)
|
||||
// is_knotted = ((src.dildo_shape == "knotted")?"They swallowed the knot":"Their face is turning blue")
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
attack(user,user)
|
||||
return FIRELOSS
|
||||
|
||||
/obj/item/assembly/flash/DoRevenantThrowEffects(atom/target)
|
||||
AOE_flash()
|
||||
|
||||
/obj/item/assembly/flash/update_icon(flash = FALSE)
|
||||
cut_overlays()
|
||||
attached_overlays = list()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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///////////////////
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
. = ..()
|
||||
if(is_type_in_list(src, GLOB.ventcrawl_machinery) && isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(L.ventcrawler)
|
||||
if(SEND_SIGNAL(L, COMSIG_CHECK_VENTCRAWL))
|
||||
. += "<span class='notice'>Alt-click to crawl through it.</span>"
|
||||
|
||||
/obj/machinery/atmospherics/New(loc, process = TRUE, setdir)
|
||||
@@ -318,7 +318,7 @@
|
||||
|
||||
/obj/machinery/atmospherics/AltClick(mob/living/L)
|
||||
if(is_type_in_typecache(src, GLOB.ventcrawl_machinery))
|
||||
return L.handle_ventcrawl(src)
|
||||
return SEND_SIGNAL(L, COMSIG_HANDLE_VENTCRAWL, src)
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
new /obj/item/stack/sheet/metal (loc, 5)
|
||||
qdel(src)
|
||||
|
||||
obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
|
||||
/obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I)
|
||||
..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return FALSE
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
obj/machinery/atmospherics/pipe/simple/multiz ///This is an atmospherics pipe which can relay air up a deck (Z+1). It currently only supports being on pipe layer 1
|
||||
/// This is an atmospherics pipe which can relay air up/down a deck.
|
||||
/obj/machinery/atmospherics/pipe/simple/multiz
|
||||
name = "multi deck pipe adapter"
|
||||
desc = "An adapter which allows pipes to connect to other pipenets on different decks."
|
||||
icon_state = "multiz_pipe"
|
||||
@@ -24,6 +25,4 @@ obj/machinery/atmospherics/pipe/simple/multiz ///This is an atmospherics pipe wh
|
||||
if(above)
|
||||
nodes += above
|
||||
above.nodes += src //Two way travel :)
|
||||
return ..()
|
||||
else
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
name = "Simple Drink"
|
||||
reward = 1500
|
||||
|
||||
datum/bounty/reagent/simple_drink/New()
|
||||
/datum/bounty/reagent/simple_drink/New()
|
||||
// Don't worry about making this comprehensive. It doesn't matter if some drinks are skipped.
|
||||
var/static/list/possible_reagents = list(\
|
||||
/datum/reagent/consumable/ethanol/antifreeze,\
|
||||
@@ -91,7 +91,7 @@ datum/bounty/reagent/simple_drink/New()
|
||||
name = "Complex Drink"
|
||||
reward = 4000
|
||||
|
||||
datum/bounty/reagent/complex_drink/New()
|
||||
/datum/bounty/reagent/complex_drink/New()
|
||||
// Don't worry about making this comprehensive. It doesn't matter if some drinks are skipped.
|
||||
var/static/list/possible_reagents = list(\
|
||||
/datum/reagent/consumable/ethanol/atomicbomb,\
|
||||
@@ -124,7 +124,7 @@ datum/bounty/reagent/complex_drink/New()
|
||||
reward = 2750
|
||||
required_volume = 30
|
||||
|
||||
datum/bounty/reagent/chemical/New()
|
||||
/datum/bounty/reagent/chemical/New()
|
||||
// Don't worry about making this comprehensive. It doesn't matter if some chems are skipped.
|
||||
var/static/list/possible_reagents = list(\
|
||||
/datum/reagent/medicine/leporazine,\
|
||||
|
||||
@@ -473,7 +473,7 @@
|
||||
//Soft Suits
|
||||
|
||||
//Blanket
|
||||
datum/export/gear/space/helmet
|
||||
/datum/export/gear/space/helmet
|
||||
cost = 55
|
||||
unit_name = "space helmet"
|
||||
export_types = list(/obj/item/clothing/head/helmet/space)
|
||||
@@ -485,7 +485,7 @@ datum/export/gear/space/helmet
|
||||
export_types = list(/obj/item/clothing/suit/space)
|
||||
include_subtypes = TRUE
|
||||
|
||||
datum/export/gear/space/helmet/plasma
|
||||
/datum/export/gear/space/helmet/plasma
|
||||
cost = 100
|
||||
unit_name = "plasmaman space helmet"
|
||||
export_types = list(/obj/item/clothing/suit/space/eva/plasmaman)
|
||||
@@ -495,7 +495,7 @@ datum/export/gear/space/helmet/plasma
|
||||
unit_name = "plasmaman space suit"
|
||||
export_types = list(/obj/item/clothing/suit/space/eva/plasmaman)
|
||||
|
||||
datum/export/gear/space/helmet/synda
|
||||
/datum/export/gear/space/helmet/synda
|
||||
cost = 150 //Flash proof
|
||||
unit_name = "syndicate space helmet"
|
||||
export_types = list(/obj/item/clothing/head/helmet/space/syndicate)
|
||||
@@ -510,7 +510,7 @@ datum/export/gear/space/helmet/synda
|
||||
//Glasses
|
||||
|
||||
//Blanket
|
||||
datum/export/gear/glasses //glasses are not worth selling
|
||||
/datum/export/gear/glasses //glasses are not worth selling
|
||||
cost = 3
|
||||
unit_name = "glasses"
|
||||
export_types = list(/obj/item/clothing/glasses)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -895,19 +895,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
continue
|
||||
var/class_link = ""
|
||||
var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]")
|
||||
var/extra_color_data = ""
|
||||
var/extra_loadout_data = ""
|
||||
if(loadout_item)
|
||||
class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'"
|
||||
if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC)
|
||||
extra_color_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color_polychromic=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color_polychromic=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
for(var/loadout_color in loadout_item[LOADOUT_COLOR])
|
||||
extra_color_data += "<span style='border: 1px solid #161616; background-color: [loadout_color];'> </span>"
|
||||
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color];'> </span>"
|
||||
else
|
||||
var/loadout_color_non_poly = "#FFFFFF"
|
||||
if(length(loadout_item[LOADOUT_COLOR]))
|
||||
loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1]
|
||||
extra_color_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
extra_color_data += "<span style='border: 1px solid #161616; background-color: [loadout_color_non_poly];'> </span>"
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color_non_poly];'> </span>"
|
||||
if(gear.loadout_flags & LOADOUT_CAN_NAME)
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_rename=1;loadout_gear_name=[html_encode(gear.name)];'>Name</a> [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]"
|
||||
if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION)
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_redescribe=1;loadout_gear_name=[html_encode(gear.name)];'>Description</a>"
|
||||
else if((gear_points - gear.cost) < 0)
|
||||
class_link = "style='white-space:normal;' class='linkOff'"
|
||||
else if(donoritem)
|
||||
@@ -916,7 +920,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
|
||||
else
|
||||
class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'"
|
||||
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a>[extra_color_data]</td>"
|
||||
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a>[extra_loadout_data]</td>"
|
||||
dat += "<td width = 5% style='vertical-align:top'>[gear.cost]</td><td>"
|
||||
if(islist(gear.restricted_roles))
|
||||
if(gear.restricted_roles.len)
|
||||
@@ -929,14 +933,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += gear.restricted_roles.Join(";")
|
||||
dat += "</font>"
|
||||
if(!istype(gear, /datum/gear/unlockable))
|
||||
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
|
||||
// the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description"
|
||||
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]</i></font></td></tr>"
|
||||
else
|
||||
//we add the user's progress to the description assuming they have progress
|
||||
var/datum/gear/unlockable/unlockable = gear
|
||||
var/progress_made = unlockable_loadout_data[unlockable.progress_key]
|
||||
if(!progress_made)
|
||||
progress_made = 0
|
||||
dat += "</td><td><font size=2><i>[gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
|
||||
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
|
||||
|
||||
dat += "</table>"
|
||||
if(4) // Content preferences
|
||||
@@ -2700,7 +2705,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
loadout_data["SAVE_[loadout_slot]"] += list(new_loadout_data) //double packed because it does the union of the CONTENTS of the lists
|
||||
else
|
||||
loadout_data["SAVE_[loadout_slot]"] = list(new_loadout_data) //double packed because you somehow had no save slot in your loadout?
|
||||
if(href_list["loadout_color"])
|
||||
|
||||
if(href_list["loadout_color"] || href_list["loadout_color_polychromic"] || href_list["loadout_rename"] || href_list["loadout_redescribe"])
|
||||
//if the gear doesn't exist, or they don't have it, ignore the request
|
||||
var/name = html_decode(href_list["loadout_gear_name"])
|
||||
var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
|
||||
if(!G)
|
||||
@@ -2708,29 +2715,44 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/user_gear = has_loadout_gear(loadout_slot, "[G.type]")
|
||||
if(!user_gear)
|
||||
return
|
||||
if(!length(user_gear[LOADOUT_COLOR]))
|
||||
user_gear[LOADOUT_COLOR] = list("#FFFFFF")
|
||||
var/current_color = user_gear[LOADOUT_COLOR][1]
|
||||
var/new_color = input(user, "Polychromic options", "Choose Color", current_color) as color|null
|
||||
user_gear[LOADOUT_COLOR][1] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
if(href_list["loadout_color_polychromic"])
|
||||
var/name = html_decode(href_list["loadout_gear_name"])
|
||||
var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
|
||||
if(!G)
|
||||
return
|
||||
var/user_gear = has_loadout_gear(loadout_slot, "[G.type]")
|
||||
if(!user_gear)
|
||||
return
|
||||
var/list/color_options = list()
|
||||
for(var/i=1, i<=length(G.loadout_initial_colors), i++)
|
||||
color_options += "Color [i]"
|
||||
var/color_to_change = input(user, "Polychromic options", "Recolor [name]") as null|anything in color_options
|
||||
if(color_to_change)
|
||||
var/color_index = text2num(copytext(color_to_change, 7))
|
||||
var/current_color = user_gear[LOADOUT_COLOR][color_index]
|
||||
var/new_color = input(user, "Polychromic options", "Choose [color_to_change] Color", current_color) as color|null
|
||||
if(new_color)
|
||||
user_gear[LOADOUT_COLOR][color_index] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
|
||||
//possible requests: recolor, recolor (polychromic), rename, redescribe
|
||||
//always make sure the gear allows said request before proceeding
|
||||
|
||||
//non-poly coloring can only be done by non-poly items
|
||||
if(href_list["loadout_color"] && !(G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
|
||||
if(!length(user_gear[LOADOUT_COLOR]))
|
||||
user_gear[LOADOUT_COLOR] = list("#FFFFFF")
|
||||
var/current_color = user_gear[LOADOUT_COLOR][1]
|
||||
var/new_color = input(user, "Polychromic options", "Choose Color", current_color) as color|null
|
||||
user_gear[LOADOUT_COLOR][1] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
|
||||
//poly coloring can only be done by poly items
|
||||
if(href_list["loadout_color_polychromic"] && (G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
|
||||
var/list/color_options = list()
|
||||
for(var/i=1, i<=length(G.loadout_initial_colors), i++)
|
||||
color_options += "Color [i]"
|
||||
var/color_to_change = input(user, "Polychromic options", "Recolor [name]") as null|anything in color_options
|
||||
if(color_to_change)
|
||||
var/color_index = text2num(copytext(color_to_change, 7))
|
||||
var/current_color = user_gear[LOADOUT_COLOR][color_index]
|
||||
var/new_color = input(user, "Polychromic options", "Choose [color_to_change] Color", current_color) as color|null
|
||||
if(new_color)
|
||||
user_gear[LOADOUT_COLOR][color_index] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
|
||||
//both renaming and redescribing strip the input to stop html injection
|
||||
|
||||
//renaming is only allowed if it has the flag for it
|
||||
if(href_list["loadout_rename"] && (G.loadout_flags & LOADOUT_CAN_NAME))
|
||||
var/new_name = stripped_input(user, "Enter new name for item. Maximum [MAX_NAME_LEN] characters.", "Loadout Item Naming", null, MAX_NAME_LEN)
|
||||
if(new_name)
|
||||
user_gear[LOADOUT_CUSTOM_NAME] = new_name
|
||||
|
||||
//redescribing is only allowed if it has the flag for it
|
||||
if(href_list["loadout_redescribe"] && (G.loadout_flags & LOADOUT_CAN_DESCRIPTION)) //redescribe isnt a real word but i can't think of the right term to use
|
||||
var/new_description = stripped_input(user, "Enter new description for item. Maximum 500 characters.", "Loadout Item Redescribing", null, 500)
|
||||
if(new_description)
|
||||
user_gear[LOADOUT_CUSTOM_DESCRIPTION] = new_description
|
||||
|
||||
ShowChoices(user)
|
||||
return 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
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/obj/item/clothing/mask/gas/examine(mob/user)
|
||||
. = ..()
|
||||
if(flavor_adjust)
|
||||
. += "<span class='info'>Alt-click to toggle identity concealment. it's currently <b>[flags_inv & HIDEFACE ? "on" : "off"]</b>.</span>"
|
||||
. += "<span class='info'>Alt-click to toggle identity concealment. It's currently <b>[flags_inv & HIDEFACE ? "on" : "off"]</b>.</span>"
|
||||
|
||||
/obj/item/clothing/mask/gas/AltClick(mob/user)
|
||||
. = ..()
|
||||
@@ -143,14 +143,17 @@
|
||||
"Blanc" = image(icon = src.icon, icon_state = "mime"),
|
||||
"Excité" = image(icon = src.icon, icon_state = "sexymime"),
|
||||
"Triste" = image(icon = src.icon, icon_state = "sadmime"),
|
||||
"Effrayé" = image(icon = src.icon, icon_state = "scaredmime")
|
||||
"Effrayé" = image(icon = src.icon, icon_state = "scaredmime"),
|
||||
"Timid Woman" = image(icon = src.icon, icon_state = "timidwoman"),
|
||||
"Timid Man" = image(icon = src.icon, icon_state = "timidman")
|
||||
)
|
||||
|
||||
/obj/item/clothing/mask/gas/mime/ui_action_click(mob/user)
|
||||
if(!istype(user) || user.incapacitated())
|
||||
return
|
||||
|
||||
var/static/list/options = list("Blanc" = "mime", "Triste" = "sadmime", "Effrayé" = "scaredmime", "Excité" ="sexymime")
|
||||
var/static/list/options = list("Blanc" = "mime", "Triste" = "sadmime", "Effrayé" = "scaredmime", "Excité" ="sexymime",
|
||||
"Timid Woman" = "timidwoman", "Timid Man" = "timidman")
|
||||
|
||||
var/choice = show_radial_menu(user,src, mimemask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
|
||||
|
||||
@@ -170,6 +173,20 @@
|
||||
item_state = "sexymime"
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/clothing/mask/gas/timidcostume
|
||||
name = "timid woman mask"
|
||||
desc = "Most people who wear these are not really that timid."
|
||||
clothing_flags = ALLOWINTERNALS
|
||||
icon_state = "timidwoman"
|
||||
item_state = "timidwoman"
|
||||
flags_cover = MASKCOVERSEYES
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/clothing/mask/gas/timidcostume/man
|
||||
name = "timid man mask"
|
||||
icon_state = "timidman"
|
||||
item_state = "timidman"
|
||||
|
||||
/obj/item/clothing/mask/gas/monkeymask
|
||||
name = "monkey mask"
|
||||
desc = "A mask used when acting as a monkey."
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
mutantrace_variation = STYLE_MUZZLE
|
||||
|
||||
/obj/item/clothing/mask/surgical/aesthetic
|
||||
name = "aesthetic sterile mask"
|
||||
desc = "A sterile mask designed to help prevent the spread of diseases. This one doesn't seem like it does a whole lot, somehow."
|
||||
flags_inv = HIDEFACE
|
||||
flags_cover = null
|
||||
visor_flags_inv = null
|
||||
visor_flags_cover = null
|
||||
permeability_coefficient = 1
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
|
||||
/obj/item/clothing/mask/surgical/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
|
||||
@@ -237,6 +237,12 @@
|
||||
icon_state = "choker"
|
||||
poly_colors = list("#222222")
|
||||
|
||||
/obj/item/clothing/neck/necklace/cowbell
|
||||
name = "cowbell collar"
|
||||
desc = "Who would wear this? Take this off, you aren't a cow, you're just an awful degenerate."
|
||||
icon = 'icons/obj/clothing/neck.dmi'
|
||||
icon_state = "cowbell"
|
||||
|
||||
/obj/item/key/collar
|
||||
name = "Collar Key"
|
||||
desc = "A key for a tiny lock on a collar or bag."
|
||||
@@ -289,7 +295,7 @@
|
||||
//VERY SUPER BADASS NECKERCHIEFS//
|
||||
//////////////////////////////////
|
||||
|
||||
obj/item/clothing/neck/neckerchief
|
||||
/obj/item/clothing/neck/neckerchief
|
||||
icon = 'icons/obj/clothing/masks.dmi' //In order to reuse the bandana sprite
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/sourceBandanaType
|
||||
|
||||
@@ -413,6 +413,22 @@
|
||||
var/wallcharges = 4
|
||||
var/newlocobject = null
|
||||
|
||||
/obj/item/clothing/shoes/timidcostume
|
||||
name = "timid woman boots"
|
||||
desc = "Ready to rock your hips back and forth? These boots have a polychromic finish."
|
||||
icon_state = "timidwoman"
|
||||
item_state = "timidwoman"
|
||||
|
||||
/obj/item/clothing/shoes/timidcostume/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/polychromic, list("#0094FF"), 1)
|
||||
|
||||
/obj/item/clothing/shoes/timidcostume/man
|
||||
name = "timid man shoes"
|
||||
desc = "Ready to go kart racing? These shoes have a polychromic finish."
|
||||
icon_state = "timidman"
|
||||
item_state = "timidman"
|
||||
|
||||
/obj/item/clothing/shoes/wallwalkers/equipped(mob/user,slot)
|
||||
. = ..()
|
||||
if(slot == SLOT_SHOES)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1088,6 +1088,36 @@
|
||||
icon_state = "winterhood_poly"
|
||||
item_state = "winterhood_poly"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/timidcostume
|
||||
name = "timid woman hoodie"
|
||||
desc = "A snug, tight yet warm outfit with belts wrapped around it. Looks to be made of polychromic materials."
|
||||
icon_state = "timidwoman"
|
||||
item_state = "timidwoman"
|
||||
hoodtype = /obj/item/clothing/head/hooded/winterhood/timidcostume
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/timidcostume/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/polychromic, list("#EB0C07", "#5E2400", "#CEA100"), 3)
|
||||
|
||||
/obj/item/clothing/head/hooded/winterhood/timidcostume
|
||||
name = "timid woman hood"
|
||||
desc = "A hood attached to the hoodie."
|
||||
icon_state = "timidwoman"
|
||||
item_state = "timidwoman"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/timidcostume/man
|
||||
name = "timid man hoodie"
|
||||
desc = "A snug, tight yet warm outfit a belt wrapped around it. Looks to be made of polychromic materials."
|
||||
icon_state = "timidman"
|
||||
item_state = "timidman"
|
||||
hoodtype = /obj/item/clothing/head/hooded/winterhood/timidcostume/man
|
||||
|
||||
/obj/item/clothing/head/hooded/winterhood/timidcostume/man
|
||||
name = "timid man hood"
|
||||
icon_state = "timidman"
|
||||
item_state = "timidman"
|
||||
|
||||
|
||||
/obj/item/clothing/suit/striped_sweater
|
||||
name = "striped sweater"
|
||||
desc = "Reminds you of someone, but you just can't put your finger on it..."
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -79,13 +79,175 @@
|
||||
if(initial(above_suit))
|
||||
. += "<span class='notice'>\The [src] can be worn above or below your suit. Alt-click to toggle.</span>"
|
||||
|
||||
//////////////
|
||||
//Waistcoats//
|
||||
//////////////
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat
|
||||
name = "waistcoat"
|
||||
name = "black waistcoat"
|
||||
desc = "For some classy, murderous fun."
|
||||
icon_state = "waistcoat"
|
||||
item_state = "waistcoat"
|
||||
minimize_when_attached = FALSE
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/red
|
||||
name = "red waistcoat"
|
||||
icon_state = "waistcoat_red"
|
||||
item_state = "waistcoat_red"
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/grey
|
||||
name = "grey waistcoat"
|
||||
icon_state = "waistcoat_grey"
|
||||
item_state = "waistcoat_grey"
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/brown
|
||||
name = "red waistcoat"
|
||||
icon_state = "waistcoat_brown"
|
||||
item_state = "waistcoat_brown"
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/sweatervest
|
||||
name = "black sweatervest"
|
||||
icon_state = "sweatervest"
|
||||
item_state = "sweatervest"
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/sweatervest/blue
|
||||
name = "blue sweatervest"
|
||||
icon_state = "sweatervest_blue"
|
||||
item_state = "sweatervest_blue"
|
||||
|
||||
/obj/item/clothing/accessory/waistcoat/sweatervest/red
|
||||
name = "red sweatervest"
|
||||
icon_state = "sweatervest_red"
|
||||
item_state = "sweatervest_red"
|
||||
|
||||
////////////
|
||||
//Sweaters//
|
||||
////////////
|
||||
|
||||
/obj/item/clothing/accessory/sweater
|
||||
name = "grey sweater"
|
||||
desc = "Nicely comfy and warm!"
|
||||
icon_state = "sweater"
|
||||
item_state = "sweater"
|
||||
minimize_when_attached = FALSE
|
||||
|
||||
/obj/item/clothing/accessory/sweater/pink
|
||||
name = "pink sweater"
|
||||
icon_state = "sweater_pink"
|
||||
item_state = "sweater_pink"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/heart
|
||||
name = "heart sweater"
|
||||
icon_state = "sweater_heart"
|
||||
item_state = "sweater_heart"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/blue
|
||||
name = "blue sweater"
|
||||
icon_state = "sweater_blue"
|
||||
item_state = "sweater_blue"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/nt
|
||||
name = "nanotrasen sweater"
|
||||
icon_state = "sweater_nt"
|
||||
item_state = "sweater_nt"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/mint
|
||||
name = "mint sweater"
|
||||
icon_state = "sweater_mint"
|
||||
item_state = "sweater_mint"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/shoulderless
|
||||
name = "shoulderless sweater"
|
||||
icon_state = "sweater_shoulderless"
|
||||
item_state = "sweater_shoulderless"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/uglyxmas
|
||||
name = "ugly xmas sweater"
|
||||
icon_state = "sweater_uglyxmas"
|
||||
item_state = "sweater_uglyxmas"
|
||||
|
||||
/obj/item/clothing/accessory/sweater/flower
|
||||
name = "flower sweater"
|
||||
icon_state = "sweater_flower"
|
||||
item_state = "sweater_flower"
|
||||
|
||||
////////////////
|
||||
//Suit Jackets//
|
||||
////////////////
|
||||
|
||||
/obj/item/clothing/accessory/suitjacket
|
||||
name = "tan suit jacket"
|
||||
desc = "For those times when you have to attend a fancy business meeting without wearing your pants."
|
||||
icon_state = "jacket_tan"
|
||||
item_state = "jacket_tan"
|
||||
minimize_when_attached = FALSE
|
||||
|
||||
/obj/item/clothing/accessory/suitjacket/charcoal
|
||||
name = "charcoal suit jacket"
|
||||
icon_state = "jacket_charcoal"
|
||||
item_state = "jacket_charcoal"
|
||||
|
||||
/obj/item/clothing/accessory/suitjacket/navy
|
||||
name = "navy suit jacket"
|
||||
icon_state = "jacket_navy"
|
||||
item_state = "jacket_navy"
|
||||
|
||||
/obj/item/clothing/accessory/suitjacket/burgundy
|
||||
name = "burgundy suit jacket"
|
||||
icon_state = "jacket_burgundy"
|
||||
item_state = "jacket_burgundy"
|
||||
|
||||
/obj/item/clothing/accessory/suitjacket/checkered
|
||||
name = "checkered suit jacket"
|
||||
icon_state = "jacket_checkered"
|
||||
item_state = "jacket_checkered"
|
||||
|
||||
///////////////////////
|
||||
//Tactical Turtlnecks//
|
||||
///////////////////////
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck
|
||||
name = "black turtleneck"
|
||||
desc = "Extra cool. Extra fool."
|
||||
icon_state = "turtleneck"
|
||||
item_state = "turtleneck"
|
||||
minimize_when_attached = FALSE
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/red
|
||||
name = "red turtleneck"
|
||||
icon_state = "turtleneck_red"
|
||||
item_state = "turtleneck_red"
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/comfy
|
||||
name = "comfy turtleneck"
|
||||
icon_state = "turtleneck_comfy"
|
||||
item_state = "turtleneck_comfy"
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/tactifool
|
||||
name = "black sweaterneck"
|
||||
desc = "Extra fool. Extra cool."
|
||||
icon_state = "tactifool"
|
||||
item_state = "tactifool"
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/tactifool/green
|
||||
name = "green sweaterneck"
|
||||
icon_state = "tactifool_green"
|
||||
item_state = "tactifool_green"
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/tactifool/blue
|
||||
name = "blue sweaterneck"
|
||||
icon_state = "tactifool_blue"
|
||||
item_state = "tactifool_blue"
|
||||
|
||||
/obj/item/clothing/accessory/turtleneck/tactifool/syndicate
|
||||
name = "tactifool sweaterneck"
|
||||
icon_state = "tactifool_syndicate"
|
||||
item_state = "tactifool_syndicate"
|
||||
|
||||
/////////////////
|
||||
//Miscellaneous//
|
||||
/////////////////
|
||||
|
||||
/obj/item/clothing/accessory/maidapron
|
||||
name = "maid apron"
|
||||
desc = "The best part of a maid costume."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -144,22 +144,23 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
if(L && (L.density || prob(10)))
|
||||
L.ex_act(EXPLODE_HEAVY)
|
||||
|
||||
obj/effect/immovablerod/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/U = user
|
||||
if(U.job in list("Research Director"))
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
|
||||
for(var/mob/M in urange(8, src))
|
||||
if(!M.stat)
|
||||
shake_camera(M, 2, 3)
|
||||
if(wizard)
|
||||
U.visible_message("<span class='boldwarning'>[src] transforms into [wizard] as [U] suplexes them!</span>", "<span class='warning'>As you grab [src], it suddenly turns into [wizard] as you suplex them!</span>")
|
||||
to_chat(wizard, "<span class='boldwarning'>You're suddenly jolted out of rod-form as [U] somehow manages to grab you, slamming you into the ground!</span>")
|
||||
wizard.Stun(60)
|
||||
wizard.apply_damage(25, BRUTE)
|
||||
qdel(src)
|
||||
else
|
||||
U.visible_message("<span class='boldwarning'>[U] suplexes [src] into the ground!</span>", "<span class='warning'>You suplex [src] into the ground!</span>")
|
||||
new /obj/structure/festivus/anchored(drop_location())
|
||||
new /obj/effect/anomaly/flux(drop_location())
|
||||
qdel(src)
|
||||
/obj/effect/immovablerod/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/U = user
|
||||
if(U.job in list("Research Director"))
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
for(var/mob/M in urange(8, src))
|
||||
if(!M.stat)
|
||||
shake_camera(M, 2, 3)
|
||||
if(wizard)
|
||||
U.visible_message("<span class='boldwarning'>[src] transforms into [wizard] as [U] suplexes them!</span>", "<span class='warning'>As you grab [src], it suddenly turns into [wizard] as you suplex them!</span>")
|
||||
to_chat(wizard, "<span class='boldwarning'>You're suddenly jolted out of rod-form as [U] somehow manages to grab you, slamming you into the ground!</span>")
|
||||
wizard.Stun(60)
|
||||
wizard.apply_damage(25, BRUTE)
|
||||
qdel(src)
|
||||
else
|
||||
U.visible_message("<span class='boldwarning'>[U] suplexes [src] into the ground!</span>", "<span class='warning'>You suplex [src] into the ground!</span>")
|
||||
new /obj/structure/festivus/anchored(drop_location())
|
||||
new /obj/effect/anomaly/flux(drop_location())
|
||||
qdel(src)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, spawn_location)
|
||||
smoke.start()
|
||||
trader.visible_message("<b>[src]</b> suddenly appears in a puff of smoke!")
|
||||
trader.visible_message("<b>[trader]</b> suddenly appears in a puff of smoke!")
|
||||
|
||||
/datum/round_event/travelling_trader/announce(fake)
|
||||
priority_announce("A mysterious figure has been detected on sensors at [get_area(spawn_location)]", "Mysterious Figure")
|
||||
|
||||
/datum/round_event/travelling_trader/end()
|
||||
if(trader)
|
||||
trader.visible_message("The <b>[src]</b> has given up on waiting!")
|
||||
if(trader) // the /datum/round_event/travelling_trader has given up on waiting!
|
||||
trader.visible_message("The <b>[trader]</b> has given up on waiting!")
|
||||
qdel(trader)
|
||||
|
||||
//the actual trader mob
|
||||
@@ -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
|
||||
@@ -188,18 +188,18 @@
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody = 1,
|
||||
/mob/living/simple_animal/hostile/retaliate/goose = 1)
|
||||
|
||||
mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
|
||||
. = ..()
|
||||
acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection."))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(obj/item/supplied_item) //item is likely to be in contents of whats supplied
|
||||
for(var/atom/something in supplied_item.contents)
|
||||
if(istype(something, requested_item))
|
||||
qdel(something) //typically things holding mobs release the mob when the container is deleted, so delete the mob first here
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea
|
||||
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea
|
||||
var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src))
|
||||
var/chosen_animal = pickweight(possible_rewards)
|
||||
var/mob/living/new_animal = new chosen_animal(jar)
|
||||
@@ -223,6 +223,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
|
||||
/obj/structure/reagent_dispensers/keg/quintuple_sec = 3)
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents
|
||||
. = ..() // RETURN A HINT.
|
||||
requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer,
|
||||
/datum/reagent/consumable/ethanol/kahlua,
|
||||
/datum/reagent/consumable/ethanol/whiskey,
|
||||
@@ -242,7 +243,6 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
|
||||
/datum/reagent/consumable/ethanol/triple_sec,
|
||||
/datum/reagent/consumable/ethanol/sake,
|
||||
/datum/reagent/consumable/ethanol/applejack))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents
|
||||
if(istype(supplied_item, /obj/item/reagent_containers))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
var/isGlass = TRUE //Whether the 'bottle' is made of glass or not so that milk cartons dont shatter when someone gets hit by it
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/on_reagent_change(changetype)
|
||||
if (gulp_size < 5)
|
||||
gulp_size = 5
|
||||
else
|
||||
gulp_size = max(round(reagents.total_volume / 5), 5)
|
||||
gulp_size = max(round(reagents.total_volume / 5), 5)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone)
|
||||
if(!reagents || !reagents.total_volume)
|
||||
@@ -596,7 +593,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
|
||||
|
||||
@@ -52,10 +52,7 @@
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change(changetype)
|
||||
cut_overlays()
|
||||
|
||||
if (gulp_size < 15)
|
||||
gulp_size = 15
|
||||
else
|
||||
gulp_size = max(round(reagents.total_volume / 15), 15)
|
||||
gulp_size = max(round(reagents.total_volume / 15), 15)
|
||||
|
||||
if (reagents.reagent_list.len > 0)
|
||||
var/datum/reagent/largest_reagent = reagents.get_master_reagent()
|
||||
|
||||
@@ -308,7 +308,7 @@
|
||||
tastes = list("cake" = 5, "sweetness" = 1, "clouds" = 1)
|
||||
foodtype = GRAIN | DAIRY | SUGAR
|
||||
|
||||
obj/item/reagent_containers/food/snacks/store/cake/pound_cake
|
||||
/obj/item/reagent_containers/food/snacks/store/cake/pound_cake
|
||||
name = "pound cake"
|
||||
desc = "A condensed cake made for filling people up quickly."
|
||||
icon_state = "pound_cake"
|
||||
|
||||
@@ -151,10 +151,13 @@
|
||||
to_chat(user, "<span class='warning'>You need more space cleaner!</span>")
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/soap))
|
||||
var/obj/item/soap/P = O
|
||||
if(istype(O, /obj/item/soap) || istype(O, /obj/item/reagent_containers/rag))
|
||||
var/cleanspeed = 50
|
||||
if(istype(O, /obj/item/soap))
|
||||
var/obj/item/soap/used_soap = O
|
||||
cleanspeed = used_soap.cleanspeed
|
||||
user.visible_message("[user] starts to clean \the [src].", "<span class='notice'>You start to clean \the [src]...</span>")
|
||||
if(do_after(user, P.cleanspeed, target = src))
|
||||
if(do_after(user, cleanspeed, target = src))
|
||||
user.visible_message("[user] has cleaned \the [src].", "<span class='notice'>You clean \the [src].</span>")
|
||||
dirty = 0
|
||||
update_icon()
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/donut/chaos
|
||||
|
||||
datum/crafting_recipe/food/donut/meat
|
||||
/datum/crafting_recipe/food/donut/meat
|
||||
time = 15
|
||||
name = "Meat donut"
|
||||
reqs = list(
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -34,16 +34,14 @@
|
||||
|
||||
/obj/item/grown/cotton/attack_self(mob/user)
|
||||
user.show_message("<span class='notice'>You pull some [cotton_name] out of the [name]!</span>", MSG_VISUAL)
|
||||
var/seed_modifier = 0
|
||||
if(seed)
|
||||
seed_modifier = round(seed.potency / 25)
|
||||
var/obj/item/stack/cotton = new cotton_type(user.loc, 1 + seed_modifier)
|
||||
var/old_cotton_amount = cotton.amount
|
||||
for(var/obj/item/stack/ST in user.loc)
|
||||
if(ST != cotton && istype(ST, cotton_type) && ST.amount < ST.max_amount)
|
||||
ST.attackby(cotton, user)
|
||||
if(cotton.amount > old_cotton_amount)
|
||||
to_chat(user, "<span class='notice'>You add the newly-formed [cotton_name] to the stack. It now contains [cotton.amount] [cotton_name].</span>")
|
||||
var/cottonAmt = 1 + round(seed.potency / 25) // cotton inhand we're holding
|
||||
for(var/obj/item/grown/cotton/ctn in user.loc) // cotton on the floor
|
||||
if(ctn.type != type)
|
||||
continue
|
||||
cottonAmt += 1 + round(ctn.seed.potency / 25)
|
||||
qdel(ctn)
|
||||
new cotton_type(user.drop_location(), cottonAmt)
|
||||
// above code stolen from grass
|
||||
qdel(src)
|
||||
|
||||
//reinforced mutated variant
|
||||
|
||||
@@ -92,6 +92,11 @@
|
||||
return BULLET_ACT_HIT
|
||||
else if(istype(Proj , /obj/item/projectile/energy/florayield))
|
||||
return myseed.bullet_act(Proj)
|
||||
else if(istype(Proj , /obj/item/projectile/energy/florarevolution))
|
||||
if(myseed)
|
||||
if(myseed.mutatelist.len > 0)
|
||||
myseed.instability = (myseed.instability/2)
|
||||
mutatespecie()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -384,7 +389,6 @@
|
||||
/obj/machinery/hydroponics/proc/hardmutate()
|
||||
mutate(4, 10, 2, 4, 50, 4, 10, 3)
|
||||
|
||||
|
||||
/obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant!
|
||||
if(!myseed || dead)
|
||||
return
|
||||
@@ -600,7 +604,34 @@
|
||||
desc = initial(desc)
|
||||
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
|
||||
update_icon()
|
||||
|
||||
else if(istype(O, /obj/item/gun/energy/floragun))
|
||||
var/obj/item/gun/energy/floragun/flowergun = O
|
||||
if(flowergun.cell.charge < flowergun.cell.maxcharge)
|
||||
to_chat(user, "<span class='notice'>[flowergun] must be fully charged to lock in a mutation!</span>")
|
||||
return
|
||||
if(!myseed)
|
||||
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||
return
|
||||
if(myseed.endurance <= 20)
|
||||
to_chat(user, "<span class='warning'>[myseed.plantname] isn't hardy enough to sequence its mutation!</span>")
|
||||
return
|
||||
if(!myseed.mutatelist)
|
||||
to_chat(user, "<span class='warning'>[myseed.plantname] has nothing else to mutate into!</span>")
|
||||
return
|
||||
else
|
||||
var/list/fresh_mut_list = list()
|
||||
for(var/muties in myseed.mutatelist)
|
||||
var/obj/item/seeds/another_mut = new muties
|
||||
fresh_mut_list[another_mut.plantname] = muties
|
||||
var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sortList(fresh_mut_list))
|
||||
if(!user.canUseTopic(src, BE_CLOSE) || !locked_mutation)
|
||||
return
|
||||
myseed.mutatelist = list(fresh_mut_list[locked_mutation])
|
||||
myseed.endurance = (myseed.endurance/2)
|
||||
flowergun.cell.use(flowergun.cell.charge)
|
||||
flowergun.update_icon()
|
||||
to_chat(user, "<span class='notice'>[myseed.plantname]'s mutation was set to [locked_mutation], depleting [flowergun]'s cell!</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
var/yield = 3 // Amount of growns created per harvest. If is -1, the plant/shroom/weed is never meant to be harvested.
|
||||
var/potency = 10 // The 'power' of a plant. Generally effects the amount of reagent in a plant, also used in other ways.
|
||||
var/growthstages = 6 // Amount of growth sprites the plant has.
|
||||
var/instability = 5 //Chance that a plant will mutate in each stage of it's life.
|
||||
var/instability = 5 //Chance that a plant will mutate in each stage of it's life.
|
||||
var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom.
|
||||
var/list/mutatelist = list() // The type of plants that this plant can mutate into.
|
||||
var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
|
||||
@@ -105,7 +105,7 @@
|
||||
S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes.
|
||||
return S
|
||||
|
||||
obj/item/seeds/proc/is_gene_forbidden(typepath)
|
||||
/obj/item/seeds/proc/is_gene_forbidden(typepath)
|
||||
return (typepath in forbiddengenes)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -378,7 +378,7 @@ a creative player the means to solve many problems. Circuits are held inside an
|
||||
|
||||
|
||||
// Checks if the target object is reachable. Useful for various manipulators and manipulator-like objects.
|
||||
/obj/item/integrated_circuit/proc/check_target(atom/target, exclude_contents = FALSE, exclude_components = FALSE, exclude_self = FALSE)
|
||||
/obj/item/integrated_circuit/proc/check_target(atom/target, exclude_contents = FALSE, exclude_components = FALSE, exclude_self = FALSE, exclude_outside = FALSE)
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
@@ -394,7 +394,7 @@ a creative player the means to solve many problems. Circuits are held inside an
|
||||
if(target == assembly.battery)
|
||||
return FALSE
|
||||
|
||||
if(target.Adjacent(acting_object) && isturf(target.loc))
|
||||
if(!exclude_outside && target.Adjacent(acting_object) && isturf(target.loc))
|
||||
return TRUE
|
||||
|
||||
if(!exclude_contents && (target in acting_object.GetAllContents()))
|
||||
|
||||
@@ -292,7 +292,7 @@
|
||||
activate_pin(2)
|
||||
|
||||
// Required for making the connector port script work
|
||||
obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
/obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
return air_contents
|
||||
|
||||
|
||||
|
||||
@@ -186,6 +186,8 @@
|
||||
AM.forceMove(src)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/proc/drop(obj/item/AM, turf/T = drop_location())
|
||||
if(!check_target(AM, FALSE, TRUE, TRUE, TRUE))
|
||||
return
|
||||
var/atom/A = get_object()
|
||||
A.investigate_log("dropped ([AM]) from [src].", INVESTIGATE_CIRCUIT)
|
||||
AM.forceMove(T)
|
||||
|
||||
@@ -137,6 +137,10 @@
|
||||
//Shooting Code:
|
||||
A.preparePixelProjectile(target, src)
|
||||
A.fire()
|
||||
if(ismob(loc.loc))
|
||||
installed_gun.shoot_live_shot(loc.loc)
|
||||
else
|
||||
installed_gun.shoot_live_shot() //Shitcode, but we don't have much of a choice
|
||||
log_attack("[assembly] [REF(assembly)] has fired [installed_gun].")
|
||||
return A
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -60,3 +60,14 @@
|
||||
/datum/keybinding/carbon/select_harm_intent/down(client/user)
|
||||
user.mob?.a_intent_change(INTENT_HARM)
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/carbon/give
|
||||
hotkey_keys = list("CtrlG")
|
||||
name = "Give_Item"
|
||||
full_name = "Give item"
|
||||
description = "Give the item you're currently holding"
|
||||
|
||||
/datum/keybinding/carbon/give/down(client/user)
|
||||
var/mob/living/carbon/C = user.mob
|
||||
C.give()
|
||||
return TRUE
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -522,7 +522,7 @@
|
||||
max_charges = 1
|
||||
item_flags = NEEDS_PERMIT | NOBLUDGEON
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 18
|
||||
force = 15
|
||||
|
||||
/obj/item/ammo_casing/magic/hook
|
||||
name = "hook"
|
||||
@@ -536,11 +536,11 @@
|
||||
icon_state = "hook"
|
||||
icon = 'icons/obj/lavaland/artefacts.dmi'
|
||||
pass_flags = PASSTABLE
|
||||
damage = 25
|
||||
armour_penetration = 100
|
||||
damage = 15
|
||||
armour_penetration = 10
|
||||
knockdown = 5
|
||||
damage_type = BRUTE
|
||||
hitsound = 'sound/effects/splat.ogg'
|
||||
knockdown = 30
|
||||
var/chain
|
||||
|
||||
/obj/item/projectile/hook/fire(setAngle)
|
||||
|
||||
@@ -250,6 +250,8 @@
|
||||
if(points)
|
||||
if(I)
|
||||
I.mining_points += points
|
||||
if(usr.client)
|
||||
usr.client.increment_progress("miner", points)
|
||||
points = 0
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>No ID detected.</span>")
|
||||
|
||||
@@ -20,25 +20,6 @@
|
||||
data["totalPoints"] = points
|
||||
return data
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("Claim")
|
||||
var/mob/M = usr
|
||||
var/obj/item/card/id/I = M.get_idcard(TRUE)
|
||||
if(points)
|
||||
if(I)
|
||||
I.mining_points += points
|
||||
if(usr.client)
|
||||
usr.client.increment_progress("miner", points)
|
||||
points = 0
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>No ID detected.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>No points to claim.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/point_bank/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -341,4 +341,4 @@
|
||||
|
||||
/datum/sprite_accessory/insect_fluff/witchwing
|
||||
name = "Witch Wing"
|
||||
icon_state = "witchwing"
|
||||
icon_state = "witchwing"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
datum/sprite_accessory/caps
|
||||
/datum/sprite_accessory/caps
|
||||
icon = 'icons/mob/mutant_bodyparts.dmi'
|
||||
color_src = HAIR
|
||||
relevant_layers = list(BODY_ADJ_LAYER)
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
name = "Bald"
|
||||
icon_state = "bald"
|
||||
|
||||
/datum/sprite_accessory/hair/adhara
|
||||
name = "Adhara"
|
||||
icon_state = "hair_adhara"
|
||||
|
||||
/datum/sprite_accessory/hair/afro
|
||||
name = "Afro"
|
||||
icon_state = "hair_afro"
|
||||
@@ -29,6 +33,14 @@
|
||||
name = "Ahoge"
|
||||
icon_state = "hair_antenna"
|
||||
|
||||
/datum/sprite_accessory/hair/amazon
|
||||
name = "Amazon"
|
||||
icon_state = "hair_amazon"
|
||||
|
||||
/datum/sprite_accessory/hair/anita
|
||||
name = "Anita"
|
||||
icon_state = "hair_anita"
|
||||
|
||||
/datum/sprite_accessory/hair/balding
|
||||
name = "Balding Hair"
|
||||
icon_state = "hair_e"
|
||||
@@ -61,6 +73,18 @@
|
||||
name = "Beehive 2"
|
||||
icon_state = "hair_beehive2"
|
||||
|
||||
/datum/sprite_accessory/hair/belenko
|
||||
name = "Beleneko"
|
||||
icon_state = "hair_belenko"
|
||||
|
||||
/datum/sprite_accessory/hair/belenkotied
|
||||
name = "Belenko (Tied)"
|
||||
icon_state = "hair_belenkotied"
|
||||
|
||||
/datum/sprite_accessory/hair/belle
|
||||
name = "Belle"
|
||||
icon_state = "hair_belle"
|
||||
|
||||
/datum/sprite_accessory/hair/bob
|
||||
name = "Bob Hair"
|
||||
icon_state = "hair_bob"
|
||||
@@ -309,6 +333,10 @@
|
||||
name = "Flow Hair"
|
||||
icon_state = "hair_f"
|
||||
|
||||
/datum/sprite_accessory/hair/fluffy
|
||||
name = "Fluffy"
|
||||
icon_state = "hair_fluffy"
|
||||
|
||||
/datum/sprite_accessory/hair/fringetail
|
||||
name = "Fringe Tail"
|
||||
icon_state = "hair_fringetail"
|
||||
@@ -365,6 +393,10 @@
|
||||
name = "Hitop"
|
||||
icon_state = "hair_hitop"
|
||||
|
||||
/datum/sprite_accessory/hair/inkling
|
||||
name = "Inkling"
|
||||
icon_state = "hair_inkling"
|
||||
|
||||
/datum/sprite_accessory/hair/jade
|
||||
name = "Jade"
|
||||
icon_state = "hair_jade"
|
||||
@@ -373,6 +405,10 @@
|
||||
name = "Jensen"
|
||||
icon_state = "hair_jensen"
|
||||
|
||||
/datum/sprite_accessory/hair/jessica
|
||||
name = "Jessica"
|
||||
icon_state = "hair_jessica"
|
||||
|
||||
/datum/sprite_accessory/hair/joestar
|
||||
name = "Joestar"
|
||||
icon_state = "hair_joestar"
|
||||
@@ -389,6 +425,10 @@
|
||||
name = "Kusanagi"
|
||||
icon_state = "hair_kusanagi"
|
||||
|
||||
/datum/sprite_accessory/hair/kleeia
|
||||
name = "Kleeia"
|
||||
icon_state = "hair_kleeia"
|
||||
|
||||
/datum/sprite_accessory/hair/long
|
||||
name = "Long Hair 1"
|
||||
icon_state = "hair_long"
|
||||
@@ -445,6 +485,10 @@
|
||||
name = "Mohawk"
|
||||
icon_state = "hair_d"
|
||||
|
||||
/datum/sprite_accessory/hair/newyou
|
||||
name = "New You"
|
||||
icon_state = "hair_newyou"
|
||||
|
||||
/datum/sprite_accessory/hair/reversemohawk
|
||||
name = "Mohawk (Reverse)"
|
||||
icon_state = "hair_reversemohawk"
|
||||
@@ -575,6 +619,10 @@
|
||||
name = "Ponytail (Side) 4"
|
||||
icon_state = "hair_sidetail4"
|
||||
|
||||
/datum/sprite_accessory/hair/sharptail
|
||||
name = "Ponytail (Sharp)"
|
||||
icon_state = "hair_sharptail"
|
||||
|
||||
/datum/sprite_accessory/hair/spikytail
|
||||
name = "Ponytail (Spiky)"
|
||||
icon_state = "hair_spikyponytail"
|
||||
@@ -679,6 +727,26 @@
|
||||
name = "Skinhead"
|
||||
icon_state = "hair_skinhead"
|
||||
|
||||
/datum/sprite_accessory/hair/simple
|
||||
name = "Simple"
|
||||
icon_state = "hair_simple"
|
||||
|
||||
/datum/sprite_accessory/hair/skrellvshort
|
||||
name = "Skrell Replicant (Very Short)"
|
||||
icon_state = "hair_skrellvshort"
|
||||
|
||||
/datum/sprite_accessory/hair/skrellshort
|
||||
name = "Skrell Replicant (Short)"
|
||||
icon_state = "hair_skrellshort"
|
||||
|
||||
/datum/sprite_accessory/hair/skrell
|
||||
name = "Skrell Replicant (Average)"
|
||||
icon_state = "hair_skrell"
|
||||
|
||||
/datum/sprite_accessory/hair/skrelllong
|
||||
name = "Skrell Replicant (Long)"
|
||||
icon_state = "hair_skrelllong"
|
||||
|
||||
/datum/sprite_accessory/hair/sleaze
|
||||
name = "Sleaze"
|
||||
icon_state = "hair_sleaze"
|
||||
@@ -699,6 +767,10 @@
|
||||
name = "Spiky 3"
|
||||
icon_state = "hair_spiky2"
|
||||
|
||||
/datum/sprite_accessory/hair/supernova
|
||||
name = "Supernova"
|
||||
icon_state = "hair_supernova"
|
||||
|
||||
/datum/sprite_accessory/hair/swept
|
||||
name = "Swept Back Hair"
|
||||
icon_state = "hair_swept"
|
||||
@@ -743,6 +815,10 @@
|
||||
name = "Trimmed (Flat)"
|
||||
icon_state = "hair_trimflat"
|
||||
|
||||
/datum/sprite_accessory/hair/twincurls
|
||||
name = "Twincurls"
|
||||
icon_state = "hair_twincurls"
|
||||
|
||||
/datum/sprite_accessory/hair/twintails
|
||||
name = "Twintails"
|
||||
icon_state = "hair_twintail"
|
||||
@@ -787,6 +863,10 @@
|
||||
name = "Very Short Over Eye (Alt)"
|
||||
icon_state = "hair_veryshortovereyealternate"
|
||||
|
||||
/datum/sprite_accessory/hair/vivi
|
||||
name = "Vivi"
|
||||
icon_state = "hair_vivi"
|
||||
|
||||
/datum/sprite_accessory/hair/volaju
|
||||
name = "Volaju"
|
||||
icon_state = "hair_volaju"
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
|
||||
// please make sure they're sorted alphabetically and categorized
|
||||
|
||||
/datum/sprite_accessory/underwear/socks/garter
|
||||
name = "Garter"
|
||||
icon_state = "garter"
|
||||
has_color = TRUE
|
||||
|
||||
/datum/sprite_accessory/underwear/socks/socks_knee
|
||||
name = "Knee-high"
|
||||
icon_state = "socks_knee"
|
||||
@@ -83,6 +88,10 @@
|
||||
name = "Pantyhose"
|
||||
icon_state = "pantyhose"
|
||||
|
||||
/datum/sprite_accessory/underwear/socks/pantyhose_ripped
|
||||
name = "Pantyhose - Ripped"
|
||||
icon_state = "pantyhose_ripped"
|
||||
|
||||
/datum/sprite_accessory/underwear/socks/socks_short
|
||||
name = "Short"
|
||||
icon_state = "socks_short"
|
||||
|
||||
@@ -757,7 +757,7 @@
|
||||
icon_state = "husky"
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
datum/sprite_accessory/tails/mam_tails/insect
|
||||
/datum/sprite_accessory/tails/mam_tails/insect
|
||||
name = "Insect"
|
||||
icon_state = "insect"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
@@ -343,6 +343,20 @@
|
||||
icon_state = "fishnet_body"
|
||||
gender = FEMALE
|
||||
|
||||
/datum/sprite_accessory/underwear/top/shibari
|
||||
name = "Shibari Ropes"
|
||||
icon_state = "shibari"
|
||||
gender = FEMALE
|
||||
has_color = TRUE
|
||||
covers_chest = FALSE
|
||||
|
||||
/datum/sprite_accessory/underwear/top/shibari_sleeved
|
||||
name = "Shibari Ropes - sleeves"
|
||||
icon_state = "shibari_sleeves"
|
||||
gender = FEMALE
|
||||
has_color = TRUE
|
||||
covers_chest = FALSE
|
||||
|
||||
/datum/sprite_accessory/underwear/top/swimsuit
|
||||
name = "Swimsuit Top"
|
||||
icon_state = "bra_swimming"
|
||||
|
||||
@@ -556,7 +556,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/list/dest = list() //List of possible destinations (mobs)
|
||||
var/target = null //Chosen target.
|
||||
|
||||
dest += getpois(mobs_only=1) //Fill list, prompt user with list
|
||||
dest += getpois(mobs_only = TRUE) //Fill list, prompt user with list
|
||||
target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest
|
||||
|
||||
if (!target)//Make sure we actually have a target
|
||||
@@ -893,7 +893,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if (!eye_name)
|
||||
return
|
||||
|
||||
var/mob/mob_eye = creatures[eye_name]
|
||||
do_observe(creatures[eye_name])
|
||||
|
||||
/mob/dead/observer/proc/do_observe(mob/mob_eye)
|
||||
//Istype so we filter out points of interest that are not mobs
|
||||
if(client && mob_eye && istype(mob_eye))
|
||||
client.eye = mob_eye
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user