merge conflicts fixed finally

This commit is contained in:
Seris02
2020-02-05 18:42:16 +08:00
1239 changed files with 52279 additions and 12808 deletions
+7 -2
View File
@@ -133,14 +133,14 @@
return FALSE
/datum/ntnet/proc/log_data_transfer(datum/netdata/data)
logs += "[STATION_TIME_TIMESTAMP("hh:mm:ss")] - [data.generate_netlog()]"
logs += "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] - [data.generate_netlog()]"
if(logs.len > setting_maxlogcount)
logs = logs.Copy(logs.len - setting_maxlogcount, 0)
return
// Simplified logging: Adds a log. log_string is mandatory parameter, source is optional.
/datum/ntnet/proc/add_log(log_string, obj/item/computer_hardware/network_card/source = null)
var/log_text = "[STATION_TIME_TIMESTAMP("hh:mm:ss")] - "
var/log_text = "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] - "
if(source)
log_text += "[source.get_network_tag()] - "
else
@@ -202,6 +202,11 @@
if(filename == P.filename)
return P
/datum/ntnet/proc/get_chat_channel_by_id(id)
for(var/datum/ntnet_conversation/chan in chat_channels)
if(chan.id == id)
return chan
// Resets the IDS alarm
/datum/ntnet/proc/resetIDS()
intrusion_detection_alarm = FALSE
+7 -2
View File
@@ -9,6 +9,9 @@
icon_state = "bus"
density = TRUE
circuit = /obj/item/circuitboard/machine/ntnet_relay
ui_x = 400
ui_y = 300
var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame.
var/enabled = 1 // Set to 0 if the relay was turned off
var/dos_failure = 0 // Set to 1 if the relay failed due to (D)DoS attack
@@ -66,7 +69,7 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", 500, 300, master_ui, state)
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
ui.open()
@@ -88,10 +91,12 @@
dos_failure = 0
update_icon()
SSnetworks.station_network.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.")
return TRUE
if("toggle")
enabled = !enabled
SSnetworks.station_network.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].")
update_icon()
return TRUE
/obj/machinery/ntnet_relay/Initialize()
uid = gl_uid++
@@ -113,4 +118,4 @@
D.target = null
D.error = "Connection to quantum relay severed"
return ..()
return ..()
+18 -13
View File
@@ -222,18 +222,23 @@
/obj/effect/vr_clean_master/Initialize()
. = ..()
vr_area = get_area(src)
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
vr_area = get_base_area(src)
if(!vr_area)
return INITIALIZE_HINT_QDEL
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES, TIMER_LOOP)
/obj/effect/vr_clean_master/proc/clean_up()
if (vr_area)
for (var/obj/item/ammo_casing/casing in vr_area)
qdel(casing)
for(var/obj/effect/decal/cleanable/C in vr_area)
qdel(C)
for (var/A in corpse_party)
var/mob/M = A
if(M && M.stat == DEAD && get_area(M) == vr_area)
qdel(M)
corpse_party -= M
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
if (!vr_area)
qdel(src)
return
var/list/contents = get_sub_areas_contents(vr_area)
for (var/obj/item/ammo_casing/casing in contents)
qdel(casing)
for(var/obj/effect/decal/cleanable/C in contents)
qdel(C)
for (var/A in corpse_party)
var/mob/M = A
if(!QDELETED(M) && (M in contents) && M.stat == DEAD)
qdel(M)
corpse_party -= M
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
+3 -3
View File
@@ -135,10 +135,10 @@ GLOBAL_PROTECT(protected_ranks)
var/previous_rights = 0
//load text from file and process each line separately
for(var/line in world.file2list("[global.config.directory]/admin_ranks.txt"))
if(!line || findtextEx(line,"#",1,2))
if(!line || findtextEx_char(line,"#",1,2))
continue
var/next = findtext(line, "=")
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, line[next])))
if(!R)
continue
GLOB.admin_ranks += R
@@ -146,7 +146,7 @@ GLOBAL_PROTECT(protected_ranks)
var/prev = findchar(line, "+-*", next, 0)
while(prev)
next = findchar(line, "+-*", prev + 1, 0)
R.process_keyword(copytext(line, prev, next), previous_rights)
R.process_keyword(copytext_char(line, prev, next), previous_rights)
prev = next
previous_rights = R.rights
if(!CONFIG_GET(flag/admin_legacy_system) || dbfail)
+7 -8
View File
@@ -343,12 +343,12 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set category = "Admin"
set name = "Aghost"
if(!holder)
return
return FALSE
if(isobserver(mob))
//re-enter
var/mob/dead/observer/ghost = mob
if(!ghost.mind || !ghost.mind.current) //won't do anything if there is no body
return
return FALSE
if(!ghost.can_reenter_corpse)
log_admin("[key_name(usr)] re-entered corpse")
message_admins("[key_name_admin(usr)] re-entered corpse")
@@ -357,6 +357,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Reenter") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else if(isnewplayer(mob))
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>")
return FALSE
else
//ghostize
log_admin("[key_name(usr)] admin ghosted.")
@@ -366,7 +367,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if(body && !body.key)
body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Ghost") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return TRUE
/client/proc/invisimin()
set name = "Invisimin"
@@ -448,11 +449,9 @@ GLOBAL_PROTECT(admin_verbs_hideable)
mob.name = initial(mob.name)
mob.mouse_opacity = initial(mob.mouse_opacity)
else
var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null)
var/new_key = ckeyEx(stripped_input(usr, "Enter your desired display name.", "Fake Key", key, 26))
if(!new_key)
return
if(length(new_key) >= 26)
new_key = copytext(new_key, 1, 26)
holder.fakekey = new_key
createStealthKey()
if(isobserver(mob))
@@ -559,9 +558,9 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set desc = "Gives a spell to a mob."
var/list/spell_list = list()
var/type_length = length("/obj/effect/proc_holder/spell") + 2
var/type_length = length_char("/obj/effect/proc_holder/spell") + 2
for(var/A in GLOB.spells)
spell_list[copytext("[A]", type_length)] = A
spell_list[copytext_char("[A]", type_length)] = A
var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_list
if(!S)
return
+2 -1
View File
@@ -137,7 +137,8 @@ GLOBAL_LIST(round_end_notifiees)
return "The Database is not enabled!"
GLOB.bunker_passthrough |= ckey(params)
GLOB.bunker_passthrough[ckey(params)] = world.realtime
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
return "[params] has been added to the current round's bunker bypass list."
+2 -2
View File
@@ -149,10 +149,10 @@
else
var/timeleft = SSshuttle.emergency.timeLeft()
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]</a><BR>"
dat += "<a href='?_src_=holder;[HrefToken()];call_shuttle=2'>Send Back</a><br>"
else
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]</a><BR>"
dat += "<B>Continuous Round Status</B><BR>"
dat += "<a href='?_src_=holder;[HrefToken()];toggle_continuous=1'>[CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]</a>"
if(CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag])
+2 -2
View File
@@ -345,7 +345,7 @@
if(!SSticker.HasRoundStarted())
alert("The game hasn't started yet!")
return
var/objective = copytext(sanitize(input("Enter an objective")),1,MAX_MESSAGE_LEN)
var/objective = stripped_input(usr, "Enter an objective")
if(!objective)
return
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Traitor All", "[objective]"))
@@ -408,7 +408,7 @@
var/obj/item/organ/tail/cat/tail = new
ears.Insert(H, drop_if_replaced=FALSE)
tail.Insert(H, drop_if_replaced=FALSE)
var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san")) //John Robust -> Robust-kun
var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san"), "[PLURAL]" = list("san")) //John Robust -> Robust-kun
var/list/names = splittext(H.real_name," ")
var/forename = names.len > 1 ? names[2] : names[1]
var/newname = "[forename]-[pick(honorifics["[H.gender]"])]"
+14 -16
View File
@@ -845,7 +845,11 @@
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_LAVALAND];jobban4=[REF(M)]'><font color=red>Lavaland</font></a></td>"
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_LAVALAND];jobban4=[REF(M)]'>Lavaland</a></td>"
// Ghost cafe
if(jobban_isbanned(M,ROLE_GHOSTCAFE))
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_GHOSTCAFE];jobban4=[REF(M)]'><font color=red>Lavaland</font></a></td>"
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_GHOSTCAFE];jobban4=[REF(M)]'>Lavaland</a></td>"
dat += "</tr></table>"
//Antagonist (Orange)
@@ -1979,8 +1983,8 @@
var/atom/movable/AM = locate(href_list["adminplayerobservefollow"])
var/client/C = usr.client
if(!isobserver(usr))
C.admin_ghost()
if(!isobserver(usr) && !C.admin_ghost())
return
var/mob/dead/observer/A = C.mob
A.ManualFollow(AM)
@@ -2002,8 +2006,8 @@
var/z = text2num(href_list["Z"])
var/client/C = usr.client
if(!isobserver(usr))
C.admin_ghost()
if(!isobserver(usr) && !C.admin_ghost())
return
sleep(2)
C.jumptocoord(x,y,z)
@@ -2465,8 +2469,6 @@
if(!check_rights(R_ADMIN))
return
src.admincaster_feed_channel.channel_name = stripped_input(usr, "Provide a Feed Channel Name.", "Network Channel Handler", "")
while (findtext(src.admincaster_feed_channel.channel_name," ") == 1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
@@ -2506,9 +2508,7 @@
else if(href_list["ac_set_new_message"])
if(!check_rights(R_ADMIN))
return
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story.", "Network Channel Handler", ""))
while (findtext(src.admincaster_feed_message.returnBody(-1)," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,length(src.admincaster_feed_message.returnBody(-1))+1)
src.admincaster_feed_message.body = adminscrub(stripped_input(usr, "Write your Feed story.", "Network Channel Handler", ""))
src.access_news_network()
else if(href_list["ac_submit_new_message"])
@@ -2567,17 +2567,13 @@
else if(href_list["ac_set_wanted_name"])
if(!check_rights(R_ADMIN))
return
src.admincaster_wanted_message.criminal = adminscrub(input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
while(findtext(src.admincaster_wanted_message.criminal," ") == 1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,length(admincaster_wanted_message.criminal)+1)
src.admincaster_wanted_message.criminal = adminscrub(stripped_input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
if(!check_rights(R_ADMIN))
return
src.admincaster_wanted_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
while (findtext(src.admincaster_wanted_message.body," ") == 1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,length(src.admincaster_wanted_message.body)+1)
src.admincaster_wanted_message.body = adminscrub(stripped_input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
src.access_news_network()
else if(href_list["ac_submit_wanted"])
@@ -2878,6 +2874,8 @@
return
if(SSdbcore.Connect())
var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'")
if(!query_get_mentor.warn_execute())
return
if(query_get_mentor.NextRow())
to_chat(usr, "<span class='danger'>[ckey] is already a mentor.</span>")
return
+16 -15
View File
@@ -869,8 +869,8 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
else if(ispath(expression[i]))
val = expression[i]
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
else if(expression[i][1] in list("'", "\""))
val = copytext_char(expression[i], 2, -1)
else if(expression[i] == "\[")
var/list/expressions_list = expression[++i]
@@ -961,11 +961,11 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(is_proper_datum(object))
D = object
if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude))
if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude)) //3 == length("SS") + 1
to_chat(usr, "<span class='danger'>World variables are not allowed to be accessed. Use global.</span>")
return null
else if(expression [start] == "{" && long)
else if(expression [start] == "{" && long) //3 == length("0x") + 1
if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x")
to_chat(usr, "<span class='danger'>Invalid pointer syntax: [expression[start + 1]]</span>")
return null
@@ -1070,9 +1070,10 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/word = ""
var/list/query_list = list()
var/len = length(query_text)
var/char = ""
for(var/i = 1, i <= len, i++)
var/char = copytext(query_text, i, i + 1)
for(var/i = 1, i <= len, i += length(char))
char = query_text[i]
if(char in whitespace)
if(word != "")
@@ -1091,7 +1092,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
query_list += word
word = ""
var/char2 = copytext(query_text, i + 1, i + 2)
var/char2 = query_text[i + length(char)]
if(char2 in multi[char])
query_list += "[char][char2]"
@@ -1107,13 +1108,13 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
word = "'"
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
for(i += length(char), i <= len, i += length(char))
char = query_text[i]
if(char == "'")
if(copytext(query_text, i + 1, i + 2) == "'")
if(query_text[i + length(char)] == "'")
word += "'"
i++
i += length(query_text[i + length(char)])
else
break
@@ -1135,13 +1136,13 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
word = "\""
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
for(i += length(char), i <= len, i += length(char))
char = query_text[i]
if(char == "\"")
if(copytext(query_text, i + 1, i + 2) == "'")
if(query_text[i + length(char)] == "'")
word += "\""
i++
i += length(query_text[i + length(char)])
else
break
@@ -256,7 +256,7 @@
node += "*"
i++
else if (copytext(token(i), 1, 2) == "/")
else if(token(i)[1] == "/")
i = object_type(i, node)
else
@@ -377,7 +377,7 @@
//object_type: <type path>
/datum/SDQL_parser/proc/object_type(i, list/node)
if (copytext(token(i), 1, 2) != "/")
if(token(i)[1] != "/")
return parse_error("Expected type, but it didn't begin with /")
var/path = text2path(token(i))
@@ -416,7 +416,7 @@
//string: ''' <some text> ''' | '"' <some text > '"'
/datum/SDQL_parser/proc/string(i, list/node)
if(copytext(token(i), 1, 2) in list("'", "\""))
if(token(i)[1] in list("'", "\""))
node += token(i)
else
@@ -427,7 +427,7 @@
//array: '[' expression, expression, ... ']'
/datum/SDQL_parser/proc/array(var/i, var/list/node)
// Arrays get turned into this: list("[", list(exp_1a = exp_1b, ...), ...), "[" is to mark the next node as an array.
if(copytext(token(i), 1, 2) != "\[")
if(token(i)[1] != "\[")
parse_error("Expected an array but found '[token(i)]'")
return i + 1
@@ -613,7 +613,7 @@
node += "null"
i++
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))//3 == length("0x") + 1
node += hex2num(copytext(token(i), 3))
i++
@@ -621,12 +621,12 @@
node += text2num(token(i))
i++
else if(copytext(token(i), 1, 2) in list("'", "\""))
else if(token(i)[1] in list("'", "\""))
i = string(i, node)
else if(copytext(token(i), 1, 2) == "\[") // Start a list.
else if(token(i)[1] == "\[") // Start a list.
i = array(i, node)
else if(copytext(token(i), 1, 2) == "/")
else if(token(i)[1] == "/")
i = object_type(i, node)
else
i = variable(i, node)
+1 -1
View File
@@ -165,7 +165,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(msg,1,MAX_MESSAGE_LEN))
msg = sanitize(copytext_char(msg,1,MAX_MESSAGE_LEN))
if(!msg || !C || !C.mob)
qdel(src)
return
+4 -4
View File
@@ -41,7 +41,7 @@
return
var/client/C
if(istext(whom))
if(cmptext(copytext(whom,1,2),"@"))
if(whom[1] == "@")
whom = findStealthKey(whom)
C = GLOB.directory[whom]
else if(istype(whom, /client))
@@ -76,7 +76,7 @@
var/client/recipient
var/irc = 0
if(istext(whom))
if(cmptext(copytext(whom,1,2),"@"))
if(whom[1] == "@")
whom = findStealthKey(whom)
if(whom == "IRCKEY")
irc = 1
@@ -133,7 +133,7 @@
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots
msg = trim(sanitize(copytext(msg,1,MAX_MESSAGE_LEN)))
msg = trim(sanitize(msg), MAX_MESSAGE_LEN)
if(!msg)
return
@@ -287,7 +287,7 @@
if(!stealthkey)
stealthkey = GenIrcStealthKey()
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
if(!msg)
return "Error: No message"
+1 -1
View File
@@ -5,7 +5,7 @@
if(!check_rights(0))
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
if(!msg)
return
msg = emoji_parse(msg)
+1 -1
View File
@@ -14,7 +14,7 @@
if (src.handle_spam_prevention(msg,MUTE_DEADCHAT))
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
mob.log_talk(msg, LOG_DSAY)
if (!msg)
+13 -3
View File
@@ -541,7 +541,9 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
var/list/areas_all = list()
var/list/areas_with_APC = list()
var/list/areas_with_multiple_APCs = list()
var/list/sub_areas_APC = list()
var/list/areas_with_air_alarm = list()
var/list/sub_areas_air_alarm = list()
var/list/areas_with_RC = list()
var/list/areas_with_light = list()
var/list/areas_with_LS = list()
@@ -578,6 +580,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!A)
dat += "Skipped over [APC] in invalid location, [APC.loc]."
continue
LAZYSET(sub_areas_APC, A.type, get_sub_areas(A, FALSE))
if(!(A.type in areas_with_APC))
areas_with_APC.Add(A.type)
else if(A.type in areas_all)
@@ -585,10 +588,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
CHECK_TICK
for(var/obj/machinery/airalarm/AA in GLOB.machines)
var/area/A = get_area(AA)
var/area/A = get_base_area(AA)
if(!A) //Make sure the target isn't inside an object, which results in runtimes.
dat += "Skipped over [AA] in invalid location, [AA.loc].<br>"
continue
LAZYSET(sub_areas_air_alarm, A.type, get_sub_areas(A, FALSE))
if(!(A.type in areas_with_air_alarm))
areas_with_air_alarm.Add(A.type)
CHECK_TICK
@@ -638,8 +642,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
areas_with_camera.Add(A.type)
CHECK_TICK
var/list/areas_without_APC = areas_all - areas_with_APC
var/list/areas_without_air_alarm = areas_all - areas_with_air_alarm
var/list/areas_without_APC = areas_all - (areas_with_APC + flatten_list(sub_areas_APC))
var/list/areas_without_air_alarm = areas_all - (areas_with_air_alarm + flatten_list(sub_areas_air_alarm))
var/list/areas_without_RC = areas_all - areas_with_RC
var/list/areas_without_light = areas_all - areas_with_light
var/list/areas_without_LS = areas_all - areas_with_LS
@@ -656,12 +660,18 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
dat += "<h1>AREAS WITH MULTIPLE APCS:</h1>"
for(var/areatype in areas_with_multiple_APCs)
dat += "[areatype]<br>"
if(sub_areas_APC[areatype])
dat += "&nbsp;&nbsp;SUB-AREAS:<br>&nbsp;&nbsp;"
dat += jointext(sub_areas_APC[areatype], "<br>&nbsp;&nbsp;")
CHECK_TICK
if(areas_without_air_alarm.len)
dat += "<h1>AREAS WITHOUT AN AIR ALARM:</h1>"
for(var/areatype in areas_without_air_alarm)
dat += "[areatype]<br>"
if(sub_areas_air_alarm[areatype])
dat += "&nbsp;&nbsp;SUB-AREAS:<br>&nbsp;&nbsp;"
dat += jointext(sub_areas_air_alarm[areatype], "<br>&nbsp;&nbsp;")
CHECK_TICK
if(areas_without_RC.len)
@@ -58,7 +58,7 @@
if(isorgan(organ))
O = organ
O.Remove(C)
O.Remove()
else
I = organ
I.removed(C)
@@ -33,7 +33,7 @@
var/map = input(src, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file
if(!map)
return
if(copytext("[map]",-4) != ".dmm")
if(copytext("[map]", -4) != ".dmm")//4 == length(".dmm")
to_chat(src, "<span class='warning'>Filename must end in '.dmm': [map]</span>")
return
var/datum/map_template/M
+3 -3
View File
@@ -307,9 +307,9 @@ GLOBAL_PROTECT(VVpixelmovement)
// the type with the base type removed from the begaining
var/fancytype = types[D.type]
if (findtext(fancytype, types[type]))
fancytype = copytext(fancytype, length(types[type])+1)
var/shorttype = copytext("[D.type]", length("[type]")+1)
if (length(shorttype) > length(fancytype))
fancytype = copytext(fancytype, length(types[type]) + 1)
var/shorttype = copytext("[D.type]", length("[type]") + 1)
if (length_char(shorttype) > length_char(fancytype))
shorttype = fancytype
if (!length(shorttype))
shorttype = "/"
+3
View File
@@ -24,6 +24,8 @@
return
GLOB.bunker_passthrough |= ckey(ckeytobypass)
GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
@@ -37,6 +39,7 @@
return
GLOB.bunker_passthrough -= ckey(ckeytobypass)
SSpersistence.SavePanicBunker()
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
send2irc("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
+4 -4
View File
@@ -6,7 +6,7 @@
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
if(!msg)
return
log_prayer("[src.key]/([src.name]): [msg]")
@@ -54,21 +54,21 @@
//log_admin("HELP: [key_name(src)]: [msg]")
/proc/CentCom_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=orange>CENTCOM:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
C.overrideCooldown()
/proc/Syndicate_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=crimson>SYNDICATE:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
C.overrideCooldown()
/proc/Nuke_request(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=orange>NUKE CODE REQUEST:</font>[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
+15 -2
View File
@@ -419,7 +419,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(record_found)//If they have a record we can determine a few things.
new_character.real_name = record_found.fields["name"]
new_character.gender = record_found.fields["sex"]
new_character.gender = record_found.fields["gender"]
new_character.age = record_found.fields["age"]
new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"])
else
@@ -1249,7 +1249,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
return
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_CUSTOM_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1314,6 +1314,19 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(ADMIN_PUNISHMENT_PIE)
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
if (ADMIN_PUNISHMENT_CUSTOM_PIE)
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new(get_turf(target))
if(!A.reagents)
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
if(amount)
A.create_reagents(amount)
if(A.reagents)
var/chosen_id = choose_reagent_id(usr)
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
if(amount)
A.reagents.add_reagent(chosen_id, amount)
A.splat(target)
punish_log(target, punishment)
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(antagonists)
return
/datum/antagonist/proc/edit_memory(mob/user)
var/new_memo = copytext(trim(input(user,"Write new memory", "Memory", antag_memory) as null|message),1,MAX_MESSAGE_LEN)
var/new_memo = stripped_multiline_input(user, "Write new memory", "Memory", antag_memory, MAX_MESSAGE_LEN)
if (isnull(new_memo))
return
antag_memory = new_memo
@@ -0,0 +1,34 @@
/datum/antagonist/abductee
name = "Abductee"
roundend_category = "abductees"
antagpanel_category = "Abductee"
var/datum/brain_trauma/abductee/brain_trauma
/datum/antagonist/abductee/on_gain()
give_objective()
. = ..()
/datum/antagonist/abductee/greet()
to_chat(owner, "<span class='warning'><b>Your mind snaps!</b></span>")
to_chat(owner, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
owner.announce_objectives()
/datum/antagonist/abductee/proc/give_objective()
var/mob/living/carbon/human/H = owner.current
if(istype(H))
H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY)
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
objectives += O
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee")
var/mob/living/carbon/C = mob_override || owner?.current
if(istype(C))
if(brain_trauma)
qdel(brain_trauma) //make sure there's no lingering trauma
brain_trauma = C.gain_trauma(/datum/brain_trauma/abductee, TRAUMA_RESILIENCE_SURGERY)
/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override)
update_abductor_icons_removed(mob_override ? mob_override.mind : owner)
qdel(brain_trauma)
@@ -18,7 +18,7 @@
/datum/objective/abductee/paint/New()
var/color = pick(list("red", "blue", "green", "yellow", "orange", "purple", "black", "in rainbows", "in blood"))
explanation_text+= " [color]!"
explanation_text = " [color]!"
/datum/objective/abductee/speech
explanation_text = "Your brain is broken... you can only communicate in"
@@ -0,0 +1,18 @@
/datum/brain_trauma/abductee
name = "abductee mindsnapped"
desc = "The patient's brain has been scrambled by experimental procedures."
scan_desc = "brain scrambling"
gain_text = "<span class='danger'>Your mind snaps.. you feel fragmented.</span>"
lose_text = "<span class='boldnotice'>Your mind heals itself and you feel whole again.</span>"
random_gain = FALSE
clonable = TRUE
/datum/brain_trauma/abductee/on_gain()
. = ..()
if(owner.mind)
if(!owner.mind.has_antag_datum(/datum/antagonist/abductee))
owner.mind.add_antag_datum(/datum/antagonist/abductee)
/datum/brain_trauma/abductee/on_lose()
. = ..()
owner.mind?.remove_antag_datum(/datum/antagonist/abductee)
@@ -159,35 +159,6 @@
return "<div class='panel redborder'>[result.Join("<br>")]</div>"
/datum/antagonist/abductee
name = "Abductee"
roundend_category = "abductees"
antagpanel_category = "Abductee"
/datum/antagonist/abductee/on_gain()
give_objective()
. = ..()
/datum/antagonist/abductee/greet()
to_chat(owner, "<span class='warning'><b>Your mind snaps!</b></span>")
to_chat(owner, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
owner.announce_objectives()
/datum/antagonist/abductee/proc/give_objective()
var/mob/living/carbon/human/H = owner.current
if(istype(H))
H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY)
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
objectives += O
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee")
/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override)
update_abductor_icons_removed(mob_override ? mob_override.mind : owner)
// LANDMARKS
/obj/effect/landmark/abductor
var/team_number = 1
@@ -29,6 +29,11 @@
var/stealth_armor = list("melee" = 15, "bullet" = 15, "laser" = 15, "energy" = 15, "bomb" = 15, "bio" = 15, "rad" = 15, "fire" = 70, "acid" = 70)
var/combat_armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 90, "acid" = 90)
/obj/item/clothing/suit/armor/abductor/vest/Initialize()
. = ..()
stealth_armor = getArmor(arglist(stealth_armor))
combat_armor = getArmor(arglist(combat_armor))
/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop()
if(HAS_TRAIT_FROM(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT))
REMOVE_TRAIT(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)
@@ -629,15 +634,12 @@
icon_state = "abductor_headset"
item_state = "abductor_headset"
keyslot2 = new /obj/item/encryptionkey/heads/captain
bowman = TRUE
/obj/item/radio/headset/abductor/Initialize(mapload)
. = ..()
make_syndie()
/obj/item/radio/headset/abductor/ComponentInitialize()
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
/obj/item/radio/headset/abductor/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_SCREWDRIVER)
return // Stops humans from disassembling abductor headsets.
@@ -33,7 +33,7 @@
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
user.put_in_hands(IC)
IC.Remove(target)
IC.Remove()
return 1
else
to_chat(user, "<span class='warning'>You don't find anything in [target]'s [target_zone]!</span>")
@@ -73,13 +73,14 @@
active_mind_control = FALSE
return TRUE
/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/Remove(special = FALSE)
active = 0
if(initial(uses) == 1)
uses = initial(uses)
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
hud.remove_from_hud(owner)
clear_mind_control()
if(!QDELETED(owner))
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
hud.remove_from_hud(owner)
clear_mind_control()
..()
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
@@ -14,6 +14,7 @@
/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O)
return TRUE
/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0)
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
..()
/obj/item/organ/heart/gland/access/Remove(special = FALSE)
if(!QDELETED(owner))
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
return ..()
@@ -11,9 +11,10 @@
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
..()
/obj/item/organ/heart/gland/electric/Remove(special = FALSE)
if(!QDELETED(owner))
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
return ..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
@@ -65,14 +65,14 @@
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
owner.visible_message("<span class='warning'>[owner] vomits up his [implant.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [implant.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
implant.Remove(owner)
implant.Remove()
implant.forceMove(owner.drop_location())
/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver)
if(liver)
owner.visible_message("<span class='warning'>[owner] vomits up his [liver.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [liver.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
liver.Remove(owner)
liver.Remove()
liver.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble in your bowels...</span>")
@@ -87,7 +87,7 @@
if(lungs)
owner.visible_message("<span class='warning'>[owner] vomits up his [lungs.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [lungs.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
lungs.Remove(owner)
lungs.Remove()
lungs.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble inside your chest...</span>")
@@ -102,7 +102,7 @@
if(eyes)
owner.visible_message("<span class='warning'>[owner]'s [eyes.name] fall out of their sockets!</span>", "<span class='userdanger'>Your [eyes.name] fall out of their sockets!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
eyes.Remove(owner)
eyes.Remove()
eyes.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble behind your eye sockets...</span>")
@@ -203,7 +203,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/mob/camera/blob/proc/blob_talk(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
@@ -84,7 +84,7 @@
//It is called from your coffin on close (by you only)
if(poweron_masquerade == TRUE || owner.current.AmStaked())
return FALSE
owner.current.adjustStaminaLoss(-2 + (regenRate * -8) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
owner.current.adjustStaminaLoss(-1.5 + (regenRate * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
owner.current.adjustCloneLoss(-0.1 * (regenRate * 2) * mult, 0)
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0)
// No Bleeding
@@ -125,7 +125,7 @@
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
C.adjustToxLoss(-toxinheal * mult * 2, forced = TRUE) //Toxin healing because vamps arent immune
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
AddBloodVolume((bruteheal * -0.5 + fireheal * -1) / mult * costMult) // Costs blood to heal
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal
return TRUE // Healed! Done for this tick.
if(amInCoffinWhileTorpor) // Limbs? (And I have no other healing)
var/list/missing = owner.current.get_missing_limbs() // Heal Missing
@@ -189,7 +189,7 @@
/datum/antagonist/bloodsucker/proc/HandleDeath()
// FINAL DEATH
// Fire Damage? (above double health)
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.getMaxHealth() * 1.5)
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5)
FinalDeath()
return
// Staked while "Temp Death" or Asleep
@@ -32,11 +32,11 @@
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
/datum/action/bloodsucker/New()
if (bloodcost > 0)
if(bloodcost > 0)
desc += "<br><br><b>COST:</b> [bloodcost] Blood" // Modify description to add cost.
if (warn_constant_cost)
if(warn_constant_cost)
desc += "<br><br><i>Your over-time blood consumption increases while [name] is active.</i>"
if (amSingleUse)
if(amSingleUse)
desc += "<br><br><i>Useable once per night.</i>"
..()
@@ -47,35 +47,35 @@
/datum/action/bloodsucker/Trigger()
// Active? DEACTIVATE AND END!
if (active && CheckCanDeactivate(TRUE))
if(active && CheckCanDeactivate(TRUE))
DeactivatePower()
return
if (!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
return
PayCost()
if (amToggle)
if(amToggle)
active = !active
UpdateButtonIcon()
if (!amToggle || !active)
if(!amToggle || !active)
StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert.
ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends.
if (active) // Did we not manually disable? Handle it here.
if(active) // Did we not manually disable? Handle it here.
DeactivatePower()
if (amSingleUse)
if(amSingleUse)
RemoveAfterUse()
/datum/action/bloodsucker/proc/CheckCanPayCost(display_error)
if(!owner || !owner.mind)
return FALSE
// Cooldown?
if (cooldownUntil > world.time)
if (display_error)
if(cooldownUntil > world.time)
if(display_error)
to_chat(owner, "[src] is unavailable. Wait [(cooldownUntil - world.time) / 10] seconds.")
return FALSE
// Have enough blood?
var/mob/living/L = owner
if (L.blood_volume < bloodcost)
if (display_error)
if(L.blood_volume < bloodcost)
if(display_error)
to_chat(owner, "<span class='warning'>You need at least [bloodcost] blood to activate [name]</span>")
return FALSE
return TRUE
@@ -1,4 +1,3 @@
#define TIME_BLOODSUCKER_NIGHT 900 // 15 minutes
#define TIME_BLOODSUCKER_DAY_WARN 90 // 1.5 minutes
#define TIME_BLOODSUCKER_DAY_FINAL_WARN 25 // 25 sec
#define TIME_BLOODSUCKER_DAY 60 // 1.5 minutes // 10 is a second, 600 is a minute.
@@ -11,6 +10,7 @@
var/cancel_me = FALSE
var/amDay = FALSE
var/time_til_cycle = 0
var/nightime_duration = 900 //15 Minutes
/obj/effect/sunlight/Initialize()
countdown()
@@ -21,7 +21,7 @@
while(!cancel_me)
time_til_cycle = TIME_BLOODSUCKER_NIGHT
time_til_cycle = nightime_duration
// Part 1: Night (all is well)
while(time_til_cycle > TIME_BLOODSUCKER_DAY_WARN)
@@ -81,7 +81,9 @@
"<span class = 'announce'>The solar flare has ended, and the daylight danger has passed...for now.</span>")
amDay = FALSE
day_end() // Remove VANISHING ACT power from all vamps who have it! Clear Warnings (sunlight, locker protection)
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [TIME_BLOODSUCKER_NIGHT / 60] minutes.)")
nightime_duration += 100 //Each day makes the night a minute longer.
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [nightime_duration / 60] minutes.)")
/obj/effect/sunlight/proc/hud_tick()
@@ -97,7 +99,7 @@
sleep(10)
time_til_cycle --
/obj/effect/sunlight/proc/warn_daylight(danger_level=0, vampwarn = "", vassalwarn = "")
/obj/effect/sunlight/proc/warn_daylight(danger_level =0, vampwarn = "", vassalwarn = "")
for(var/datum/mind/M in SSticker.mode.bloodsuckers)
if(!istype(M))
continue
@@ -22,7 +22,7 @@
// STATS
var/vamplevel = 0
var/vamplevel_unspent = 1
var/regenRate = 0.3 // How many points of Brute do I heal per tick?
var/regenRate = 0.4 // How many points of Brute do I heal per tick?
var/feedAmount = 15 // Amount of blood drawn from a target per tick.
var/maxBloodVolume = 600 // Maximum blood a Vamp can hold via feeding. // BLOOD_VOLUME_NORMAL 550 // BLOOD_VOLUME_SAFE 475 //BLOOD_VOLUME_OKAY 336 //BLOOD_VOLUME_BAD 224 // BLOOD_VOLUME_SURVIVE 122
// OBJECTIVES
@@ -34,6 +34,7 @@
var/warn_sun_locker = FALSE // So we only get the locker burn message once per day.
var/warn_sun_burn = FALSE // So we only get the sun burn message once per day.
var/had_toxlover = FALSE
var/level_bloodcost
// LISTS
var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \
TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE)
@@ -98,7 +99,7 @@
/datum/antagonist/bloodsucker/proc/SelectFirstName()
// Names (EVERYONE gets one))
if (owner.current.gender == MALE)
if(owner.current.gender == MALE)
vampname = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \
"Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient
"Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin
@@ -119,7 +120,7 @@
return
// Titles [Master]
if (!am_fledgling)
if (owner.current.gender == MALE)
if(owner.current.gender == MALE)
vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master")
else
vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress")
@@ -130,18 +131,18 @@
/datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE)
// Already have Reputation
if (!forced && vampreputation != null)
if(!forced && vampreputation != null)
return
// Reputations [Master]
if (!am_fledgling)
if(!am_fledgling)
vampreputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \
"Inqisitor","Harvester","Reviled","Robust","Betrayer","Destructor","Damned","Accursed","Terrible","Vicious","Profane","Vile","Depraved","Foul","Slayer","Manslayer","Sovereign","Slaughterer", \
"Forsaken","Mad","Dragon","Savage","Villainous","Nefarious","Inquisitor","Marauder","Horrible","Immortal","Undying","Overlord","Corrupt","Hellspawn","Tyrant","Sanguineous")
if (owner.current.gender == MALE)
if (prob(10)) // Gender override
if(owner.current.gender == MALE)
if(prob(10)) // Gender override
vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
else
if (prob(10)) // Gender override
if(prob(10)) // Gender override
vampreputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen")
to_chat(owner, "<span class='announce'>You have earned a reputation! You are now known as <i>[ReturnFullName(TRUE)]</i>!</span>")
@@ -202,7 +203,7 @@
// Make Changes
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
H.physiology.cold_mod = 0
H.physiology.stun_mod *= 0.35
H.physiology.stun_mod *= 0.5
H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
@@ -261,7 +262,7 @@
owner.hasSoul = TRUE
//owner.current.hellbound = FALSE
datum/antagonist/bloodsucker/proc/RankUp()
/datum/antagonist/bloodsucker/proc/RankUp()
set waitfor = FALSE
if(!owner || !owner.current)
return
@@ -272,21 +273,23 @@ datum/antagonist/bloodsucker/proc/RankUp()
else
to_chat(owner, "<EM><span class='notice'>You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.</span></EM>")
if(vamplevel_unspent >= 2)
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks.</span><br>")
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.</span><br>")
datum/antagonist/bloodsucker/proc/LevelUpPowers()
/datum/antagonist/bloodsucker/proc/LevelUpPowers()
for(var/datum/action/bloodsucker/power in powers)
power.level_current ++
datum/antagonist/bloodsucker/proc/SpendRank()
/datum/antagonist/bloodsucker/proc/SpendRank()
set waitfor = FALSE
if (vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client)
if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current))
return
/////////
// Powers
//TODO: Make this into a radial
var/mob/living/L = owner.current
level_bloodcost = maxBloodVolume * 0.2
//If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker
//TODO: Make this into a radial, or perhaps a tgui next UI
// Purchase Power Prompt
var/list/options = list() // Taken from gasmask.dm, for Clown Masks.
var/list/options = list()
for(var/pickedpower in typesof(/datum/action/bloodsucker))
var/datum/action/bloodsucker/power = pickedpower
// If I don't own it, and I'm allowed to buy it.
@@ -295,7 +298,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
options["\[ Not Now \]"] = null
// Abort?
if(options.len > 1)
var/choice = input(owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...") in options
var/choice = input(owner.current, "You have the opportunity to grow more ancient at the cost of [level_bloodcost] units of blood. Select a power to advance your Rank.", "Your Blood Thickens...") in options
// Cheat-Safety: Can't keep opening/closing coffin to spam levels
if(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal.
return
@@ -305,10 +308,14 @@ datum/antagonist/bloodsucker/proc/SpendRank()
if(!choice || !options[choice] || (locate(options[choice]) in powers)) // ADDED: Check to see if you already have this power, due to window stacking.
to_chat(owner.current, "<span class='notice'>You prevent your blood from thickening just yet, but you may try again later.</span>")
return
if(L.blood_volume < level_bloodcost)
to_chat(owner.current, "<span class='warning'>You dont have enough blood to thicken your blood, you need [level_bloodcost - L.blood_volume] units more!</span>")
return
// Buy New Powers
var/datum/action/bloodsucker/P = options[choice]
AddBloodVolume(-level_bloodcost)
BuyPower(new P)
to_chat(owner.current, "<span class='notice'>You have learned [initial(P.name)]!</span>")
to_chat(owner.current, "<span class='notice'>You have used [level_bloodcost] units of blood and learned [initial(P.name)]!</span>")
else
to_chat(owner.current, "<span class='notice'>You grow more ancient by the night!</span>")
/////////
@@ -326,7 +333,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
// Vamp Stats
regenRate += 0.05 // Points of brute healed (starts at 0.3)
feedAmount += 2 // Increase how quickly I munch down vics (15)
maxBloodVolume += 50 // Increase my max blood (600)
maxBloodVolume += 100 // Increase my max blood (600)
/////////
vamplevel ++
vamplevel_unspent --
@@ -283,8 +283,8 @@
streak = ""
restraining = 0
streak = streak+element
if(length(streak) > max_streak_length)
streak = copytext(streak,2)
if(length_char(streak) > max_streak_length)
streak = streak[1]
return
@@ -8,7 +8,7 @@
return SSticker.mode.make_vassal(C,owner)
/datum/antagonist/bloodsucker/proc/FreeAllVassals()
for (var/datum/antagonist/vassal/V in vassals)
for(var/datum/antagonist/vassal/V in vassals)
SSticker.mode.remove_vassal(V.owner)
/datum/antagonist/vassal
@@ -22,7 +22,7 @@
/datum/antagonist/vassal/can_be_owned(datum/mind/new_owner)
// If we weren't created by a bloodsucker, then we cannot be a vassal (assigned from antag panel)
if (!master)
if(!master)
return FALSE
return ..()
@@ -63,9 +63,9 @@
/datum/antagonist/vassal/on_removal()
SSticker.mode.vassals -= owner // Add if not already in here (and you might be, if you were picked at round start)
// Mindslave Remove
if (master && master.owner)
if(master && master.owner)
master.vassals -= src
if (owner.enslaved_to == master.owner.current)
if(owner.enslaved_to == master.owner.current)
owner.enslaved_to = null
// Master Pinpointer
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer/vassal_edition)
@@ -60,6 +60,8 @@
breakout_time = 600
pryLidTimer = 400
resistance_flags = NONE
integrity_failure = 70
armor = list("melee" = 50, "bullet" = 20, "laser" = 30, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
/obj/structure/closet/crate/coffin/meatcoffin
name = "meat coffin"
@@ -75,7 +77,9 @@
resistance_flags = NONE
material_drop = /obj/item/reagent_containers/food/snacks/meat/slab
material_drop_amount = 3
integrity_failure = 40
armor = list("melee" = 70, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
/obj/structure/closet/crate/coffin/metalcoffin
name = "metal coffin"
desc = "A big metal sardine can inside of another big metal sardine can, in space."
@@ -90,6 +94,8 @@
resistance_flags = NONE
material_drop = /obj/item/stack/sheet/metal
material_drop_amount = 5
integrity_failure = 60
armor = list("melee" = 40, "bullet" = 15, "laser" = 50, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
//////////////////////////////////////////////
@@ -107,7 +107,7 @@
var/convert_progress = 3 // Resets on each new character to be added to the chair. Some effects should lower it...
var/disloyalty_confirm = FALSE // Command & Antags need to CONFIRM they are willing to lose their role (and will only do it if the Vassal'ing succeeds)
var/disloyalty_offered = FALSE // Has the popup been issued? Don't spam them.
var/convert_cost = 100
/obj/structure/bloodsucker/vassalrack/deconstruct(disassembled = TRUE)
new /obj/item/stack/sheet/metal(src.loc, 4)
@@ -116,10 +116,10 @@
/obj/structure/bloodsucker/vassalrack/examine(mob/user)
. = ..()
if((user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) || isobserver(user))
if(isvamp(user) || isobserver(user))
. += {"<span class='cult'>This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service.</span>"}
. += {"<span class='cult'>You need to first secure the vassal rack by clicking on it while it is in your lair.</span>"}
. += {"<span class='cult'>Simply click and hold on a victim, and then drag their sprite on the vassal rack.</span>"}
. += {"<span class='cult'>Simply click and hold on a victim, and then drag their sprite on the vassal rack. Alt click on the vassal rack to unbuckle them.</span>"}
. += {"<span class='cult'>Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant.</span>"}
. += {"<span class='cult'>To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools.</span>"}
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
@@ -177,7 +177,7 @@
M.pixel_y = -2 //M.get_standard_pixel_y_offset(120)//180)
update_icon()
// Torture Stuff
convert_progress = 2 // Goes down unless you start over.
convert_progress = 4 // Goes down unless you start over.
disloyalty_confirm = FALSE // New guy gets the chance to say NO if he's special.
disloyalty_offered = FALSE // Prevents spamming torture window.
@@ -190,7 +190,7 @@
else
M.visible_message("<span class='danger'>[user] tries to pull [M] rack!</span>",\
"<span class='danger'>[user] attempts to release you from the rack!</span>") // For sound if not seen --> "<span class='italics'>You hear a squishy wet noise.</span>")
if(!do_mob(user, M, 100))
if(!do_mob(user, M, 200))
return
// Did the time. Now try to do it.
..()
@@ -248,7 +248,7 @@
// Bloodsucker Owner! Let the boy go.
if(C.mind)
var/datum/antagonist/vassal/vassaldatum = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
if (istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
unbuckle_mob(C)
useLock = FALSE // Failsafe
return
@@ -256,7 +256,9 @@
torture_victim(user, C)
/obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target)
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
// Check Bloodmob/living/M, force = FALSE, check_loc = TRUE
var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals
if(user.blood_volume < convert_cost + 5)
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target].</span>")
return
@@ -275,7 +277,7 @@
// All done!
if(convert_progress <= 0)
// FAIL: Can't be Vassal
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
if(!SSticker.mode.can_make_vassal(target, user, display_warning = FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
to_chat(user, "<span class='danger'>[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.<i>\[ALT+click to release\]</span>")
convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
// SUCCESS: All done!
@@ -301,10 +303,9 @@
return
// Check: Blood
if(user.blood_volume < convert_cost)
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target].</span>")
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target], you need [convert_cost - user.blood_volume] units more!</span>")
useLock = FALSE
return
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
bloodsuckerdatum.AddBloodVolume(-convert_cost)
target.add_mob_blood(user)
user.visible_message("<span class='notice'>[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!</span>", \
@@ -5,7 +5,7 @@
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
button_icon_state = "power_strength"
bloodcost = 10
cooldown = 130
cooldown = 90
target_range = 1
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -66,16 +66,14 @@
// Target Type: Mob
if(isliving(target))
var/mob/living/carbon/user_C = user
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.3 + 5
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.4 + 15
// Knockdown!
var/powerlevel = min(5, 1 + level_current)
if(rand(5 + powerlevel) >= 5)
target.visible_message("<span class='danger'>[user] lands a vicious punch, sending [target] away!</span>", \
"<span class='userdanger'>[user] has landed a horrifying punch on you, sending you flying!!</span>", null, COMBAT_MESSAGE_RANGE)
target.Knockdown(min(5, rand(10, 10 * powerlevel)) )
// Chance of KO
if(rand(6 + powerlevel) >= 6 && target.stat <= UNCONSCIOUS)
target.Unconscious(40)
// Attack!
playsound(get_turf(target), 'sound/weapons/punch4.ogg', 60, 1, -1)
user.do_attack_animation(target, ATTACK_EFFECT_SMASH)
@@ -22,12 +22,12 @@
return
// Wearing mask
var/mob/living/L = owner
if (L.is_mouth_covered())
if (display_error)
if(L.is_mouth_covered())
if(display_error)
to_chat(owner, "<span class='warning'>You cannot feed with your mouth covered! Remove your mask.</span>")
return FALSE
// Find my Target!
if (!FindMyTarget(display_error)) // Sets feed_target within after Validating
if(!FindMyTarget(display_error)) // Sets feed_target within after Validating
return FALSE
// Not in correct state
// DONE!
@@ -35,36 +35,36 @@
/datum/action/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
// Bloodsuckers + Animals MUST be grabbed aggressively!
if (!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
if(!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
// NOTE: It's OKAY that we are checking if(!target) below, AFTER animals here. We want passive check vs animal to warn you first, THEN the standard warning.
// Animals:
if (isliving(target) && !iscarbon(target))
if (display_error)
if(isliving(target) && !iscarbon(target))
if(display_error)
to_chat(owner, "<span class='warning'>Lesser beings require a tighter grip.</span>")
return FALSE
// Bloodsuckers:
else if (iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if (display_error)
else if(iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if(display_error)
to_chat(owner, "<span class='warning'>Other Bloodsuckers will not fall for your subtle approach.</span>")
return FALSE
// Must have Target
if (!target) // || !ismob(target)
if (display_error)
if(!target) // || !ismob(target)
if(display_error)
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
return FALSE
// Not even living!
if (!isliving(target) || issilicon(target))
if (display_error)
if(!isliving(target) || issilicon(target))
if(display_error)
to_chat(owner, "<span class='warning'>You may only feed from living beings.</span>")
return FALSE
if (target.blood_volume <= 0)
if (display_error)
if(target.blood_volume <= 0)
if(display_error)
to_chat(owner, "<span class='warning'>Your victim has no blood to take.</span>")
return FALSE
if (ishuman(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(NOBLOOD in H.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id())
if (display_error)
if(display_error)
to_chat(owner, "<span class='warning'>Your victim's blood is not suitable for you to take.</span>")
return FALSE
return TRUE
@@ -75,9 +75,9 @@
feed_target = null
target_grappled = FALSE
// If you are pulling a mob, that's your target. If you don't like it, then release them.
if (owner.pulling && ismob(owner.pulling))
if(owner.pulling && ismob(owner.pulling))
// Check grapple target Valid
if (!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
if(!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
return FALSE
target_grappled = TRUE
feed_target = owner.pulling
@@ -86,11 +86,11 @@
var/list/mob/living/seen_targets = view(1, owner)
var/list/mob/living/seen_mobs = list()
for(var/mob/living/M in seen_targets)
if (isliving(M) && M != owner)
if(isliving(M) && M != owner)
seen_mobs += M
// None Seen!
if (seen_mobs.len == 0)
if (display_error)
if(seen_mobs.len == 0)
if(display_error)
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
return FALSE
// Check Valids...
@@ -98,19 +98,19 @@
var/list/targets_dead = list()
for(var/mob/living/M in seen_mobs)
// Check adjecent Valid target
if (M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
if(M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
// Prioritize living, but remember dead as backup
if (M.stat < DEAD)
if(M.stat < DEAD)
targets_valid += M
else
targets_dead += M
// No Living? Try dead.
if (targets_valid.len == 0 && targets_dead.len > 0)
if(targets_valid.len == 0 && targets_dead.len > 0)
targets_valid = targets_dead
// No Targets
if (targets_valid.len == 0)
if(targets_valid.len == 0)
// Did I see targets? Then display at least one error
if (seen_mobs.len > 1)
if(seen_mobs.len > 1)
if (display_error)
to_chat(owner, "<span class='warning'>None of these are valid targets to feed from subtly.</span>")
else
@@ -136,28 +136,28 @@
// Initial Wait
var/feed_time = (amSilent ? 45 : 25) - (2.5 * level_current)
feed_time = max(15, feed_time)
if (amSilent)
if(amSilent)
to_chat(user, "<span class='notice'>You lean quietly toward [target] and secretly draw out your fangs...</span>")
else
to_chat(user, "<span class='warning'>You pull [target] close to you and draw out your fangs...</span>")
if (!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
if(!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
to_chat(user, "<span class='warning'>Your feeding was interrupted.</span>")
//DeactivatePower(user,target)
return
// Put target to Sleep (Bloodsuckers are immune to their own bite's sleep effect)
if (!amSilent)
if(!amSilent)
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
if(target.stat <= UNCONSCIOUS)
sleep(1)
// Wait, then Cancel if Invalid
if (!ContinueActive(user,target)) // Cancel. They're gone.
if(!ContinueActive(user,target)) // Cancel. They're gone.
//DeactivatePower(user,target)
return
// Pull Target Close
if (!target.density) // Pull target to you if they don't take up space.
if(!target.density) // Pull target to you if they don't take up space.
target.Move(user.loc)
// Broadcast Message
if (amSilent)
if(amSilent)
//if (!iscarbon(target))
// user.visible_message("<span class='notice'>[user] shifts [target] closer to [user.p_their()] mouth.</span>", \
// "<span class='notice'>You secretly slip your fangs into [target]'s flesh.</span>", \
@@ -173,7 +173,7 @@
if(M != owner && M != target && iscarbon(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
was_unnoticed = FALSE
break
if (was_unnoticed)
if(was_unnoticed)
to_chat(user, "<span class='notice'>You think no one saw you...</span>")
else
to_chat(user, "<span class='warning'>Someone may have noticed...</span>")
@@ -197,16 +197,16 @@
// FEEEEEEEEED!!! //
bloodsuckerdatum.poweron_feed = TRUE
while (bloodsuckerdatum && target && active)
while(bloodsuckerdatum && target && active)
//user.mobility_flags &= ~MOBILITY_MOVE // user.canmove = 0 // Prevents spilling blood accidentally.
// Abort? A bloody mistake.
if (!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
if(!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
// May have disabled Feed during do_mob
if (!active || !ContinueActive(user, target))
if(!active || !ContinueActive(user, target))
break
if (amSilent)
if(amSilent)
to_chat(user, "<span class='warning'>Your feeding has been interrupted...but [target.p_they()] didn't seem to notice you.<span>")
else
to_chat(user, "<span class='warning'>Your feeding has been interrupted!</span>")
@@ -214,11 +214,11 @@
"<span class='userdanger'>Your teeth are ripped from [target]'s throat. [target.p_their(TRUE)] blood sprays everywhere!</span>")
// Deal Damage to Target (should have been more careful!)
if (iscarbon(target))
if(iscarbon(target))
var/mob/living/carbon/C = target
C.bleed(15)
playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1)
if (ishuman(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.bleed_rate += 5
target.add_splatter_floor(get_turf(target))
@@ -228,7 +228,7 @@
target.emote("scream")
// Killed Target?
if (was_alive)
if(was_alive)
CheckKilledTarget(user,target)
return
@@ -237,40 +237,40 @@
// Handle Feeding! User & Victim Effects (per tick)
bloodsuckerdatum.HandleFeeding(target, blood_take_mult)
amount_taken += amSilent ? 0.3 : 1
if (!amSilent)
if(!amSilent)
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
if (amount_taken > 5 && target.stat < DEAD && ishuman(target))
if(amount_taken > 5 && target.stat < DEAD && ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood) // GOOD // in bloodsucker_life.dm
///////////////////////////////////////////////////////////
// Not Human?
if (!ishuman(target))
if(!ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_bad) // BAD // in bloodsucker_life.dm
if (!warning_target_inhuman)
if(!warning_target_inhuman)
to_chat(user, "<span class='notice'>You recoil at the taste of a lesser lifeform.</span>")
warning_target_inhuman = TRUE
// Dead Blood?
if (target.stat >= DEAD)
if (ishuman(target))
if(target.stat >= DEAD)
if(ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_dead) // BAD // in bloodsucker_life.dm
if (!warning_target_dead)
if(!warning_target_dead)
to_chat(user, "<span class='notice'>Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.</span>")
warning_target_dead = TRUE
// Full?
if (!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
to_chat(user, "<span class='notice'>You are full. Further blood will be wasted.</span>")
warning_full = TRUE
// Blood Remaining? (Carbons/Humans only)
if (iscarbon(target) && !target.AmBloodsucker(1))
if (target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
if(iscarbon(target) && !target.AmBloodsucker(1))
if(target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
to_chat(user, "<span class='warning'>Your victim's blood volume is fatally low!</span>")
else if (target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
to_chat(user, "<span class='warning'>Your victim's blood volume is dangerously low.</span>")
else if (target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
else if(target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
to_chat(user, "<span class='notice'>Your victim's blood is at an unsafe level.</span>")
warning_target_bloodvol = target.blood_volume // If we had a warning to give, it's been given by now.
// Done?
if (target.blood_volume <= 0)
if(target.blood_volume <= 0)
to_chat(user, "<span class='notice'>You have bled your victim dry.</span>")
break
@@ -279,7 +279,7 @@
// DONE!
//DeactivatePower(user,target)
if (amSilent)
if(amSilent)
to_chat(user, "<span class='notice'>You slowly release [target]'s wrist." + (target.stat == 0 ? " [target.p_their(TRUE)] face lacks expression, like you've already been forgotten.</span>" : ""))
else
user.visible_message("<span class='warning'>[user] unclenches their teeth from [target]'s neck.</span>", \
@@ -289,13 +289,13 @@
log_combat(owner, target, "fed on blood", addition="(and took [amount_taken] blood)")
// Killed Target?
if (was_alive)
if(was_alive)
CheckKilledTarget(user,target)
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
// Bad Vampire. You shouldn't do that.
if (target && target.stat >= DEAD && ishuman(target))
if(target && target.stat >= DEAD && ishuman(target))
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm
/datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
@@ -304,18 +304,18 @@
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
// Bloodsuckers not affected by "the Kiss" of another vampire
if (!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
if(!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
target.Unconscious(50,0)
target.Knockdown(40 + 5 * level_current,1)
// NOTE: THis is based on level of power!
if (ishuman(target))
if(ishuman(target))
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
/datum/action/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
// No longer Feeding
if (bloodsuckerdatum)
if(bloodsuckerdatum)
bloodsuckerdatum.poweron_feed = FALSE
feed_target = null
// My mouth is no longer full
@@ -6,7 +6,7 @@
name = "Fortitude"//"Cellular Emporium"
desc = "Withstand egregious physical wounds and walk away from attacks that would stun, pierce, and dismember lesser beings. You cannot run while active."
button_icon_state = "power_fortitude"
bloodcost = 5
bloodcost = 30
cooldown = 80
bloodsucker_can_buy = TRUE
amToggle = TRUE
@@ -23,7 +23,7 @@
ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if (ishuman(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
this_resist = max(0.3, 0.7 - level_current * 0.1)
H.physiology.brute_mod *= this_resist//0.5
@@ -34,7 +34,7 @@
user.toggle_move_intent()
while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN)
// Pay Blood Toll (if awake)
if (user.stat == CONSCIOUS)
if(user.stat == CONSCIOUS)
bloodsuckerdatum.AddBloodVolume(-0.5) // Used to be 0.3 blood per 2 seconds, but we're making it more expensive to keep on.
sleep(20) // Check every few ticks that we haven't disabled this power
// Return to Running (if you were before)
@@ -48,7 +48,7 @@
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
REMOVE_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if (ishuman(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.physiology.brute_mod /= this_resist//0.5
H.physiology.burn_mod /= this_resist//0.5
@@ -7,7 +7,7 @@
background_icon_state_on = "vamp_power_off_oneshot" // Even though this never goes off.
background_icon_state_off = "vamp_power_off_oneshot"
bloodcost = 25
bloodcost = 100
cooldown = 99999 // It'll never come back.
amToggle = FALSE
amSingleUse = TRUE
@@ -23,11 +23,16 @@
return
// Have No Lair (NOTE: You only got this power if you had a lair, so this means it's destroyed)
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if (display_error)
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if(display_error)
to_chat(owner, "<span class='warning'>Your coffin has been destroyed!</span>")
return FALSE
return TRUE
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', beat_volume, 1)
/datum/action/bloodsucker/gohome/ActivatePower()
var/mob/living/carbon/user = owner
@@ -35,34 +40,31 @@
// IMPORTANT: Check for lair at every step! It might get destroyed.
to_chat(user, "<span class='notice'>You focus on separating your consciousness from your physical form...</span>")
// STEP ONE: Flicker Lights
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 20, 1)
flicker_lights(3, 20)
sleep(50)
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
flicker_lights(4, 40)
sleep(50)
for(var/obj/machinery/light/L in view(6, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
flicker_lights(4, 60)
for(var/obj/machinery/light/L in view(6, get_turf(owner)))
L.flicker(5)
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 60, 1)
// ( STEP TWO: Lights OFF? )
// CHECK: Still have Coffin?
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
to_chat(user, "<span class='warning'>Your coffin has been destroyed! You no longer have a destination.</span>")
return FALSE
if (!owner)
if(!owner)
return
// SEEN?: (effects ONLY if there are witnesses! Otherwise you just POOF)
// NOTE: Stolen directly from statue.dm, thanks guys!
var/am_seen = FALSE // Do Effects (seen by anyone)
var/drop_item = FALSE // Drop Stuff (seen by non-vamp)
if (isturf(owner.loc)) // Only check if I'm not in a Locker or something.
if(isturf(owner.loc)) // Only check if I'm not in a Locker or something.
// A) Check for Darkness (we can just leave)
var/turf/T = get_turf(user)
if(T && T.lighting_object && T.get_lumcount()>= 0.1)
// B) Check for Viewers
for(var/mob/living/M in viewers(owner))
for(var/mob/living/M in viewers(get_turf(owner)))
if(M != owner && isliving(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind) // M.client <--- add this in after testing!
am_seen = TRUE
if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
@@ -76,7 +78,7 @@
var/obj/O = user.legcuffed
user.dropItemToGround(O)
// SEEN!
if (drop_item)
if(drop_item)
// DROP: Clothes, held items, and cuffs etc
// NOTE: Taken from unequip_everything() in inventory.dm. We need to
// *force* all items to drop, so we had to just gut the code out of it.
@@ -86,30 +88,28 @@
user.dropItemToGround(I,TRUE)
for(var/obj/item/I in owner.held_items) // drop_all_held_items()
user.dropItemToGround(I, TRUE)
if (am_seen)
if(am_seen)
// POOF EFFECTS
playsound(get_turf(owner), 'sound/magic/summon_karp.ogg', 60, 1)
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
puff.set_up(3, 0, get_turf(owner))
puff.start()
//STEP FIVE: Create animal at prev location
var/mob/living/simple_animal/SA = pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
new SA (owner.loc)
// TELEPORT: Move to Coffin & Close it!
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm?
// SLEEP
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
user.resting = TRUE
//user.Unconscious(30,0)
user.Stun(30,1)
// CLOSE LID: If fail, force me in.
if (!bloodsuckerdatum.coffin.close(owner))
if(!bloodsuckerdatum.coffin.close(owner))
bloodsuckerdatum.coffin.insert(owner) // Puts me inside.
// The following was taken from close() proc in closets.dm
// (but we had to do it this way because there is no way to force entry)
playsound(bloodsuckerdatum.coffin.loc, bloodsuckerdatum.coffin.close_sound, 15, 1, -3)
bloodsuckerdatum.coffin.opened = FALSE
bloodsuckerdatum.coffin.density = TRUE
bloodsuckerdatum.coffin.update_icon()
// Lock Coffin
bloodsuckerdatum.coffin.LockMe(owner)
// ( STEP FIVE: Create animal at prev location? )
//var/mob/living/simple_animal/SA = /mob/living/simple_animal/hostile/retaliate/bat // pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
//new SA (owner.loc)
@@ -8,7 +8,7 @@
desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed."
button_icon_state = "power_speed"
bloodcost = 6
cooldown = 30
cooldown = 50
target_range = 15
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -6,7 +6,7 @@
desc = "Spring at your target and aggressively grapple them without warning. Attacks from concealment or the rear may even knock them down."
button_icon_state = "power_lunge"
bloodcost = 10
cooldown = 100
cooldown = 120
target_range = 3
power_activates_immediately = TRUE
message_Trigger = ""//"Whom will you subvert to your will?"
@@ -28,7 +28,7 @@
return TRUE
/datum/action/bloodsucker/targeted/lunge/CheckValidTarget(atom/A)
return isliving(A)
return iscarbon(A)
/datum/action/bloodsucker/targeted/lunge/CheckCanTarget(atom/A, display_error)
// Check: Self
@@ -10,7 +10,7 @@
desc = "Dominate the mind of a mortal who can see your eyes."
button_icon_state = "power_mez"
bloodcost = 30
cooldown = 200
cooldown = 300
target_range = 1
power_activates_immediately = FALSE
message_Trigger = "Whom will you subvert to your will?"
@@ -6,7 +6,7 @@
button_icon_state = "power_tres"
bloodcost = 10
cooldown = 60
cooldown = 80
amToggle = FALSE
//target_range = 2
@@ -15,7 +15,7 @@
to_chat(user, "<span class='notice'>We begin our stasis, preparing energy to arise once more.</span>")
if(user.stat != DEAD)
user.emote("deathgasp")
user.tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
user.tod = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)
user.fakedeath("changeling") //play dead
user.update_stat()
user.update_canmove()
@@ -18,7 +18,7 @@
var/list/organs = user.getorganszone(BODY_ZONE_HEAD, 1)
for(var/obj/item/organ/I in organs)
I.Remove(user, 1)
I.Remove(TRUE)
explosion(get_turf(user), 0, 0, 2, 0, TRUE)
for(var/mob/living/carbon/human/H in range(2,user))
@@ -22,7 +22,7 @@
if(!istype(O))
continue
O.Remove(user)
O.Remove()
if(iscarbon(user))
var/mob/living/carbon/C = user
C.vomit(0, toxic = TRUE)
@@ -104,6 +104,6 @@
transfer_personality(H)
brainmob.fully_replace_character_name(null, "[braintype] [H.real_name]")
name = "[initial(name)] ([brainmob.name])"
B.Remove(H)
B.Remove()
qdel(B)
H.update_hair()
@@ -83,7 +83,7 @@
return
if(client.handle_spam_prevention(message,MUTE_IC))
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message)
return
src.log_talk(message, LOG_SAY, tag="clockwork eminence")
+1 -1
View File
@@ -753,7 +753,7 @@
var/turf/T = get_turf(target)
if(T)
for(var/obj/effect/decal/cleanable/blood/B in view(T, 2))
if(B.blood_state == "blood")
if(B.blood_state == BLOOD_STATE_BLOOD)
if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
temp += 30
else
+1 -1
View File
@@ -22,7 +22,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
icon = 'icons/obj/rune.dmi'
icon_state = "1"
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = LOW_OBJ_LAYER
layer = SIGIL_LAYER
color = RUNE_COLOR_RED
var/invocation = "Aiy ele-mayo." //This is said by cultists when the rune is invoked.
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
var/short_desc = ""
var/long_desc = ""
var/stat_block = ""
var/threshold_block = ""
var/threshold_block = list()
var/category = ""
var/list/symptoms
@@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
resistance += initial(S.resistance)
stage_speed += initial(S.stage_speed)
transmittable += initial(S.transmittable)
threshold_block += "<br><br>[initial(S.threshold_desc)]"
threshold_block += initial(S.threshold_desc)
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
if(symptoms.len == 1) //lazy boy's dream
name = initial(S.name)
@@ -318,7 +318,11 @@ the new instance inside the host to be updated to the template's stats.
var/list/dat = list()
if(examining_ability)
dat += "<a href='byond://?src=[REF(src)];main_menu=1'>Back</a><br><h1>[examining_ability.name]</h1>[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]"
dat += "<a href='byond://?src=[REF(src)];main_menu=1'>Back</a><br>"
dat += "<h1>[examining_ability.name]</h1>"
dat += "[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]"
for(var/entry in examining_ability.threshold_block)
dat += "<b>[entry]</b>: [examining_ability.threshold_block[entry]]<br>"
else
dat += "<h1>Disease Statistics</h1><br>\
Resistance: [DT.totalResistance()]<br>\
+1
View File
@@ -52,6 +52,7 @@
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = owner
O.find_target()
objectives += O
if(3) //protect/kill
@@ -11,9 +11,10 @@
var/default_timer_set = 90
var/minimum_timer_set = 90
var/maximum_timer_set = 3600
var/ui_style = "nanotrasen"
ui_style = "nanotrasen"
var/numeric_input = ""
var/ui_mode = NUKEUI_AWAIT_DISK
var/timing = FALSE
var/exploding = FALSE
var/exploded = FALSE
@@ -97,6 +98,8 @@
if(!user.transferItemToLoc(I, src))
return
auth = I
update_ui_mode()
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
add_fingerprint(user)
return
@@ -233,113 +236,159 @@
var/volume = (get_time_left() <= 20 ? 30 : 5)
playsound(loc, 'sound/items/timer.ogg', volume, 0)
/obj/machinery/nuclearbomb/proc/update_ui_mode()
if(exploded)
ui_mode = NUKEUI_EXPLODED
return
if(!auth)
ui_mode = NUKEUI_AWAIT_DISK
return
if(timing)
ui_mode = NUKEUI_TIMING
return
if(!safety)
ui_mode = NUKEUI_AWAIT_ARM
return
if(!yes_code)
ui_mode = NUKEUI_AWAIT_CODE
return
ui_mode = NUKEUI_AWAIT_TIMER
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state=GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "nuclear_bomb", name, 500, 600, master_ui, state)
ui = new(user, src, ui_key, "nuclear_bomb", name, 350, 442, master_ui, state)
ui.set_style(ui_style)
ui.open()
/obj/machinery/nuclearbomb/ui_data(mob/user)
var/list/data = list()
data["disk_present"] = auth
data["code_approved"] = yes_code
var/first_status
if(auth)
if(yes_code)
first_status = timing ? "Func/Set" : "Functional"
else
first_status = "Auth S2."
var/hidden_code = (ui_mode == NUKEUI_AWAIT_CODE && numeric_input != "ERROR")
var/current_code = ""
if(hidden_code)
while(length(current_code) < length(numeric_input))
current_code = "[current_code]*"
else
if(timing)
first_status = "Set"
else
first_status = "Auth S1."
var/second_status = exploded ? "Warhead triggered, thanks for flying Nanotrasen" : (safety ? "Safe" : "Engaged")
current_code = numeric_input
while(length(current_code) < 5)
current_code = "[current_code]-"
var/first_status
var/second_status
switch(ui_mode)
if(NUKEUI_AWAIT_DISK)
first_status = "DEVICE LOCKED"
if(timing)
second_status = "TIME: [get_time_left()]"
else
second_status = "AWAIT DISK"
if(NUKEUI_AWAIT_CODE)
first_status = "INPUT CODE"
second_status = "CODE: [current_code]"
if(NUKEUI_AWAIT_TIMER)
first_status = "INPUT TIME"
second_status = "TIME: [current_code]"
if(NUKEUI_AWAIT_ARM)
first_status = "DEVICE READY"
second_status = "TIME: [get_time_left()]"
if(NUKEUI_TIMING)
first_status = "DEVICE ARMED"
second_status = "TIME: [get_time_left()]"
if(NUKEUI_EXPLODED)
first_status = "DEVICE DEPLOYED"
second_status = "THANK YOU"
data["status1"] = first_status
data["status2"] = second_status
data["anchored"] = anchored
data["safety"] = safety
data["timing"] = timing
data["time_left"] = get_time_left()
data["timer_set"] = timer_set
data["timer_is_not_default"] = timer_set != default_timer_set
data["timer_is_not_min"] = timer_set != minimum_timer_set
data["timer_is_not_max"] = timer_set != maximum_timer_set
var/message = "AUTH"
if(auth)
message = "[numeric_input]"
if(yes_code)
message = "*****"
data["message"] = message
return data
/obj/machinery/nuclearbomb/ui_act(action, params)
if(..())
return
playsound(src, "terminal_type", 20, FALSE)
switch(action)
if("eject_disk")
if(auth && auth.loc == src)
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
auth.forceMove(get_turf(src))
auth = null
. = TRUE
if("insert_disk")
if(!auth)
else
var/obj/item/I = usr.is_holding_item_of_type(/obj/item/disk/nuclear)
if(I && disk_check(I) && usr.transferItemToLoc(I, src))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
auth = I
. = TRUE
update_ui_mode()
if("keypad")
if(auth)
var/digit = params["digit"]
switch(digit)
if("R")
if("C")
if(auth && ui_mode == NUKEUI_AWAIT_ARM)
set_safety()
yes_code = FALSE
playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE)
update_ui_mode()
else
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
numeric_input = ""
yes_code = FALSE
. = TRUE
if("E")
if(numeric_input == r_code)
numeric_input = ""
yes_code = TRUE
. = TRUE
else
numeric_input = "ERROR"
switch(ui_mode)
if(NUKEUI_AWAIT_CODE)
if(numeric_input == r_code)
numeric_input = ""
yes_code = TRUE
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
. = TRUE
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
numeric_input = "ERROR"
if(NUKEUI_AWAIT_TIMER)
var/number_value = text2num(numeric_input)
if(number_value)
timer_set = CLAMP(number_value, minimum_timer_set, maximum_timer_set)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
set_safety()
. = TRUE
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
update_ui_mode()
if("0","1","2","3","4","5","6","7","8","9")
if(numeric_input != "ERROR")
numeric_input += digit
if(length(numeric_input) > 5)
numeric_input = "ERROR"
else
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
. = TRUE
if("timer")
if(auth && yes_code)
var/change = params["change"]
if(change == "reset")
timer_set = default_timer_set
else if(change == "decrease")
timer_set = max(minimum_timer_set, timer_set - 10)
else if(change == "increase")
timer_set = min(maximum_timer_set, timer_set + 10)
else if(change == "input")
var/user_input = input(usr, "Set time to detonation.", name) as null|num
if(!user_input)
return
var/N = text2num(user_input)
if(!N)
return
timer_set = CLAMP(N,minimum_timer_set,maximum_timer_set)
. = TRUE
if("safety")
if(auth && yes_code && !exploded)
set_safety()
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
if("arm")
if(auth && yes_code && !safety && !exploded)
playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE)
set_active()
update_ui_mode()
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
if("anchor")
if(auth && yes_code)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
set_anchor()
if("toggle_timer")
if(auth && yes_code && !safety && !exploded)
set_active()
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
/obj/machinery/nuclearbomb/proc/set_anchor()
@@ -100,10 +100,9 @@
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
/obj/item/organ/heart/demon/Remove(mob/living/carbon/M, special = 0)
..()
if(M.mind)
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
/obj/item/organ/heart/demon/Remove(special = FALSE)
owner?.mind?.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
return ..()
/obj/item/organ/heart/demon/Stop()
return 0 // Always beating.
+3 -1
View File
@@ -19,6 +19,7 @@
job_description = "Swarmer"
death = FALSE
roundstart = FALSE
short_desc = "You are a swarmer, a weapon of a long dead civilization."
flavour_text = {"
<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
@@ -274,7 +275,8 @@
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
toggle_cam(S, 0)
if(!QDELETED(S)) //If it got blown up no need to turn it off.
toggle_cam(S, 0)
return TRUE
/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
@@ -22,11 +22,19 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
desc = "You aren't entirely sure what this does, but it's very beepy and boopy."
background_icon_state = "bg_tech_blue"
icon_icon = 'icons/mob/actions/actions_AI.dmi'
check_flags = AB_CHECK_CONSCIOUS //can't doomsday if dead.
var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time
var/uses //If we have multiple uses of the same power
var/auto_use_uses = TRUE //If we automatically use up uses on each activation
var/cooldown_period //If applicable, the time in deciseconds we have to wait before using any more modules
/datum/action/innate/ai/New()
..()
if(uses > 1)
desc = "[desc] It has [uses] use\s remaining."
button.desc = desc
/datum/action/innate/ai/Grant(mob/living/L)
. = ..()
if(!isAI(owner))
@@ -38,7 +46,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/IsAvailable()
. = ..()
if(owner_AI && owner_AI.malf_cooldown > world.time)
return
return FALSE
/datum/action/innate/ai/Trigger()
. = ..()
@@ -49,12 +57,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/proc/adjust_uses(amt, silent)
uses += amt
if(!silent && uses)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
if(!uses)
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
qdel(src)
if(uses)
if(!silent)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtonIcon()
return
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
qdel(src)
//Framework for ranged abilities that can have different effects by left-clicking stuff.
/datum/action/innate/ai/ranged
@@ -74,13 +86,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/ranged/adjust_uses(amt, silent)
uses += amt
if(!silent && uses)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
if(!uses)
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
Remove(owner)
QDEL_IN(src, 100) //let any active timers on us finish up
if(uses)
if(!silent)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtonIcon()
return
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
Remove(owner)
QDEL_IN(src, 100) //let any active timers on us finish up
/datum/action/innate/ai/ranged/Destroy()
QDEL_NULL(linked_ability)
@@ -97,7 +112,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
var/datum/action/innate/ai/ranged/attached_action
/obj/effect/proc_holder/ranged_ai/Destroy()
QDEL_NULL(attached_action)
attached_action = null
return ..()
/obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user)
@@ -185,6 +200,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
A.playsound_local(A, AM.unlock_sound, 50, 0)
else //Adding uses to an existing module
action.uses += initial(action.uses)
action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining."
action.UpdateButtonIcon()
temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!"
processing_time -= AM.cost
@@ -238,6 +255,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
return
if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;")
return
if (active)
return //prevent the AI from activating an already active doomsday
active = TRUE
set_us_up_the_bomb(owner)
@@ -245,64 +264,64 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
set waitfor = FALSE
to_chat(owner, "<span class='small boldannounce'>run -o -a 'selfdestruct'</span>")
sleep(5)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='small boldannounce'>Running executable 'selfdestruct'...</span>")
sleep(rand(10, 30))
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
owner.playsound_local(owner, 'sound/misc/bloblarm.ogg', 50, 0)
to_chat(owner, "<span class='userdanger'>!!! UNAUTHORIZED SELF-DESTRUCT ACCESS !!!</span>")
to_chat(owner, "<span class='boldannounce'>This is a class-3 security violation. This incident will be reported to Central Command.</span>")
for(var/i in 1 to 3)
sleep(20)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldannounce'>Sending security report to Central Command.....[rand(0, 9) + (rand(20, 30) * i)]%</span>")
sleep(3)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='small boldannounce'>auth 'akjv9c88asdf12nb' ******************</span>")
owner.playsound_local(owner, 'sound/items/timer.ogg', 50, 0)
sleep(30)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldnotice'>Credentials accepted. Welcome, akjv9c88asdf12nb.</span>")
owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0)
sleep(5)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldnotice'>Arm self-destruct device? (Y/N)</span>")
owner.playsound_local(owner, 'sound/misc/compiler-stage1.ogg', 50, 0)
sleep(20)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='small boldannounce'>Y</span>")
sleep(15)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldnotice'>Confirm arming of self-destruct device? (Y/N)</span>")
owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0)
sleep(10)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='small boldannounce'>Y</span>")
sleep(rand(15, 25))
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldnotice'>Please repeat password to confirm.</span>")
owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0)
sleep(14)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='small boldannounce'>******************</span>")
sleep(40)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "<span class='boldnotice'>Credentials accepted. Transmitting arming signal...</span>")
owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0)
sleep(30)
if(!owner || QDELETED(owner))
if(QDELETED(owner) || owner.stat == DEAD)
return
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf")
set_security_level("delta")
@@ -724,9 +743,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/blackout
name = "Blackout"
desc = "Overloads lights across the station."
desc = "Overloads random lights across the station."
button_icon_state = "blackout"
uses = 3
auto_use_uses = FALSE
/datum/action/innate/ai/blackout/Activate()
for(var/obj/machinery/power/apc/apc in GLOB.apcs_list)
@@ -736,6 +756,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
apc.overload++
to_chat(owner, "<span class='notice'>Overcurrent applied to the powernet.</span>")
owner.playsound_local(owner, "sparks", 50, 0)
adjust_uses(-1)
//Disable Emergency Lights
@@ -784,11 +805,6 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
auto_use_uses = FALSE
cooldown_period = 30
/datum/action/innate/ai/reactivate_cameras/New()
..()
desc = "[desc] There are 30 reactivations remaining."
button.desc = desc
/datum/action/innate/ai/reactivate_cameras/Activate()
var/fixed_cameras = 0
for(var/V in GLOB.cameranet.cameras)
@@ -803,8 +819,6 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
to_chat(owner, "<span class='notice'>Diagnostic complete! Cameras reactivated: <b>[fixed_cameras]</b>. Reactivations remaining: <b>[uses]</b>.</span>")
owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0)
adjust_uses(0, TRUE) //Checks the uses remaining
if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
desc = "[initial(desc)] There are [uses] reactivations remaining."
//Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision.
@@ -246,7 +246,7 @@
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/mob/living/carbon/human/target = null
var/list/mob/living/carbon/human/possible = list()
var/list/mob/living/carbon/human/possible
var/obj/item/voodoo_link = null
var/cooldown_time = 30 //3s
var/cooldown = 0
@@ -284,7 +284,7 @@
user.unset_machine()
/obj/item/voodoo/attack_self(mob/user)
if(!target && possible.len)
if(!target && length(possible))
target = input(user, "Select your victim!", "Voodoo") as null|anything in possible
return
@@ -324,12 +324,12 @@
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
LAZYINITLIST(possible)
possible = null
if(!voodoo_link)
return
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
possible |= H
LAZYOR(possible, H)
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
if(prob(50) || force)
@@ -163,7 +163,7 @@
/datum/spellbook_entry/timestop
name = "Time Stop"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
spell_type = /obj/effect/proc_holder/spell/aoe_turf/timestop
category = "Defensive"
/datum/spellbook_entry/smoke
+1 -1
View File
@@ -109,7 +109,7 @@
var/wizard_name_second = pick(GLOB.wizard_second)
var/randomname = "[wizard_name_first] [wizard_name_second]"
var/mob/living/wiz_mob = owner.current
var/newname = copytext(sanitize(input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN)
var/newname = reject_bad_name(stripped_input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname, MAX_NAME_LEN))
if (!newname)
newname = randomname
+1 -1
View File
@@ -46,7 +46,7 @@
return FALSE
switch(type)
if("feet")
if(!H.shoes)
if(!H.shoes || !(H.shoes.body_parts_covered & FEET))
affecting = H.get_bodypart(pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
H.Knockdown(60)
if(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND)
+3 -2
View File
@@ -25,12 +25,13 @@
listening = FALSE
languages = message_language
say("The recorded message is '[recorded]'.", language = message_language)
activate_cooldown = max(round(length(recorded) * 0.5), 3 SECONDS)
/obj/item/assembly/playback/activate()
if(recorded == "") // Why say anything when there isn't anything to say
. = ..()
if(!. || !recorded) // Why say anything when there isn't anything to say
return FALSE
say("[recorded]", language = languages) // Repeat the message in the language it was said in
return TRUE
/obj/item/assembly/playback/proc/record()
if(!secured || holder)
+38 -53
View File
@@ -11,7 +11,6 @@
var/code = DEFAULT_SIGNALER_CODE
var/frequency = FREQ_SIGNALER
var/delay = 0
var/datum/radio_frequency/radio_connection
var/suicider = null
var/hearing_range = 1
@@ -48,64 +47,50 @@
holder.update_icon()
return
/obj/item/assembly/signaler/ui_interact(mob/user, flag1)
. = ..()
if(is_secured(user))
var/t1 = "-------"
var/dat = {"
<TT>
<A href='byond://?src=[REF(src)];send=1'>Send Signal</A><BR>
<B>Frequency/Code</B> for signaler:<BR>
Frequency:
[format_frequency(src.frequency)]
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
Code:
[src.code]
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
[t1]
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
/obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
if(!is_secured(user))
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/ui_width = 280
var/ui_height = 132
ui = new(user, src, ui_key, "signaler", name, ui_width, ui_height, master_ui, state)
ui.open()
/obj/item/assembly/signaler/ui_data(mob/user)
var/list/data = list()
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
/obj/item/assembly/signaler/Topic(href, href_list)
..()
return data
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
/obj/item/assembly/signaler/ui_act(action, params)
if(..())
return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
. = TRUE
if("freq")
frequency = unformat_frequency(params["freq"])
frequency = sanitize_frequency(frequency, TRUE)
set_frequency(frequency)
. = TRUE
if("code")
code = text2num(params["code"])
code = round(code)
. = TRUE
if("reset")
if(params["reset"] == "freq")
frequency = initial(frequency)
else
code = initial(code)
. = TRUE
if (href_list["set"])
if(href_list["set"] == "freq")
var/new_freq = input(usr, "Input a new signalling frequency", "Remote Signaller Frequency", format_frequency(frequency)) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_freq = unformat_frequency(new_freq)
new_freq = sanitize_frequency(new_freq, TRUE)
set_frequency(new_freq)
if(href_list["set"] == "code")
var/new_code = input(usr, "Input a new signalling code", "Remote Signaller Code", code) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = CLAMP(new_code, 1, 100)
code = new_code
if(href_list["send"])
spawn( 0 )
signal()
if(usr)
attack_self(usr)
return
update_icon()
/obj/item/assembly/signaler/attackby(obj/item/W, mob/user, params)
if(issignaler(W))
var/obj/item/assembly/signaler/signaler2 = W
+13 -12
View File
@@ -207,7 +207,7 @@
pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0
if(name == initial(name))
name = "[get_area_name(src)] Air Alarm"
name = "[get_area_name(src, get_base_area = TRUE)] Air Alarm"
power_change()
set_frequency(frequency)
@@ -250,7 +250,7 @@
"danger_level" = danger_level,
)
var/area/A = get_area(src)
var/area/A = get_base_area(src)
data["atmos_alarm"] = A.atmosalm
data["fire_alarm"] = A.fire
@@ -386,9 +386,10 @@
send_signal(device_id, list("checks" = text2num(params["val"])^2), usr)
. = TRUE
if("set_external_pressure", "set_internal_pressure")
var/area/A = get_area(src)
var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null
if(!isnull(target) && !..())
var/target = params["value"]
if(!isnull(target))
send_signal(device_id, list("[action]" = target), usr)
. = TRUE
if("reset_external_pressure")
@@ -420,12 +421,12 @@
apply_mode()
. = TRUE
if("alarm")
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if(A.atmosalert(2, src))
post_alert(2)
. = TRUE
if("reset")
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if(A.atmosalert(0, src))
post_alert(0)
. = TRUE
@@ -456,7 +457,7 @@
return 0
/obj/machinery/airalarm/proc/refresh_all()
var/area/A = get_area(src)
var/area/A = get_base_area(src)
for(var/id_tag in A.air_vent_names)
var/list/I = A.air_vent_info[id_tag]
if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
@@ -507,7 +508,7 @@
return "Flood"
/obj/machinery/airalarm/proc/apply_mode()
var/area/A = get_area(src)
var/area/A = get_base_area(src)
switch(mode)
if(AALARM_MODE_SCRUBBING)
for(var/device_id in A.air_scrub_names)
@@ -645,7 +646,7 @@
icon_state = "alarm1"
var/overlay_state = AALARM_OVERLAY_OFF
var/area/A = get_area(src)
var/area/A = get_base_area(src)
switch(max(danger_level, A.atmosalm))
if(0)
add_overlay(AALARM_OVERLAY_GREEN)
@@ -715,7 +716,7 @@
return
var/datum/signal/alert_signal = new(list(
"zone" = get_area_name(src),
"zone" = get_area_name(src, get_base_area = TRUE),
"type" = "Atmospheric"
))
if(alert_level==2)
@@ -728,7 +729,7 @@
frequency.post_signal(src, alert_signal, range = -1)
/obj/machinery/airalarm/proc/apply_danger_level()
var/area/A = get_area(src)
var/area/A = get_base_area(src)
var/new_area_danger_level = 0
for(var/obj/machinery/airalarm/AA in A)
@@ -5,6 +5,7 @@
icon_state = "relief_valve-t-map"
can_unwrench = TRUE
construction_type = /obj/item/pipe/binary
interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
var/opened = FALSE
var/open_pressure = ONE_ATMOSPHERE * 3
var/close_pressure = ONE_ATMOSPHERE
@@ -50,9 +51,11 @@
if(!is_operational())
return
var/datum/gas_mixture/air_contents = airs[1]
var/our_pressure = air_contents.return_pressure()
if(opened && our_pressure < close_pressure)
var/datum/gas_mixture/air_one = airs[1]
var/datum/gas_mixture/air_two = airs[2]
var/air_one_pressure = air_one.return_pressure()
var/our_pressure = abs(air_one_pressure - air_two.return_pressure())
if(opened && air_one_pressure < close_pressure)
close()
else if(!opened && our_pressure >= open_pressure)
open()
@@ -30,7 +30,7 @@
underlays.Cut()
var/turf/T = loc
if(level == 2 || !T.intact)
if(level == 2 || (istype(T) && !T.intact))
showpipe = TRUE
plane = GAME_PLANE
else
@@ -138,7 +138,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 195, master_ui, state)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 185, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
@@ -14,32 +14,22 @@
construction_type = /obj/item/pipe/trinary/flippable
pipe_state = "mixer"
ui_x = 370
ui_y = 165
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/components/trinary/mixer/examine(mob/user)
. = ..()
. += "<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>"
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>"
/obj/machinery/atmospherics/components/trinary/mixer/CtrlClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
on = !on
update_icon()
investigate_log("Mixer, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Mixer, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return ..()
return ..()
/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user)
. = ..()
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
target_pressure = MAX_OUTPUT_PRESSURE
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
investigate_log("Mixer, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Mixer, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return TRUE
update_icon()
return ..()
//node 3 is the outlet, nodes 1 & 2 are intakes
@@ -64,12 +54,6 @@
var/on_state = on && nodes[1] && nodes[2] && nodes[3] && is_operational()
icon_state = "mixer_[on_state ? "on" : "off"][flipped ? "_f" : ""]"
/obj/machinery/atmospherics/components/trinary/mixer/power_change()
var/old_stat = stat
..()
if(stat != old_stat)
update_icon()
/obj/machinery/atmospherics/components/trinary/mixer/New()
..()
var/datum/gas_mixture/air3 = airs[3]
@@ -81,8 +65,13 @@
if(!on || !(nodes[1] && nodes[2] && nodes[3]) && !is_operational())
return
//Get those gases, mah boiiii
var/datum/gas_mixture/air1 = airs[1]
var/datum/gas_mixture/air2 = airs[2]
if(!air1 || !air2)
return
var/datum/gas_mixture/air3 = airs[3]
var/output_starting_pressure = air3.return_pressure()
@@ -92,60 +81,57 @@
return
//Calculate necessary moles to transfer using PV=nRT
var/general_transfer = (target_pressure - output_starting_pressure) * air3.volume / R_IDEAL_GAS_EQUATION
var/pressure_delta = target_pressure - output_starting_pressure
var/transfer_moles1 = 0
var/transfer_moles2 = 0
if(air1.temperature > 0)
transfer_moles1 = (node1_concentration * pressure_delta) * air3.volume / (air1.temperature * R_IDEAL_GAS_EQUATION)
if(air2.temperature > 0)
transfer_moles2 = (node2_concentration * pressure_delta) * air3.volume / (air2.temperature * R_IDEAL_GAS_EQUATION)
var/transfer_moles1 = air1.temperature ? node1_concentration * general_transfer / air1.temperature : 0
var/transfer_moles2 = air2.temperature ? node2_concentration * general_transfer / air2.temperature : 0
var/air1_moles = air1.total_moles()
var/air2_moles = air2.total_moles()
if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2))
var/ratio = 0
if((transfer_moles1 > 0 ) && (transfer_moles2 > 0))
if(!node2_concentration)
if(air1.temperature <= 0)
return
transfer_moles1 = min(transfer_moles1, air1_moles)
transfer_moles2 = 0
else if(!node1_concentration)
if(air2.temperature <= 0)
return
transfer_moles2 = min(transfer_moles2, air2_moles)
transfer_moles1 = 0
else
if(air1.temperature <= 0 || air2.temperature <= 0)
return
if((transfer_moles2 <= 0) || (transfer_moles1 <= 0))
return
if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2))
var/ratio = 0
ratio = min(air1_moles / transfer_moles1, air2_moles / transfer_moles2)
if((transfer_moles2 == 0 ) && ( transfer_moles1 > 0))
ratio = air1_moles / transfer_moles1
if((transfer_moles1 == 0 ) && ( transfer_moles2 > 0))
ratio = air2_moles / transfer_moles2
transfer_moles1 *= ratio
transfer_moles2 *= ratio
transfer_moles1 *= ratio
transfer_moles2 *= ratio
//Actually transfer the gas
if(transfer_moles1 > 0)
if(transfer_moles1)
var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1)
air3.merge(removed1)
if(transfer_moles2 > 0)
var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2)
air3.merge(removed2)
if(transfer_moles1)
var/datum/pipeline/parent1 = parents[1]
parent1.update = TRUE
if(transfer_moles2)
var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2)
air3.merge(removed2)
var/datum/pipeline/parent2 = parents[2]
parent2.update = TRUE
var/datum/pipeline/parent3 = parents[3]
parent3.update = TRUE
return
/obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_mixer", name, 370, 165, master_ui, state)
ui = new(user, src, ui_key, "atmos_mixer", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/mixer/ui_data()
@@ -153,8 +139,8 @@
data["on"] = on
data["set_pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
data["node1_concentration"] = round(node1_concentration*100)
data["node2_concentration"] = round(node2_concentration*100)
data["node1_concentration"] = round(node1_concentration*100, 1)
data["node2_concentration"] = round(node2_concentration*100, 1)
return data
/obj/machinery/atmospherics/components/trinary/mixer/ui_act(action, params)
@@ -182,18 +168,19 @@
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
if("node1")
var/value = text2num(params["concentration"])
node1_concentration = max(0, min(1, node1_concentration + value))
node2_concentration = max(0, min(1, node2_concentration - value))
adjust_node1_value(value)
investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
if("node2")
var/value = text2num(params["concentration"])
node2_concentration = max(0, min(1, node2_concentration + value))
node1_concentration = max(0, min(1, node1_concentration - value))
adjust_node1_value(100 - value)
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
update_icon()
/obj/machinery/atmospherics/components/trinary/mixer/proc/adjust_node1_value(newValue)
node1_concentration = newValue / 100
node2_concentration = 1 - node1_concentration
/obj/machinery/atmospherics/components/trinary/mixer/can_unwrench(mob/user)
. = ..()
@@ -4,6 +4,7 @@
icon = 'icons/obj/atmospherics/components/relief_valve.dmi'
icon_state = "relief_valve-e-map"
can_unwrench = TRUE
interaction_flags_machine = INTERACT_MACHINE_OFFLINE | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE
var/opened = FALSE
var/open_pressure = ONE_ATMOSPHERE * 3
var/close_pressure = ONE_ATMOSPHERE
@@ -10,6 +10,8 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 30)
layer = OBJ_LAYER
circuit = /obj/item/circuitboard/machine/thermomachine
ui_x = 300
ui_y = 230
pipe_flags = PIPING_ONE_PER_TURF
@@ -126,7 +128,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "thermomachine", name, 400, 240, master_ui, state)
ui = new(user, src, ui_key, "thermomachine", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/thermomachine/ui_data(mob/user)
@@ -38,7 +38,7 @@
id_tag = assign_uid_vents()
/obj/machinery/atmospherics/components/unary/vent_pump/Destroy()
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if (A)
A.air_vent_names -= id_tag
A.air_vent_info -= id_tag
@@ -155,7 +155,7 @@
"sigtype" = "status"
))
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if(!A.air_vent_names[id_tag])
name = "\improper [A.name] vent pump #[A.air_vent_names.len + 1]"
A.air_vent_names[id_tag] = name
@@ -39,7 +39,7 @@
filter_types += gas_id2path(f)
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if (A)
A.air_scrub_names -= id_tag
A.air_scrub_info -= id_tag
@@ -112,7 +112,7 @@
"sigtype" = "status"
))
var/area/A = get_area(src)
var/area/A = get_base_area(src)
if(!A.air_scrub_names[id_tag])
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
A.air_scrub_names[id_tag] = name
@@ -1,6 +1,7 @@
//3-Way Manifold
/obj/machinery/atmospherics/pipe/heat_exchanging/manifold
icon_state = "manifold"
icon = 'icons/obj/atmospherics/pipes/he-manifold.dmi'
icon_state = "manifold-2"
name = "pipe manifold"
desc = "A manifold composed of regular pipes."
@@ -15,7 +16,7 @@
var/mutable_appearance/center
/obj/machinery/atmospherics/pipe/manifold/Initialize()
/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/Initialize()
icon_state = ""
center = mutable_appearance(icon, "manifold_center")
return ..()
@@ -84,14 +84,14 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_pump", name, 420, 415, master_ui, state)
ui = new(user, src, ui_key, "portable_pump", name, 300, 315, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/pump/ui_data()
var/data = list()
data["on"] = on
data["direction"] = direction
data["connected"] = connected_port ? 1 : 0
data["direction"] = direction == PUMP_IN ? TRUE : FALSE
data["connected"] = connected_port ? TRUE : FALSE
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["target_pressure"] = round(pump.target_pressure ? pump.target_pressure : 0)
data["default_pressure"] = round(PUMP_DEFAULT_PRESSURE)
@@ -102,6 +102,8 @@
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
else
data["holding"] = null
return data
/obj/machinery/portable_atmospherics/pump/ui_act(action, params)
@@ -67,7 +67,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 435, master_ui, state)
ui = new(user, src, ui_key, "portable_scrubber", name, 320, 335, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/scrubber/ui_data()
@@ -85,6 +85,8 @@
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
else
data["holding"] = null
return data
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
+26 -21
View File
@@ -7,8 +7,6 @@
#define AMMO_DROP_LIFETIME 300
#define CTF_REQUIRED_PLAYERS 4
/obj/item/twohanded/ctf
name = "banner"
icon = 'icons/obj/items_and_weapons.dmi'
@@ -210,7 +208,6 @@
toggle_all_ctf(user)
return
people_who_want_to_play |= user.ckey
var/num = people_who_want_to_play.len
var/remaining = CTF_REQUIRED_PLAYERS - num
@@ -267,6 +264,8 @@
M.key = new_team_member.key
M.faction += team
M.equipOutfit(ctf_gear)
M.dna.species.punchdamagehigh = 25
M.dna.species.punchdamagelow = 25
spawned_mobs += M
/obj/machinery/capture_the_flag/Topic(href, href_list)
@@ -371,6 +370,10 @@
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
@@ -378,11 +381,7 @@
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped()
. = ..()
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
/obj/item/ammo_box/magazine/m50/ctf
ammo_type = /obj/item/ammo_casing/a50/ctf
@@ -405,22 +404,14 @@
/obj/item/gun/ballistic/automatic/laser/ctf/dropped()
. = ..()
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/gun/ballistic/automatic/laser/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
/obj/item/ammo_box/magazine/recharge/ctf
ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
/obj/item/ammo_box/magazine/recharge/ctf/dropped()
. = ..()
addtimer(CALLBACK(src, .proc/floor_vanish), 1)
/obj/item/ammo_box/magazine/recharge/ctf/proc/floor_vanish()
if(isturf(loc))
qdel(src)
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
/obj/item/ammo_casing/caseless/laser/ctf
projectile_type = /obj/item/projectile/beam/ctf
@@ -438,9 +429,9 @@
. = FALSE
if(istype(target, /obj/structure/barricade/security/ctf))
. = TRUE
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/shielded/ctf))
if(isliving(target))
var/mob/living/H = target
if((RED_TEAM in H.faction) || (BLUE_TEAM in H.faction))
. = TRUE
// RED TEAM GUNS
@@ -473,6 +464,19 @@
icon_state = "bluelaser"
impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
// MELEE GANG
/obj/item/claymore/ctf
slot_flags = SLOT_BACK
/obj/item/claymore/ctf/pre_attack(atom/target, mob/user, params)
if(!is_ctf_target(target))
return FALSE
return ..()
/obj/item/claymore/ctf/dropped()
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
/datum/outfit/ctf
name = "CTF"
ears = /obj/item/radio/headset
@@ -486,6 +490,7 @@
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)
if(visualsOnly)
+21 -9
View File
@@ -13,7 +13,9 @@
var/death = TRUE //Kill the mob
var/roundstart = TRUE //fires on initialize
var/instant = FALSE //fires on New
var/flavour_text = "The mapper forgot to set this!"
var/short_desc = "The mapper forgot to set this!"
var/flavour_text = ""
var/important_info = ""
var/faction = null
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
var/random = FALSE //Don't set a name or gender, just go random
@@ -110,7 +112,12 @@
if(ckey)
M.ckey = ckey
if(show_flavour)
to_chat(M, "[flavour_text]")
var/output_message = "<span class='big bold'>[short_desc]</span>"
if(flavour_text != "")
output_message += "\n<span class='bold'>[flavour_text]</span>"
if(important_info != "")
output_message += "\n<span class='userdanger'>[important_info]</span>"
to_chat(M, output_message)
var/datum/mind/MM = M.mind
var/datum/antagonist/A
if(antagonist_type)
@@ -340,7 +347,7 @@
name = "sleeper"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
flavour_text = "<span class='big bold'>You are a space doctor!</span>"
short_desc = "You are a space doctor!"
assignedrole = "Space Doctor"
job_description = "Off-station Doctor"
@@ -397,7 +404,8 @@
name = "bartender sleeper"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
flavour_text = "<span class='big bold'>You are a space bartender!</span><b> Time to mix drinks and change lives. Smoking space drugs makes it easier to understand your patrons' odd dialect.</b>"
short_desc = "You are a space bartender!"
flavour_text = "Time to mix drinks and change lives. Smoking space drugs makes it easier to understand your patrons' odd dialect."
assignedrole = "Space Bartender"
id_job = "Bartender"
@@ -422,7 +430,8 @@
name = "beach bum sleeper"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
flavour_text = "<span class='big bold'>You're, like, totally a dudebro, bruh.</span><b> Ch'yea. You came here, like, on spring break, hopin' to pick up some bangin' hot chicks, y'knaw?</b>"
short_desc = "You're a spunky lifeguard!"
flavour_text = "It's up to you to make sure nobody drowns or gets eaten by sharks and stuff."
assignedrole = "Beach Bum"
/obj/effect/mob_spawn/human/beach/alive/lifeguard
@@ -511,7 +520,7 @@
name = "sleeper"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
flavour_text = "<span class='big bold'>You are a Nanotrasen Commander!</span>"
short_desc = "You are a Nanotrasen Commander!"
/obj/effect/mob_spawn/human/nanotrasensoldier/alive
death = FALSE
@@ -522,7 +531,7 @@
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
faction = "nanotrasenprivate"
flavour_text = "<span class='big bold'>You are a Nanotrasen Private Security Officer!</span>"
short_desc = "You are a Nanotrasen Private Security Officer!"
/////////////////Spooky Undead//////////////////////
@@ -539,7 +548,8 @@
job_description = "Skeleton"
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
flavour_text = "<span class='big bold'>By unknown powers, your skeletal remains have been reanimated!</span><b> Walk this mortal plain and terrorize all living adventurers who dare cross your path.</b>"
short_desc = "By unknown powers, your skeletal remains have been reanimated!"
flavour_text = "Walk this mortal plain and terrorize all living adventurers who dare cross your path."
assignedrole = "Skeleton"
/obj/effect/mob_spawn/human/zombie
@@ -554,7 +564,9 @@
job_description = "Zombie"
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
flavour_text = "<span class='big bold'>By unknown powers, your rotting remains have been resurrected!</span><b> Walk this mortal plain and terrorize all living adventurers who dare cross your path.</b>"
short_desc = "By unknown powers, your rotting remains have been resurrected!"
flavour_text = "Walk this mortal plain and terrorize all living adventurers who dare cross your path."
/obj/effect/mob_spawn/human/abductor
@@ -595,8 +595,9 @@
job_description = "Syndicate Snow Operative"
faction = ROLE_SYNDICATE
outfit = /datum/outfit/snowsyndie
flavour_text = "<span class='big bold'>You are a syndicate operative recently awoken from cryostasis in an underground outpost. Monitor Nanotrasen communications and record information. All intruders should be \
disposed of swiftly to assure no gathered information is stolen or lost. Try not to wander too far from the outpost as the caves can be a deadly place even for a trained operative such as yourself.</span>"
short_desc = "You are a syndicate operative recently awoken from cryostasis in an underground outpost."
flavour_text = "You are a syndicate operative recently awoken from cryostasis in an underground outpost. Monitor Nanotrasen communications and record information. All intruders should be \
disposed of swiftly to assure no gathered information is stolen or lost. Try not to wander too far from the outpost as the caves can be a deadly place even for a trained operative such as yourself."
/datum/outfit/snowsyndie
name = "Syndicate Snow Operative"
+1 -1
View File
@@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "[global.con
t = trim(t)
if (length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
else if (t[1] == "#")
continue
var/pos = findtext(t, " ")
-1
View File
@@ -64,4 +64,3 @@
description = "Nanotrasen has secured a contract in a reenactment of a famous movie, but we only have lethal energy based swords. Send us some convincing replicas so we save on medical costs."
reward = 1200
required_count = 3
wanted_types = list(/obj/item/toy/sword, /obj/item/toy/sword/cx)
+45 -35
View File
@@ -3,13 +3,20 @@
desc = "Used to order supplies, approve requests, and control the shuttle."
icon_screen = "supply"
circuit = /obj/item/circuitboard/computer/cargo
req_access = list(ACCESS_CARGO)
ui_x = 780
ui_y = 750
var/requestonly = FALSE
var/contraband = FALSE
var/self_paid = FALSE
var/safety_warning = "For safety reasons, the automated supply shuttle \
cannot transport live organisms, human remains, classified nuclear weaponry \
or homing beacons."
cannot transport live organisms, human remains, classified nuclear weaponry, \
homing beacons or machinery housing any form of artificial intelligence."
var/blockade_warning = "Bluespace instability detected. Shuttle movement impossible."
/// radio used by the console to send messages on supply channel
var/obj/item/radio/headset/radio
/// var that tracks message cooldown
var/message_cooldown
light_color = "#E2853D"//orange
@@ -18,11 +25,11 @@
desc = "Used to request supplies from cargo."
icon_screen = "request"
circuit = /obj/item/circuitboard/computer/cargo/request
req_access = list()
requestonly = TRUE
/obj/machinery/computer/cargo/Initialize()
. = ..()
radio = new /obj/item/radio/headset/headset_cargo(src)
var/obj/item/circuitboard/computer/cargo/board = circuit
contraband = board.contraband
if (board.obj_flags & EMAGGED)
@@ -30,6 +37,10 @@
else
obj_flags &= ~EMAGGED
/obj/machinery/computer/cargo/Destroy()
QDEL_NULL(radio)
..()
/obj/machinery/computer/cargo/proc/get_export_categories()
. = EXPORT_CARGO
if(contraband)
@@ -38,11 +49,11 @@
. |= EXPORT_EMAG
/obj/machinery/computer/cargo/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
user.visible_message("<span class='warning'>[user] swipes a suspicious card through [src]!</span>",
"<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
if(user)
user.visible_message("<span class='warning'>[user] swipes a suspicious card through [src]!</span>",
"<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
obj_flags |= EMAGGED
contraband = TRUE
@@ -51,23 +62,21 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.contraband = TRUE
board.obj_flags |= EMAGGED
req_access = list()
return TRUE
update_static_data(user)
/obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cargo", name, 1000, 800, master_ui, state)
ui = new(user, src, ui_key, "cargo", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/cargo/ui_data()
var/list/data = list()
data["requestonly"] = requestonly
data["location"] = SSshuttle.supply.getStatusText()
data["points"] = SSshuttle.points
data["away"] = SSshuttle.supply.getDockedId() == "supply_away"
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
data["points"] = SSshuttle.points
data["loan"] = !!SSshuttle.shuttle_loan
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
var/message = "Remember to stamp and send back the supply manifests."
@@ -76,29 +85,13 @@
if(SSshuttle.supplyBlocked)
message = blockade_warning
data["message"] = message
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
if(!data["supplies"][P.group])
data["supplies"][P.group] = list(
"name" = P.group,
"packs" = list()
)
if((P.hidden && !(obj_flags & EMAGGED)) || (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.DropPodOnly)
continue
data["supplies"][P.group]["packs"] += list(list(
"name" = P.name,
"cost" = P.cost,
"id" = pack,
"desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name.
))
data["cart"] = list()
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
data["cart"] += list(list(
"object" = SO.pack.name,
"cost" = SO.pack.cost,
"id" = SO.id
"id" = SO.id,
"orderer" = SO.orderer,
))
data["requests"] = list()
@@ -113,14 +106,31 @@
return data
/obj/machinery/computer/cargo/ui_static_data(mob/user)
var/list/data = list()
data["requestonly"] = requestonly
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
if(!data["supplies"][P.group])
data["supplies"][P.group] = list(
"name" = P.group,
"packs" = list()
)
if((P.hidden && !(obj_flags & EMAGGED)) || (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.DropPodOnly)
continue
data["supplies"][P.group]["packs"] += list(list(
"name" = P.name,
"cost" = P.cost,
"id" = pack,
"desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
"access" = P.access
))
return data
/obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui)
if(..())
return
if(!allowed(usr))
to_chat(usr, "<span class='notice'>Access denied.</span>")
return
if(action != "add" && requestonly)
return
switch(action)
if("send")
if(!SSshuttle.supply.canMove())
+4 -5
View File
@@ -229,12 +229,12 @@
/datum/export/gear/magboots
cost = 50
unit_name = "magboots"
export_types = list(/obj/item/clothing/shoes/magboots, /obj/item/clothing/shoes/magboots/atmos)
export_types = list(/obj/item/clothing/shoes/magboots)
/datum/export/gear/nosellboots
cost = -5000 //We DONT want scew antags
unit_name = "error shipment stolen"
export_types = list(/obj/item/clothing/shoes/magboots/advance, /obj/item/clothing/shoes/magboots/deathsquad)
export_types = list(/obj/item/clothing/shoes/magboots/advance)
/datum/export/gear/syndamagboots
cost = 250
@@ -279,7 +279,7 @@
/datum/export/gear/magicboots //Magic as in Antag - Wiz/Cults
cost = 450
unit_name = "magic shoes"
export_types = list(/obj/item/clothing/shoes/sandal/marisa, /obj/item/clothing/shoes/sandal/magic, /obj/item/clothing/shoes/cult, /obj/item/clothing/shoes/clockwork, /obj/item/clothing/shoes/clown_shoes/taeclowndo, /obj/item/clothing/shoes/sandal/slippers)
export_types = list(/obj/item/clothing/shoes/sandal/marisa, /obj/item/clothing/shoes/sandal/magic, /obj/item/clothing/shoes/cult, /obj/item/clothing/shoes/clockwork, /obj/item/clothing/shoes/clown_shoes/taeclowndo)
include_subtypes = TRUE
//Headsets/Ears
@@ -585,8 +585,7 @@ datum/export/gear/glasses //glasses are not worth selling
export_types = list(/obj/item/clothing/under/scratch, /obj/item/clothing/under/sl_suit, /obj/item/clothing/under/rank/vice, /obj/item/clothing/under/suit_jacket, \
/obj/item/clothing/under/burial, /obj/item/clothing/under/skirt/black, /obj/item/clothing/under/captainparade, /obj/item/clothing/under/hosparademale, \
/obj/item/clothing/under/hosparadefem, /obj/item/clothing/under/assistantformal, /obj/item/clothing/under/stripeddress, /obj/item/clothing/under/redeveninggown, \
/obj/item/clothing/under/plaid_skirt, /obj/item/clothing/under/geisha, /obj/item/clothing/under/trek, /obj/item/clothing/under/wedding, /obj/item/clothing/under/aviatoruniform,\
/obj/item/clothing/under/mega, /obj/item/clothing/under/cia, /obj/item/clothing/under/casualwear, /obj/item/clothing/under/rank)
/obj/item/clothing/under/plaid_skirt, /obj/item/clothing/under/geisha, /obj/item/clothing/under/trek, /obj/item/clothing/under/rank)
include_subtypes = TRUE
/datum/export/gear/armored_jumpsuit
+34 -3
View File
@@ -92,11 +92,42 @@
export_types = list(/obj/item/stock_parts/cell/bluespace)
/datum/export/cellyellow
cost = 40
cost = 200
unit_name = "slime power cell"
export_types = list(/obj/item/stock_parts/cell/high/slime)
/datum/export/cellyellowhyper
cost = 120 //Takes a lot to make and is really good
cost = 1200 //Takes a lot to make and is really good
unit_name = "hyper slime power cell"
export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged)
export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged)
//Glass working stuff
/datum/export/glasswork_dish
cost = 300
unit_name = "small glass dish"
export_types = list(/obj/item/reagent_containers/glass/beaker/glass_dish)
include_subtypes = FALSE
/datum/export/glasswork_lens
cost = 1800
unit_name = "small glass lens"
export_types = list(/obj/item/lens)
/datum/export/glasswork_spouty
cost = 1200
unit_name = "flask with spout"
export_types = list(/obj/item/reagent_containers/glass/beaker/flask/spouty)
include_subtypes = FALSE
/datum/export/glasswork_smallflask
cost = 600
unit_name = "small flask"
export_types = list(/obj/item/reagent_containers/glass/beaker/flask)
include_subtypes = FALSE
/datum/export/glasswork_largeflask
cost = 1000
unit_name = "large flask"
export_types = list(/obj/item/reagent_containers/glass/beaker/flask/large)
include_subtypes = FALSE
+1 -1
View File
@@ -342,7 +342,7 @@
/datum/export/weapon/real_toolbox
cost = 600
unit_name = "golden toolbox"
export_types = list(/obj/item/storage/toolbox/gold_real)
export_types = list(/obj/item/storage/toolbox/plastitanium/gold_real)
/datum/export/weapon/melee
cost = 50
+1 -1
View File
@@ -90,7 +90,7 @@
/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cargo_express", name, 1000, 800, master_ui, state)
ui = new(user, src, ui_key, "cargo_express", name, 600, 700, master_ui, state)
ui.open()
/obj/machinery/computer/cargo/express/ui_data(mob/user)
+1 -1
View File
@@ -226,7 +226,7 @@
crate_name = "swat taser crate"
/datum/supply_pack/security/armory/woodstock
name = "Classic WoodStock Shotguns Crate"
name = "WoodStock Classic Shotguns Crate"
desc = "Contains three rustic, pumpaction shotguns. Requires Armory access to open."
cost = 3000
contains = list(/obj/item/gun/ballistic/shotgun,
+87 -155
View File
@@ -3,12 +3,18 @@
// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
// cost = 700- Minimum cost, or infinite points are possible.
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Costumes & Toys /////////////////////////////////
////////////////////////////////// Toys //////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/costumes_toys
group = "Costumes & Toys"
/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C)
var/list/L = contains.Copy()
for(var/i in 1 to num_contained)
var/item = pick_n_take(L)
new item(C)
/datum/supply_pack/costumes_toys/randomised
name = "Collectable Hats Crate"
desc = "Flaunt your status with three unique, highly-collectable hats!"
@@ -92,40 +98,6 @@
/obj/item/ammo_box/magazine/toy/pistol)
crate_name = "foam force crate"
/datum/supply_pack/costumes_toys/formalwear
name = "Formalwear Crate"
desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing."
cost = 4750 //Lots of fancy clothing that can be sold back!
contains = list(/obj/item/clothing/under/blacktango,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/lawyer/bluesuit,
/obj/item/clothing/suit/toggle/lawyer,
/obj/item/clothing/under/lawyer/purpsuit,
/obj/item/clothing/suit/toggle/lawyer/purple,
/obj/item/clothing/under/lawyer/blacksuit,
/obj/item/clothing/suit/toggle/lawyer/black,
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/neck/tie/blue,
/obj/item/clothing/neck/tie/red,
/obj/item/clothing/neck/tie/black,
/obj/item/clothing/head/bowler,
/obj/item/clothing/head/fedora,
/obj/item/clothing/head/flatcap,
/obj/item/clothing/head/beret,
/obj/item/clothing/head/that,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/under/suit_jacket/charcoal,
/obj/item/clothing/under/suit_jacket/navy,
/obj/item/clothing/under/suit_jacket/burgundy,
/obj/item/clothing/under/suit_jacket/checkered,
/obj/item/clothing/under/suit_jacket/tan,
/obj/item/lipstick/random)
crate_name = "formalwear crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/clownpin
name = "Hilarious Firing Pin Crate"
desc = "I uh... I'm not really sure what this does. Wanna buy it?"
@@ -167,47 +139,6 @@
contains = list(/obj/item/storage/box/lasertagpins)
crate_name = "laser tag crate"
/datum/supply_pack/costumes_toys/costume_original
name = "Original Costume Crate"
desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!"
cost = 1750
contains = list(/obj/item/clothing/head/snowman,
/obj/item/clothing/suit/snowman,
/obj/item/clothing/head/chicken,
/obj/item/clothing/suit/chickensuit,
/obj/item/clothing/mask/gas/monkeymask,
/obj/item/clothing/suit/monkeysuit,
/obj/item/clothing/head/cardborg,
/obj/item/clothing/suit/cardborg,
/obj/item/clothing/head/xenos,
/obj/item/clothing/suit/xenos,
/obj/item/clothing/suit/hooded/ian_costume,
/obj/item/clothing/suit/hooded/carp_costume,
/obj/item/clothing/suit/hooded/bee_costume)
crate_name = "original costume crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/costume
name = "Standard Costume Crate"
desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing."
cost = 1300
access = ACCESS_THEATRE
contains = list(/obj/item/storage/backpack/clown,
/obj/item/clothing/shoes/clown_shoes,
/obj/item/clothing/mask/gas/clown_hat,
/obj/item/clothing/under/rank/clown,
/obj/item/bikehorn,
/obj/item/clothing/under/rank/mime,
/obj/item/clothing/shoes/sneakers/black,
/obj/item/clothing/gloves/color/white,
/obj/item/clothing/mask/gas/mime,
/obj/item/clothing/head/beret,
/obj/item/clothing/suit/suspenders,
/obj/item/reagent_containers/food/drinks/bottle/bottleofnothing,
/obj/item/storage/backpack/mime)
crate_name = "standard costume crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/randomised/toys
name = "Toy Crate"
desc = "Who cares about pride and accomplishment? Skip the gaming and get straight to the sweet rewards with this product! Contains five random toys. Warranty void if used to prank research directors."
@@ -278,6 +209,86 @@
crate_name = "plushie crate"
crate_type = /obj/structure/closet/crate/wooden
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Costumes //////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/costumes_toys/formalwear
name = "Formalwear Crate"
desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing."
cost = 4750 //Lots of fancy clothing that can be sold back!
contains = list(/obj/item/clothing/under/blacktango,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/lawyer/bluesuit,
/obj/item/clothing/suit/toggle/lawyer,
/obj/item/clothing/under/lawyer/purpsuit,
/obj/item/clothing/suit/toggle/lawyer/purple,
/obj/item/clothing/under/lawyer/blacksuit,
/obj/item/clothing/suit/toggle/lawyer/black,
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/neck/tie/blue,
/obj/item/clothing/neck/tie/red,
/obj/item/clothing/neck/tie/black,
/obj/item/clothing/head/bowler,
/obj/item/clothing/head/fedora,
/obj/item/clothing/head/flatcap,
/obj/item/clothing/head/beret,
/obj/item/clothing/head/that,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/under/suit_jacket/charcoal,
/obj/item/clothing/under/suit_jacket/navy,
/obj/item/clothing/under/suit_jacket/burgundy,
/obj/item/clothing/under/suit_jacket/checkered,
/obj/item/clothing/under/suit_jacket/tan,
/obj/item/lipstick/random)
crate_name = "formalwear crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/costume_original
name = "Original Costume Crate"
desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!"
cost = 1750
contains = list(/obj/item/clothing/head/snowman,
/obj/item/clothing/suit/snowman,
/obj/item/clothing/head/chicken,
/obj/item/clothing/suit/chickensuit,
/obj/item/clothing/mask/gas/monkeymask,
/obj/item/clothing/suit/monkeysuit,
/obj/item/clothing/head/cardborg,
/obj/item/clothing/suit/cardborg,
/obj/item/clothing/head/xenos,
/obj/item/clothing/suit/xenos,
/obj/item/clothing/suit/hooded/ian_costume,
/obj/item/clothing/suit/hooded/carp_costume,
/obj/item/clothing/suit/hooded/bee_costume)
crate_name = "original costume crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/costume
name = "Standard Costume Crate"
desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing."
cost = 1300
access = ACCESS_THEATRE
contains = list(/obj/item/storage/backpack/clown,
/obj/item/clothing/shoes/clown_shoes,
/obj/item/clothing/mask/gas/clown_hat,
/obj/item/clothing/under/rank/clown,
/obj/item/bikehorn,
/obj/item/clothing/under/rank/mime,
/obj/item/clothing/shoes/sneakers/black,
/obj/item/clothing/gloves/color/white,
/obj/item/clothing/mask/gas/mime,
/obj/item/clothing/head/beret,
/obj/item/clothing/suit/suspenders,
/obj/item/reagent_containers/food/drinks/bottle/bottleofnothing,
/obj/item/storage/backpack/mime)
crate_name = "standard costume crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/wizard
name = "Wizard Costume Crate"
desc = "Pretend to join the Wizard Federation with this full wizard outfit! Nanotrasen would like to remind its employees that actually joining the Wizard Federation is subject to termination of job and life."
@@ -288,82 +299,3 @@
/obj/item/clothing/head/wizard/fake)
crate_name = "wizard costume crate"
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C)
var/list/L = contains.Copy()
for(var/i in 1 to num_contained)
var/item = pick_n_take(L)
new item(C)
/datum/supply_pack/costumes_toys/wardrobes/autodrobe
name = "Autodrobe Supply Crate"
desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill."
cost = 1500
contains = list(/obj/item/vending_refill/autodrobe)
crate_name = "autodrobe supply crate"
/datum/supply_pack/costumes_toys/wardrobes/cargo
name = "Cargo Wardrobe Supply Crate"
desc = "This crate contains a refill for the CargoDrobe."
cost = 750
contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe)
crate_name = "cargo department supply crate"
/datum/supply_pack/costumes_toys/wardrobes/engineering
name = "Engineering Wardrobe Supply Crate"
desc = "This crate contains refills for the EngiDrobe and AtmosDrobe."
cost = 1500
contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe,
/obj/item/vending_refill/wardrobe/atmos_wardrobe)
crate_name = "engineering department wardrobe supply crate"
/datum/supply_pack/costumes_toys/wardrobes/general
name = "General Wardrobes Supply Crate"
desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe."
cost = 3750
contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe,
/obj/item/vending_refill/wardrobe/bar_wardrobe,
/obj/item/vending_refill/wardrobe/chef_wardrobe,
/obj/item/vending_refill/wardrobe/jani_wardrobe,
/obj/item/vending_refill/wardrobe/chap_wardrobe)
crate_name = "general wardrobes vendor refills"
/datum/supply_pack/costumes_toys/wardrobes/hydroponics
name = "Hydrobe Supply Crate"
desc = "This crate contains a refill for the Hydrobe."
cost = 750
contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe)
crate_name = "hydrobe supply crate"
/datum/supply_pack/costumes_toys/wardrobes/medical
name = "Medical Wardrobe Supply Crate"
desc = "This crate contains refills for the MediDrobe, ChemDrobe, GeneDrobe, and ViroDrobe."
cost = 3000
contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe,
/obj/item/vending_refill/wardrobe/chem_wardrobe,
/obj/item/vending_refill/wardrobe/gene_wardrobe,
/obj/item/vending_refill/wardrobe/viro_wardrobe)
crate_name = "medical department wardrobe supply crate"
/datum/supply_pack/costumes_toys/wardrobes/science
name = "Science Wardrobe Supply Crate"
desc = "This crate contains refills for the SciDrobe and RoboDrobe."
cost = 1500
contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe,
/obj/item/vending_refill/wardrobe/science_wardrobe)
crate_name = "science department wardrobe supply crate"
/datum/supply_pack/costumes_toys/wardrobes/security
name = "Security Wardrobe Supply Crate"
desc = "This crate contains refills for the SecDrobe and LawDrobe."
cost = 1500
contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe,
/obj/item/vending_refill/wardrobe/law_wardrobe)
crate_name = "security department supply crate"
/datum/supply_pack/costumes_toys/kinkmate
name = "Kinkmate construction kit"
cost = 2000
contraband = TRUE
contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate)
crate_name = "Kinkmate construction kit"
+19 -17
View File
@@ -11,11 +11,13 @@
/datum/supply_pack/emergency/vehicle
name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN
desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, two cans of spraypaint, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
cost = 2500
contraband = TRUE
contains = list(/obj/vehicle/ridden/atv,
/obj/item/key,
/obj/item/toy/crayon/spraycan,
/obj/item/toy/crayon/spraycan,
/obj/item/clothing/suit/jacket/leather/overcoat,
/obj/item/clothing/gloves/color/black,
/obj/item/clothing/head/soft,
@@ -126,21 +128,6 @@
crate_name = "emergency rcds"
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/emergency/soft_suit
name = "Emergency Space Suit"
desc = "Are there bombs going off left and right? Are there meteors shooting around the station? Well then! Here's two fragile space suits for emergencies. Comes with air and masks."
cost = 1200
contains = list(/obj/item/tank/internals/air,
/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/fragile,
/obj/item/clothing/suit/space/fragile,
/obj/item/clothing/head/helmet/space/fragile,
/obj/item/clothing/head/helmet/space/fragile)
crate_name = "emergency crate"
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/emergency/bomb
name = "Explosive Emergency Crate"
desc = "Science gone bonkers? Beeping behind the airlock? Buy now and be the hero the station des... I mean needs! (Time not included.)"
@@ -208,7 +195,7 @@
crate_name = "metal foam grenade crate"
/datum/supply_pack/emergency/mre
name = "MRE supply kit (emergency rations)"
name = "MRE Packs (Emergency Rations)"
desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank."
cost = 2000
contains = list(/obj/item/storage/box/mre/menu1/safe,
@@ -296,6 +283,21 @@
crate_name = "space suit crate"
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/emergency/soft_suit
name = "Space Suits (Fragile)"
desc = "Are there bombs going off left and right? Are there meteors shooting around the station? Well then! Here's two fragile space suits for emergencies. Comes with air and masks."
cost = 1200
contains = list(/obj/item/tank/internals/air,
/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/fragile,
/obj/item/clothing/suit/space/fragile,
/obj/item/clothing/head/helmet/space/fragile,
/obj/item/clothing/head/helmet/space/fragile)
crate_name = "emergency crate"
crate_type = /obj/structure/closet/crate/internals
/datum/supply_pack/emergency/spacejets
name = "Spare EVA Jetpacks"
desc = "Contains three EVA grade jectpaks. Requires EVA access to open."
+8
View File
@@ -149,6 +149,14 @@
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
/datum/supply_pack/engine/supermatter_spray
name = "Supermatter Spray Crate"
desc = "The single thing that can truly heal the supermatter."
cost = 2000
contains = list(/obj/item/supermatterspray)
crate_name = "supermatter shard crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engine/tesla_coils
name = "Tesla Coil Crate"
desc = "Whether it's high-voltage executions, creating research points, or just plain old power generation: This pack of four Tesla coils can do it all!"
+19 -1
View File
@@ -3,7 +3,7 @@
// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
// cost = 700- Minimum cost, or infinite points are possible.
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Engineering /////////////////////////////////////
///////////////////////////// Engineering ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/engineering
@@ -45,6 +45,7 @@
/obj/item/clothing/glasses/meson/engine,
/obj/item/clothing/glasses/meson/engine)
crate_name = "engineering gear crate"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engineering/engihardsuit
name = "Engineering Hardsuit"
@@ -55,6 +56,7 @@
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/engine)
crate_name = "engineering hardsuit"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engineering/atmoshardsuit
name = "Atmospherics Hardsuit"
@@ -114,6 +116,22 @@
crate_name = "PACMAN generator crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engineering/airpump
name = "Portable Air Pump Crate"
desc = "We all know you work in a high pressure workplace. Keep it that way with two additional air pumps!"
cost = 3000
contains = list(/obj/machinery/portable_atmospherics/pump,
/obj/machinery/portable_atmospherics/pump)
crate_name = "portable air pump crate"
/datum/supply_pack/engineering/airscrubber
name = "Portable Scrubber Crate"
desc = "Miasma got you down? Plasma in the vents? Freshen up with these two brand-new air scrubbers!"
cost = 3000
contains = list(/obj/machinery/portable_atmospherics/scrubber,
/obj/machinery/portable_atmospherics/scrubber)
crate_name = "portable scrubber crate"
/datum/supply_pack/engineering/power
name = "Power Cell Crate"
desc = "Looking for power overwhelming? Look no further. Contains three high-voltage power cells."
+7 -7
View File
@@ -69,6 +69,11 @@
contains = list(/obj/item/grown/log)
crate_name = "lumber crate"
/datum/supply_pack/materials/rawlumber/generate()
. = ..()
for(var/i in 1 to 49)
new /obj/item/grown/log(.)
/datum/supply_pack/materials/wood50
name = "50 Wood Planks"
desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
@@ -89,7 +94,7 @@
/datum/supply_pack/materials/rawcottonbulk
name = "Raw Cotton Crate (Bulk)"
desc = "We have so much of this stuff we need to get rid of it in -bulk- now. This crate contains 240 raw cotton sheets."
cost = 1300 // 100 net cost (per 40 cotton) , 20 x 20 = 400. 300 profit if turned into cloth sheets or more if turned to silk then 10 x 200 = 2000
cost = 1300 // 600 net cost 20 x 120 = 2400 profit if turned into cloth sheets or if turned into silk 200 x 60 = 12000
contains = list(/obj/item/stack/sheet/cotton/thirty,
/obj/item/stack/sheet/cotton/thirty,
/obj/item/stack/sheet/cotton/thirty,
@@ -102,13 +107,8 @@
crate_name = "bulk cotton crate"
crate_type = /obj/structure/closet/crate/hydroponics
/datum/supply_pack/critter/animal_feed/generate()
. = ..()
for(var/i in 1 to 49)
new /obj/item/grown/log(.)
/datum/supply_pack/materials/rcdammo
name = "Spare RDC ammo"
name = "Spare RCD ammo"
desc = "This crate contains sixteen RCD compressed matter packs, to help with any holes or projects people might be working on."
cost = 3750
contains = list(/obj/item/rcd_ammo,
+68 -64
View File
@@ -10,6 +10,10 @@
group = "Medical"
crate_type = /obj/structure/closet/crate/medical
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Equipment ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/medical/bodybags
name = "Bodybags"
desc = "For when the bodies hit the floor. Contains 4 boxes of bodybags."
@@ -20,24 +24,6 @@
/obj/item/storage/box/bodybags,)
crate_name = "bodybag crate"
/datum/supply_pack/medical/firstaidbruises
name = "Bruise Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing bruises and broken bones."
cost = 1000
contains = list(/obj/item/storage/firstaid/brute,
/obj/item/storage/firstaid/brute,
/obj/item/storage/firstaid/brute)
crate_name = "brute treatment kit crate"
/datum/supply_pack/medical/firstaidburns
name = "Burn Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing severe burns."
cost = 1000
contains = list(/obj/item/storage/firstaid/fire,
/obj/item/storage/firstaid/fire,
/obj/item/storage/firstaid/fire)
crate_name = "burn treatment kit crate"
/datum/supply_pack/medical/bloodpacks
name = "Blood Pack Variety Crate"
desc = "Contains nine different blood packs for reintroducing blood to patients, plus two universal synthetic blood packs."
@@ -86,16 +72,6 @@
/obj/item/defibrillator/loaded)
crate_name = "defibrillator crate"
/datum/supply_pack/medical/firstaid
name = "First Aid Kit Crate"
desc = "Contains four first aid kits for healing most types of wounds."
cost = 1000
contains = list(/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular)
crate_name = "first aid kit crate"
/datum/supply_pack/medical/iv_drip
name = "IV Drip Crate"
desc = "Contains a single IV drip stand for intravenous delivery."
@@ -103,17 +79,6 @@
contains = list(/obj/machinery/iv_drip)
crate_name = "iv drip crate"
/datum/supply_pack/science/adv_surgery_tools
name = "Med-Co Advanced surgery tools"
desc = "A full set of Med-Co advanced surgery tools! In addition to that it contains both a can of synthflesh and a can of sterilizine. Requires Surgery access to open."
cost = 5500
access = ACCESS_SURGERY
contains = list(/obj/item/storage/belt/medical/surgery_belt_adv,
/obj/item/reagent_containers/medspray/synthflesh,
/obj/item/reagent_containers/medspray/sterilizine)
crate_name = "medco newest surgery tools"
crate_type = /obj/structure/closet/crate/medical
/datum/supply_pack/medical/medicalhardsuit
name = "Medical Hardsuit"
desc = "Got people being spaced left and right? Hole in the same room as the dead body of Hos or cap? Fear not, now you can buy one medical hardsuit with a mask and air tank to save your fellow crewmembers. Requires medical access to open."
@@ -151,13 +116,57 @@
/obj/item/storage/pill_bottle/stimulant)
crate_name = "medical supplies crate"
/datum/supply_pack/medical/vending
name = "Medical Vending Crate"
desc = "Contains refills for medical vending machines."
cost = 2000
contains = list(/obj/item/vending_refill/medical,
/obj/item/vending_refill/wallmed)
crate_name = "medical vending crate"
/datum/supply_pack/medical/adv_surgery_tools
name = "Med-Co Advanced Surgery Tools"
desc = "A full set of Med-Co advanced surgery tools, this crate also comes with a spay of synth flesh as well as a can of . Requires Surgery access to open."
cost = 5500
access = ACCESS_SURGERY
contains = list(/obj/item/storage/belt/medical/surgery_belt_adv,
/obj/item/reagent_containers/medspray/synthflesh,
/obj/item/reagent_containers/medspray/sterilizine)
crate_name = "medco surgery tools"
crate_type = /obj/structure/closet/crate/medical
/datum/supply_pack/medical/surgery
name = "Surgical Supplies Crate"
desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
cost = 1300
contains = list(/obj/item/storage/backpack/duffelbag/med/surgery,
/obj/item/reagent_containers/medspray/sterilizine,
/obj/item/roller)
crate_name = "surgical supplies crate"
//////////////////////////////////////////////////////////////////////////////
///////////////////////////// Medical Kits ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/medical/firstaidbruises
name = "Bruise Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing bruises and broken bones."
cost = 1000
contains = list(/obj/item/storage/firstaid/brute,
/obj/item/storage/firstaid/brute,
/obj/item/storage/firstaid/brute)
crate_name = "brute treatment kit crate"
/datum/supply_pack/medical/firstaidburns
name = "Burn Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing severe burns."
cost = 1000
contains = list(/obj/item/storage/firstaid/fire,
/obj/item/storage/firstaid/fire,
/obj/item/storage/firstaid/fire)
crate_name = "burn treatment kit crate"
/datum/supply_pack/medical/firstaid
name = "First Aid Kit Crate"
desc = "Contains four first aid kits for healing most types of wounds."
cost = 1000
contains = list(/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular,
/obj/item/storage/firstaid/regular)
crate_name = "first aid kit crate"
/datum/supply_pack/medical/sprays
name = "Medical Sprays"
@@ -193,6 +202,15 @@
/obj/item/storage/firstaid/o2)
crate_name = "oxygen deprivation kit crate"
/datum/supply_pack/medical/firstaidtoxins
name = "Toxin Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins."
cost = 1000
contains = list(/obj/item/storage/firstaid/toxin,
/obj/item/storage/firstaid/toxin,
/obj/item/storage/firstaid/toxin)
crate_name = "toxin treatment kit crate"
/datum/supply_pack/medical/advrad
name = "Radiation Treatment Crate Deluxe"
desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pills, as well as a radiation treatment deluxe pill bottle!"
@@ -206,23 +224,9 @@
crate_name = "radiation protection crate"
crate_type = /obj/structure/closet/crate/radiation
/datum/supply_pack/medical/surgery
name = "Surgical Supplies Crate"
desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
cost = 1300
contains = list(/obj/item/storage/backpack/duffelbag/med/surgery,
/obj/item/reagent_containers/medspray/sterilizine,
/obj/item/roller)
crate_name = "surgical supplies crate"
/datum/supply_pack/medical/firstaidtoxins
name = "Toxin Treatment Kit Crate"
desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins."
cost = 1000
contains = list(/obj/item/storage/firstaid/toxin,
/obj/item/storage/firstaid/toxin,
/obj/item/storage/firstaid/toxin)
crate_name = "toxin treatment kit crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Virology ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/medical/virus
name = "Virus Crate"
@@ -266,4 +270,4 @@
/obj/item/storage/box/syringes,
/obj/item/storage/box/beakers)
crate_name = "virus containment unit crate"
crate_type = /obj/structure/closet/crate/secure/plasma
crate_type = /obj/structure/closet/crate/secure/plasma
+110 -76
View File
@@ -13,16 +13,6 @@
//////////////////// Paperwork and Writing Supplies //////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/misc/abandonedcrate
name = "Loot Box"
desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE."
contraband = TRUE
cost = 15000
contains = list(/obj/structure/closet/crate/secure/loot)
crate_name = "abandoned crate"
crate_type = /obj/structure/closet/crate/large
dangerous = TRUE
/datum/supply_pack/misc/artsupply
name = "Art Supplies"
desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
@@ -83,7 +73,7 @@
name = "Captain Pen"
desc = "A spare Captain fountain pen."
access = ACCESS_CAPTAIN
cost = 10000
cost = 5000
contains = list(/obj/item/pen/fountain/captain)
crate_name = "captain pen"
crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen
@@ -153,7 +143,7 @@
/obj/item/bedsheet/purple,
/obj/item/bedsheet/red,
/obj/item/bedsheet/yellow,
/obj/item/bedsheet/brown,
/obj/item/bedsheet/brown,
/obj/item/bedsheet/black,
/obj/item/bedsheet/rainbow)
crate_name = "colored bedsheet crate"
@@ -182,18 +172,6 @@
/obj/structure/piano/unanchored)
crate_type = /obj/structure/closet/crate/wooden
/datum/supply_pack/misc/cbtpack
name = "CBT Equipment"
desc = "(*!&@#CBT is a special term coined by high ranking syndicate operatives for a special form of information extraction. While the training required to use this shipment is highly classified, the distribution of it's contents are not. In addition to this crates unusual contents, we have added a bar of soap.#@*$"
hidden = TRUE
cost = 2400
contains = list(/mob/living/simple_animal/chicken,
/obj/item/toy/beach_ball/holoball,
/obj/item/melee/baton/cattleprod,
/obj/item/soap/syndie)
crate_name = "cbt crate"
crate_type = /obj/structure/closet/crate/large
/datum/supply_pack/misc/casinocrate
name = "Casino Crate"
desc = "Start up your own grand casino with this crate filled with slot machine and arcade boards!"
@@ -216,8 +194,8 @@
name = "Coin Crate"
desc = "Psssst, hey, you. Yes, you. I've heard that coins can do some special things on your station, give you access to some pretty cool stuff. Here's the deal, you give me some credits, and I give so some coins. Sound like a deal? I'll give you 10 for 10000 creds."
contraband = TRUE
cost = 10000
contains = list(/obj/item/coin/silver)
cost = 3000
contains = list(/obj/item/coin/silver) // 400 x 10 = 2 sheets of silver for 2300cr
crate_name = "coin crate"
crate_type = /obj/structure/closet/crate/large
@@ -226,10 +204,77 @@
for(var/i in 1 to 9)
new /obj/item/coin/silver(.)
/datum/supply_pack/misc/dueling_stam
name = "Dueling Pistols"
desc = "Resolve all your quarrels with some nonlethal fun."
cost = 2000
contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina)
crate_name = "dueling pistols"
/datum/supply_pack/misc/dueling_lethal
name = "Lethal Dueling Pistols"
desc = "Settle your differences the true spaceman way."
cost = 3000
contraband = TRUE
contains = list(/obj/item/storage/lockbox/dueling/hugbox,
/obj/item/storage/lockbox/dueling/hugbox,
/obj/item/storage/lockbox/dueling/hugbox)
crate_name = "dueling pistols (lethal)"
/datum/supply_pack/misc/dueling_death
name = "Elimination Dueling Pistols"
desc = "It's high noon."
cost = 5000
hidden = TRUE
contains = list(/obj/item/storage/lockbox/dueling)
crate_name = "dueling pistols (elimination)"
/datum/supply_pack/misc/dirtymags
name = "Dirty Magazines"
desc = "Get your mind out of the gutter operative, you have work to do. Three items per order. Possible Results: .357 Speedloaders, Kitchen Gun Mags, Stetchkin Mags."
hidden = TRUE
cost = 12000
var/num_contained = 3
contains = list(/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/m45/kitchengun,
/obj/item/ammo_box/magazine/m45/kitchengun)
crate_name = "crate"
/datum/supply_pack/misc/dirtymags/fill(obj/structure/closet/crate/C)
var/list/L = contains.Copy()
for(var/i in 1 to num_contained)
var/item = pick_n_take(L)
new item(C)
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Misc Supplies ///////////////////////////////
///////////////////////////////// Misc Supplies //////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/misc/candles
name = "Candle Crate"
desc = "Set up a romantic dinner or host a séance with these extra candles and crayons."
cost = 850
contains = list(/obj/item/storage/fancy/candle_box,
/obj/item/storage/fancy/candle_box,
/obj/item/storage/box/matches)
crate_name = "candle crate"
/datum/supply_pack/misc/diamondring
name = "Diamond Ring"
desc = "Show them your love is like a diamond: unbreakable and forever lasting. Shipped straight from child slave cartels in the space african mines."
cost = 10000
contains = list(/obj/item/storage/fancy/ringbox/diamond)
crate_name = "diamond ring crate"
/datum/supply_pack/misc/exoticfootwear
name = "Exotic Footwear Crate"
desc = "Popularised by lizards and exotic dancers, the footwear included in this shipment is sure to give your feet the breathing room they deserve. Sweet Kicks Inc. is not responsible for any damage, distress, or @r0u$a1 caused by this shipment."
@@ -246,13 +291,34 @@
/obj/item/clothing/shoes/kindleKicks)
crate_name = "footie crate"
/datum/supply_pack/misc/wrapping_paper
name = "Festive Wrapping Paper Crate"
desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, or the Clown's severed head? You can do all that, with this crate full of wrapping paper."
cost = 1000
contains = list(/obj/item/stack/wrapping_paper)
crate_type = /obj/structure/closet/crate/wooden
crate_name = "festive wrapping paper crate"
/datum/supply_pack/misc/funeral
name = "Funeral Supplies"
desc = "Mourn your dead properly buy sending them off with love filled notes, clean clothes, and a proper ceremony. Contains two candle packs, funeral garb, flowers, a paperbin , and crayons to help aid in religious rituals. Coffin included."
cost = 1200
contains = list(/obj/item/clothing/under/burial,
/obj/item/storage/fancy/candle_box,
/obj/item/storage/fancy/candle_box,
/obj/item/reagent_containers/food/snacks/grown/harebell,
/obj/item/reagent_containers/food/snacks/grown/harebell,
/obj/item/reagent_containers/food/snacks/grown/poppy/geranium,
/obj/item/reagent_containers/food/snacks/grown/poppy/geranium,
/obj/item/reagent_containers/food/snacks/grown/poppy/lily,
/obj/item/reagent_containers/food/snacks/grown/poppy/lily,
/obj/item/storage/crayons,
/obj/item/paper_bin
)
crate_name = "coffin"
crate_type = /obj/structure/closet/crate/coffin
/datum/supply_pack/misc/jewelry
name = "Jewelry Crate"
desc = "Bling out with this crate of jewelry. Includes gold necklace and a set of two rings."
cost = 5000
contains = list(/obj/item/clothing/neck/necklace/dope,
/obj/item/storage/fancy/ringbox,
/obj/item/storage/fancy/ringbox/silver
)
crate_name = "jewelry crate"
/datum/supply_pack/misc/jukebox
name = "Jukebox"
@@ -260,6 +326,16 @@
contains = list(/obj/machinery/jukebox)
crate_name = "Jukebox"
/datum/supply_pack/misc/abandonedcrate
name = "Loot Box"
desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE."
contraband = TRUE
cost = 15000
contains = list(/obj/structure/closet/crate/secure/loot)
crate_name = "abandoned crate"
crate_type = /obj/structure/closet/crate/large
dangerous = TRUE
/datum/supply_pack/misc/potted_plants
name = "Potted Plants Crate"
desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown."
@@ -284,25 +360,6 @@
/obj/item/clothing/suit/hooded/chaplain_hoodie)
crate_name = "religious supplies crate"
/datum/supply_pack/misc/funeral
name = "Funeral Supplies"
desc = "Mourn your dead properly buy sending them off with love filled notes, clean clothes, and a proper ceremony. Contains two candle packs, funeral garb, flowers, a paperbin , and crayons to help aid in religious rituals. Coffin included."
cost = 1200
contains = list(/obj/item/clothing/under/burial,
/obj/item/storage/fancy/candle_box,
/obj/item/storage/fancy/candle_box,
/obj/item/reagent_containers/food/snacks/grown/harebell,
/obj/item/reagent_containers/food/snacks/grown/harebell,
/obj/item/reagent_containers/food/snacks/grown/poppy/geranium,
/obj/item/reagent_containers/food/snacks/grown/poppy/geranium,
/obj/item/reagent_containers/food/snacks/grown/poppy/lily,
/obj/item/reagent_containers/food/snacks/grown/poppy/lily,
/obj/item/storage/crayons,
/obj/item/paper_bin
)
crate_name = "coffin"
crate_type = /obj/structure/closet/crate/coffin
/datum/supply_pack/misc/shower
name = "Shower Supplies"
desc = "Everyone needs a bit of R&R. Make sure you get can get yours by ordering this crate filled with towels, rubber duckies, and some soap!"
@@ -362,29 +419,6 @@
/obj/item/stack/tile/carpet/monochrome/fifty)
crate_name = "premium carpet crate"
/datum/supply_pack/misc/party
name = "Party Equipment"
desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, a drinking shaker, and a bottle of patron & goldschlager!"
cost = 2000
contains = list(/obj/item/storage/box/drinkingglasses,
/obj/item/reagent_containers/food/drinks/shaker,
/obj/item/reagent_containers/food/drinks/bottle/patron,
/obj/item/reagent_containers/food/drinks/bottle/goldschlager,
/obj/item/reagent_containers/food/drinks/ale,
/obj/item/reagent_containers/food/drinks/ale,
/obj/item/reagent_containers/food/drinks/beer,
/obj/item/reagent_containers/food/drinks/beer,
/obj/item/reagent_containers/food/drinks/beer,
/obj/item/reagent_containers/food/drinks/beer,
/obj/item/flashlight/glowstick,
/obj/item/flashlight/glowstick/red,
/obj/item/flashlight/glowstick/blue,
/obj/item/flashlight/glowstick/cyan,
/obj/item/flashlight/glowstick/orange,
/obj/item/flashlight/glowstick/yellow,
/obj/item/flashlight/glowstick/pink)
crate_name = "party equipment crate"
/datum/supply_pack/misc/noslipfloor
name = "High-traction Floor Tiles"
desc = "Make slipping a thing of the past with sixty industrial-grade anti-slip floortiles!"

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