"
- t += "O" //up-left
- t += "^" //up
- t += "O " //up-right
- t += "<"//left
- t += "R"//reset to 0
- t += "> "//right
- t += "O"//down-left
- t += "v"//down
- t += "O "//down-right
- t += " "
- t += "
"
+ emoji_table = collate.Join()
+
+ menu += " To use an emoji in a pda message, refer to the guide and add \":\" around the emoji. Your PDA supports the following emoji: "
+ menu += emoji_table
+
if (99) //Newscaster message permission error
menu = "
ERROR : NOT AUTHORIZED [host_pda.id ? "" : "- ID SLOT EMPTY"]
"
@@ -679,6 +700,11 @@ Code:
return
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
+ //emoji previews
+ if(href_list["emoji"])
+ var/parse = emoji_parse(":[href_list["emoji"]]:")
+ to_chat(usr, parse)
+
//Bot control section! Viciously ripped from radios for being laggy and terrible.
if(href_list["op"])
switch(href_list["op"])
diff --git a/code/game/objects/items/devices/compressionkit.dm b/code/game/objects/items/devices/compressionkit.dm
index 6e62c389c7..eebe4dc69b 100644
--- a/code/game/objects/items/devices/compressionkit.dm
+++ b/code/game/objects/items/devices/compressionkit.dm
@@ -46,7 +46,7 @@
var/list/organs = M.getorganszone("head") + M.getorganszone("eyes") + M.getorganszone("mouth")
for(var/internal_organ in organs)
var/obj/item/organ/I = internal_organ
- I.Remove(M)
+ I.Remove()
I.forceMove(T)
head.drop_limb()
qdel(head)
diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm
index ff58af2405..0fa557f666 100644
--- a/code/game/objects/items/devices/desynchronizer.dm
+++ b/code/game/objects/items/devices/desynchronizer.dm
@@ -14,6 +14,7 @@
var/last_use = 0
var/next_use = 0
var/obj/effect/abstract/sync_holder/sync_holder
+ var/resync_timer
/obj/item/desynchronizer/attack_self(mob/living/user)
if(world.time < next_use)
@@ -56,16 +57,20 @@
SEND_SIGNAL(AM, COMSIG_MOVABLE_SECLUDED_LOCATION)
last_use = world.time
icon_state = "desynchronizer-on"
- addtimer(CALLBACK(src, .proc/resync), duration)
+ resync_timer = addtimer(CALLBACK(src, .proc/resync), duration , TIMER_STOPPABLE)
/obj/item/desynchronizer/proc/resync()
new /obj/effect/temp_visual/desynchronizer(sync_holder.drop_location())
QDEL_NULL(sync_holder)
+ if(resync_timer)
+ deltimer(resync_timer)
+ resync_timer = null
icon_state = initial(icon_state)
next_use = world.time + (world.time - last_use) // Could be 2*world.time-last_use but that would just be confusing
/obj/item/desynchronizer/Destroy()
- resync()
+ if(sync_holder)
+ resync()
return ..()
/obj/effect/abstract/sync_holder
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index eff8f1b7dc..9a09be093d 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -73,8 +73,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
- ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
+ // Variable window height, depending on how many GPS units there are
+ // to show, clamped to relatively safe range.
+ var/gps_window_height = CLAMP(325 + GLOB.GPS_list.len * 14, 325, 700)
+ ui = new(user, src, ui_key, "gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
@@ -91,6 +93,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
+ data["currentArea"] = "[get_area_name(curr, TRUE)]"
+ data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
@@ -104,16 +108,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
- signal["area"] = get_area_name(G, TRUE)
- signal["coord"] = "[pos.x], [pos.y], [pos.z]"
+ signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
- var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
- if(!direction)
- direction = "CENTER"
- signal["degrees"] = "N/A"
- signal["direction"] = direction
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index cef75942a0..f28aacc46c 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -101,7 +101,7 @@
if(href_list["reset_radio_short"])
pai.unshort_radio()
if(href_list["setlaws"])
- var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1]) as message),1,MAX_MESSAGE_LEN)
+ var/newlaws = stripped_multiline_input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", MAX_MESSAGE_LEN)
if(newlaws && pai)
pai.add_supplied_law(0,newlaws)
if(href_list["toggle_holo"])
diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm
index d5cf6daabb..d499683fbc 100644
--- a/code/game/objects/items/devices/radio/electropack.dm
+++ b/code/game/objects/items/devices/radio/electropack.dm
@@ -61,7 +61,7 @@
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
return
-
+
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
@@ -127,7 +127,7 @@
/obj/item/electropack/ui_interact(mob/user)
if(!ishuman(user))
return
-
+
user.set_machine(src)
var/dat = {"
@@ -200,14 +200,14 @@ Code:
/obj/item/electropack/shockcollar/attackby(obj/item/W, mob/user, params) //moves it here because on_click is being bad
if(istype(W, /obj/item/pen))
- var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
+ var/t = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot", MAX_NAME_LEN)
if(t)
- tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
- name = "[initial(name)] - [tagname]"
+ tagname = t
+ name = "[initial(name)] - [t]"
else
return ..()
-/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
+/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
var/dat = {"
Frequency/Code for shock collar:
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 8c6666085e..e04501144e 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -26,6 +26,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
slot_flags = ITEM_SLOT_EARS
var/obj/item/encryptionkey/keyslot2 = null
dog_fashion = null
+ var/bowman = FALSE
/obj/item/radio/headset/suicide_act(mob/living/carbon/user)
user.visible_message("[user] begins putting \the [src]'s antenna up [user.p_their()] nose! It looks like [user.p_theyre()] trying to give [user.p_them()]self cancer!")
@@ -52,6 +53,11 @@ GLOBAL_LIST_INIT(channel_tokens, list(
else
. += "A small screen on the headset flashes, it's too small to read without holding or wearing the headset."
+/obj/item/radio/headset/ComponentInitialize()
+ . = ..()
+ if (bowman)
+ AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+
/obj/item/radio/headset/Initialize()
. = ..()
recalculateChannels()
@@ -81,10 +87,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs."
icon_state = "syndie_headset"
item_state = "syndie_headset"
-
-/obj/item/radio/headset/syndicate/alt/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+ bowman = TRUE
/obj/item/radio/headset/syndicate/alt/leader
name = "team leader headset"
@@ -112,10 +115,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "This is used by your elite security force. Protects ears from flashbangs."
icon_state = "sec_headset_alt"
item_state = "sec_headset_alt"
-
-/obj/item/radio/headset/headset_sec/alt/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+ bowman = TRUE
/obj/item/radio/headset/headset_eng
name = "engineering radio headset"
@@ -161,10 +161,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "The headset of the boss. Protects ears from flashbangs."
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
-
-/obj/item/radio/headset/heads/captain/alt/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+ bowman = TRUE
/obj/item/radio/headset/heads/rd
name = "\proper the research director's headset"
@@ -183,10 +180,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs."
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
-
-/obj/item/radio/headset/heads/hos/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+ bowman = TRUE
/obj/item/radio/headset/heads/ce
name = "\proper the chief engineer's headset"
@@ -258,10 +252,7 @@ GLOBAL_LIST_INIT(channel_tokens, list(
icon_state = "cent_headset_alt"
item_state = "cent_headset_alt"
keyslot = null
-
-/obj/item/radio/headset/headset_cent/alt/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
+ bowman = TRUE
/obj/item/radio/headset/ai
name = "\proper Integrated Subspace Transceiver "
@@ -273,7 +264,11 @@ GLOBAL_LIST_INIT(channel_tokens, list(
/obj/item/radio/headset/attackby(obj/item/W, mob/user, params)
user.set_machine(src)
-
+ if (istype(W,/obj/item/headsetupgrader))
+ if (!bowman)
+ to_chat(user,"You upgrade [src].")
+ bowmanize()
+ qdel(W)
if(istype(W, /obj/item/screwdriver))
if(keyslot || keyslot2)
for(var/ch_name in channels)
@@ -341,3 +336,24 @@ GLOBAL_LIST_INIT(channel_tokens, list(
use_command = !use_command
to_chat(user, "You toggle high-volume mode [use_command ? "on" : "off"].")
return TRUE
+
+/obj/item/radio/headset/proc/bowmanize()
+ cut_overlays()
+ var/icon/yeas = icon(icon,icon_state)
+ icon_state = "antenna_alt"
+ var/mutable_appearance/center = mutable_appearance(icon,"center_alt")
+ center.color = yeas.GetPixel(15,18)
+ var/mutable_appearance/centeralt = mutable_appearance(icon,"centeralt_alt")
+ centeralt.color = yeas.GetPixel(14,22)
+ var/mutable_appearance/centercenter = mutable_appearance(icon,"centercenter_alt")
+ centercenter.color = yeas.GetPixel(13,19)
+ var/mutable_appearance/centerpixel = mutable_appearance(icon,"centerpixel_alt")
+ centerpixel.color = yeas.GetPixel(13,21)
+ add_overlay(center)
+ add_overlay(centeralt)
+ add_overlay(centercenter)
+ add_overlay(centerpixel)
+ name = replacetext(name,"headset", "bowman headset")
+ desc = "[desc] Protects ears from flashbangs."
+ bowman = TRUE
+ AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 8ccd15e397..b87b7b11bd 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -112,7 +112,14 @@
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
+ var/ui_width = 360
+ var/ui_height = 106
+ if(subspace_transmission)
+ if(channels.len > 0)
+ ui_height += 6 + channels.len * 21
+ else
+ ui_height += 24
+ ui = new(user, src, ui_key, "radio", name, ui_width, ui_height, master_ui, state)
ui.open()
/obj/item/radio/ui_data(mob/user)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 801e4cc7c8..0a3fd98511 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -28,7 +28,7 @@ SLIME SCANNER
/obj/item/t_scanner/attack_self(mob/user)
on = !on
- icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"
+ icon_state = copytext_char(icon_state, 1, -1) + "[on]"
if(on)
START_PROCESSING(SSobj, src)
@@ -410,19 +410,17 @@ SLIME SCANNER
// Blood Level
if(M.has_dna())
var/mob/living/carbon/C = M
- var/blood_id = C.get_blood_id()
- if(blood_id)
+ var/blood_typepath = C.get_blood_id()
+ if(blood_typepath)
if(ishuman(C))
if(H.bleed_rate)
msg += "Subject is bleeding!\n"
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
var/blood_type = C.dna.blood_type
- if(blood_id != ("blood" || "jellyblood"))//special blood substance
- var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
+ if(!(blood_typepath in GLOB.blood_reagent_types))
+ var/datum/reagent/R = GLOB.chemical_reagents_list[blood_typepath]
if(R)
blood_type = R.name
- else
- blood_type = blood_id
if(C.scan_blood_volume() <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.scan_blood_volume() > (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "LOW blood level [blood_percent] %, [C.scan_blood_volume()] cl,type: [blood_type]\n"
else if(C.scan_blood_volume() <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index fc768cd38e..64e2830dd4 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -251,3 +251,9 @@ effective or pretty fucking useless.
else
GLOB.active_jammers -= src
update_icon()
+
+/obj/item/headsetupgrader
+ name = "headset upgrader"
+ desc = "A tool that can be used to upgrade a normal headset to be able to protect from flashbangs."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "headset_upgrade"
diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm
index b37c147357..c4a15a1871 100644
--- a/code/game/objects/items/eightball.dm
+++ b/code/game/objects/items/eightball.dm
@@ -54,7 +54,7 @@
to_chat(user, "[src] was shaken recently, it needs time to settle.")
return
- user.visible_message("[user] starts shaking [src].", "You start shaking [src].", "You hear shaking and sloshing.")
+ user.visible_message("[user] starts shaking [src].", "You start shaking [src].", "You hear shaking and sloshing.")
shaking = TRUE
@@ -95,16 +95,47 @@
// except it actually ASKS THE DEAD (wooooo)
/obj/item/toy/eightball/haunted
- shake_time = 150
- cooldown_time = 1800
+ shake_time = 30 SECONDS
+ cooldown_time = 3 MINUTES
flags_1 = HEAR_1
var/last_message
var/selected_message
- var/list/votes
+ //these kind of store the same thing but one is easier to work with.
+ var/list/votes = list()
+ var/list/voted = list()
+ var/static/list/haunted_answers = list(
+ "yes" = list(
+ "It is certain",
+ "It is decidedly so",
+ "Without a doubt",
+ "Yes definitely",
+ "You may rely on it",
+ "As I see it, yes",
+ "Most likely",
+ "Outlook good",
+ "Yes",
+ "Signs point to yes"
+ ),
+ "maybe" = list(
+ "Reply hazy try again",
+ "Ask again later",
+ "Better not tell you now",
+ "Cannot predict now",
+ "Concentrate and ask again"
+ ),
+ "no" = list(
+ "Don't count on it",
+ "My reply is no",
+ "My sources say no",
+ "Outlook not so good",
+ "Very doubtful"
+ )
+ )
/obj/item/toy/eightball/haunted/Initialize(mapload)
. = ..()
- votes = list()
+ for (var/answer in haunted_answers)
+ votes[answer] = 0
GLOB.poi_list |= src
/obj/item/toy/eightball/haunted/Destroy()
@@ -122,7 +153,7 @@
interact(user)
return ..()
-/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
+/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
. = ..()
last_message = raw_message
@@ -137,38 +168,31 @@
if(isobserver(usr))
interact(usr)
-/obj/item/toy/eightball/haunted/proc/get_vote_tallies()
- var/list/answers = list()
- for(var/ckey in votes)
- var/selected = votes[ckey]
- if(selected in answers)
- answers[selected]++
- else
- answers[selected] = 1
-
- return answers
-
-
/obj/item/toy/eightball/haunted/get_answer()
- if(!votes.len)
- return pick(possible_answers)
+ var/top_amount = 0
+ var/top_vote
- var/list/tallied_votes = get_vote_tallies()
+ for(var/vote in votes)
+ var/amount_of_votes = length(votes[vote])
+ if(amount_of_votes > top_amount)
+ top_vote = vote
+ top_amount = amount_of_votes
+ //If one option actually has votes and there's a tie, pick between them 50/50
+ else if(top_amount && amount_of_votes == top_amount && prob(50))
+ top_vote = vote
+ top_amount = amount_of_votes
- // I miss python sorting, then I wouldn't have to muck about with
- // all this
- var/most_popular_answer
- var/most_amount = 0
- // yes, if there is a tie, there is an arbitary decision
- // but we never said the spirit world was fair
- for(var/A in tallied_votes)
- var/amount = tallied_votes[A]
- if(amount > most_amount)
- most_popular_answer = A
+ if(isnull(top_vote))
+ top_vote = pick(votes)
- return most_popular_answer
+ for(var/vote in votes)
+ votes[vote] = 0
-/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.observer_state)
+ voted.Cut()
+
+ return top_vote
+
+/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -179,21 +203,13 @@
var/list/data = list()
data["shaking"] = shaking
data["question"] = selected_message
- var/list/tallied_votes = get_vote_tallies()
data["answers"] = list()
-
- for(var/pa in possible_answers)
+ for(var/pa in haunted_answers)
var/list/L = list()
L["answer"] = pa
- var/amount = 0
- if(pa in tallied_votes)
- amount = tallied_votes[pa]
- L["amount"] = amount
- var/selected = FALSE
- if(votes[user.ckey] == pa)
- selected = TRUE
- L["selected"] = selected
+ L["amount"] = votes[pa]
+ L["selected"] = voted[user.ckey]
data["answers"] += list(L)
return data
@@ -206,8 +222,11 @@
switch(action)
if("vote")
var/selected_answer = params["answer"]
- if(!(selected_answer in possible_answers))
+ if(!(selected_answer in haunted_answers))
+ return
+ if(user.ckey in voted)
return
else
- votes[user.ckey] = selected_answer
- . = TRUE
+ votes[selected_answer] += 1
+ voted[user.ckey] = selected_answer
+ . = TRUE
\ No newline at end of file
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index cb16b558d3..afdde02e32 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -177,7 +177,7 @@
/obj/item/grenade/chem_grenade/prime()
if(stage != READY)
- return
+ return FALSE
var/list/datum/reagents/reactants = list()
for(var/obj/item/reagent_containers/glass/G in beakers)
@@ -192,7 +192,7 @@
O.forceMove(drop_location())
beakers = list()
stage_change(EMPTY)
- return
+ return FALSE
if(nadeassembly)
var/mob/M = get_mob_by_ckey(assemblyattacher)
@@ -205,6 +205,7 @@
update_mob()
qdel(src)
+ return TRUE
//Large chem grenades accept slime cores and use the appropriately.
/obj/item/grenade/chem_grenade/large
@@ -219,7 +220,7 @@
/obj/item/grenade/chem_grenade/large/prime()
if(stage != READY)
- return
+ return FALSE
for(var/obj/item/slime_extract/S in beakers)
if(S.Uses)
@@ -237,7 +238,7 @@
else
S.forceMove(get_turf(src))
no_splash = TRUE
- ..()
+ return ..()
//I tried to just put it in the allowed_containers list but
//if you do that it must have reagents. If you're going to
@@ -288,7 +289,7 @@
/obj/item/grenade/chem_grenade/adv_release/prime()
if(stage != READY)
- return
+ return FALSE
var/total_volume = 0
for(var/obj/item/reagent_containers/RC in beakers)
@@ -296,7 +297,7 @@
if(!total_volume)
qdel(src)
qdel(nadeassembly)
- return
+ return FALSE
var/fraction = unit_spread/total_volume
var/datum/reagents/reactants = new(unit_spread)
reactants.my_atom = src
@@ -313,6 +314,7 @@
else
addtimer(CALLBACK(src, .proc/prime), det_time)
log_game("A grenade detonated at [AREACOORD(DT)]")
+ return TRUE
diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm
index 16a5e6d1d3..77b4b33a8c 100644
--- a/code/game/objects/items/grenades/grenade.dm
+++ b/code/game/objects/items/grenades/grenade.dm
@@ -34,12 +34,12 @@
/obj/item/grenade/proc/clown_check(mob/living/carbon/human/user)
var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY)
- if(clumsy && (clumsy_check == GRENADE_CLUMSY_FUMBLE))
- if(prob(50))
+ if(clumsy)
+ if(clumsy_check == GRENADE_CLUMSY_FUMBLE && prob(50))
to_chat(user, "Huh? How does this thing work?")
preprime(user, 5, FALSE)
return FALSE
- else if(!clumsy && (clumsy_check == GRENADE_NONCLUMSY_FUMBLE))
+ else if(clumsy_check == GRENADE_NONCLUMSY_FUMBLE && !(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)))
to_chat(user, "You pull the pin on [src]. Attached to it is a pink ribbon that says, \"HONK\"")
preprime(user, 5, FALSE)
return FALSE
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index f6f14554ed..8ce0f33307 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -310,6 +310,7 @@
trap_damage = 0
item_flags = DROPDEL
flags_1 = NONE
+ breakouttime = 50
/obj/item/restraints/legcuffs/beartrap/energy/New()
..()
diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm
index e92c9b2d2e..47cf6f4ba7 100644
--- a/code/game/objects/items/holosign_creator.dm
+++ b/code/game/objects/items/holosign_creator.dm
@@ -92,6 +92,14 @@
creation_time = 0
max_signs = 3
+/obj/item/holosign_creator/combifan
+ name = "ATMOS holo-combifan projector"
+ desc = "A holographic projector that creates holographic combi-fans that prevent changes in atmosphere and temperature conditions. Somehow."
+ icon_state = "signmaker_atmos"
+ holosign_type = /obj/structure/holosign/barrier/combifan
+ creation_time = 0
+ max_signs = 3
+
/obj/item/holosign_creator/medical
name = "\improper PENLITE barrier projector"
desc = "A holographic projector that creates PENLITE holobarriers. Useful during quarantines since they halt those with malicious diseases."
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 5367f3461c..45abd4fb49 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -72,20 +72,21 @@
display_names += list(initial(A.name) = A)
var/choice = input(M,"What holy armor kit would you like to order?","Holy Armor Theme") as null|anything in display_names
- if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || GLOB.holy_armor_type)
+ var/turf/T = get_turf(M)
+ if(!T || QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || GLOB.holy_armor_type)
return
var/index = display_names.Find(choice)
var/A = holy_armor_list[index]
GLOB.holy_armor_type = A
- var/holy_armor_box = new A
+ var/holy_armor_box = new A(T)
SSblackbox.record_feedback("tally", "chaplain_armor", 1, "[choice]")
if(holy_armor_box)
qdel(src)
- M.put_in_active_hand(holy_armor_box)///YOU COMPILED
+ M.put_in_hands(holy_armor_box)
/obj/item/storage/box/holy
name = "Templar Kit"
diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm
index 9837936e5f..ee169cc661 100644
--- a/code/game/objects/items/miscellaneous.dm
+++ b/code/game/objects/items/miscellaneous.dm
@@ -19,3 +19,11 @@
icon_state = "skub"
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("skubbed")
+
+/obj/item/supermatterspray
+ name = "supermatter spray"
+ desc = "A spray bottle containing some kind of magical spray to fix the SM. \"Do not inhale.\" is written on the side. Unless aimed at the supermatter, it does nothing."
+ icon = 'icons/obj/supermatter.dmi'
+ icon_state = "supermatterspray"
+ w_class = WEIGHT_CLASS_SMALL
+ var/usesleft = 2
\ No newline at end of file
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index c23622ad65..2e8005e631 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -1,12 +1,16 @@
/obj/item/shield
name = "shield"
+ icon = 'icons/obj/items_and_weapons.dmi'
block_chance = 50
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
+ var/transparent = FALSE // makes beam projectiles pass through the shield
+
+/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
+ return TRUE
/obj/item/shield/riot
name = "riot shield"
desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder."
- icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "riot"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
@@ -19,6 +23,19 @@
materials = list(MAT_GLASS=7500, MAT_METAL=1000)
attack_verb = list("shoved", "bashed")
var/cooldown = 0 //shield bash cooldown. based on world.time
+ transparent = TRUE
+ max_integrity = 75
+
+/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ if(transparent && (hitby.pass_flags & PASSGLASS))
+ return FALSE
+ if(attack_type == THROWN_PROJECTILE_ATTACK)
+ final_block_chance += 30
+ if(attack_type == LEAP_ATTACK)
+ final_block_chance = 100
+ . = ..()
+ if(.)
+ on_shield_block(owner, hitby, attack_text, damage, attack_type)
/obj/item/shield/riot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/melee/baton))
@@ -26,14 +43,40 @@
user.visible_message("[user] bashes [src] with [W]!")
playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
cooldown = world.time
+ else if(istype(W, /obj/item/stack/sheet/mineral/titanium))
+ if(obj_integrity >= max_integrity)
+ to_chat(user, "[src] is already in perfect condition.")
+ else
+ var/obj/item/stack/sheet/mineral/titanium/T = W
+ T.use(1)
+ obj_integrity = max_integrity
+ to_chat(user, "You repair [src] with [T].")
else
return ..()
-/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(attack_type == THROWN_PROJECTILE_ATTACK)
- final_block_chance += 30
- if(attack_type == LEAP_ATTACK)
- final_block_chance = 100
+/obj/item/shield/riot/examine(mob/user)
+ . = ..()
+ var/healthpercent = round((obj_integrity/max_integrity) * 100, 1)
+ switch(healthpercent)
+ if(50 to 99)
+ . += "It looks slightly damaged."
+ if(25 to 50)
+ . += "It appears heavily damaged."
+ if(0 to 25)
+ . += "It's falling apart!"
+
+/obj/item/shield/riot/proc/shatter(mob/living/carbon/human/owner)
+ playsound(owner, 'sound/effects/glassbr3.ogg', 100)
+ new /obj/item/shard((get_turf(src)))
+
+/obj/item/shield/riot/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
+ if(obj_integrity <= damage)
+ var/turf/T = get_turf(owner)
+ T.visible_message("[hitby] destroys [src]!")
+ shatter(owner)
+ qdel(src)
+ return FALSE
+ take_damage(damage)
return ..()
/obj/item/shield/riot/roman
@@ -43,11 +86,18 @@
item_state = "roman_shield"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
+ transparent = FALSE
+ max_integrity = 65
/obj/item/shield/riot/roman/fake
desc = "Bears an inscription on the inside: \"Romanes venio domus\". It appears to be a bit flimsy."
block_chance = 0
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ max_integrity = 30
+
+/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner)
+ playsound(owner, 'sound/effects/grillehit.ogg', 100)
+ new /obj/item/stack/sheet/metal(get_turf(src))
/obj/item/shield/riot/buckler
name = "wooden buckler"
@@ -59,11 +109,17 @@
materials = list()
resistance_flags = FLAMMABLE
block_chance = 30
+ transparent = FALSE
+ max_integrity = 55
+
+/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
+ playsound(owner, 'sound/effects/bang.ogg', 50)
+ new /obj/item/stack/sheet/mineral/wood(get_turf(src))
+
/obj/item/shield/energy
name = "energy combat shield"
desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere."
- icon = 'icons/obj/items_and_weapons.dmi'
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
@@ -91,7 +147,7 @@
/obj/item/shield/energy/attack_self(mob/living/carbon/human/user)
if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
- to_chat(user, "You beat yourself in the head with [src].")
+ to_chat(user, "You beat yourself in the head with [src]!")
user.take_bodypart_damage(5)
active = !active
icon_state = "[base_icon_state][active]"
@@ -101,21 +157,20 @@
throwforce = on_throwforce
throw_speed = on_throw_speed
w_class = WEIGHT_CLASS_BULKY
- playsound(user, 'sound/weapons/saberon.ogg', 35, 1)
+ playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE)
to_chat(user, "[src] is now active.")
else
force = initial(force)
throwforce = initial(throwforce)
throw_speed = initial(throw_speed)
w_class = WEIGHT_CLASS_TINY
- playsound(user, 'sound/weapons/saberoff.ogg', 35, 1)
+ playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE)
to_chat(user, "[src] can now be concealed.")
add_fingerprint(user)
/obj/item/shield/riot/tele
name = "telescopic shield"
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
- icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "teleriot0"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
@@ -135,7 +190,7 @@
/obj/item/shield/riot/tele/attack_self(mob/living/user)
active = !active
icon_state = "teleriot[active]"
- playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
+ playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
if(active)
force = 8
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index f6bff2f880..21de34faa1 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -10,7 +10,15 @@
*/
GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe("directional window", /obj/structure/window/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
- new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE) \
+ new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
+ null, \
+ new/datum/stack_recipe_list("glass working bases", list( \
+ new/datum/stack_recipe("chem dish", /obj/item/glasswork/glass_base/dish, 10), \
+ new/datum/stack_recipe("lens", /obj/item/glasswork/glass_base/glass_lens, 15), \
+ new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \
+ new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \
+ new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \
+ )), \
))
/obj/item/stack/sheet/glass
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index a80f0d5a3b..2bd7dd0d38 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -154,6 +154,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
+ new/datum/stack_recipe("crate", /obj/structure/closet/crate, 5, time = 90, one_per_turf = TRUE), \
null, \
new /datum/stack_recipe_list("airlock assemblies", list( \
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 6, time = 50, one_per_turf = 1, on_floor = 1), \
@@ -277,6 +278,9 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
recipes = GLOB.wood_recipes
return ..()
+/obj/item/stack/sheet/mineral/wood/twenty
+ amount = 20
+
/obj/item/stack/sheet/mineral/wood/fifty
amount = 50
@@ -306,6 +310,15 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \
recipes = GLOB.bamboo_recipes
return ..()
+/obj/item/stack/sheet/mineral/bamboo/ten
+ amount = 10
+
+/obj/item/stack/sheet/mineral/bamboo/twenty
+ amount = 20
+
+/obj/item/stack/sheet/mineral/bamboo/fifty
+ amount = 50
+
/*
* Cloth
*/
@@ -782,3 +795,4 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton/durathread
pull_effort = 70
loom_result = /obj/item/stack/sheet/durathread
+
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 324b40ac7f..36c4992e8f 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -399,11 +399,14 @@
. = ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
- blood_DNA = from.blood_DNA
- fingerprints = from.fingerprints
- fingerprintshidden = from.fingerprintshidden
- fingerprintslast = from.fingerprintslast
- //TODO bloody overlay
+ if(from.blood_DNA)
+ blood_DNA = from.blood_DNA.Copy()
+ if(from.fingerprints)
+ fingerprints = from.fingerprints.Copy()
+ if(from.fingerprintshidden)
+ fingerprintshidden = from.fingerprintshidden.Copy()
+ if(from.fingerprintslast)
+ fingerprintslast = from.fingerprintslast
/obj/item/stack/microwave_act(obj/machinery/microwave/M)
if(istype(M) && M.dirty < 100)
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 18acb5e14d..fa4e5a3886 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -233,39 +233,111 @@
turf_type = /turf/open/floor/carpet/royalblue
tableVariant = /obj/structure/table/wood/fancy/royalblue
+/obj/item/stack/tile/carpet/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/fifty
amount = 50
+/obj/item/stack/tile/carpet/black/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/black/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/black/fifty
amount = 50
+/obj/item/stack/tile/carpet/blackred/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/blackred/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/blackred/fifty
amount = 50
+/obj/item/stack/tile/carpet/monochrome/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/monochrome/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/monochrome/fifty
amount = 50
+/obj/item/stack/tile/carpet/blue/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/blue/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/blue/fifty
amount = 50
+/obj/item/stack/tile/carpet/cyan/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/cyan/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/cyan/fifty
amount = 50
+/obj/item/stack/tile/carpet/green/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/green/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/green/fifty
amount = 50
+/obj/item/stack/tile/carpet/orange/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/orange/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/orange/fifty
amount = 50
+/obj/item/stack/tile/carpet/purple/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/purple/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/purple/fifty
amount = 50
+/obj/item/stack/tile/carpet/red/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/red/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/red/fifty
amount = 50
+/obj/item/stack/tile/carpet/royalblack/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/royalblack/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/royalblack/fifty
amount = 50
+/obj/item/stack/tile/carpet/royalblue/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/royalblue/twenty
+ amount = 20
+
/obj/item/stack/tile/carpet/royalblue/fifty
amount = 50
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index d5aa43148c..daddc403b2 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -322,6 +322,26 @@
for(var/i in 1 to 5)
new /obj/item/grenade/empgrenade(src)
+/obj/item/storage/box/minibombs
+ name = "box of syndicate minibombs"
+ desc = "A box containing 2 highly explosive syndicate minibombs."
+ icon_state = "syndiebox"
+ illustration = "frag"
+
+/obj/item/storage/box/minibombs/PopulateContents()
+ new /obj/item/grenade/syndieminibomb(src)
+ new /obj/item/grenade/syndieminibomb(src)
+
+/obj/item/storage/box/bombananas
+ name = "box of bombananas"
+ desc = "A box containing 2 highly explosive bombananas. Discard peel at enemy after consumption."
+ icon_state = "syndiebox"
+ illustration = "frag"
+
+/obj/item/storage/box/bombananas/PopulateContents()
+ new /obj/item/reagent_containers/food/snacks/grown/banana/bombanana(src)
+ new /obj/item/reagent_containers/food/snacks/grown/banana/bombanana(src)
+
/obj/item/storage/box/trackimp
name = "boxed tracking implant kit"
desc = "Box full of scum-bag tracking utensils."
@@ -1267,4 +1287,4 @@
/obj/item/storage/box/marshmallow/PopulateContents()
for (var/i in 1 to 5)
- new /obj/item/reagent_containers/food/snacks/marshmallow(src)
\ No newline at end of file
+ new /obj/item/reagent_containers/food/snacks/marshmallow(src)
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index 78f306df6e..92e09022b2 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -12,6 +12,7 @@
* Cigarette Box
* Cigar Case
* Heart Shaped Box w/ Chocolates
+ * Ring Box
*/
/obj/item/storage/fancy
@@ -352,3 +353,33 @@
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 8
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/tinychocolate))
+
+/*
+ * Ring Box
+ */
+
+/obj/item/storage/fancy/ringbox
+ name = "ring box"
+ desc = "A tiny box covered in soft red felt made for holding rings."
+ icon = 'icons/obj/ring.dmi'
+ icon_state = "gold ringbox"
+ icon_type = "gold ring"
+ w_class = WEIGHT_CLASS_TINY
+ spawn_type = /obj/item/clothing/gloves/ring
+
+/obj/item/storage/fancy/ringbox/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.max_items = 1
+ STR.can_hold = typecacheof(list(/obj/item/clothing/gloves/ring))
+
+/obj/item/storage/fancy/ringbox/diamond
+ icon_state = "diamond ringbox"
+ icon_type = "diamond ring"
+ spawn_type = /obj/item/clothing/gloves/ring/diamond
+
+/obj/item/storage/fancy/ringbox/silver
+ icon_state = "silver ringbox"
+ icon_type = "silver ring"
+ spawn_type = /obj/item/clothing/gloves/ring/silver
+
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index 31efabf210..bfffe0fc60 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -35,7 +35,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/update_icon()
..()
cut_overlays()
- if(blood_DNA && blood_DNA.len)
+ if(length(blood_DNA))
add_blood_overlay()
if(has_latches)
var/icon/I = icon('icons/obj/storage.dmi', latches)
@@ -251,16 +251,12 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
-/obj/item/storage/toolbox/gold_real
+/obj/item/storage/toolbox/plastitanium/gold_real
name = "golden toolbox"
desc = "A larger then normal toolbox made of gold plated plastitanium."
icon_state = "gold"
item_state = "toolbox_gold"
has_latches = FALSE
- force = 16 // Less then a spear
- throwforce = 14
- throw_speed = 5
- throw_range = 10
/obj/item/storage/toolbox/gold_real/PopulateContents()
new /obj/item/screwdriver/nuke(src)
@@ -293,7 +289,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
desc = replacetext(desc, "robust", "safe")
desc = replacetext(desc, "heavier", "bouncier")
DISABLE_BITFIELD(flags_1, CONDUCT_1)
- materials = null
+ materials = typelist("materials", null)
damtype = STAMINA
force += 3 //to compensate the higher stamina K.O. threshold compared to actual health.
throwforce += 3
@@ -317,8 +313,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
flags_1 = null
materials = null
damtype = STAMINA
- force = 17
- throwforce = 17
+ force = 15
+ throwforce = 15
attack_verb = list("robusted", "bounced")
can_rubberify = FALSE //we are already the future.
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 35429c2f42..611870912c 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -343,7 +343,7 @@
new /obj/item/implanter/radio/syndicate(src)
/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
- new /obj/item/clothing/under/rank/centcom_officer(src)
+ new /obj/item/clothing/under/rank/centcom_officer/syndicate(src)
new /obj/item/clothing/shoes/sneakers/black(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/radio/headset/headset_cent/empty(src)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index 946eb1eb7b..c4457ea991 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -15,7 +15,7 @@
attack_verb = list("beaten")
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
- var/stunforce = 140
+ var/stunforce = 70
var/status = FALSE
var/obj/item/stock_parts/cell/cell
var/hitcost = 1000
@@ -188,8 +188,8 @@
stunpwr *= round(stuncharge/hitcost, 0.1)
- L.Knockdown(stunpwr)
- L.adjustStaminaLoss(stunpwr*0.1)//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
+ L.Knockdown(stunpwr, override_stamdmg = 0)
+ L.apply_damage(stunpwr*0.55, STAMINA, user.zone_selected)
L.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user)
@@ -274,7 +274,7 @@
w_class = WEIGHT_CLASS_BULKY
force = 3
throwforce = 5
- stunforce = 100
+ stunforce = 60
hitcost = 2000
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index f763fe87fc..7157103f14 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -33,6 +33,9 @@
H.update_internals_hud_icon(0)
else
if(!H.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
+ if(HAS_TRAIT(H, TRAIT_NO_INTERNALS))
+ to_chat(H, "Due to cumbersome equipment or anatomy, you are currently unable to use internals!")
+ return
var/obj/item/clothing/check
var/internals = FALSE
@@ -156,7 +159,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "tanks", name, 420, 200, master_ui, state)
+ ui = new(user, src, ui_key, "tanks", name, 400, 120, master_ui, state)
ui.open()
/obj/item/tank/ui_data(mob/user)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 92798528ae..8f5a6e8e0b 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1244,7 +1244,7 @@
/obj/item/toy/clockwork_watch/examine(mob/user)
. = ..()
- . += "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]"
+ . += "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]"
/*
* Toy Dagger
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index b9862c3423..fc9e138f4b 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -25,8 +25,8 @@
*/
/obj/item/twohanded
var/wielded = 0
- var/force_unwielded = 0
- var/force_wielded = 0
+ var/force_unwielded // default to null, the number force will be set to on unwield()
+ var/force_wielded // same as above but for wield()
var/wieldsound = null
var/unwieldsound = null
var/slowdown_wielded = 0
@@ -38,9 +38,9 @@
wielded = 0
if(!isnull(force_unwielded))
force = force_unwielded
- var/sf = findtext(name," (Wielded)")
+ var/sf = findtext(name, " (Wielded)", -10)//10 == length(" (Wielded)")
if(sf)
- name = copytext(name,1,sf)
+ name = copytext(name, 1, sf)
else //something wrong
name = "[initial(name)]"
update_icon()
@@ -73,7 +73,7 @@
to_chat(user, "You don't have enough intact hands.")
return
wielded = 1
- if(force_wielded)
+ if(!isnull(force_wielded))
force = force_wielded
name = "[name] (Wielded)"
update_icon()
@@ -347,7 +347,6 @@
icon_state = "dualsaber[item_color][wielded]"
else
icon_state = "dualsaber0"
-
clean_blood()
/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user)
@@ -738,7 +737,7 @@
on = !on
to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]")
force = on ? force_on : initial(force)
- throwforce = on ? force_on : initial(force)
+ throwforce = on ? force_on : force
icon_state = "chainsaw_[on ? "on" : "off"]"
var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index b7b25f0b5a..cd6cc5f520 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -312,23 +312,27 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
attack_verb = list("stubbed", "poked")
resistance_flags = FIRE_PROOF
var/extended = 0
+ var/extended_force = 20
+ var/extended_throwforce = 23
+ var/extended_icon_state = "switchblade_ext"
+ var/retracted_icon_state = "switchblade"
/obj/item/switchblade/attack_self(mob/user)
extended = !extended
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
if(extended)
- force = 20
+ force = extended_force
w_class = WEIGHT_CLASS_NORMAL
- throwforce = 23
- icon_state = "switchblade_ext"
+ throwforce = extended_throwforce
+ icon_state = extended_icon_state
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
else
- force = 3
+ force = initial(force)
w_class = WEIGHT_CLASS_SMALL
- throwforce = 5
- icon_state = "switchblade"
+ throwforce = initial(throwforce)
+ icon_state = retracted_icon_state
attack_verb = list("stubbed", "poked")
hitsound = 'sound/weapons/genhit.ogg'
sharpness = IS_BLUNT
@@ -337,6 +341,25 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS)
+/obj/item/switchblade/crafted
+ icon_state = "switchblade_ms"
+ desc = "A concealable spring-loaded knife."
+ force = 2
+ throwforce = 3
+ extended_force = 15
+ extended_throwforce = 18
+ extended_icon_state = "switchblade_ext_ms"
+ retracted_icon_state = "switchblade_ms"
+
+/obj/item/switchblade/crafted/attackby(obj/item/I, mob/user, params)
+ . = ..()
+ if(istype(I, /obj/item/stack/sheet/mineral/silver))
+ icon_state = extended ? "switchblade_ext_msf" : "switchblade_msf"
+ extended_icon_state = "switchblade_ext_msf"
+ retracted_icon_state = "switchblade_msf"
+ icon_state = "switchblade_msf"
+ to_chat(user, "You use part of the silver to improve your Switchblade. Stylish!")
+
/obj/item/phone
name = "red phone"
desc = "Should anything ever go wrong..."
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 5f3fc48eb7..45b9715b04 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -60,8 +60,8 @@
var/flagslist = splittext(set_obj_flags,";")
var/list/string_to_objflag = GLOB.bitfields["obj_flags"]
for (var/flag in flagslist)
- if (findtext(flag,"!",1,2))
- flag = copytext(flag,1-(length(flag))) // Get all but the initial !
+ if(flag[1] == "!")
+ flag = copytext(flag, length(flag[1]) + 1) // Get all but the initial !
obj_flags &= ~string_to_objflag[flag]
else
obj_flags |= string_to_objflag[flag]
@@ -178,7 +178,7 @@
machine = null
//called when the user unsets the machine.
-/atom/movable/proc/on_unset_machine(mob/user)
+/atom/proc/on_unset_machine(mob/user)
return
/mob/proc/set_machine(obj/O)
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index 5b9a764925..fcd1f80a4f 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -52,7 +52,7 @@
var/area/A = get_area(src)
if(!A.blob_allowed)
return FALSE
- if(!A.power_equip)
+ if(!A.powered(EQUIP))
return FALSE
if(!SSmapping.level_trait(T.z,ZTRAIT_STATION))
return FALSE
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 053512a256..b72a4b816e 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -305,7 +305,7 @@
/datum/barsign/meow_mix
name = "Meow Mix"
- icon = "meow_mix"
+ icon = "Meow Mix"
desc = "No, we don't serve catnip, officer!"
/datum/barsign/hiddensigns
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 9a095bf69d..daf15832fb 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -532,7 +532,7 @@
/obj/structure/closet/CtrlShiftClick(mob/living/user)
if(!HAS_TRAIT(user, TRAIT_SKITTISH))
return ..()
- if(!user.canUseTopic(src) || !isturf(user.loc))
+ if(!user.canUseTopic(src) || !isturf(user.loc) || !user.Adjacent(src) || !user.CanReach(src))
return
dive_into(user)
diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
index 9d554181eb..63c8856ac3 100644
--- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
@@ -126,8 +126,10 @@
new /obj/item/clothing/mask/bandana/black(src)
if(prob(40))
new /obj/item/clothing/under/assistantformal(src)
+ new /obj/item/clothing/suit/hooded/wintercoat/aformal(src)
if(prob(40))
new /obj/item/clothing/under/assistantformal(src)
+ new /obj/item/clothing/suit/hooded/wintercoat/aformal(src)
if(prob(30))
new /obj/item/clothing/suit/hooded/wintercoat(src)
new /obj/item/clothing/shoes/winterboots(src)
@@ -169,4 +171,6 @@
if(prob(30))
new /obj/item/clothing/suit/hooded/wintercoat(src)
new /obj/item/clothing/shoes/winterboots(src)
+ if (prob(30))
+ new /obj/item/clothing/suit/hooded/wintercoat/polychromic(src)
return
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index eaa9074bd8..a6c0b22ad7 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -13,6 +13,8 @@
climb_time = 10 //real fast, because let's be honest stepping into or onto a crate is easy
climb_stun = 0 //climbing onto crates isn't hard, guys
delivery_icon = "deliverycrate"
+ material_drop = /obj/item/stack/sheet/plasteel
+ material_drop_amount = 5
var/obj/item/paper/fluff/jobs/cargo/manifest/manifest
/obj/structure/closet/crate/New()
@@ -81,7 +83,7 @@
/obj/structure/closet/crate/coffin/examine(mob/user)
. = ..()
- if(user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
+ if(user.mind?.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
. += {"This is a coffin which you can use to regenerate your burns and other wounds faster."}
. += {"You can also thicken your blood if you survive the day, and hide from the sun safely while inside."}
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
@@ -142,6 +144,9 @@
new /obj/item/reagent_containers/blood/OMinus(src)
new /obj/item/reagent_containers/blood/OPlus(src)
new /obj/item/reagent_containers/blood/lizard(src)
+ new /obj/item/reagent_containers/blood/jellyblood(src)
+ new /obj/item/reagent_containers/blood/insect(src)
+ new /obj/item/reagent_containers/blood/synthetics(src)
for(var/i in 1 to 3)
new /obj/item/reagent_containers/blood/random(src)
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 8c25a2ca5c..70533df0ad 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -80,7 +80,7 @@
/obj/structure/displaycase/proc/trigger_alarm()
//Activate Anti-theft
if(alert)
- var/area/alarmed = get_area(src)
+ var/area/alarmed = get_base_area(src)
alarmed.burglaralert(src)
playsound(src, 'sound/effects/alert.ogg', 50, 1)
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index 271ae72d47..f35e9e7d55 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -205,6 +205,9 @@
if(!mineral)
if(istype(G, /obj/item/stack/sheet/mineral) && G.sheettype)
var/M = G.sheettype
+ var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]")
+ if(!mineralassembly)
+ return
if(G.get_amount() >= 2)
playsound(src, 'sound/items/crowbar.ogg', 100, 1)
user.visible_message("[user] adds [G.name] to the airlock assembly.", \
@@ -214,7 +217,6 @@
return
to_chat(user, "You install [M] plating into the airlock assembly.")
G.use(2)
- var/mineralassembly = text2path("/obj/structure/door_assembly/door_assembly_[M]")
var/obj/structure/door_assembly/MA = new mineralassembly(loc)
transfer_assembly_vars(src, MA, TRUE)
else
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index d7e2d5564a..52441c2987 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -7,7 +7,7 @@
anchored = TRUE
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- layer = CLOSED_TURF_LAYER
+ layer = LOW_OBJ_LAYER
density = TRUE
opacity = 1
max_integrity = 100
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index 92fb13c947..e9d9e4ce77 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -12,9 +12,11 @@
roundstart = FALSE
death = FALSE
mob_species = /datum/species/pod
- flavour_text = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \
- seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \
- for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago."
+ short_desc = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed."
+ flavour_text = "Your masters, benevolent as they were, created uncounted seed vaults and spread them across \
+ the universe to every planet they could chart. You are in one such seed vault. \
+ Your goal is to cultivate and spread life wherever it will go while waiting for contact from your creators. \
+ Estimated time of last contact: Deployment, 5000 millennia ago."
assignedrole = "Lifebringer"
/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
@@ -48,8 +50,10 @@
anchored = FALSE
move_resist = MOVE_FORCE_NORMAL
density = FALSE
- flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. You would never leave its beautiful expanse. \
- You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest."
+ short_desc = "You are an ash walker. Your tribe worships the Necropolis."
+ flavour_text = "The wastes are sacred ground, its monsters a blessed bounty. You would never leave its sacred ground. \
+ You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. \
+ Fresh sacrifices for your nest."
assignedrole = "Ash Walker"
/obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn)
@@ -88,8 +92,9 @@
roundstart = FALSE
death = FALSE
mob_species = /datum/species/shadow
- flavour_text = "You are cursed. Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \
- did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland."
+ short_desc = "You are cursed."
+ flavour_text = "Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \
+ did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland."
assignedrole = "Exile"
/obj/effect/mob_spawn/human/exile/Destroy()
@@ -126,9 +131,10 @@
var/has_owner = FALSE
var/can_transfer = TRUE //if golems can switch bodies to this new shell
var/mob/living/owner = null //golem's owner if it has one
- flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \
+ short_desc = "You are a Free Golem. Your family worships The Liberator."
+ flavour_text = "In his infinite and divine wisdom, he set your clan free to \
travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
- golems, so that no golem may ever be forced to serve again."
+ golems, so that no golem may ever be forced to serve again."
/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null)
if(species) //spawners list uses object name to register so this goes before ..()
@@ -139,8 +145,9 @@
if(!mapload && A)
notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_GOLEM, ignore_dnr_observers = TRUE)
if(has_owner && creator)
- flavour_text = "You are a Golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \
- Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
+ short_desc = "You are a golem."
+ flavour_text = "You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools."
+ important_info = "Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
owner = creator
/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name)
@@ -213,8 +220,9 @@
death = FALSE
random = TRUE
mob_species = /datum/species/human
- flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. Each day you barely scrape by, and between the terrible \
- conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
+ short_desc = "You've been stranded in this godless prison of a planet for longer than you can remember."
+ flavour_text = "Each day you barely scrape by, and between the terrible conditions of your makeshift shelter, \
+ the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
assignedrole = "Hermit"
@@ -225,20 +233,20 @@
if(1)
flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \
- life and sent you to this hell are forever branded into your memory."
+ life and sent you to this hell are forever branded into your memory."
outfit.uniform = /obj/item/clothing/under/assistantformal
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
outfit.back = /obj/item/storage/backpack
if(2)
flavour_text += "you're an exile from the Tiger Cooperative. Their technological fanaticism drove you to question the power and beliefs of the Exolitics, and they saw you as a \
heretic and subjected you to hours of horrible torture. You were hours away from execution when a high-ranking friend of yours in the Cooperative managed to secure you a pod, \
- scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since."
+ scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since."
outfit.uniform = /obj/item/clothing/under/rank/prisoner
outfit.shoes = /obj/item/clothing/shoes/sneakers/orange
outfit.back = /obj/item/storage/backpack
if(3)
flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \
- to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there."
+ to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there."
outfit.uniform = /obj/item/clothing/under/rank/medical
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
outfit.back = /obj/item/storage/backpack/medic
@@ -246,7 +254,7 @@
if(4)
flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so kindly put it. It seems that they were right when you, on a tour \
at one of Nanotrasen's state-of-the-art research facilities, were in one of the escape pods alone and saw the red button. It was big and shiny, and it caught your eye. You pressed \
- it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now."
+ it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now."
outfit.uniform = /obj/item/clothing/under/color/grey/glorf
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
outfit.back = /obj/item/storage/backpack
@@ -264,9 +272,10 @@
desc = "A small sleeper typically used to instantly restore minor wounds. This one seems broken, and its occupant is comatose."
job_description = "Lavaland Veterinarian"
mob_name = "a translocated vet"
- flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \
- everyone's gone. One of the cats scratched you just a few minutes ago. That's why you were in the pod - to heal the scratch. The scabs are still fresh; you see them right now. So where is \
- everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they can tell you what happened."
+ short_desc = "You are a animal doctor who just woke up in lavaland"
+ flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \
+ you see them right now. So where is \
+ everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they c everyone's gone. One of the cats scratched you just a few minutes ago. That's why you were in the pod - to heal the scratch. The scabs are still fresh; an tell you what happened."
assignedrole = "Translocated Vet"
/obj/effect/mob_spawn/human/doctor/alive/lavaland/Destroy()
@@ -285,8 +294,9 @@
outfit = /datum/outfit/lavalandprisoner
roundstart = FALSE
death = FALSE
- flavour_text = "Good. It seems as though your ship crashed. You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
- though fate has other plans for you. You remember that you were convicted of "
+ short_desc = "You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
+ though fate has other plans for you."
+ flavour_text = "Good. It seems as though your ship crashed. You remember that you were convicted of "
assignedrole = "Escaped Prisoner"
/obj/effect/mob_spawn/human/prisoner_transport/special(mob/living/L)
@@ -298,7 +308,7 @@
var/list/crimes = list("murder", "larceny", "embezzlement", "unionization", "dereliction of duty", "kidnapping", "gross incompetence", "grand theft", "collaboration with the Syndicate", \
"worship of a forbidden deity", "interspecies relations", "mutiny")
flavour_text += "[pick(crimes)]. but regardless of that, it seems like your crime doesn't matter now. You don't know where you are, but you know that it's out to kill you, and you're not going \
- to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]."
+ to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]."
/datum/outfit/lavalandprisoner
name = "Lavaland Prisoner"
@@ -325,8 +335,9 @@
roundstart = FALSE
random = TRUE
outfit = /datum/outfit/hotelstaff
- flavour_text = "You are a staff member of a top-of-the-line space hotel! Cater to guests and DON'T leave the hotel, lest the manager fire you for\
- dereliction of duty!"
+ short_desc = "You are a staff member of a top-of-the-line space hotel!"
+ flavour_text = "You are a staff member of a top-of-the-line space hotel! Cater to guests and make sure the manager doesn't fire you."
+ important_info = "DON'T leave the hotel"
assignedrole = "Hotel Staff"
/datum/outfit/hotelstaff
@@ -343,8 +354,10 @@
mob_name = "hotel security member"
job_description = "Hotel Security"
outfit = /datum/outfit/hotelstaff/security
- flavour_text = "You are a peacekeeper assigned to this hotel to protect the interests of the company while keeping the peace between \
- guests and the staff. Do NOT leave the hotel, as that is grounds for contract termination."
+ short_desc = "You are a peacekeeper."
+ flavour_text = "You have been assigned to this hotel to protect the interests of the company while keeping the peace between \
+ guests and the staff."
+ important_info = "Do NOT leave the hotel, as that is grounds for contract termination."
objectives = "Do not leave your assigned hotel. Try and keep the peace between staff and guests, non-lethal force heavily advised if possible."
/datum/outfit/hotelstaff/security
@@ -383,7 +396,8 @@
/obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell)
. = ..()
owner = owner_mind
- flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil. Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
+ flavour_text = "You have been given a reprieve from your eternity of torment, to be [owner.name]'s friend for [owner.p_their()] short mortal coil."
+ important_info = "Be aware that if you do not live up to [owner.name]'s expectations, they can send you back to hell with a single thought. [owner.name]'s death will also return you to hell."
var/area/A = get_area(src)
if(!mapload && A)
notify_ghosts("\A friendship shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
@@ -441,9 +455,9 @@
/obj/effect/mob_spawn/human/syndicate/battlecruiser
name = "Syndicate Battlecruiser Ship Operative"
- flavour_text = "You are a crewmember aboard the syndicate flagship: the SBC Starfury.Your job is to follow your captain's orders, maintain the ship, and keep the engine running. If you are not familiar with how the supermatter engine functions: do not attempt to start it. \
- \
- The armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives."
+ short_desc = "You are a crewmember aboard the syndicate flagship: the SBC Starfury."
+ flavour_text = "Your job is to follow your captain's orders, maintain the ship, and keep the engine running. If you are not familiar with how the supermatter engine functions: do not attempt to start it."
+ important_info = "The armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives."
outfit = /datum/outfit/syndicate_empty/SBC
/datum/outfit/syndicate_empty/SBC
@@ -453,10 +467,9 @@
belt = /obj/item/storage/belt/military/assault
/obj/effect/mob_spawn/human/syndicate/battlecruiser/assault
- name = "Syndicate Battlecruiser Assault Operative"
- flavour_text = "You are an assault operative aboard the syndicate flagship: the SBC Starfury.Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13. There is an armory, multiple assault ships, and beam cannons to attack the station with. \
- \
- Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!"
+ short_desc = "You are an assault operative aboard the syndicate flagship: the SBC Starfury."
+ flavour_text = "Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13. There is an armory, multiple assault ships, and beam cannons to attack the station with."
+ important_info = "Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!"
outfit = /datum/outfit/syndicate_empty/SBC/assault
/datum/outfit/syndicate_empty/SBC/assault
@@ -472,9 +485,9 @@
/obj/effect/mob_spawn/human/syndicate/battlecruiser/captain
name = "Syndicate Battlecruiser Captain"
- flavour_text = "You are the captain aboard the syndicate flagship: the SBC Starfury.Your job is to oversee your crew, defend the ship, and destroy Space Station 13. The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal. \
- \
- As the captain, this whole operation falls on your shoulders. You do not need to nuke the station, causing sufficient damage and preventing your ship from being destroyed will be enough."
+ short_desc = "You are the captain aboard the syndicate flagship: the SBC Starfury."
+ flavour_text = "Your job is to oversee your crew, defend the ship, and destroy Space Station 13. The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal."
+ important_info = "As the captain, this whole operation falls on your shoulders. You do not need to nuke the station, causing sufficient damage and preventing your ship from being destroyed will be enough."
outfit = /datum/outfit/syndicate_empty/SBC/assault/captain
id_access_list = list(150,151)
@@ -500,10 +513,11 @@
death = FALSE
random = TRUE
mob_species = /datum/species/human
- flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
- Work as a team with your fellow survivors and do not abandon them."
+ short_desc = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station."
+ flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. \
+ The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
+ your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/security
shoes = /obj/item/clothing/shoes/jackboots
id = /obj/item/card/id/away/old/sec
@@ -527,10 +541,11 @@
death = FALSE
random = TRUE
mob_species = /datum/species/human
- flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
- Work as a team with your fellow survivors and do not abandon them."
+ short_desc = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station."
+ flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. The last thing \
+ you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
+ your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/engineer
shoes = /obj/item/clothing/shoes/workboots
id = /obj/item/card/id/away/old/eng
@@ -552,10 +567,11 @@
death = FALSE
random = TRUE
mob_species = /datum/species/human
- flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
- cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
- your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
- Work as a team with your fellow survivors and do not abandon them."
+ short_desc = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station."
+ flavour_text = "You vaguely recall rushing into a cryogenics pod due to an oncoming radiation storm. \
+ The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
+ your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
+ important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/scientist
shoes = /obj/item/clothing/shoes/laceup
id = /obj/item/card/id/away/old/sci
@@ -582,7 +598,8 @@
anchored = TRUE
density = FALSE
show_flavour = FALSE //Flavour only exists for spawners menu
- flavour_text = "You are a space pirate. The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot."
+ short_desc = "You are a space pirate."
+ flavour_text = "The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot."
assignedrole = "Space Pirate"
var/rank = "Mate"
@@ -617,9 +634,10 @@
density = FALSE
death = FALSE
assignedrole = "Ghost Cafe Visitor"
- flavour_text = "Is this what life after death is like?"
+ short_desc = "You are a Ghost Cafe Visitor!"
+ flavour_text = "You know one thing for sure. You arent actually alive. Are you in a simulation?"
skip_reentry_check = TRUE
- banType = "ghostcafe"
+ banType = ROLE_GHOSTCAFE
/datum/action/toggle_dead_chat_mob
icon_icon = 'icons/mob/mob.dmi'
@@ -642,12 +660,14 @@
/obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn)
if(new_spawn.client)
new_spawn.client.prefs.copy_to(new_spawn)
+ var/area/A = get_area(src)
var/datum/outfit/O = new /datum/outfit/ghostcafe()
O.equip(new_spawn, FALSE, new_spawn.client)
SSjob.equip_loadout(null, new_spawn, FALSE)
SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn)
new_spawn.AddElement(/datum/element/ghost_role_eligibility)
new_spawn.AddElement(/datum/element/dusts_on_catatonia)
+ new_spawn.AddElement(/datum/element/dusts_on_leaving_area,list(A.type,/area/hilbertshotel))
ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_PACIFISM,GHOSTROLE_TRAIT)
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 94619e1858..7c373f2734 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -166,6 +166,9 @@
if(S.sheettype && S.sheettype != "runed")
var/M = S.sheettype
if(state == GIRDER_DISPLACED)
+ var/F = text2path("/obj/structure/falsewall/[M]")
+ if(!F)
+ return
if(S.get_amount() < 2)
to_chat(user, "You need at least two sheets to create a false wall!")
return
@@ -174,11 +177,13 @@
return
S.use(2)
to_chat(user, "You create a false wall. Push on it to open or close the passage.")
- var/F = text2path("/obj/structure/falsewall/[M]")
var/obj/structure/FW = new F (loc)
transfer_fingerprints_to(FW)
qdel(src)
else
+ var/F = text2path("/turf/closed/wall/mineral/[M]")
+ if(!F)
+ return
if(S.get_amount() < 2)
to_chat(user, "You need at least two sheets to add plating!")
return
@@ -189,7 +194,7 @@
S.use(2)
to_chat(user, "You add the plating.")
var/turf/T = get_turf(src)
- T.PlaceOnTop(text2path("/turf/closed/wall/mineral/[M]"))
+ T.PlaceOnTop(F)
transfer_fingerprints_to(T)
qdel(src)
return
diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm
index 3b4bbea559..611a6d024d 100644
--- a/code/game/objects/structures/guillotine.dm
+++ b/code/game/objects/structures/guillotine.dm
@@ -97,7 +97,7 @@
icon_state = "guillotine_raised"
/obj/structure/guillotine/proc/drop_blade(mob/user)
- if (buckled_mobs.len && blade_sharpness)
+ if (has_buckled_mobs() && blade_sharpness)
var/mob/living/carbon/human/H = buckled_mobs[1]
if (!H)
diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm
index ceed9cb759..81433b562d 100644
--- a/code/game/objects/structures/headpike.dm
+++ b/code/game/objects/structures/headpike.dm
@@ -42,8 +42,9 @@
if(.)
return
to_chat(user, "You take down [src].")
- victim.forceMove(drop_location())
- victim = null
+ if(victim)
+ victim.forceMove(drop_location())
+ victim = null
spear.forceMove(drop_location())
spear = null
qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 617f42ed29..9d22f669d5 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -93,6 +93,24 @@
/obj/structure/holosign/barrier/firelock/blocksTemperature()
return TRUE
+/obj/structure/holosign/barrier/combifan
+ name = "holo combifan"
+ desc = "A holographic barrier resembling a blue-accented tiny fan. Though it does not prevent solid objects from passing through, gas and temperature changes are kept out."
+ icon_state = "holo_combifan"
+ max_integrity = 30
+ density = FALSE
+ anchored = TRUE
+ alpha = 150
+ CanAtmosPass = ATMOS_PASS_NO
+ resistance_flags = FIRE_PROOF
+
+/obj/structure/holosign/barrier/combolock/blocksTemperature()
+ return TRUE
+
+/obj/structure/holosign/barrier/combolock/Initialize()
+ . = ..()
+ air_update_turf(TRUE)
+
/obj/structure/holosign/barrier/cyborg
name = "Energy Field"
desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles."
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 0a5794c59d..d4645ec69a 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -20,14 +20,14 @@
return
if(broken || !Adjacent(user))
return
-
+
if(ishuman(user))
var/mob/living/carbon/human/H = user
//see code/modules/mob/dead/new_player/preferences.dm at approx line 545 for comments!
//this is largely copypasted from there.
//handle facial hair (if necessary)
- if(H.gender == MALE)
+ if(H.gender != FEMALE)
var/new_style = input(user, "Select a facial hair style", "Grooming") as null|anything in GLOB.facial_hair_styles_list
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return //no tele-grooming
@@ -133,7 +133,7 @@
switch(choice)
if("name")
- var/newname = copytext(sanitize(input(H, "Who are we again?", "Name change", H.name) as null|text),1,MAX_NAME_LEN)
+ var/newname = reject_bad_name(stripped_input(H, "Who are we again?", "Name change", H.name, MAX_NAME_LEN))
if(!newname)
return
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index 4c85e7464e..df6d033af4 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -109,8 +109,10 @@
var/cur_note = text2ascii(note) - 96
if(cur_note < 1 || cur_note > 7)
continue
- for(var/i=2 to length(note))
- var/ni = copytext(note,i,i+1)
+ var/notelen = length(note)
+ var/ni = ""
+ for(var/i = length(note[1]) + 1, i <= notelen, i += length(ni))
+ ni = note[i]
if(!text2num(ni))
if(ni == "#" || ni == "b" || ni == "n")
cur_acc[cur_note] = ni
@@ -199,9 +201,10 @@
//split into lines
lines = splittext(text, "\n")
if(lines.len)
- if(copytext(lines[1],1,6) == "BPM: ")
- tempo = sanitize_tempo(600 / text2num(copytext(lines[1],6)))
- lines.Cut(1,2)
+ var/bpm_string = "BPM: "
+ if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1))
+ tempo = sanitize_tempo(600 / text2num(copytext(lines[1], length(bpm_string) + 1)))
+ lines.Cut(1, 2)
else
tempo = sanitize_tempo(5) // default 120 BPM
if(lines.len > MUSIC_MAXLINES)
@@ -209,7 +212,7 @@
lines.Cut(MUSIC_MAXLINES + 1)
var/linenum = 1
for(var/l in lines)
- if(length(l) > MUSIC_MAXLINECHARS)
+ if(length_char(l) > MUSIC_MAXLINECHARS)
to_chat(usr, "Line [linenum] too long!")
lines.Remove(l)
else
@@ -236,11 +239,11 @@
if(!in_range(instrumentObj, usr))
return
- if(length(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
+ if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no")
if(cont == "no")
break
- while(length(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
+ while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
ParseSong(t)
else if(href_list["help"])
@@ -284,11 +287,9 @@
else if(href_list["modifyline"])
var/num = round(text2num(href_list["modifyline"]),1)
- var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null)
+ var/content = stripped_input(usr, "Enter your line: ", instrumentObj.name, lines[num], MUSIC_MAXLINECHARS)
if(!content || !in_range(instrumentObj, usr))
return
- if(length(content) > MUSIC_MAXLINECHARS)
- content = copytext(content, 1, MUSIC_MAXLINECHARS)
if(num > lines.len || num < 1)
return
lines[num] = content
diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm
index f156287d43..5fabcafd75 100644
--- a/code/game/objects/structures/tank_dispenser.dm
+++ b/code/game/objects/structures/tank_dispenser.dm
@@ -71,7 +71,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, "tank_dispenser", name, 275, 100, master_ui, state)
+ ui = new(user, src, ui_key, "tank_dispenser", name, 275, 103, master_ui, state)
ui.open()
/obj/structure/tank_dispenser/ui_data(mob/user)
diff --git a/code/game/say.dm b/code/game/say.dm
index 7f01bf163d..b275d8b69c 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -75,8 +75,8 @@ GLOBAL_LIST_INIT(freqtospan, list(
return ""
/atom/movable/proc/say_mod(input, message_mode)
- var/ending = copytext(input, length(input))
- if(copytext(input, length(input) - 1) == "!!")
+ var/ending = copytext_char(input, -1)
+ if(copytext_char(input, -2) == "!!")
return verb_yell
else if(ending == "?")
return verb_ask
@@ -89,7 +89,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
if(!input)
input = "..."
- if(copytext(input, length(input) - 1) == "!!")
+ if(copytext_char(input, -2) == "!!")
spans |= SPAN_YELL
var/spanned = attach_spans(input, spans)
@@ -124,12 +124,12 @@ GLOBAL_LIST_INIT(freqtospan, list(
var/returntext = GLOB.reverseradiochannels["[freq]"]
if(returntext)
return returntext
- return "[copytext("[freq]", 1, 4)].[copytext("[freq]", 4, 5)]"
+ return "[copytext_char("[freq]", 1, 4)].[copytext_char("[freq]", 4, 5)]"
/atom/movable/proc/attach_spans(input, list/spans)
var/customsayverb = findtext(input, "*")
if(customsayverb)
- input = capitalize(copytext(input, customsayverb+1))
+ input = capitalize(copytext(input, length(input[customsayverb]) + 1))
if(input)
return "[message_spans_start(spans)][input]"
else
@@ -143,7 +143,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
return output
/proc/say_test(text)
- var/ending = copytext(text, length(text))
+ var/ending = copytext_char(text, -1)
if (ending == "?")
return "1"
else if (ending == "!")
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index 577c45a7f0..c4c7ab2d7b 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -245,48 +245,47 @@
return TRUE
/turf/open/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
- if(C.movement_type & FLYING)
- return 0
- if(has_gravity(src))
- var/obj/buckled_obj
- if(C.buckled)
- buckled_obj = C.buckled
- if(!(lube&GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube.
- return 0
- else
- if(!(lube&SLIP_WHEN_CRAWLING) && (C.lying || !(C.status_flags & CANKNOCKDOWN))) // can't slip unbuckled mob if they're lying or can't fall.
- return 0
- if(lube & NO_SLIP_WHEN_WALKING)
- if(C.m_intent == MOVE_INTENT_WALK)
- return 0
- if(ishuman(C) && !(lube & SLIP_WHEN_JOGGING))
- var/mob/living/carbon/human/H = C
- if(!H.sprinting && H.getStaminaLoss() <= 20)
- return 0
- if(!(lube&SLIDE_ICE))
- to_chat(C, "You slipped[ O ? " on the [O.name]" : ""]!")
- playsound(C.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+ if(!(lube & FLYING_DOESNT_HELP) && (C.movement_type & FLYING || !has_gravity(src)))
+ return FALSE
+ var/obj/buckled_obj
+ if(C.buckled)
+ buckled_obj = C.buckled
+ if(!(lube&GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube.
+ return FALSE
+ else
+ if(!(lube&SLIP_WHEN_CRAWLING) && (C.lying || !(C.status_flags & CANKNOCKDOWN))) // can't slip unbuckled mob if they're lying or can't fall.
+ return FALSE
+ if(lube & NO_SLIP_WHEN_WALKING)
+ if(C.m_intent == MOVE_INTENT_WALK)
+ return FALSE
+ if(ishuman(C) && !(lube & SLIP_WHEN_JOGGING))
+ var/mob/living/carbon/human/H = C
+ if(!H.sprinting && H.getStaminaLoss() <= 20)
+ return FALSE
+ if(!(lube&SLIDE_ICE))
+ to_chat(C, "You slipped[ O ? " on the [O.name]" : ""]!")
+ playsound(C.loc, 'sound/misc/slip.ogg', 50, 1, -3)
- SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "slipped", /datum/mood_event/slipped)
- for(var/obj/item/I in C.held_items)
- C.accident(I)
+ SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "slipped", /datum/mood_event/slipped)
+ for(var/obj/item/I in C.held_items)
+ C.accident(I)
- var/olddir = C.dir
- if(!(lube & SLIDE_ICE))
- C.Knockdown(knockdown_amount)
- C.stop_pulling()
- else
- C.Stun(20)
+ var/olddir = C.dir
+ if(!(lube & SLIDE_ICE))
+ C.Knockdown(knockdown_amount)
+ C.stop_pulling()
+ else
+ C.Stun(20)
- if(buckled_obj)
- buckled_obj.unbuckle_mob(C)
- lube |= SLIDE_ICE
+ if(buckled_obj)
+ buckled_obj.unbuckle_mob(C)
+ lube |= SLIDE_ICE
- if(lube&SLIDE)
- new /datum/forced_movement(C, get_ranged_target_turf(C, olddir, 4), 1, FALSE, CALLBACK(C, /mob/living/carbon/.proc/spin, 1, 1))
- else if(lube&SLIDE_ICE)
- new /datum/forced_movement(C, get_ranged_target_turf(C, olddir, 1), 1, FALSE) //spinning would be bad for ice, fucks up the next dir
- return 1
+ if(lube&SLIDE)
+ new /datum/forced_movement(C, get_ranged_target_turf(C, olddir, 4), 1, FALSE, CALLBACK(C, /mob/living/carbon/.proc/spin, 1, 1))
+ else if(lube&SLIDE_ICE)
+ new /datum/forced_movement(C, get_ranged_target_turf(C, olddir, 1), 1, FALSE) //spinning would be bad for ice, fucks up the next dir
+ return TRUE
/turf/open/proc/MakeSlippery(wet_setting = TURF_WET_WATER, min_wet_time = 0, wet_time_to_add = 0, max_wet_time = MAXIMUM_WET_TIME, permanent)
AddComponent(/datum/component/wet_floor, wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm
index be46d124ea..d55cb0b475 100644
--- a/code/game/turfs/simulated/wall/mineral_walls.dm
+++ b/code/game/turfs/simulated/wall/mineral_walls.dm
@@ -138,7 +138,8 @@
var/duration = (48/W.force) * 2 //In seconds, for now.
if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/twohanded/fireaxe))
duration /= 4 //Much better with hatchets and axes.
- if(do_after(user, duration*10, target=src)) //Into deciseconds.
+ var/src_type = type
+ if(do_after(user, duration*10, target=src) && type == src_type) //Into deciseconds.
dismantle_wall(FALSE,FALSE)
return
return ..()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 5278374abd..26daa32107 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -88,8 +88,9 @@
/turf/open/space/proc/CanBuildHere()
return TRUE
-/turf/open/space/handle_slip()
- return
+/turf/open/space/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
+ if(lube & FLYING_DOESNT_HELP)
+ return ..()
/turf/open/space/attackby(obj/item/C, mob/user, params)
..()
diff --git a/code/game/world.dm b/code/game/world.dm
index 7afaf62bb8..8e18f2ea51 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -115,9 +115,12 @@ GLOBAL_LIST(topic_status_cache)
GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log"
GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log"
GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log"
+ GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log"
+ GLOB.reagent_log = "[GLOB.log_directory]/reagents.log"
GLOB.world_crafting_log = "[GLOB.log_directory]/crafting.log"
+
#ifdef UNIT_TESTS
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
start_log(GLOB.test_log)
@@ -131,7 +134,9 @@ GLOBAL_LIST(topic_status_cache)
start_log(GLOB.world_qdel_log)
start_log(GLOB.world_runtime_log)
start_log(GLOB.world_job_debug_log)
+ start_log(GLOB.tgui_log)
start_log(GLOB.subsystem_log)
+ start_log(GLOB.reagent_log)
start_log(GLOB.world_crafting_log)
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
diff --git a/code/modules/NTNet/network.dm b/code/modules/NTNet/network.dm
index 645f05ac90..d86ad792fe 100644
--- a/code/modules/NTNet/network.dm
+++ b/code/modules/NTNet/network.dm
@@ -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
diff --git a/code/modules/NTNet/relays.dm b/code/modules/NTNet/relays.dm
index eaf2aa466b..373f6451b9 100644
--- a/code/modules/NTNet/relays.dm
+++ b/code/modules/NTNet/relays.dm
@@ -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 ..()
\ No newline at end of file
diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm
index 7cda24d98b..29d7224950 100644
--- a/code/modules/VR/vr_sleeper.dm
+++ b/code/modules/VR/vr_sleeper.dm
@@ -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)
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 4f2aa35860..8856982cf2 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -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)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 8a7269ccad..f23fc5c070 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -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, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.")
+ 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
diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm
index 52ba3c521e..e2ddcdcf6a 100644
--- a/code/modules/admin/chat_commands.dm
+++ b/code/modules/admin/chat_commands.dm
@@ -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."
diff --git a/code/modules/admin/check_antagonists.dm b/code/modules/admin/check_antagonists.dm
index 30fa664f42..8cb2a9a477 100644
--- a/code/modules/admin/check_antagonists.dm
+++ b/code/modules/admin/check_antagonists.dm
@@ -149,10 +149,10 @@
else
var/timeleft = SSshuttle.emergency.timeLeft()
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
- dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)] "
+ dat += "ETA: [(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")] "
dat += "Send Back "
else
- dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)] "
+ dat += "ETA: [(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")] "
dat += "Continuous Round Status "
dat += "[CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]"
if(CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag])
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index 70ae133a31..68ae3568af 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -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]"])]"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c66927b856..70b25bebdd 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -845,7 +845,11 @@
dat += "
"
dat += ""
//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, "[ckey] is already a mentor.")
return
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index d2693a83b6..da7c264774 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -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, "World variables are not allowed to be accessed. Use global.")
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, "Invalid pointer syntax: [expression[start + 1]]")
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
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
index 272bf83ca4..64d0c00010 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -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:
/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: ''' ''' | '"' '"'
/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)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 2f842263c7..1800824564 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -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
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index e2b994f769..bbd6b55e4f 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -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"
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index 1ebd632c23..9081357ef6 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -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)
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 52c5284cbb..4df6f22686 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -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)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index f08112939a..ad2eeb7289 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -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]. "
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 += "
AREAS WITH MULTIPLE APCS:
"
for(var/areatype in areas_with_multiple_APCs)
dat += "[areatype] "
+ if(sub_areas_APC[areatype])
+ dat += " SUB-AREAS: "
+ dat += jointext(sub_areas_APC[areatype], " ")
CHECK_TICK
if(areas_without_air_alarm.len)
dat += "
AREAS WITHOUT AN AIR ALARM:
"
for(var/areatype in areas_without_air_alarm)
dat += "[areatype] "
+ if(sub_areas_air_alarm[areatype])
+ dat += " SUB-AREAS: "
+ dat += jointext(sub_areas_air_alarm[areatype], " ")
CHECK_TICK
if(areas_without_RC.len)
diff --git a/code/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm
index a3b7e4247c..b2648735ec 100644
--- a/code/modules/admin/verbs/manipulate_organs.dm
+++ b/code/modules/admin/verbs/manipulate_organs.dm
@@ -58,7 +58,7 @@
if(isorgan(organ))
O = organ
- O.Remove(C)
+ O.Remove()
else
I = organ
I.removed(C)
diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm
index c5c9a0daf4..d71cdca991 100644
--- a/code/modules/admin/verbs/map_template_loadverb.dm
+++ b/code/modules/admin/verbs/map_template_loadverb.dm
@@ -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, "Filename must end in '.dmm': [map]")
return
var/datum/map_template/M
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index 611ebcf7bf..537c31d3b4 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -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 = "/"
diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm
index 2897427d6f..daaf15c70f 100644
--- a/code/modules/admin/verbs/panicbunker.dm
+++ b/code/modules/admin/verbs/panicbunker.dm
@@ -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.")
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index 0555f6b40a..f3da1954a9 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -6,7 +6,7 @@
to_chat(usr, "Speech is currently admin-disabled.")
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 = "CENTCOM:[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]: [msg]"
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 = "SYNDICATE:[ADMIN_FULLMONTY(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]: [msg]"
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 = "NUKE CODE REQUEST:[ADMIN_FULLMONTY(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]: [msg]"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 1437555af1..37c79b1123 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -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)
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 1894d8c7ae..e15225b388 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -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
diff --git a/code/modules/antagonists/abductor/abductee/abductee.dm b/code/modules/antagonists/abductor/abductee/abductee.dm
new file mode 100644
index 0000000000..901d2f5b11
--- /dev/null
+++ b/code/modules/antagonists/abductor/abductee/abductee.dm
@@ -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, "Your mind snaps!")
+ to_chat(owner, "You can't remember how you got here...")
+ 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)
diff --git a/code/modules/antagonists/abductor/abductee/abductee_objectives.dm b/code/modules/antagonists/abductor/abductee/abductee_objectives.dm
index f188319644..2d62bf1ac9 100644
--- a/code/modules/antagonists/abductor/abductee/abductee_objectives.dm
+++ b/code/modules/antagonists/abductor/abductee/abductee_objectives.dm
@@ -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"
diff --git a/code/modules/antagonists/abductor/abductee/trauma.dm b/code/modules/antagonists/abductor/abductee/trauma.dm
new file mode 100644
index 0000000000..1518825e1b
--- /dev/null
+++ b/code/modules/antagonists/abductor/abductee/trauma.dm
@@ -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 = "Your mind snaps.. you feel fragmented."
+ lose_text = "Your mind heals itself and you feel whole again."
+ 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)
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index 92504641a9..564e9a8617 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -159,35 +159,6 @@
return "
[result.Join(" ")]
"
-/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, "Your mind snaps!")
- to_chat(owner, "You can't remember how you got here...")
- 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
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index dc6d12453d..332329a221 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -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.
diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
index 98164de099..971051588e 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
@@ -33,7 +33,7 @@
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "You pull [IC] out of [target]'s [target_zone].")
user.put_in_hands(IC)
- IC.Remove(target)
+ IC.Remove()
return 1
else
to_chat(user, "You don't find anything in [target]'s [target_zone]!")
diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm
index 82170444d0..0d30ebe992 100644
--- a/code/modules/antagonists/abductor/equipment/gland.dm
+++ b/code/modules/antagonists/abductor/equipment/gland.dm
@@ -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)
diff --git a/code/modules/antagonists/abductor/equipment/glands/access.dm b/code/modules/antagonists/abductor/equipment/glands/access.dm
index 548650d4e3..c795233dc9 100644
--- a/code/modules/antagonists/abductor/equipment/glands/access.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/access.dm
@@ -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)
- ..()
\ No newline at end of file
+/obj/item/organ/heart/gland/access/Remove(special = FALSE)
+ if(!QDELETED(owner))
+ UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
+ return ..()
\ No newline at end of file
diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm
index 63d95f8b1f..82ee77d192 100644
--- a/code/modules/antagonists/abductor/equipment/glands/electric.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm
@@ -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("[owner]'s skin starts emitting electric arcs!",\
diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm
index bf9a00e13c..c60ec90480 100644
--- a/code/modules/antagonists/abductor/equipment/glands/heal.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm
@@ -65,14 +65,14 @@
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
owner.visible_message("[owner] vomits up his [implant.name]!", "You suddenly vomit up your [implant.name]!")
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("[owner] vomits up his [liver.name]!", "You suddenly vomit up your [liver.name]!")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
- liver.Remove(owner)
+ liver.Remove()
liver.forceMove(owner.drop_location())
else
to_chat(owner, "You feel a weird rumble in your bowels...")
@@ -87,7 +87,7 @@
if(lungs)
owner.visible_message("[owner] vomits up his [lungs.name]!", "You suddenly vomit up your [lungs.name]!")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
- lungs.Remove(owner)
+ lungs.Remove()
lungs.forceMove(owner.drop_location())
else
to_chat(owner, "You feel a weird rumble inside your chest...")
@@ -102,7 +102,7 @@
if(eyes)
owner.visible_message("[owner]'s [eyes.name] fall out of their sockets!", "Your [eyes.name] fall out of their sockets!")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
- eyes.Remove(owner)
+ eyes.Remove()
eyes.forceMove(owner.drop_location())
else
to_chat(owner, "You feel a weird rumble behind your eye sockets...")
diff --git a/code/modules/antagonists/blob/blob/overmind.dm b/code/modules/antagonists/blob/blob/overmind.dm
index f094fa83db..5d3c8cd8ca 100644
--- a/code/modules/antagonists/blob/blob/overmind.dm
+++ b/code/modules/antagonists/blob/blob/overmind.dm
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
index 10728d0664..0179c60ef1 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
index dffdeaf7fc..626ad43b10 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
@@ -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 += "
COST: [bloodcost] Blood" // Modify description to add cost.
- if (warn_constant_cost)
+ if(warn_constant_cost)
desc += "
Your over-time blood consumption increases while [name] is active."
- if (amSingleUse)
+ if(amSingleUse)
desc += "
Useable once per night."
..()
@@ -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, "You need at least [bloodcost] blood to activate [name]")
return FALSE
return TRUE
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm
index bb6e2a69f9..263f91a9a6 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm
@@ -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 @@
"The solar flare has ended, and the daylight danger has passed...for now.")
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
diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm
index 844b523135..24e967f00b 100644
--- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm
+++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm
@@ -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, "You have earned a reputation! You are now known as [ReturnFullName(TRUE)]!")
@@ -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, "You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.")
if(vamplevel_unspent >= 2)
- to_chat(owner, "Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks. ")
+ to_chat(owner, "Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks. ")
-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, "You prevent your blood from thickening just yet, but you may try again later.")
return
+ if(L.blood_volume < level_bloodcost)
+ to_chat(owner.current, "You dont have enough blood to thicken your blood, you need [level_bloodcost - L.blood_volume] units more!")
+ return
// Buy New Powers
var/datum/action/bloodsucker/P = options[choice]
+ AddBloodVolume(-level_bloodcost)
BuyPower(new P)
- to_chat(owner.current, "You have learned [initial(P.name)]!")
+ to_chat(owner.current, "You have used [level_bloodcost] units of blood and learned [initial(P.name)]!")
else
to_chat(owner.current, "You grow more ancient by the night!")
/////////
@@ -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 --
diff --git a/code/modules/antagonists/bloodsucker/datum_hunter.dm b/code/modules/antagonists/bloodsucker/datum_hunter.dm
index 2d680d0e09..5fc6716a7d 100644
--- a/code/modules/antagonists/bloodsucker/datum_hunter.dm
+++ b/code/modules/antagonists/bloodsucker/datum_hunter.dm
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/datum_vassal.dm b/code/modules/antagonists/bloodsucker/datum_vassal.dm
index 716b7ff223..345c6f3c10 100644
--- a/code/modules/antagonists/bloodsucker/datum_vassal.dm
+++ b/code/modules/antagonists/bloodsucker/datum_vassal.dm
@@ -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)
diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
index 946c472f11..a25244c48d 100644
--- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
+++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
@@ -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)
//////////////////////////////////////////////
diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
index f66ce4a208..9e46203483 100644
--- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
+++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
@@ -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))
. += {"This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service."}
. += {"You need to first secure the vassal rack by clicking on it while it is in your lair."}
- . += {"Simply click and hold on a victim, and then drag their sprite on the vassal rack."}
+ . += {"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."}
. += {"Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant."}
. += {"To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools."}
/* 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("[user] tries to pull [M] rack!",\
"[user] attempts to release you from the rack!") // For sound if not seen --> "You hear a squishy wet noise.")
- 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, "You don't have enough blood to initiate the Dark Communion with [target].")
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, "[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.\[ALT+click to release\]")
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, "You don't have enough blood to initiate the Dark Communion with [target].")
+ to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target], you need [convert_cost - user.blood_volume] units more!")
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("[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!", \
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_brawn.dm b/code/modules/antagonists/bloodsucker/powers/bs_brawn.dm
index 49aada3611..712a15dff9 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_brawn.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_brawn.dm
@@ -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("[user] lands a vicious punch, sending [target] away!", \
"[user] has landed a horrifying punch on you, sending you flying!!", 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)
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_feed.dm b/code/modules/antagonists/bloodsucker/powers/bs_feed.dm
index 7c4cf46e3c..2da84b6075 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_feed.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_feed.dm
@@ -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, "You cannot feed with your mouth covered! Remove your mask.")
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, "Lesser beings require a tighter grip.")
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, "Other Bloodsuckers will not fall for your subtle approach.")
return FALSE
// Must have Target
- if (!target) // || !ismob(target)
- if (display_error)
+ if(!target) // || !ismob(target)
+ if(display_error)
to_chat(owner, "You must be next to or grabbing a victim to feed from them.")
return FALSE
// Not even living!
- if (!isliving(target) || issilicon(target))
- if (display_error)
+ if(!isliving(target) || issilicon(target))
+ if(display_error)
to_chat(owner, "You may only feed from living beings.")
return FALSE
- if (target.blood_volume <= 0)
- if (display_error)
+ if(target.blood_volume <= 0)
+ if(display_error)
to_chat(owner, "Your victim has no blood to take.")
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, "Your victim's blood is not suitable for you to take.")
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, "You must be next to or grabbing a victim to feed from them.")
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, "None of these are valid targets to feed from subtly.")
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, "You lean quietly toward [target] and secretly draw out your fangs...")
else
to_chat(user, "You pull [target] close to you and draw out your fangs...")
- 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, "Your feeding was interrupted.")
//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("[user] shifts [target] closer to [user.p_their()] mouth.", \
// "You secretly slip your fangs into [target]'s flesh.", \
@@ -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, "You think no one saw you...")
else
to_chat(user, "Someone may have noticed...")
@@ -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, "Your feeding has been interrupted...but [target.p_they()] didn't seem to notice you.")
else
to_chat(user, "Your feeding has been interrupted!")
@@ -214,11 +214,11 @@
"Your teeth are ripped from [target]'s throat. [target.p_their(TRUE)] blood sprays everywhere!")
// 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, "You recoil at the taste of a lesser lifeform.")
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, "Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.")
warning_target_dead = TRUE
// Full?
- if (!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
+ if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
to_chat(user, "You are full. Further blood will be wasted.")
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, "Your victim's blood volume is fatally low!")
- 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, "Your victim's blood volume is dangerously low.")
- 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, "Your victim's blood is at an unsafe level.")
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, "You have bled your victim dry.")
break
@@ -279,7 +279,7 @@
// DONE!
//DeactivatePower(user,target)
- if (amSilent)
+ if(amSilent)
to_chat(user, "You slowly release [target]'s wrist." + (target.stat == 0 ? " [target.p_their(TRUE)] face lacks expression, like you've already been forgotten." : ""))
else
user.visible_message("[user] unclenches their teeth from [target]'s neck.", \
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm b/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm
index 3305504c15..f0724f8204 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_gohome.dm b/code/modules/antagonists/bloodsucker/powers/bs_gohome.dm
index 0da9ab5ba3..476f8ae012 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_gohome.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_gohome.dm
@@ -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, "Your coffin has been destroyed!")
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, "You focus on separating your consciousness from your physical form...")
// 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, "Your coffin has been destroyed! You no longer have a destination.")
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)
+
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_haste.dm b/code/modules/antagonists/bloodsucker/powers/bs_haste.dm
index ee1dd3007c..a1aaf50499 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_haste.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_haste.dm
@@ -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?"
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm b/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm
index 2c1b8d6321..48e12332a2 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm
@@ -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
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm
index 2fe7115d98..dc9d1d46a0 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm
@@ -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?"
diff --git a/code/modules/antagonists/bloodsucker/powers/bs_trespass.dm b/code/modules/antagonists/bloodsucker/powers/bs_trespass.dm
index 159c7b20b7..45d1dda3ef 100644
--- a/code/modules/antagonists/bloodsucker/powers/bs_trespass.dm
+++ b/code/modules/antagonists/bloodsucker/powers/bs_trespass.dm
@@ -6,7 +6,7 @@
button_icon_state = "power_tres"
bloodcost = 10
- cooldown = 60
+ cooldown = 80
amToggle = FALSE
//target_range = 2
diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm
index 88328c582c..8ed5b5e39c 100644
--- a/code/modules/antagonists/changeling/powers/fakedeath.dm
+++ b/code/modules/antagonists/changeling/powers/fakedeath.dm
@@ -15,7 +15,7 @@
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
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()
diff --git a/code/modules/antagonists/changeling/powers/headcrab.dm b/code/modules/antagonists/changeling/powers/headcrab.dm
index 1e06fb39de..4ef0d2f240 100644
--- a/code/modules/antagonists/changeling/powers/headcrab.dm
+++ b/code/modules/antagonists/changeling/powers/headcrab.dm
@@ -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))
diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm
index 2a0451bc76..17d82ec72d 100644
--- a/code/modules/antagonists/changeling/powers/panacea.dm
+++ b/code/modules/antagonists/changeling/powers/panacea.dm
@@ -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)
diff --git a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm b/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm
index d84338faea..f83afebe24 100644
--- a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm
+++ b/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm
@@ -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()
diff --git a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm
index 86099d8c79..e4722dbcb0 100644
--- a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm
+++ b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm
@@ -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")
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 794010d9c0..1bb1b8533a 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -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
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index da002e568c..7948b30035 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -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.
diff --git a/code/modules/antagonists/disease/disease_abilities.dm b/code/modules/antagonists/disease/disease_abilities.dm
index dc2249006c..7b30d10c5d 100644
--- a/code/modules/antagonists/disease/disease_abilities.dm
+++ b/code/modules/antagonists/disease/disease_abilities.dm
@@ -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 += "
"
if(symptoms.len == 1) //lazy boy's dream
name = initial(S.name)
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index 516f30d896..a20a9cef85 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -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 += "Back
[examining_ability.name]
[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]"
+ dat += "Back "
+ dat += "
[examining_ability.name]
"
+ dat += "[examining_ability.stat_block][examining_ability.long_desc][examining_ability.threshold_block]"
+ for(var/entry in examining_ability.threshold_block)
+ dat += "[entry]: [examining_ability.threshold_block[entry]] "
else
dat += "
Disease Statistics
\
Resistance: [DT.totalResistance()] \
diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm
index 52e13bdc69..2a91f53ed4 100644
--- a/code/modules/antagonists/ninja/ninja.dm
+++ b/code/modules/antagonists/ninja/ninja.dm
@@ -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
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index 2186e8b49e..fe3b5a3aeb 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -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()
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index c669ff7877..c703c85762 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -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.
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index ce455d9e67..7680d61034 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -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 = {"
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.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.
@@ -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)
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index 3cc3b48e50..e6ca95472e 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -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, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
- if(!uses)
- if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
- to_chat(owner, "[name] has run out of uses!")
- qdel(src)
+ if(uses)
+ if(!silent)
+ to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
+ 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, "[name] has run out of uses!")
+ 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, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
- if(!uses)
- if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
- to_chat(owner, "[name] has run out of uses!")
- Remove(owner)
- QDEL_IN(src, 100) //let any active timers on us finish up
+ if(uses)
+ if(!silent)
+ to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
+ 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, "[name] has run out of uses!")
+ 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, "run -o -a 'selfdestruct'")
sleep(5)
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "Running executable 'selfdestruct'...")
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, "!!! UNAUTHORIZED SELF-DESTRUCT ACCESS !!!")
to_chat(owner, "This is a class-3 security violation. This incident will be reported to Central Command.")
for(var/i in 1 to 3)
sleep(20)
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "Sending security report to Central Command.....[rand(0, 9) + (rand(20, 30) * i)]%")
sleep(3)
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "auth 'akjv9c88asdf12nb' ******************")
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, "Credentials accepted. Welcome, akjv9c88asdf12nb.")
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, "Arm self-destruct device? (Y/N)")
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, "Y")
sleep(15)
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "Confirm arming of self-destruct device? (Y/N)")
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, "Y")
sleep(rand(15, 25))
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "Please repeat password to confirm.")
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, "******************")
sleep(40)
- if(!owner || QDELETED(owner))
+ if(QDELETED(owner) || owner.stat == DEAD)
return
to_chat(owner, "Credentials accepted. Transmitting arming signal...")
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, "Overcurrent applied to the powernet.")
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, "Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].")
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.
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index e6bb3f1295..492da73e66 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -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)
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index bd4f1a8acd..70cb29e7a3 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -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
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index a88eb1e42a..f75d32e781 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -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
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index c67b79478e..7c8952eb33 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -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)
diff --git a/code/modules/assembly/playback.dm b/code/modules/assembly/playback.dm
index eecb991434..42135f7ff9 100644
--- a/code/modules/assembly/playback.dm
+++ b/code/modules/assembly/playback.dm
@@ -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)
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index 4fba44a3f2..53cbb8ea2a 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -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 = {"
-
-
-Send Signal
-Frequency/Code for signaler:
-Frequency:
-[format_frequency(src.frequency)]
-Set
-
-Code:
-[src.code]
-Set
-[t1]
-"}
- 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
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index e49368016b..f7c5dce30f 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -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)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
index 5835912cd3..bc58ef158f 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm
@@ -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()
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index ff2a655aac..86e8863b2b 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -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
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 2fd1bdc121..1099020662 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -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()
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
index 8c7d82d549..5b929452fe 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
@@ -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)
- . = ..()
- . += "You can hold Ctrl and click on it to toggle it on and off."
- . += "You can hold Alt and click on it to maximize its pressure."
/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,"You maximize the pressure on the [src].")
- 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)
. = ..()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
index 9da9e49e01..4b6a4a4c10 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm
@@ -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
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
index c69c4c47b0..877826c1c1 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
@@ -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)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 3cbf1b4d0e..f2f2329661 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -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
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 22cd9d7fca..10eac9c717 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -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
diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
index e8704b4c40..ce4aba6ab7 100644
--- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm
@@ -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 ..()
diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm
index 7c517720a8..ddb907a2ad 100644
--- a/code/modules/atmospherics/machinery/portable/pump.dm
+++ b/code/modules/atmospherics/machinery/portable/pump.dm
@@ -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)
diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm
index d52f2d8356..0c902e0426 100644
--- a/code/modules/atmospherics/machinery/portable/scrubber.dm
+++ b/code/modules/atmospherics/machinery/portable/scrubber.dm
@@ -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)
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index bd4e716357..3562350473 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -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)
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 34886c5b27..7421b9e09a 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -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 = "[short_desc]"
+ if(flavour_text != "")
+ output_message += "\n[flavour_text]"
+ if(important_info != "")
+ output_message += "\n[important_info]"
+ 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 = "You are a space doctor!"
+ 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 = "You are a space bartender! Time to mix drinks and change lives. Smoking space drugs makes it easier to understand your patrons' odd dialect."
+ 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 = "You're, like, totally a dudebro, bruh. Ch'yea. You came here, like, on spring break, hopin' to pick up some bangin' hot chicks, y'knaw?"
+ 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 = "You are a Nanotrasen Commander!"
+ 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 = "You are a Nanotrasen Private Security Officer!"
+ 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 = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
+ 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 = "By unknown powers, your rotting remains have been resurrected! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
+ 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
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index 85ac20ca0d..fc797d227c 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -595,8 +595,9 @@
job_description = "Syndicate Snow Operative"
faction = ROLE_SYNDICATE
outfit = /datum/outfit/snowsyndie
- 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."
+ 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"
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index 744fb78ba5..d4c9fdbee7 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -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, " ")
diff --git a/code/modules/cargo/bounties/silly.dm b/code/modules/cargo/bounties/silly.dm
index f790126cf2..e0d2c87a2d 100644
--- a/code/modules/cargo/bounties/silly.dm
+++ b/code/modules/cargo/bounties/silly.dm
@@ -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)
\ No newline at end of file
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index 526062d0f7..64b208a90b 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -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("[user] swipes a suspicious card through [src]!",
- "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.")
+ if(user)
+ user.visible_message("[user] swipes a suspicious card through [src]!",
+ "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.")
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, "Access denied.")
- return
- if(action != "add" && requestonly)
- return
switch(action)
if("send")
if(!SSshuttle.supply.canMove())
diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm
index 77b57466d9..d15fc18b6e 100644
--- a/code/modules/cargo/exports/gear.dm
+++ b/code/modules/cargo/exports/gear.dm
@@ -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
diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm
index e53db0bf7b..e4efaf0810 100644
--- a/code/modules/cargo/exports/parts.dm
+++ b/code/modules/cargo/exports/parts.dm
@@ -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)
\ No newline at end of file
+ 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
diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm
index 18a525b8dd..5b78a5d630 100644
--- a/code/modules/cargo/exports/weapons.dm
+++ b/code/modules/cargo/exports/weapons.dm
@@ -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
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index a4ede0cad2..20dc724707 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -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)
diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm
index 259ea2d7e3..ea8ef8ba0f 100644
--- a/code/modules/cargo/packs/armory.dm
+++ b/code/modules/cargo/packs/armory.dm
@@ -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,
diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm
index 40d21e4505..4a64979502 100644
--- a/code/modules/cargo/packs/costumes_toys.dm
+++ b/code/modules/cargo/packs/costumes_toys.dm
@@ -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"
diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm
index 747e820f52..e32811f2d0 100644
--- a/code/modules/cargo/packs/emergency.dm
+++ b/code/modules/cargo/packs/emergency.dm
@@ -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."
diff --git a/code/modules/cargo/packs/engine.dm b/code/modules/cargo/packs/engine.dm
index 499881a110..27891f3ab6 100644
--- a/code/modules/cargo/packs/engine.dm
+++ b/code/modules/cargo/packs/engine.dm
@@ -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!"
diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm
index 6492df5215..22258d19a7 100644
--- a/code/modules/cargo/packs/engineering.dm
+++ b/code/modules/cargo/packs/engineering.dm
@@ -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."
diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm
index c9862282dc..6c1742896f 100644
--- a/code/modules/cargo/packs/materials.dm
+++ b/code/modules/cargo/packs/materials.dm
@@ -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,
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
index a60afe4f7a..ea327ae820 100644
--- a/code/modules/cargo/packs/medical.dm
+++ b/code/modules/cargo/packs/medical.dm
@@ -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
\ No newline at end of file
diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm
index f8656ef761..d9c9794bd8 100644
--- a/code/modules/cargo/packs/misc.dm
+++ b/code/modules/cargo/packs/misc.dm
@@ -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!"
diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm
index dd0f987d25..4aa991fc3f 100644
--- a/code/modules/cargo/packs/organic.dm
+++ b/code/modules/cargo/packs/organic.dm
@@ -3,22 +3,47 @@
// 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.
//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Organic /////////////////////////////////////////
+//////////////////////////////// Organic /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/organic
group = "Food & Hydroponics"
crate_type = /obj/structure/closet/crate/freezer
+/datum/supply_pack/organic/randomized
+ var/num_contained = 15
+
+/datum/supply_pack/organic/randomized/fill(obj/structure/closet/crate/C)
+ for(var/i in 1 to num_contained)
+ var/item = pick(contains)
+ new item(C)
+
//////////////////////////////////////////////////////////////////////////////
-/////////////////////////////// Food /////////////////////////////////////////
+//////////////////////////////// Meals ///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
-/datum/supply_pack/organic/candy/randomised
+/datum/supply_pack/organic/combomeal2
+ name = "Burger Combo #2"
+ desc = "We value our customers at the Greasy Griddle, so much so that we're willing to deliver -just for you.- This combo meal contains two burgers, a soda, fries, a toy, and some chicken nuggets."
+ cost = 3200
+ contains = list(/obj/item/reagent_containers/food/snacks/burger/bigbite,
+ /obj/item/reagent_containers/food/snacks/burger/cheese,
+ /obj/item/reagent_containers/food/snacks/fries,
+ /obj/item/reagent_containers/food/condiment/pack/ketchup,
+ /obj/item/reagent_containers/food/condiment/pack/ketchup,
+ /obj/item/reagent_containers/food/snacks/nugget,
+ /obj/item/reagent_containers/food/snacks/nugget,
+ /obj/item/reagent_containers/food/snacks/nugget,
+ /obj/item/reagent_containers/food/snacks/nugget,
+ /obj/item/toy/plush/random)
+ crate_name = "combo meal w/toy"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/organic/randomized/candy
name = "Candy Crate"
desc = "For people that have an insatiable sweet tooth! Has ten candies to be eaten up.."
cost = 2500
- var/num_contained = 10 //number of items picked to be contained in a randomised crate
+ num_contained = 10
contains = list(/obj/item/reagent_containers/food/snacks/candy,
/obj/item/reagent_containers/food/snacks/lollipop,
/obj/item/reagent_containers/food/snacks/gumball,
@@ -47,91 +72,6 @@
/obj/item/storage/fancy/donut_box)
crate_name = "candy crate"
-/datum/supply_pack/organic/randomized/chef
- name = "Excellent Meat Crate"
- desc = "The best cuts in the whole galaxy."
- cost = 2000
- contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime,
- /obj/item/reagent_containers/food/snacks/meat/slab/killertomato,
- /obj/item/reagent_containers/food/snacks/meat/slab/bear,
- /obj/item/reagent_containers/food/snacks/meat/slab/xeno,
- /obj/item/reagent_containers/food/snacks/meat/slab/spider,
- /obj/item/reagent_containers/food/snacks/meat/rawbacon,
- /obj/item/reagent_containers/food/snacks/spiderleg,
- /obj/item/reagent_containers/food/snacks/carpmeat,
- /obj/item/reagent_containers/food/snacks/meat/slab/human)
- crate_name = "food crate"
-
-/datum/supply_pack/organic/randomized/chef/fill(obj/structure/closet/crate/C)
- for(var/i in 1 to 15)
- var/item = pick(contains)
- new item(C)
-
-/datum/supply_pack/organic/exoticseeds
- name = "Exotic Seeds Crate"
- desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
- cost = 1500
- contains = list(/obj/item/seeds/nettle,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/plump,
- /obj/item/seeds/liberty,
- /obj/item/seeds/amanita,
- /obj/item/seeds/reishi,
- /obj/item/seeds/banana,
- /obj/item/seeds/bamboo,
- /obj/item/seeds/eggplant/eggy,
- /obj/item/seeds/random,
- /obj/item/seeds/random)
- crate_name = "exotic seeds crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/food
- name = "Food Crate"
- desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, an enzyme and sugar bottle, and three slabs of monkeymeat."
- cost = 1000
- contains = list(/obj/item/reagent_containers/food/condiment/flour,
- /obj/item/reagent_containers/food/condiment/flour,
- /obj/item/reagent_containers/food/condiment/rice,
- /obj/item/reagent_containers/food/condiment/rice,
- /obj/item/reagent_containers/food/condiment/milk,
- /obj/item/reagent_containers/food/condiment/milk,
- /obj/item/reagent_containers/food/condiment/soymilk,
- /obj/item/reagent_containers/food/condiment/saltshaker,
- /obj/item/reagent_containers/food/condiment/peppermill,
- /obj/item/storage/fancy/egg_box,
- /obj/item/storage/fancy/egg_box,
- /obj/item/reagent_containers/food/condiment/enzyme,
- /obj/item/reagent_containers/food/condiment/sugar,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/grown/banana,
- /obj/item/reagent_containers/food/snacks/grown/banana,
- /obj/item/reagent_containers/food/snacks/grown/banana)
- crate_name = "food crate"
-
-/datum/supply_pack/organic/randomized/chef/fruits
- name = "Fruit Crate"
- desc = "Rich in vitamins, may contain oranges."
- cost = 1500
- contains = list(/obj/item/reagent_containers/food/snacks/grown/citrus/lime,
- /obj/item/reagent_containers/food/snacks/grown/citrus/orange,
- /obj/item/reagent_containers/food/snacks/grown/banana,
- /obj/item/reagent_containers/food/snacks/grown/watermelon,
- /obj/item/reagent_containers/food/snacks/grown/apple,
- /obj/item/reagent_containers/food/snacks/grown/berries,
- /obj/item/reagent_containers/food/snacks/grown/citrus/lemon,
- /obj/item/reagent_containers/food/snacks/grown/pineapple,
- /obj/item/reagent_containers/food/snacks/grown/cherries,
- /obj/item/reagent_containers/food/snacks/grown/grapes,
- /obj/item/reagent_containers/food/snacks/grown/grapes/green,
- /obj/item/reagent_containers/food/snacks/grown/eggplant,
- /obj/item/reagent_containers/food/snacks/grown/peach,
- /obj/item/reagent_containers/food/snacks/grown/strawberry)
- crate_name = "food crate"
-
/datum/supply_pack/organic/fiestatortilla
name = "Fiesta Crate"
desc = "Spice up the kitchen with this fiesta themed food order! Contains 8 tortilla based food items, as well as a sombrero, moustache, and cloak!"
@@ -151,79 +91,6 @@
/obj/item/reagent_containers/glass/bottle/capsaicin)
crate_name = "fiesta crate"
-/datum/supply_pack/organic/grill
- name = "Grilling Starter Kit"
- desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT ONLY 5000 BUX GET NOW! Contains a cooking grill and five fuel coal sheets."
- cost = 3000
- crate_type = /obj/structure/closet/crate
- contains = list(/obj/item/stack/sheet/mineral/coal/five,
- /obj/machinery/grill/unwrenched)
- crate_name = "grilling starter kit crate"
-
-/datum/supply_pack/organic/grillfuel
- name = "Grilling Fuel Kit"
- desc = "Contains coal and coal accessories. (Note: only ten coal sheets.)"
- cost = 1000
- crate_type = /obj/structure/closet/crate
- contains = list(/obj/item/stack/sheet/mineral/coal/ten)
- crate_name = "grilling fuel kit crate"
-
-/datum/supply_pack/organic/cream_piee
- name = "High-yield Clown-grade Cream Pie Crate"
- desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results."
- cost = 6000
- contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie)
- crate_name = "party equipment crate"
- contraband = TRUE
- access = ACCESS_THEATRE
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/organic/fakemeat
- name = "Meat Crate"
- desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free chemically compounded meat! Contains 12 slabs of meat product, and 4 slabs of *carp*."
- cost = 1200 // Buying 3 food crates nets you 9 meat for 900 points, plus like, 6 bags of rice, flour, and egg boxes. This is 12 for 500, but you -only- get meat and carp.
- contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
- /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
- /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
- /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
- /obj/item/reagent_containers/food/snacks/carpmeat/imitation)
- crate_name = "meaty crate"
- crate_type = /obj/structure/closet/crate/freezer
-
-/datum/supply_pack/organic/monkeydripmeat
- name = "*Meat* Crate"
- desc = "Need some meat? With this do-it-yourself kit you'll be swimming in it! Contains a monkey cube, an IV drip, and some cryoxadone!"
- cost = 2150
- contraband = TRUE
- contains = list(/obj/item/reagent_containers/food/snacks/monkeycube,
- /obj/item/restraints/handcuffs/cable,
- /obj/machinery/iv_drip,
- /obj/item/reagent_containers/glass/beaker/cryoxadone,
- /obj/item/reagent_containers/glass/beaker/cryoxadone)
- crate_name = "monkey meat crate"
-
-/datum/supply_pack/organic/mixedboxes
- name = "Mixed Ingredient Boxes"
- desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!"
- cost = 2300
- contains = list(/obj/item/storage/box/ingredients/wildcard,
- /obj/item/storage/box/ingredients/wildcard,
- /obj/item/storage/box/ingredients/wildcard,
- /obj/item/storage/box/ingredients/wildcard)
- crate_name = "wildcard food crate"
- crate_type = /obj/structure/closet/crate/freezer
-
/datum/supply_pack/organic/pizza
name = "Pizza Crate"
desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!"
@@ -258,9 +125,129 @@
considered \[REDACTED\] and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \
of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.")
-/datum/supply_pack/organic/randomized/chef/vegetables
- name = "Vegetables Crate"
- desc = "Grown in vats."
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Raw Ingredients /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/organic/food
+ name = "Food Crate"
+ desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, an enzyme and sugar bottle, and three slabs of monkeymeat."
+ cost = 1000
+ contains = list(/obj/item/reagent_containers/food/condiment/flour,
+ /obj/item/reagent_containers/food/condiment/flour,
+ /obj/item/reagent_containers/food/condiment/rice,
+ /obj/item/reagent_containers/food/condiment/rice,
+ /obj/item/reagent_containers/food/condiment/milk,
+ /obj/item/reagent_containers/food/condiment/milk,
+ /obj/item/reagent_containers/food/condiment/soymilk,
+ /obj/item/reagent_containers/food/condiment/saltshaker,
+ /obj/item/reagent_containers/food/condiment/peppermill,
+ /obj/item/storage/fancy/egg_box,
+ /obj/item/storage/fancy/egg_box,
+ /obj/item/reagent_containers/food/condiment/enzyme,
+ /obj/item/reagent_containers/food/condiment/sugar,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/grown/banana,
+ /obj/item/reagent_containers/food/snacks/grown/banana,
+ /obj/item/reagent_containers/food/snacks/grown/banana)
+ crate_name = "food crate"
+
+/datum/supply_pack/organic/randomized/fruits
+ name = "Fruit Crate"
+ desc = "Rich in vitamins and possibly sugar. Contains 15 assorted fruits."
+ cost = 1500
+ contains = list(/obj/item/reagent_containers/food/snacks/grown/citrus/lime,
+ /obj/item/reagent_containers/food/snacks/grown/citrus/orange,
+ /obj/item/reagent_containers/food/snacks/grown/banana,
+ /obj/item/reagent_containers/food/snacks/grown/watermelon,
+ /obj/item/reagent_containers/food/snacks/grown/apple,
+ /obj/item/reagent_containers/food/snacks/grown/berries,
+ /obj/item/reagent_containers/food/snacks/grown/citrus/lemon,
+ /obj/item/reagent_containers/food/snacks/grown/pineapple,
+ /obj/item/reagent_containers/food/snacks/grown/cherries,
+ /obj/item/reagent_containers/food/snacks/grown/grapes,
+ /obj/item/reagent_containers/food/snacks/grown/grapes/green,
+ /obj/item/reagent_containers/food/snacks/grown/eggplant,
+ /obj/item/reagent_containers/food/snacks/grown/peach,
+ /obj/item/reagent_containers/food/snacks/grown/strawberry)
+ crate_name = "fruit crate"
+
+/datum/supply_pack/organic/cream_piee
+ name = "High-yield Clown-grade Cream Pie Crate"
+ desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results."
+ cost = 6000
+ contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie)
+ crate_name = "party equipment crate"
+ contraband = TRUE
+ access = ACCESS_THEATRE
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/organic/randomized
+ name = "Meat Crate (Exotic)"
+ desc = "The best cuts in the whole galaxy. Contains 15 assorted exotic meats."
+ cost = 2000
+ contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime,
+ /obj/item/reagent_containers/food/snacks/meat/slab/killertomato,
+ /obj/item/reagent_containers/food/snacks/meat/slab/bear,
+ /obj/item/reagent_containers/food/snacks/meat/slab/xeno,
+ /obj/item/reagent_containers/food/snacks/meat/slab/spider,
+ /obj/item/reagent_containers/food/snacks/meat/rawbacon,
+ /obj/item/reagent_containers/food/snacks/spiderleg,
+ /obj/item/reagent_containers/food/snacks/carpmeat,
+ /obj/item/reagent_containers/food/snacks/meat/slab/human)
+ crate_name = "exotic meat crate"
+
+/datum/supply_pack/organic/monkeydripmeat
+ name = "Meat Crate (Fresh)"
+ desc = "Need some meat? With this do-it-yourself kit you'll be swimming in it! Contains a monkey cube, an IV drip, and some cryoxadone!"
+ cost = 2150
+ contraband = TRUE
+ contains = list(/obj/item/reagent_containers/food/snacks/monkeycube,
+ /obj/item/restraints/handcuffs/cable,
+ /obj/machinery/iv_drip,
+ /obj/item/reagent_containers/glass/beaker/cryoxadone,
+ /obj/item/reagent_containers/glass/beaker/cryoxadone)
+ crate_name = "monkey meat crate"
+
+/datum/supply_pack/organic/fakemeat
+ name = "Meat Crate 'Synthetic'"
+ desc = "Run outta meat already? Keep the lizards content with this freezer filled with cruelty-free chemically compounded meat! Contains 12 slabs of meat product, and 4 slabs of *carp*."
+ cost = 1200 // Buying 3 food crates nets you 9 meat for 900 points, plus like, 6 bags of rice, flour, and egg boxes. This is 12 for 500, but you -only- get meat and carp.
+ contains = list(/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/meat/slab/meatproduct,
+ /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
+ /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
+ /obj/item/reagent_containers/food/snacks/carpmeat/imitation,
+ /obj/item/reagent_containers/food/snacks/carpmeat/imitation)
+ crate_name = "meaty crate"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/organic/mixedboxes
+ name = "Mixed Ingredient Boxes"
+ desc = "Get overwhelmed with inspiration by ordering these boxes of surprise ingredients! Get four boxes filled with an assortment of products!"
+ cost = 2300
+ contains = list(/obj/item/storage/box/ingredients/wildcard,
+ /obj/item/storage/box/ingredients/wildcard,
+ /obj/item/storage/box/ingredients/wildcard,
+ /obj/item/storage/box/ingredients/wildcard)
+ crate_name = "wildcard food crate"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/organic/randomized/vegetables
+ name = "Vegetable Crate"
+ desc = "Grown in vats. Contains 15 assorted vegetables."
cost = 1300
contains = list(/obj/item/reagent_containers/food/snacks/grown/chili,
/obj/item/reagent_containers/food/snacks/grown/corn,
@@ -270,7 +257,7 @@
/obj/item/reagent_containers/food/snacks/grown/mushroom/chanterelle,
/obj/item/reagent_containers/food/snacks/grown/onion,
/obj/item/reagent_containers/food/snacks/grown/pumpkin)
- crate_name = "food crate"
+ crate_name = "veggie crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Hydroponics /////////////////////////////////////
@@ -302,42 +289,6 @@
crate_name = "beekeeping starter crate"
crate_type = /obj/structure/closet/crate/hydroponics
-/datum/supply_pack/organic/exoticseeds
- name = "Exotic Seeds Crate"
- desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
- cost = 1500
- contains = list(/obj/item/seeds/nettle,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/plump,
- /obj/item/seeds/liberty,
- /obj/item/seeds/amanita,
- /obj/item/seeds/reishi,
- /obj/item/seeds/banana,
- /obj/item/seeds/eggplant/eggy,
- /obj/item/seeds/random,
- /obj/item/seeds/random)
- crate_name = "exotic seeds crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/* Maintenance Garden Crate basically does this and more.
-/datum/supply_pack/organic/hydroponics
- name = "Hydroponics Crate"
- desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron."
- cost = 1750
- contains = list(/obj/item/reagent_containers/spray/plantbgone,
- /obj/item/reagent_containers/spray/plantbgone,
- /obj/item/reagent_containers/glass/bottle/ammonia,
- /obj/item/reagent_containers/glass/bottle/ammonia,
- /obj/item/hatchet,
- /obj/item/cultivator,
- /obj/item/plant_analyzer,
- /obj/item/clothing/gloves/botanic_leather,
- /obj/item/clothing/suit/apron)
- crate_name = "hydroponics crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-*/
/datum/supply_pack/organic/hydroponics/hydrotank
name = "Hydroponics Backpack Crate"
desc = "Bring on the flood with this high-capacity backpack crate. Contains 500 units of life-giving H2O. Requires hydroponics access to open."
@@ -390,10 +341,30 @@
/obj/item/seeds/sunflower,
/obj/item/seeds/chanter,
/obj/item/seeds/potato,
- /obj/item/seeds/sugarcane)
+ /obj/item/seeds/sugarcane,
+ /obj/item/seeds/ambrosia)
crate_name = "seeds crate"
crate_type = /obj/structure/closet/crate/hydroponics
+/datum/supply_pack/organic/exoticseeds
+ name = "Seeds Crate (Exotic)"
+ desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
+ cost = 1500
+ contains = list(/obj/item/seeds/nettle,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/plump,
+ /obj/item/seeds/liberty,
+ /obj/item/seeds/amanita,
+ /obj/item/seeds/reishi,
+ /obj/item/seeds/banana,
+ /obj/item/seeds/eggplant/eggy,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random)
+ crate_name = "exotic seeds crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Misc /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -414,6 +385,29 @@
crate_name = "sporting crate"
crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:(
+/datum/supply_pack/organic/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/organic/vday
name = "Surplus Valentine Crate"
desc = "Turns out we got warehouses of this love-y dove-y crap. We're sending out small bargain buddle of Valentine gear. This crate has two boxes of chocolate, three poppy flowers, five candy hearts, and three cards."
diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm
index f14bc37371..8852a7e945 100644
--- a/code/modules/cargo/packs/science.dm
+++ b/code/modules/cargo/packs/science.dm
@@ -24,13 +24,13 @@
name = "Advanced Alien Alloy Crate Crate"
desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro we’ll send you a sheet of advanced alien alloy."
cost = 15000
- contraband = TRUE
DropPodOnly = TRUE
+ contraband = TRUE
contains = list(/obj/item/stack/sheet/mineral/abductor)
crate_name = "alien bro alloy crate"
/datum/supply_pack/science/beakers
- name = "Chemistry Beackers Crate"
+ name = "Chemistry Beakers Crate"
desc = "Glassware for any chemistry lab! Contains four small beakers, three large, two plastic, and one metamaterial. As well as three droppers and two pairs of latex gloves."
cost = 1500
contains = list(/obj/item/reagent_containers/glass/beaker,
@@ -82,6 +82,16 @@
/obj/item/integrated_electronics/wirer)
crate_name = "circuitry starter pack crate"
+/datum/supply_pack/science/glasswork
+ name = "Glass Blower Kit Crate"
+ desc = "Learn and make glassworks of usefull things for a profit! Contains glassworking tools and blowing rods. Glass not included."
+ cost = 1000
+ contains = list(/obj/item/glasswork/glasskit,
+ /obj/item/glasswork/glasskit,
+ /obj/item/glasswork/blowing_rod,
+ /obj/item/glasswork/blowing_rod)
+ crate_name = "glassblower gear crate"
+
/datum/supply_pack/science/monkey
name = "Monkey Cube Crate"
desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!"
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
index 69967d65d1..3b602d54d2 100644
--- a/code/modules/cargo/packs/security.dm
+++ b/code/modules/cargo/packs/security.dm
@@ -163,13 +163,6 @@
/obj/item/storage/box/handcuffs)
crate_name = "security supply crate"
-/datum/supply_pack/security/vending/security
- name = "SecTech Supply Crate"
- desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate."
- cost = 1500
- contains = list(/obj/machinery/vending/security)
- crate_name = "SecTech supply crate"
-
/datum/supply_pack/security/firingpins
name = "Standard Firing Pins Crate"
desc = "Upgrade your arsenal with 10 standard firing pins. Requires Security access to open."
diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm
index 01524b1910..942720dd6b 100644
--- a/code/modules/cargo/packs/service.dm
+++ b/code/modules/cargo/packs/service.dm
@@ -10,9 +10,24 @@
group = "Service"
//////////////////////////////////////////////////////////////////////////////
-/////////////////////////////// Cargo ////////////////////////////////////////
+//////////////////////////////// Cargo ///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
+/datum/supply_pack/service/wrapping_paper
+ name = "Cargo Packaging 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 festive (and normal) wrapping paper. Also contains a hand labeler and a destination tagger for easy shipping!"
+ cost = 1000
+ contains = list(/obj/item/stack/wrapping_paper,
+ /obj/item/stack/wrapping_paper,
+ /obj/item/stack/wrapping_paper,
+ /obj/item/stack/packageWrap,
+ /obj/item/stack/packageWrap,
+ /obj/item/stack/packageWrap,
+ /obj/item/destTagger,
+ /obj/item/hand_labeler)
+ crate_type = /obj/structure/closet/crate/wooden
+ crate_name = "wrapping paper crate"
+
/datum/supply_pack/service/cargo_supples
name = "Cargo Supplies Crate"
desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping. Now with extra toner cartidges!"
@@ -101,6 +116,23 @@
crate_name = "ice cream vat crate"
crate_type = /obj/structure/closet/crate
+/datum/supply_pack/service/grill
+ name = "Grilling Starter Kit"
+ desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT ONLY 5000 BUX GET NOW! Contains a cooking grill and five fuel coal sheets."
+ cost = 3000
+ contains = list(/obj/item/stack/sheet/mineral/coal/five,
+ /obj/machinery/grill/unwrenched)
+ crate_name = "grilling starter kit crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/service/grillfuel
+ name = "Grilling Fuel Kit"
+ desc = "Contains coal and coal accessories. (Note: only ten coal sheets.)"
+ cost = 1000
+ contains = list(/obj/item/stack/sheet/mineral/coal/ten)
+ crate_name = "grilling fuel kit crate"
+ crate_type = /obj/structure/closet/crate
+
/datum/supply_pack/service/cutlery
name = "Kitchen Cutlery Deluxe Set"
desc = "Need to slice and dice away those \"Tomatoes\"? Well we got what you need! From a nice set of knifes, forks, plates, glasses, and a whetstone for when you got some grizzle that is a bit harder to slice then normal."
@@ -115,7 +147,7 @@
/obj/item/kitchen/knife,
/obj/item/kitchen/knife/butcher,
/obj/item/kitchen/knife/butcher,
- /obj/item/kitchen/rollingpin,
+ /obj/item/kitchen/rollingpin,
/obj/item/trash/plate,
/obj/item/trash/plate,
/obj/item/trash/plate,
@@ -240,45 +272,3 @@
crate_name = "janitorial cart crate"
crate_type = /obj/structure/closet/crate/large
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Vendor Refills //////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/service/vending/bartending
- name = "Bartending Supply Crate"
- desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!"
- cost = 2000
- contains = list(/obj/item/vending_refill/boozeomat,
- /obj/item/vending_refill/coffee,
- /obj/item/book/granter/action/drink_fling)
- crate_name = "bartending supply crate"
-
-/datum/supply_pack/service/vending/cigarette
- name = "Cigarette Supply Crate"
- desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill."
- cost = 1500
- contains = list(/obj/item/vending_refill/cigarette)
- crate_name = "cigarette supply crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/vending/games
- name = "Games Supply Crate"
- desc = "Get your game on with this game vending machine refill."
- cost = 1000
- contains = list(/obj/item/vending_refill/games)
- crate_name = "games supply crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/vending/snack
- name = "Snack Supply Crate"
- desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!"
- cost = 1500
- contains = list(/obj/item/vending_refill/snack)
- crate_name = "snacks supply crate"
-
-/datum/supply_pack/service/vending/cola
- name = "Softdrinks Supply Crate"
- desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!"
- cost = 1500
- contains = list(/obj/item/vending_refill/cola)
- crate_name = "soft drinks supply crate"
diff --git a/code/modules/cargo/packs/vending.dm b/code/modules/cargo/packs/vending.dm
new file mode 100644
index 0000000000..f9982d17b6
--- /dev/null
+++ b/code/modules/cargo/packs/vending.dm
@@ -0,0 +1,148 @@
+
+//Reminders-
+// 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.
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// Vending //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/vending
+ group = "Vending"
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////// Service, Medical, Sec //////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/vending/bartending
+ name = "Bartending Supply Crate"
+ desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!"
+ cost = 2000
+ contains = list(/obj/item/vending_refill/boozeomat,
+ /obj/item/vending_refill/coffee,
+ /obj/item/book/granter/action/drink_fling)
+ crate_name = "bartending supply crate"
+
+/datum/supply_pack/vending/cigarette
+ name = "Cigarette Supply Crate"
+ desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/cigarette)
+ crate_name = "cigarette supply crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/vending/games
+ name = "Games Supply Crate"
+ desc = "Get your game on with this game vending machine refill."
+ cost = 1000
+ contains = list(/obj/item/vending_refill/games)
+ crate_name = "games supply crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/vending/kinkmate
+ name = "Kinkmate Supply and Construction Kit"
+ cost = 2000
+ contraband = TRUE
+ contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate)
+ crate_name = "Kinkmate construction kit"
+
+/datum/supply_pack/vending/medical
+ 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"
+ crate_type = /obj/structure/closet/crate/medical
+
+/datum/supply_pack/vending/security
+ name = "SecTech Supply Crate"
+ desc = "Officer Paul bought all the donuts? Then refill the security vendor with ths crate. Requires Security Access to open."
+ cost = 1500
+ access = ACCESS_SECURITY
+ contains = list(/obj/machinery/vending/security)
+ crate_name = "SecTech supply crate"
+ crate_type = /obj/structure/closet/crate/secure/gear
+
+/datum/supply_pack/vending/snack
+ name = "Snack Supply Crate"
+ desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!"
+ cost = 1500
+ contains = list(/obj/item/vending_refill/snack)
+ crate_name = "snacks supply crate"
+
+/datum/supply_pack/vending/cola
+ name = "Softdrinks Supply Crate"
+ desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!"
+ cost = 1500
+ contains = list(/obj/item/vending_refill/cola)
+ crate_name = "soft drinks supply crate"
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Wardrobe Vendors ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/vending/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/vending/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/vending/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/vending/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/vending/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/vending/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/vending/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/vending/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"
diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm
index 5f3d6dab0a..adfbe3308a 100644
--- a/code/modules/cargo/supplypod.dm
+++ b/code/modules/cargo/supplypod.dm
@@ -114,7 +114,7 @@
for(var/X in CM.internal_organs)
var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) //Pick a random direction to toss them in
var/obj/item/organ/O = X
- O.Remove(CM) //Note that this isn't the same proc as for lists
+ O.Remove() //Note that this isn't the same proc as for lists
O.forceMove(T) //Move the organ outta the body
O.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away
sleep(1)
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 37d0fddc3c..7bafefcf53 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -28,7 +28,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
//This proc sends the asset to the client, but only if it needs it.
//This proc blocks(sleeps) unless verify is set to false
-/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE)
+/proc/send_asset(client/client, asset_name, verify = TRUE)
if(!istype(client))
if(ismob(client))
var/mob/M = client
@@ -72,7 +72,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
return 1
//This proc blocks(sleeps) unless verify is set to false
-/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE)
+/proc/send_asset_list(client/client, list/asset_list, verify = TRUE)
if(!istype(client))
if(ismob(client))
var/mob/M = client
@@ -122,7 +122,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start.
//The proc calls procs that sleep for long times.
-/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
+/proc/getFilesSlow(client/client, list/files, register_asset = TRUE)
var/concurrent_tracker = 1
for(var/file in files)
if (!client)
@@ -140,13 +140,13 @@ You can set verify to TRUE if you want send() to sleep until the client has the
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
//if it's an icon or something be careful, you'll have to copy it before further use.
-/proc/register_asset(var/asset_name, var/asset)
+/proc/register_asset(asset_name, asset)
SSassets.cache[asset_name] = asset
//Generated names do not include file extention.
//Used mainly for code that deals with assets in a generic way
//The same asset will always lead to the same asset name
-/proc/generate_asset_name(var/file)
+/proc/generate_asset_name(file)
return "asset.[md5(fcopy_rsc(file))]"
@@ -156,7 +156,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
GLOBAL_LIST_EMPTY(asset_datums)
//get an assetdatum or make a new one
-/proc/get_asset_datum(var/type)
+/proc/get_asset_datum(type)
return GLOB.asset_datums[type] || new type()
/datum/asset
@@ -323,6 +323,13 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/size_id = sprite[SPR_SIZE]
return {""}
+/datum/asset/spritesheet/proc/icon_class_name(sprite_name)
+ var/sprite = sprites[sprite_name]
+ if (!sprite)
+ return null
+ var/size_id = sprite[SPR_SIZE]
+ return {"[name][size_id] [sprite_name]"}
+
#undef SPR_SIZE
#undef SPR_IDX
#undef SPRSZ_COUNT
@@ -379,14 +386,24 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/tgui
assets = list(
- "tgui.css" = 'tgui/assets/tgui.css',
- "tgui.js" = 'tgui/assets/tgui.js',
- "font-awesome.min.css" = 'tgui/assets/font-awesome.min.css',
- "fontawesome-webfont.eot" = 'tgui/assets/fonts/fontawesome-webfont.eot',
- "fontawesome-webfont.woff2" = 'tgui/assets/fonts/fontawesome-webfont.woff2',
- "fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff',
- "fontawesome-webfont.ttf" = 'tgui/assets/fonts/fontawesome-webfont.ttf',
- "fontawesome-webfont.svg" = 'tgui/assets/fonts/fontawesome-webfont.svg'
+ // tgui
+ "tgui.css" = 'tgui/assets/tgui.css',
+ "tgui.js" = 'tgui/assets/tgui.js',
+ // tgui-next
+ "tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html',
+ "tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html',
+ "tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js',
+ "tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css',
+ "shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js',
+ "shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js',
+ "shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js',
+ "shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js',
+ )
+
+/datum/asset/group/tgui
+ children = list(
+ /datum/asset/simple/tgui,
+ /datum/asset/simple/fontawesome
)
/datum/asset/simple/headers
@@ -448,7 +465,8 @@ GLOBAL_LIST_EMPTY(asset_datums)
"scanner" = 'icons/pda_icons/pda_scanner.png',
"signaler" = 'icons/pda_icons/pda_signaler.png',
"status" = 'icons/pda_icons/pda_status.png',
- "dronephone" = 'icons/pda_icons/pda_dronephone.png'
+ "dronephone" = 'icons/pda_icons/pda_dronephone.png',
+ "emoji" = 'icons/pda_icons/pda_emoji.png'
)
/datum/asset/spritesheet/simple/paper
@@ -511,7 +529,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
)
-
+
/datum/asset/simple/IRV
assets = list(
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
@@ -550,7 +568,8 @@ GLOBAL_LIST_EMPTY(asset_datums)
children = list(
/datum/asset/simple/jquery,
/datum/asset/simple/goonchat,
- /datum/asset/spritesheet/goonchat
+ /datum/asset/spritesheet/goonchat,
+ /datum/asset/simple/fontawesome
)
/datum/asset/simple/jquery
@@ -563,18 +582,23 @@ GLOBAL_LIST_EMPTY(asset_datums)
verify = FALSE
assets = list(
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
- "errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js',
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
- "fontawesome-webfont.eot" = 'tgui/assets/fonts/fontawesome-webfont.eot',
- "fontawesome-webfont.svg" = 'tgui/assets/fonts/fontawesome-webfont.svg',
- "fontawesome-webfont.ttf" = 'tgui/assets/fonts/fontawesome-webfont.ttf',
- "fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff',
- "font-awesome.css" = 'code/modules/goonchat/browserassets/css/font-awesome.css',
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
"browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
"browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
)
+/datum/asset/simple/fontawesome
+ verify = FALSE
+ assets = list(
+ "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
+ "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
+ "fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
+ "fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
+ "font-awesome.css" = 'html/font-awesome/css/all.min.css',
+ "v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
+ )
+
/datum/asset/spritesheet/goonchat
name = "chat"
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 7e466caf8a..e05cee3487 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -47,6 +47,18 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
else if (job in completed_asset_jobs) //byond bug ID:2256651
to_chat(src, "An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)")
src << browse("...", "window=asset_cache_browser")
+ // Keypress passthrough
+ if(href_list["__keydown"])
+ var/keycode = browser_keycode_to_byond(href_list["__keydown"])
+ if(keycode)
+ keyDown(keycode)
+ return
+ if(href_list["__keyup"])
+ var/keycode = browser_keycode_to_byond(href_list["__keyup"])
+ if(keycode)
+ keyUp(keycode)
+ return
+
var/mtl = CONFIG_GET(number/minute_topic_limit)
if (!holder && mtl)
@@ -411,7 +423,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
winset(src, "[child]", "[entries[child]]")
if (!ispath(child, /datum/verbs/menu))
var/procpath/verbpath = child
- if (copytext(verbpath.name,1,2) != "@")
+ if (verbpath.name[1] != "@")
new child(src)
for (var/thing in prefs.menuoptions)
@@ -502,7 +514,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
message_admins("Failed Login: [key] - New account attempting to connect during panic bunker")
- to_chat(src, "You must first join the Discord to verify your account before joining this server. To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: https://discord.gg/E6SQuhz") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
+ to_chat(src, "You must first join the Discord to verify your account before joining this server. To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: https://discord.gg/E6SQuhz If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
var/list/connectiontopic_a = params2list(connectiontopic)
var/list/panic_addr = CONFIG_GET(string/panic_server_address)
if(panic_addr && !connectiontopic_a["redirect"])
@@ -526,6 +538,8 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if(!account_join_date)
account_join_date = "Error"
account_age = -1
+ else if(ckey in GLOB.bunker_passthrough)
+ GLOB.bunker_passthrough -= ckey
qdel(query_client_in_db)
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
if(!query_get_client_age.Execute())
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 546268b5c7..006cdf8dc8 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/auto_fit_viewport = TRUE
var/uplink_spawn_loc = UPLINK_PDA
-
+
var/sprint_spacebar = FALSE
var/sprint_toggle = FALSE
@@ -1476,9 +1476,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("flavor_text")
- var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_MESSAGE_LEN*2, TRUE)
- if(!isnull(msg))
- msg = copytext(msg, 1, MAX_MESSAGE_LEN*2)
+ var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_MESSAGE_LEN, TRUE)
+ if(msg)
+ msg = msg
features["flavor_text"] = msg
if("hair")
@@ -2230,7 +2230,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("never_hypno")
cit_toggles ^= NEVER_HYPNO
-
+
if("aphro")
cit_toggles ^= NO_APHRO
@@ -2239,7 +2239,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("bimbo")
cit_toggles ^= BIMBOFICATION
-
+
//END CITADEL EDIT
if("ambientocclusion")
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 08ecefb91f..24e44f191e 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -118,7 +118,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
- path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]"
+ path = "data/player_saves/[ckey[1]]/[ckey]/[filename]"
/datum/preferences/proc/load_preferences()
if(!path)
@@ -479,15 +479,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
be_random_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body))
- if(gender == MALE)
- hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_male_list)
- facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_male_list)
- else
- hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_female_list)
- facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_female_list)
- underwear = sanitize_inlist(underwear, GLOB.underwear_list)
+ hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_list)
+ facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list)
+ underwear = sanitize_inlist(underwear, GLOB.underwear_list)
+ undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
undie_color = sanitize_hexcolor(undie_color, 3, FALSE, initial(undie_color))
- undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
shirt_color = sanitize_hexcolor(shirt_color, 3, FALSE, initial(shirt_color))
socks = sanitize_inlist(socks, GLOB.socks_list)
socks_color = sanitize_hexcolor(socks_color, 3, FALSE, initial(socks_color))
diff --git a/code/modules/client/verbs/aooc.dm b/code/modules/client/verbs/aooc.dm
index 3f86a617e6..bc32d3c222 100644
--- a/code/modules/client/verbs/aooc.dm
+++ b/code/modules/client/verbs/aooc.dm
@@ -31,7 +31,7 @@ GLOBAL_VAR_INIT(normal_aooc_colour, "#ce254f")
if(QDELETED(src))
return
- msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
+ msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
var/raw_msg = msg
if(!msg)
diff --git a/code/modules/client/verbs/looc.dm b/code/modules/client/verbs/looc.dm
index 38cfd84b9c..075cabcbbb 100644
--- a/code/modules/client/verbs/looc.dm
+++ b/code/modules/client/verbs/looc.dm
@@ -13,7 +13,7 @@ GLOBAL_VAR_INIT(normal_looc_colour, "#6699CC")
if(!mob)
return
- msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
+ msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
if(!msg)
return
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index 8a233025a1..44290d1c2f 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -28,7 +28,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
if(QDELETED(src))
return
- msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
+ msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
var/raw_msg = msg
if(!msg)
@@ -36,7 +36,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
msg = emoji_parse(msg)
- if((copytext(msg, 1, 2) in list(".",";",":","#")) || (findtext(lowertext(copytext(msg, 1, 5)), "say")))
+ if((msg[1] in list(".",";",":","#")) || findtext_char(msg, "say", 1, 5))
if(alert("Your message \"[raw_msg]\" looks like it was meant for in game communication, say it in OOC?", "Meant for OOC?", "No", "Yes") != "Yes")
return
diff --git a/code/modules/client/verbs/ping.dm b/code/modules/client/verbs/ping.dm
index de19d0d52c..02c5b5a7fd 100644
--- a/code/modules/client/verbs/ping.dm
+++ b/code/modules/client/verbs/ping.dm
@@ -14,9 +14,9 @@
/client/verb/display_ping(time as num)
set instant = TRUE
set name = ".display_ping"
- to_chat(src, "Round trip ping took [round(pingfromtime(time),1)]ms")
+ to_chat(src, "Round trip ping took [round(pingfromtime(time),1)]ms (Avg: [round(avgping, 1)]ms])")
/client/verb/ping()
set name = "Ping"
set category = "OOC"
- winset(src, null, "command=.display_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]")
\ No newline at end of file
+ winset(src, null, "command=.display_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]")
diff --git a/code/modules/clothing/glasses/vg_glasses.dm b/code/modules/clothing/glasses/vg_glasses.dm
deleted file mode 100644
index a51a03242c..0000000000
--- a/code/modules/clothing/glasses/vg_glasses.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-
-//VG rip
-
-/obj/item/clothing/glasses/sunglasses/purple
- desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes, and the colored lenses let you see the world in purple."
- name = "purple sunglasses"
- icon_state = "sun_purple"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/glasses/sunglasses/star
- name = "star-shaped sunglasses"
- desc = "Novelty sunglasses, both lenses are in the shape of a star."
- icon_state = "sun_star"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/glasses/sunglasses/rockstar
- name = "red star-shaped sunglasses"
- desc = "Novelty sunglasses with a fancy silver frame and two red-tinted star-shaped lenses. You should probably stomp on them and get a pair of normal ones."
- icon_state = "sun_star_silver"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/glasses/gglasses
- name = "Green Glasses"
- desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme."
- icon_state = "gglasses"
- item_state = "gglasses"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/glasses/welding/superior
- name = "superior welding goggles"
- desc = "Welding goggles made from more expensive materials, strangely smells like potatoes. Allows for better vision than normal goggles.."
- icon_state = "rwelding-g"
- item_state = "rwelding-g"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- actions_types = list(/datum/action/item_action/toggle)
- flash_protect = 2
- tint = 1
- visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT
- flags_cover = GLASSESCOVERSEYES
- visor_flags_inv = HIDEEYES
- glass_colour_type = /datum/client_colour/glass_colour/green
\ No newline at end of file
diff --git a/code/modules/clothing/gloves/ring.dm b/code/modules/clothing/gloves/ring.dm
new file mode 100644
index 0000000000..54aaa58849
--- /dev/null
+++ b/code/modules/clothing/gloves/ring.dm
@@ -0,0 +1,26 @@
+/obj/item/clothing/gloves/ring
+ name = "gold ring"
+ desc = "A tiny gold ring, sized to wrap around a finger."
+ gender = NEUTER
+ w_class = WEIGHT_CLASS_TINY
+ icon = 'icons/obj/ring.dmi'
+ icon_state = "ringgold"
+ body_parts_covered = 0
+ attack_verb = list("proposed")
+ transfer_prints = TRUE
+ strip_delay = 40
+
+/obj/item/clothing/gloves/ring/suicide_act(mob/living/carbon/user)
+ user.visible_message("\[user] is putting the [src] in [user.p_their()] mouth! It looks like [user] is trying to choke on the [src]!")
+ return OXYLOSS
+
+
+/obj/item/clothing/gloves/ring/diamond
+ name = "diamond ring"
+ desc = "A tiny gold ring, studded with a diamond. Cultures have used these rings in courtship for a millenia."
+ icon_state = "ringdiamond"
+
+/obj/item/clothing/gloves/ring/silver
+ name = "silver ring"
+ desc = "A tiny silver ring, sized to wrap around a finger."
+ icon_state = "ringsilver"
diff --git a/code/modules/clothing/gloves/vg_gloves.dm b/code/modules/clothing/gloves/vg_gloves.dm
deleted file mode 100644
index 6d7e775314..0000000000
--- a/code/modules/clothing/gloves/vg_gloves.dm
+++ /dev/null
@@ -1,70 +0,0 @@
-
-/obj/item/clothing/gloves/batmangloves
- desc = "Used for handling all things bat related."
- name = "batgloves"
- icon_state = "bmgloves"
- item_state = "bmgloves"
- item_color = "bmgloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-obj/item/clothing/gloves/bikergloves
- name = "Biker's Gloves"
- icon_state = "biker-gloves"
- item_state = "biker-gloves"
- item_color = "bikergloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/megagloves
- desc = "Uncomfortably bulky armored gloves."
- name = "DRN-001 Gloves"
- icon_state = "megagloves"
- item_state = "megagloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/protogloves
- desc = "Funcionally identical to the DRN-001 model's, but in red!"
- name = "Prototype Gloves"
- icon_state = "protogloves"
- item_state = "protogloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/megaxgloves
- desc = "An upgrade to the DRN-001's gauntlets, retains the uncomfortable armor, but comes with white gloves!"
- name = "Maverick Hunter gloves"
- icon_state = "megaxgloves"
- item_state = "megaxgloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/joegloves
- desc = "Large grey gloves, very similar to the Prototype's."
- name = "Sniper Gloves"
- icon_state = "joegloves"
- item_state = "joegloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/doomguy
- desc = ""
- name = "Doomguy's gloves"
- icon_state = "doom"
- item_state = "doom"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/anchor_arms
- name = "Anchor Arms"
- desc = "When you're a jerk, everybody loves you."
- icon_state = "anchorarms"
- item_state = "anchorarms"
-
-/obj/item/clothing/gloves/neorussian
- name = "neo-Russian gloves"
- desc = "Utilizes a non-slip technology that allows you to never drop your precious bottles of vodka."
- icon_state = "nr_gloves"
- item_state = "nr_gloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/gloves/neorussian/fingerless
- name = "neo-Russian fingerless gloves"
- desc = "For these tense combat situations when you just have to pick your nose."
- icon_state = "nr_fgloves"
- item_state = "nr_fgloves"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
\ No newline at end of file
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 696ff1346c..189fb46e46 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -423,3 +423,15 @@
desc = "A security cowboy hat, perfect for any true lawman"
icon_state = "cowboyhat_sec"
item_state= "cowboyhat_sec"
+
+/obj/item/clothing/head/squatter_hat
+ name = "slav squatter hat"
+ icon_state = "squatter_hat"
+ item_state = "squatter_hat"
+ desc = "Cyka blyat."
+
+/obj/item/clothing/head/russobluecamohat
+ name = "russian blue camo beret"
+ desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food."
+ icon_state = "russobluecamohat"
+ item_state = "russobluecamohat"
diff --git a/code/modules/clothing/head/vg_hats.dm b/code/modules/clothing/head/vg_hats.dm
deleted file mode 100644
index 87f64baf13..0000000000
--- a/code/modules/clothing/head/vg_hats.dm
+++ /dev/null
@@ -1,155 +0,0 @@
-/obj/item/clothing/head/helmet/dredd
- name = "Judge Helmet"
- desc = "Judge, Jury, and Executioner."
- icon_state = "dredd-helmet"
- item_state = "dredd-helmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- armor = list(melee = 40, bullet = 30, laser = 30,energy = 30, bomb = 50, bio = 90, rad = 20, fire = 50, acid = 50)
- cold_protection = HEAD
- min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
- heat_protection = HEAD
- max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
- strip_delay = 80
- dog_fashion = null
-
-/obj/item/clothing/head/helmet/aviatorhelmet
- name = "Aviator Helmet"
- desc = "Help the Bombardier!"
- armor = list(melee = 25, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0)
- item_state = "aviator_helmet"
- icon_state = "aviator_helmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/biker
- name = "Biker's Helmet"
- desc = "This helmet should protect you from russians and masked vigilantes."
- armor = list(melee = 25, bullet = 15, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0)
- icon_state = "biker_helmet"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR
-
-/obj/item/clothing/head/helmet/richard
- name = "Richard"
- desc = "Do you like hurting people?"
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
- icon_state = "richard"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR
-
-/obj/item/clothing/head/helmet/megahelmet
- name = "DRN-001 Helmet"
- desc = "The helmet of the DRN-001 model. A simple, sturdy blue helmet."
- icon_state = "megahelmet"
- item_state = "megahelmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- siemens_coefficient = 1
-
-/obj/item/clothing/head/helmet/protohelmet
- name = "Prototype Helmet"
- desc = "Shiny red helmet with white accents and a built in shaded visor that does absolutely nothing, nothing but look rad as hell."
- icon_state = "protohelmet"
- item_state = "protohelmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- siemens_coefficient = 1
-
-/obj/item/clothing/head/helmet/megaxhelmet
- name = "Maverick Hunter Helmet"
- desc = "Heavily armored upgrade to the DRN-001 model's helmet, now comes with a pointless red crystal thing!"
- icon_state = "megaxhelmet"
- item_state = "megaxhelmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/joehelmet
- name = "Sniper Helmet"
- desc = "Helmet belonging to one of the many mass produced 'Joe' type robots."
- icon_state = "joehelmet"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR
- item_state = "joehelmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/doomguy
- name = "Doomguy's helmet"
- desc = ""
- icon_state = "doom"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR
- item_state = "doom"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0)
-
-/obj/item/clothing/head/helmet/neorussian
- name = "neo-Russian helmet"
- desc = "This piece of equipment can double as a pillow, a bowl, an emergency toilet, and sometimes as a helmet."
- icon_state = "nr_helmet"
- item_state = "nr_helmet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/panzer
- name = "Panzer Cap"
- desc = "Command any mech in style."
- icon_state = "panzercap"
- item_state = "panzercap"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/russobluecamohat
- name = "russian blue camo beret"
- desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food."
- icon_state = "russobluecamohat"
- item_state = "russobluecamohat"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/russofurhat
- name = "russian fur hat"
- desc = "Russian winter got you down? Maybe your enemy, but not you!"
- icon_state = "russofurhat"
- item_state = "russofurhat"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/squatter_hat
- name = "slav squatter hat"
- icon_state = "squatter_hat"
- item_state = "squatter_hat"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- desc = "Cyka blyat."
-
-/obj/item/clothing/head/snake
- name = "snake head"
- desc = "Reenact acts of violence against reptiles, or sneak into a swamp unnoticed."
- icon_state = "snakehead"
- item_state = "snakehead"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-/obj/item/clothing/head/mummy_rags
- name = "mummy rags"
- desc = "Ancient rags taken off from some mummy."
- icon_state = "mummy"
- item_state = "mummy"
- item_color = "mummy"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
-
-/obj/item/clothing/head/clownpiece
- name = "Clownpiece's jester hat"
- desc = "A purple polka-dotted jester's hat with yellow pompons."
- icon_state = "clownpiece"
- item_state = "clownpiece"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/mitre
- name = "mitre"
- desc = "A funny hat worn by extremely boring people."
- icon_state = "mitre"
- item_state = "mitre"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/tinfoil
- name = "tinfoil hat"
- desc = "There's no evidence that the security staff is NOT out to get you."
- icon_state = "foilhat"
- item_state = "paper"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- siemens_coefficient = 2
-
-/obj/item/clothing/head/celtic
- name = "\improper Celtic crown"
- desc = "According to legend, Celtic kings would use crowns like this one to shield their subjects from harsh winters back on Earth."
- icon_state = "celtic_crown"
- item_state = "celtic_crown"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
diff --git a/code/modules/clothing/masks/vg_masks.dm b/code/modules/clothing/masks/vg_masks.dm
deleted file mode 100644
index 29b65a6b8e..0000000000
--- a/code/modules/clothing/masks/vg_masks.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-/obj/item/clothing/mask/gas/clown_hat/wiz
- name = "purple clown wig and mask"
- desc = "Some pranksters are truly magical."
- icon_state = "wizzclown"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/mask/chapmask
- name = "venetian mask"
- desc = "A plain porcelain mask that covers the entire face. Standard attire for particularly unspeakable religions. The eyes are wide shut."
- icon_state = "chapmask"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/mask/neorussian
- name = "neo-Russian mask"
- desc = "Somehow, it makes you act and look way more polite than usual."
- icon_state = "nr_mask"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index 9a46b6b759..2b43460257 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -189,7 +189,7 @@
var/tagname = null
/obj/item/clothing/neck/petcollar/attack_self(mob/user)
- tagname = copytext(sanitize(input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot") as null|text),1,MAX_NAME_LEN)
+ tagname = stripped_input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot", MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
/obj/item/clothing/neck/petcollar/worn_overlays(isinhands, icon_file, style_flags = NONE)
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 1532f50808..bdbac1165e 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -18,8 +18,9 @@
R.freqlock = TRUE
var/obj/item/card/id/W = H.wear_id
- W.registered_name = H.real_name
- W.update_label(W.registered_name, W.assignment)
+ if(W)
+ W.registered_name = H.real_name
+ W.update_label(W.registered_name, W.assignment)
/datum/outfit/ert/commander
name = "ERT Commander"
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 952dbe0ad8..8864add0d8 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -57,3 +57,32 @@
name = "blood-red magboots"
icon_state = "syndiemag0"
magboot_state = "syndiemag"
+
+/obj/item/clothing/shoes/magboots/crushing
+ desc = "Normal looking magboots that are altered to increase magnetic pull to crush anything underfoot."
+
+/obj/item/clothing/shoes/magboots/crushing/proc/crush(mob/living/user)
+ if (!isturf(user.loc) || !magpulse)
+ return
+ var/turf/T = user.loc
+ for (var/mob/living/A in T)
+ if (A != user && A.lying)
+ A.adjustBruteLoss(rand(10,13))
+ to_chat(A,"[user]'s magboots press down on you, crushing you!")
+ A.emote("scream")
+
+/obj/item/clothing/shoes/magboots/crushing/attack_self(mob/user)
+ . = ..()
+ if (magpulse)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
+ else
+ UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
+
+/obj/item/clothing/shoes/magboots/crushing/equipped(mob/user,slot)
+ . = ..()
+ if (slot == SLOT_SHOES && magpulse)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
+
+/obj/item/clothing/shoes/magboots/crushing/dropped(mob/user)
+ . = ..()
+ UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
diff --git a/code/modules/clothing/shoes/vg_shoes.dm b/code/modules/clothing/shoes/vg_shoes.dm
deleted file mode 100644
index 53b093dc72..0000000000
--- a/code/modules/clothing/shoes/vg_shoes.dm
+++ /dev/null
@@ -1,124 +0,0 @@
-
-/obj/item/clothing/shoes/leather
- name = "leather shoes"
- desc = "A sturdy pair of leather shoes."
- icon_state = "leather"
- item_color = "leather"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/magboots/deathsquad
- desc = "Very expensive and advanced magnetic boots, used only by the elite during extravehicular activity to ensure the user remains safely attached to the vehicle."
- name = "deathsquad magboots"
- icon_state = "DS-magboots0"
- magboot_state = "DS-magboots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/magboots/atmos
- desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle. These are painted in the colors of an atmospheric technician."
- name = "atmospherics magboots"
- icon_state = "atmosmagboots0"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- magboot_state = "atmosmagboots"
- resistance_flags = FIRE_PROOF
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/simonshoes
- name = "Simon's Shoes"
- desc = "Simon's Shoes."
- icon_state = "simonshoes"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/kneesocks
- name = "kneesocks"
- desc = "A pair of girly knee-high socks."
- icon_state = "kneesock"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/jestershoes
- name = "Jester Shoes"
- desc = "As worn by the clowns of old."
- icon_state = "jestershoes"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/aviatorboots
- name = "Aviator Boots"
- desc = "Boots suitable for just about any occasion."
- icon_state = "aviator_boots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/libertyshoes
- name = "Liberty Shoes"
- desc = "Freedom isn't free, neither were these shoes."
- icon_state = "libertyshoes"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/megaboots
- name = "DRN-001 Boots"
- desc = "Large armored boots, very weak to large spikes."
- icon_state = "megaboots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/protoboots
- name = "Prototype Boots"
- desc = "Functionally identical to the DRN-001 model's boots, but in red."
- icon_state = "protoboots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/megaxboots
- name = "Maverick Hunter boots"
- desc = "Regardless of how much stronger these boots are than the DRN-001 model's, they're still extremely easy to pierce with a large spike."
- icon_state = "megaxboots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/joeboots
- name = "Sniper Boots"
- desc = "Nearly identical to the Prototype's boots, except in black."
- icon_state = "joeboots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/doomguy
- name = "Doomguy's boots"
- desc = "If you look closely, you might see skull fragments still buried in these boots."
- icon_state = "doom"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/rottenshoes
- name = "rotten shoes"
- desc = "These shoes seem perfect for sneaking around."
- icon_state = "rottenshoes"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/sandal/slippers
- name = "magic slippers"
- icon_state = "slippers"
- desc = "For the wizard that puts comfort first. Who's going to laugh?"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/slippers_worn
- name = "worn bunny slippers"
- desc = "Fluffy..."
- icon_state = "slippers_worn"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/shoes/jackboots/neorussian
- name = "neo-Russian boots"
- desc = "Tovarish, no one will realize you stepped on a pile of shit if your pair already looks like shit."
- icon_state = "nr_boots"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index c9753b3053..703fe26287 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -693,6 +693,29 @@
listeningTo = null
return ..()
+/obj/item/clothing/head/helmet/space/hardsuit/soviet
+ name = "soviet hardhelmet"
+ desc = "Crafted with the pride of the proletariat. The vengeful gaze of the visor roots out all fascists and capitalists."
+ item_state = "rig0-soviet"
+ item_color = "soviet"
+ icon_state = "rig0-soviet"
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75)
+ mutantrace_variation = NONE
+
+/obj/item/clothing/suit/space/hardsuit/soviet
+ name = "soviet hardsuit"
+ desc = "Crafted with the pride of the proletariat. The last thing the enemy sees is the bottom of this armor's boot."
+ item_state = "rig-soviet"
+ icon_state = "rig-soviet"
+ slowdown = 0.8
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75)
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/soviet
+ mutantrace_variation = NONE
+
+/obj/item/clothing/suit/space/hardsuit/soviet/Initialize()
+ . = ..()
+ allowed = GLOB.security_hardsuit_allowed
+
/////////////SHIELDED//////////////////////////////////
/obj/item/clothing/suit/space/hardsuit/shielded
diff --git a/code/modules/clothing/spacesuits/vg_spess.dm b/code/modules/clothing/spacesuits/vg_spess.dm
deleted file mode 100644
index 517539f3af..0000000000
--- a/code/modules/clothing/spacesuits/vg_spess.dm
+++ /dev/null
@@ -1,120 +0,0 @@
-
- //VG Ports
-
-/obj/item/clothing/head/helmet/space/hardsuit/soviet
- name = "soviet hardhelmet"
- desc = "Crafted with the pride of the proletariat. The vengeful gaze of the visor roots out all fascists and capitalists."
- item_state = "hardsuit0-soviet"
- icon_state = "hardsuit0-soviet"
- armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20)
- item_color = "soviet"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/soviet
- name = "soviet hardsuit"
- desc = "Crafted with the pride of the proletariat. The last thing the enemy sees is the bottom of this armor's boot."
- item_state = "hardsuit-soviet"
- icon_state = "hardsuit-soviet"
- slowdown = 1
- armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20)
- allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/soviet
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/space/hardsuit/knight
- name = "Space-Knight helm"
- desc = "A well polished helmet belonging to a Space-Knight. Favored by space-jousters for its ability to stay on tight after being launched from a mass driver."
- icon_state = "hardsuit0-knight"
- item_state = "hardsuit0-knight"
- armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60)
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- item_color="knight"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/knight
- name = "Space-Knight armour"
- desc = "A well polished set of armour belonging to a Space-Knight. Maidens Rescued in Space: 100, Maidens who have slept with me in Space: 0."
- icon_state = "hardsuit-knight"
- item_state = "hardsuit-knight"
- slowdown = 1
- allowed = list(/obj/item/gun,/obj/item/melee/baton,/obj/item/tank,/obj/item/shield/energy,/obj/item/claymore)
- armor = list(melee = 60, bullet = 40, laser = 40,energy = 30, bomb = 50, bio = 100, rad = 60)
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- siemens_coefficient = 0.5
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/knight
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/space/hardsuit/knight/black
- name = "Black Knight's helm"
- desc = "An ominous black helmet with a gold trim. The small viewports create an intimidating look, while also making it nearly impossible to see anything."
- icon_state = "hardsuit0-blackknight"
- item_state = "hardsuit0-blackknight"
- armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60)
- item_color="blackknight"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/knight/black
- name = "Black Knight's armour"
- desc = "An ominous black suit of armour with a gold trim. Surprisingly good at preventing accidental loss of limbs."
- icon_state = "hardsuit-blackknight"
- item_state = "hardsuit-blackknight"
- armor = list(melee = 70, bullet = 65, laser = 50,energy = 25, bomb = 60, bio = 100, rad = 60)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/knight/black
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/space/hardsuit/knight/solaire
- name = "Solar helm"
- desc = "A simple helmet. 'Made in Astora' is inscribed on the back."
- icon_state = "hardsuit0-solaire"
- item_state = "hardsuit0-solaire"
- armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100)
- item_color="solaire"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/knight/solaire
- name = "Solar armour"
- desc = "A solar powered hardsuit with a fancy insignia on the chest. Perfect for stargazers and adventurers alike."
- icon_state = "hardsuit-solaire"
- item_state = "hardsuit-solaire"
- armor = list(melee = 60, bullet = 65, laser = 90,energy = 30, bomb = 60, bio = 100, rad = 100)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/knight/solaire
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/head/helmet/space/hardsuit/t51b
- name = "T-51b Power Armor"
- desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!"
- icon_state = "hardsuit0-t51b"
- item_state = "hardsuit0-t51b"
- armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100)
- item_color="t51b"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/t51b
- name = "T-51b Power Armor"
- desc = "Relic of a bygone era, the T-51b is powered by a TX-28 MicroFusion Pack, which holds enough fuel to power its internal hydraulics for a century!"
- icon_state = "hardsuit-t51b"
- item_state = "hardsuit-t51b"
- armor = list(melee = 35, bullet = 35, laser = 40, energy = 40, bomb = 80, bio = 100, rad = 100)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/t51b
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-
-/obj/item/clothing/head/helmet/space/bomberman
- name = "Bomberman head"
- desc = "Terrorism has never looked so adorable."
- icon_state = "bomberman"
- item_state = "bomberman"
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0)
- siemens_coefficient = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-obj/item/clothing/suit/space/bomberman
- name = "Bomberman's suit"
- desc = "Doesn't actually make you immune to bombs!"
- icon_state = "bomberman"
- item_state = "bomberman"
- slowdown = 0
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0)
- siemens_coefficient = 0
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
\ No newline at end of file
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index b8287c7f4c..7d56fbe6dd 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -81,7 +81,7 @@
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | ACID_PROOF
+ resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE
/obj/item/clothing/head/hooded/cloakhood/drake
name = "drake helm"
@@ -90,4 +90,4 @@
armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100)
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | ACID_PROOF
+ resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 127d2e4f04..84609e29d8 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -922,3 +922,78 @@
/obj/item/clothing/head/hooded/winterhood/christmashoodrg
icon_state = "christmashoodrg"
+
+/obj/item/clothing/suit/hooded/wintercoat/polychromic
+ name = "polychromic winter coat"
+ icon_state = "coatpoly"
+ item_state = "coatpoly"
+ item_color = "coatpoly"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/polychromic
+ hasprimary = TRUE
+ hassecondary = TRUE
+ hastertiary = TRUE
+ primary_color = "#6A6964"
+ secondary_color = "#C4B8A6"
+ tertiary_color = "#0000FF"
+
+/obj/item/clothing/head/hooded/winterhood/polychromic
+ icon_state = "winterhood_poly"
+ item_color = "winterhood_poly"
+ item_state = "winterhood_poly"
+
+/obj/item/clothing/head/hooded/winterhood/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens.
+ . = ..()
+ if(suit.hasprimary | suit.hassecondary)
+ if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
+ if(suit.hasprimary) //checks if overlays are enabled
+ var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[item_color]-primary") //automagical sprite selection
+ primary_worn.color = suit.primary_color //colors the overlay
+ . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite.
+ if(suit.hassecondary)
+ var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[item_color]-secondary")
+ secondary_worn.color = suit.secondary_color
+ . += secondary_worn
+
+/obj/item/clothing/suit/hooded/wintercoat/polychromic/worn_overlays(isinhands, icon_file, style_flags = NONE) //this is where the main magic happens.
+ . = ..()
+ if(hasprimary | hassecondary | hastertiary)
+ if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
+ if(hasprimary) //checks if overlays are enabled
+ var/mutable_appearance/primary_worn = mutable_appearance(icon_file, "[item_color]-primary[suittoggled ? "_t" : ""]") //automagical sprite selection
+ primary_worn.color = primary_color //colors the overlay
+ . += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite.
+ if(hassecondary)
+ var/mutable_appearance/secondary_worn = mutable_appearance(icon_file, "[item_color]-secondary[suittoggled ? "_t" : ""]")
+ secondary_worn.color = secondary_color
+ . += secondary_worn
+ if(hastertiary)
+ var/mutable_appearance/tertiary_worn = mutable_appearance(icon_file, "[item_color]-tertiary[suittoggled ? "_t" : ""]")
+ tertiary_worn.color = tertiary_color
+ . += tertiary_worn
+
+/obj/item/clothing/suit/hooded/wintercoat/AltClick(mob/user)
+ . = ..()
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+ if(hasprimary | hassecondary | hastertiary)
+ var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays
+ switch(choice) //Lets the list's options actually lead to something
+ if("Primary Color")
+ var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it.
+ if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL.
+ primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly
+ update_icon() //updates the item icon
+ user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works.
+ if("Secondary Color")
+ var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null
+ if(secondary_color_input)
+ secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ user.regenerate_icons()
+ if("Tertiary Color")
+ var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null
+ if(tertiary_color_input)
+ tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ user.regenerate_icons()
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/clothing/suits/vg_suits.dm b/code/modules/clothing/suits/vg_suits.dm
deleted file mode 100644
index be6cd9938e..0000000000
--- a/code/modules/clothing/suits/vg_suits.dm
+++ /dev/null
@@ -1,138 +0,0 @@
-
-/obj/item/clothing/suit/armor/xcomsquaddie
- name = "Squaddie Armor"
- desc = "A suit of armor with heavy padding to protect against projectile and laser attacks. Distributed to shadow organization squaddies."
- icon_state = "xcomarmor2"
- item_state = "xcomarmor2"
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list(melee = 50, bullet = 50, laser = 50, energy = 30, bomb = 60, bio = 30, rad = 20)
- siemens_coefficient = 0.5
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/armor/xcomsquaddie/dredd
- name = "Judge Armor"
- desc = "A large suit of heavy armor, fit for a Judge."
- icon_state = "dredd-suit"
- item_state = "dredd-suit"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-
-/obj/item/clothing/suit/armor/xcomarmor
- name = "Mysterious Armor"
- desc = "A suit of armor with heavy plating to protect against melee attacks. Distributed to shadow organization squaddies."
- icon_state = "xcomarmor1"
- item_state = "xcomarmor1"
- body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list(melee = 50, bullet = 50, laser = 50, energy = 30, bomb = 60, bio = 30, rad = 20)
- slowdown = 1
- siemens_coefficient = 0.5
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/armor/vest/neorussian
- name = "neo-Russian vest"
- desc = "The narkotiki camo pattern will come useful for botany raids."
- icon_state = "nr_vest"
- item_state = "nr_vest"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/armor/doomguy
- name = "Doomguy's armor"
- desc = ""
- icon_state = "doom"
- item_state = "doom"
- body_parts_covered = CHEST|GROIN
- slowdown = 0
- armor = list(melee = 50, bullet = 30, laser = 20, energy = 20, bomb = 30, bio = 0, rad = 0)
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-
-/obj/item/clothing/suit/kaminacape
- name = "Kamina's Cape"
- desc = "Don't believe in yourself, dumbass. Believe in me. Believe in the Kamina who believes in you."
- icon_state = "kaminacape"
- body_parts_covered = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/officercoat
- name = "Officer's Coat"
- desc = "Ein Mantel gemacht, um die Juden zu bestrafen."
- icon_state = "officersuit"
- body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/soldiercoat
- name = "Soldier's Coat"
- desc = "Und das heit: Erika."
- icon_state = "soldiersuit"
- body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/russofurcoat
- name = "russian fur coat"
- desc = "Let the land do the fighting for you."
- icon_state = "russofurcoat"
- allowed = list(/obj/item/gun)
- body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/doshjacket
- name = "Plasterer's Jacket"
- desc = "Perfect for doing up the house."
- icon_state = "doshjacket"
- body_parts_covered = CHEST|GROIN|ARMS
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/maidapron
- name = "Apron"
- desc = "Simple white apron."
- icon_state = "maidapron"
- body_parts_covered = CHEST|GROIN
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/clownpiece
- name = "small fairy wings"
- desc = "Some small and translucid insect-like wings."
- icon_state = "clownpiece"
- body_parts_covered = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/clownpiece/flying
- name = "small fairy wings"
- desc = "Some small and translucid insect-like wings. Looks like these are the real deal!"
- icon_state = "clownpiece-fly"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/suit/raincoat
- name = "Raincoat"
- desc = "Do you like Huey Lewis and the News?"
- icon_state = "raincoat"
- body_parts_covered =CHEST|GROIN|LEGS|ARMS|HANDS
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/suit.dmi'
- mutantrace_variation = NONE
-
-
diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm
index c27882aac7..6952a581da 100644
--- a/code/modules/clothing/under/jobs/medsci.dm
+++ b/code/modules/clothing/under/jobs/medsci.dm
@@ -178,19 +178,19 @@
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/under/rank/medical/blue
- name = "medical scrubs"
+ name = "blue medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue."
icon_state = "scrubsblue"
item_color = "scrubsblue"
can_adjust = FALSE
/obj/item/clothing/under/rank/medical/green
- name = "medical scrubs"
+ name = "green medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green."
icon_state = "scrubsgreen"
item_color = "scrubsgreen"
can_adjust = FALSE
/obj/item/clothing/under/rank/medical/purple
- name = "medical scrubs"
+ name = "purple medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple."
icon_state = "scrubspurple"
item_color = "scrubspurple"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index a2081851e1..a3a2b6b97e 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -131,6 +131,9 @@
item_color = "officer"
alt_covers_chest = TRUE
+/obj/item/clothing/under/rank/centcom_officer/syndicate
+ has_sensor = NO_SENSORS
+
/obj/item/clothing/under/rank/centcom_commander
desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
name = "\improper CentCom officer's jumpsuit"
@@ -945,4 +948,144 @@
icon_state = "christmasfemaleg"
item_state = "christmasfemaleg"
body_parts_covered = CHEST|GROIN
- can_adjust = FALSE
\ No newline at end of file
+ can_adjust = FALSE
+
+// Lunar Clothes
+/obj/item/clothing/under/lunar/qipao
+ name = "Black Qipao"
+ desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is black."
+ icon_state = "qipao"
+ item_state = "qipao"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/lunar/qipao/white
+ name = "White Qipao"
+ desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is white."
+ icon_state = "qipao_white"
+ item_state = "qipao_white"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/lunar/qipao/red
+ name = "Red Qipao"
+ desc = "A Qipao, traditionally worn in ancient Earth China by women during social events and lunar new years. This one is red."
+ icon_state = "qipao_red"
+ item_state = "qipao_red"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/lunar/cheongsam
+ name = "Black Cheongsam"
+ desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is black."
+ icon_state = "cheong"
+ item_state = "cheong"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/lunar/cheongsam/white
+ name = "White Cheongsam"
+ desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is white."
+ icon_state = "cheongw"
+ item_state = "cheongw"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/lunar/cheongsam/red
+ name = "Red Cheongsam"
+ desc = "A Cheongsam, traditionally worn in ancient Earth China by men during social events and lunar new years. This one is red.."
+ icon_state = "cheongr"
+ item_state = "cheongr"
+ body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/squatter_outfit
+ name = "slav squatter tracksuit"
+ desc = "Cyka blyat."
+ icon_state = "squatteroutfit"
+ item_state = "squatteroutfit"
+ item_color = "squatteroutfit"
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/russobluecamooutfit
+ name = "russian blue camo"
+ desc = "Drop and give me dvadtsat!"
+ icon_state = "russobluecamo"
+ item_state = "russobluecamo"
+ item_color = "russobluecamo"
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/keyholesweater
+ name = "keyhole sweater"
+ desc = "What is the point of this, anyway?"
+ icon_state = "keyholesweater"
+ item_state = "keyholesweater"
+ item_color = "keyholesweater"
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/stripper_pink
+ name = "pink stripper outfit"
+ icon_state = "stripper_p"
+ item_state = "stripper_p"
+ item_color = "stripper_p"
+
+/obj/item/clothing/under/stripper_green
+ name = "green stripper outfit"
+ icon_state = "stripper_g"
+ item_state = "stripper_g"
+ item_color = "stripper_g"
+ can_adjust = FALSE
+
+/obj/item/clothing/under/mankini
+ name = "pink mankini"
+ icon_state = "mankini"
+ item_state = "mankini"
+ item_color = "mankini"
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/wedding
+ name = "white wedding dress"
+ desc = "A white wedding gown made from the finest silk."
+ icon_state = "bride_white"
+ item_state = "bride_white"
+ item_color = "bride_white"
+ can_adjust = FALSE
+ mutantrace_variation = NONE
+
+/obj/item/clothing/under/wedding/orange
+ name = "orange wedding dress"
+ desc = "A big and puffy orange dress."
+ icon_state = "bride_orange"
+ item_state = "bride_orange"
+ item_color = "bride_orange"
+
+/obj/item/clothing/under/wedding/purple
+ name = "purple wedding dress"
+ desc = "A big and puffy purple dress."
+ icon_state = "bride_purple"
+ item_state = "bride_purple"
+ item_color = "bride_purple"
+
+/obj/item/clothing/under/wedding/blue
+ name = "blue wedding dress"
+ desc = "A big and puffy blue dress."
+ icon_state = "bride_blue"
+ item_state = "bride_blue"
+ item_color = "bride_blue"
+
+/obj/item/clothing/under/wedding/red
+ name = "red wedding dress"
+ desc = "A big and puffy red dress."
+ icon_state = "bride_red"
+ item_state = "bride_red"
+ item_color = "bride_red"
diff --git a/code/modules/clothing/under/vg_under.dm b/code/modules/clothing/under/vg_under.dm
deleted file mode 100644
index 555ed3b795..0000000000
--- a/code/modules/clothing/under/vg_under.dm
+++ /dev/null
@@ -1,436 +0,0 @@
-// Fixed to work with Citadel code. Apparently none of them had NO_MUTANTRACE flags.
-// I was pissy when I realised how to fix this because it's so fucking easy and nobody apparently had done it.
-
-/obj/item/clothing/under/stripper_pink
- name = "pink stripper outfit"
- icon_state = "stripper_p"
- item_state = "stripper_p"
- item_color = "stripper_p"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/stripper_green
- name = "green stripper outfit"
- icon_state = "stripper_g"
- item_state = "stripper_g"
- item_color = "stripper_g"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/wedding/bride_orange
- name = "orange wedding dress"
- desc = "A big and puffy orange dress."
- icon_state = "bride_orange"
- item_state = "bride_orange"
- item_color = "bride_orange"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/wedding/bride_purple
- name = "purple wedding dress"
- desc = "A big and puffy purple dress."
- icon_state = "bride_purple"
- item_state = "bride_purple"
- item_color = "bride_purple"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/wedding/bride_blue
- name = "blue wedding dress"
- desc = "A big and puffy blue dress."
- icon_state = "bride_blue"
- item_state = "bride_blue"
- item_color = "bride_blue"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/wedding/bride_red
- name = "red wedding dress"
- desc = "A big and puffy red dress."
- icon_state = "bride_red"
- item_state = "bride_red"
- item_color = "bride_red"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/wedding/bride_white
- name = "white wedding dress"
- desc = "A white wedding gown made from the finest silk."
- icon_state = "bride_white"
- item_state = "bride_white"
- item_color = "bride_white"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/mankini
- name = "pink mankini"
- icon_state = "mankini"
- item_state = "mankini"
- item_color = "mankini"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-/*
-
-/obj/item/clothing/under/psysuit
- name = "dark undersuit"
- desc = "A thick, layered grey undersuit lined with power cables. Feels a little like wearing an electrical storm."
- icon_state = "psysuit"
- item_state = "psysuit"
- item_color = "psysuit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
-
-
-/obj/item/clothing/under/officeruniform
- name = "officer's uniform"
- desc = "Bestraft die Juden fur ihre Verbrechen."
- icon_state = "officeruniform"
- item_state = "officeruniform"
- item_color = "officeruniform"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
-
-
-/obj/item/clothing/under/soldieruniform
- name = "soldier's uniform"
- desc = "Bestraft die Verbundeten fur ihren Widerstand."
- icon_state = "soldieruniform"
- item_state = "soldieruniform"
- item_color = "soldieruniform"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
-
-*/
-/obj/item/clothing/under/squatter_outfit
- name = "slav squatter tracksuit"
- desc = "Cyka blyat."
- icon_state = "squatteroutfit"
- item_state = "squatteroutfit"
- item_color = "squatteroutfit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/russobluecamooutfit
- name = "russian blue camo"
- desc = "Drop and give me dvadtsat!"
- icon_state = "russobluecamo"
- item_state = "russobluecamo"
- item_color = "russobluecamo"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/stilsuit
- name = "stillsuit"
- desc = "Designed to preserve bodymoisture."
- icon_state = "stilsuit"
- item_state = "stilsuit"
- item_color = "stilsuit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/aviatoruniform
- name = "aviator uniform"
- desc = "Now you can look absolutely dashing!"
- icon_state = "aviator_uniform"
- item_state = "aviator_uniform"
- item_color = "aviator_uniform"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/bikersuit
- name = "biker's outfit"
- icon_state = "biker"
- item_state = "biker"
- item_color = "biker"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/jacketsuit
- name = "richard's outfit"
- desc = "Do you know what time it is?"
- icon_state = "jacket"
- item_state = "jacket"
- item_color = "jacket"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-obj/item/clothing/under/mega
- name = "\improper DRN-001 suit"
- desc = "The original. Simple, yet very adaptable."
- icon_state = "mega"
- item_state = "mega"
- item_color = "mega"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/proto
- name = "The Prototype Suit"
- desc = "Even robots know scarves are the perfect accessory for a brooding rival."
- icon_state = "proto"
- item_state = "proto"
- item_color = "proto"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/megax
- name = "\improper Maverick Hunter regalia"
- desc = "The best outfit for taking out rogue borgs."
- icon_state = "megax"
- item_state = "megax"
- item_color = "megax"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/joe
- name = "The Sniper Suit"
- desc = "Mass produced combat robots with a rather unfitting name."
- icon_state = "joe"
- item_state = "joe"
- item_color = "joe"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/roll
- name = "\improper DRN-002 Dress"
- desc = "A simple red dress, the good doctor's second robot wasn't quite as exciting as the first."
- icon_state = "roll"
- item_state = "roll"
- item_color = "roll"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/gokugidown
- name = "turtle hermit undershirt"
- desc = "Something seems oddly familiar about this outfit..."
- icon_state = "gokugidown"
- item_state = "gokugidown"
- item_color = "gokugidown"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/gokugi
- name = "turtle hermit outfit"
- desc = "An outfit from one trained by the great Turtle Hermit."
- icon_state = "gokugi"
- item_state = "gokugi"
- item_color = "gokugi"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/doomguy
- name = "\improper Doomguy's pants"
- desc = ""
- icon_state = "doom"
- item_state = "doom"
- item_color = "doom"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/vault13
- name = "vault 13 Jumpsuit"
- desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it. Has a large thirteen emblazened on the back."
- icon_state = "v13-jumpsuit"
- item_state = "v13-jumpsuit"
- item_color = "v13-jumpsuit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/vault
- name = "vault jumpsuit"
- desc = "Oddly similar to the station's usual jumpsuits, but with a rustic charm to it."
- icon_state = "v-jumpsuit"
- item_state = "v-jumpsuit"
- item_color = "v-jumpsuit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/clownpiece
- name = "Clownpiece's Pierrot suit"
- desc = "A female-sized set of leggings and shirt with a pattern similar to the American flag, featuring a frilled collar."
- icon_state = "clownpiece"
- item_state = "clownpiece"
- item_color = "clownpiece"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/cia
- name = "casual IAA outfit"
- desc = "Just looking at this makes you feel in charge."
- icon_state = "cia"
- item_state = "cia"
- item_color = "cia"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/greaser
- name = "greaser outfit"
- desc = "The one that you want!"
- icon_state = "greaser_default"
- item_state = "greaser_default"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/greaser/New()
- var/greaser_colour = "default"
- switch(rand(1,4))
- if(1)
- greaser_colour = "default"
- if(2)
- greaser_colour = "cult"
- if(3)
- greaser_colour = "spider"
- if(4)
- greaser_colour = "snakes"
- desc = "Tunnel Snakes Rule!"
- icon_state = "greaser_[greaser_colour]"
- item_state = "greaser_[greaser_colour]"
- item_color = "greaser_[greaser_colour]"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-
-/obj/item/clothing/under/wintercasualwear
- name = "winter casualwear"
- desc = "Perfect for winter!"
- icon_state = "shizunewinter"
- item_state = "shizunewinter"
- item_color = "shizunewinter"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/casualwear
- name = "spring casualwear"
- desc = "Perfect for spring!"
- icon_state = "shizunenormal"
- item_state = "shizunenormal"
- item_color = "shizunenormal"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/keyholesweater
- name = "keyhole sweater"
- desc = "What is the point of this, anyway?"
- icon_state = "keyholesweater"
- item_state = "keyholesweater"
- item_color = "keyholesweater"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/casualhoodie
- name = "casual hoodie"
- desc = "Pefect for lounging about in."
- icon_state = "hoodiejeans"
- item_state = "hoodiejeans"
- item_color = "hoodiejeans"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
-/obj/item/clothing/under/casualhoodie/skirt
- icon_state = "hoodieskirt"
- item_state = "hoodieskirt"
- item_color = "hoodieskirt"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- mutantrace_variation = NONE
-
-/*
-/obj/item/clothing/under/mummy_rags
- name = "mummy rags"
- desc = "Ancient rags taken off from some mummy."
- icon_state = "mummy"
- item_state = "mummy"
- item_color = "mummy"
- can_adjust = 0
- has_sensor = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
-
-
-/obj/item/clothing/under/neorussian
- name = "neo-Russian uniform"
- desc = "Employs a special toshnit pattern, will render you invisible when you eat a potato on an empty stomach."
- icon_state = "nr_uniform"
- item_state = "nr_uniform"
- item_color = "nr_uniform"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
-*/
-
-/obj/item/clothing/under/rottensuit
- name = "rotten suit"
- desc = "This suit seems perfect for wearing underneath a disguise."
- icon_state = "rottensuit"
- item_state = "rottensuit"
- item_color = "rottensuit"
- can_adjust = 0
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/uniforms.dmi'
- mutantrace_variation = NONE
-
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
deleted file mode 100644
index 2987b52338..0000000000
--- a/code/modules/crafting/recipes.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/datum/crafting_recipe
- var/name = "" //in-game display name
- var/reqs[] = list() //type paths of items consumed associated with how many are needed
- var/result //type path of item resulting from this craft
- var/tools[] = list() //type paths of items needed but not consumed
- var/time = 30 //time in deciseconds
- var/parts[] = list() //type paths of items that will be placed in the result
- var/chem_catalysts[] = list() //like tools but for reagents
- var/category = CAT_NONE //where it shows up in the crafting UI
- var/subcategory = CAT_NONE
- var/always_availible = TRUE //Set to FALSE if it needs to be learned first.
\ No newline at end of file
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 634401d0d8..3b1b00fc3a 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -9,8 +9,7 @@
else if(M.bloody_hands > 1)
if(add_blood_DNA(M.blood_DNA, M.diseases))
M.bloody_hands--
- if(!suit_fibers)
- suit_fibers = list()
+ LAZYINITLIST(suit_fibers)
var/fibertext
var/item_multiplier = isitem(src)?1.2:1
if(M.wear_suit)
@@ -66,7 +65,6 @@
fingerprintslast = M.ckey
-
//Set ignoregloves to add prints irrespective of the mob having gloves on.
/atom/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
if(!M || !M.key)
@@ -93,15 +91,10 @@
fingerprints[full_print] = full_print
/atom/proc/transfer_fingerprints_to(atom/A)
- // Make sure everything are lists.
- LAZYINITLIST(A.fingerprints)
- LAZYINITLIST(A.fingerprintshidden)
- LAZYINITLIST(fingerprints)
- LAZYINITLIST(fingerprintshidden)
-
- // Transfer
if(fingerprints)
- A.fingerprints |= fingerprints.Copy() //detective
+ LAZYINITLIST(A.fingerprints)
+ A.fingerprints |= fingerprints //detective
if(fingerprintshidden)
- A.fingerprintshidden |= fingerprintshidden.Copy() //admin
- A.fingerprintslast = fingerprintslast
\ No newline at end of file
+ LAZYINITLIST(A.fingerprintshidden)
+ A.fingerprintshidden |= fingerprintshidden //admin
+ A.fingerprintslast = fingerprintslast
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index a2860f8c43..9b114829e1 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -123,7 +123,7 @@
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
var/found_something = FALSE
- add_log("[STATION_TIME_TIMESTAMP("hh:mm:ss")][get_timestamp()] - [target_name]", 0)
+ add_log("[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)][get_timestamp()] - [target_name]", 0)
// Fingerprints
if(length(fingerprints))
diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm
index 2f4a84c646..65e8063ce0 100644
--- a/code/modules/emoji/emoji_parse.dm
+++ b/code/modules/emoji/emoji_parse.dm
@@ -1,4 +1,4 @@
-/proc/emoji_parse(text)
+/proc/emoji_parse(text) //turns :ai: into an emoji in text.
. = text
if(!CONFIG_GET(flag/emojis))
return
@@ -12,14 +12,14 @@
parsed += copytext(text, pos, search)
if(search)
pos = search
- search = findtext(text, ":", pos+1)
+ search = findtext(text, ":", pos + length(text[pos]))
if(search)
- emoji = lowertext(copytext(text, pos+1, search))
+ emoji = lowertext(copytext(text, pos + length(text[pos]), search))
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
var/tag = sheet.icon_tag("emoji-[emoji]")
if(tag)
parsed += tag
- pos = search + 1
+ pos = search + length(text[pos])
else
parsed += copytext(text, pos, search)
pos = search
@@ -30,3 +30,24 @@
break
return parsed
+/proc/emoji_sanitize(text) //cuts any text that would not be parsed as an emoji
+ . = text
+ if(!CONFIG_GET(flag/emojis))
+ return
+ var/static/list/emojis = icon_states(icon('icons/emoji.dmi'))
+ var/final = "" //only tags are added to this
+ var/pos = 1
+ var/search = 0
+ while(1)
+ search = findtext(text, ":", pos)
+ if(search)
+ pos = search
+ search = findtext(text, ":", pos + length(text[pos]))
+ if(search)
+ var/word = lowertext(copytext(text, pos + length(text[pos]), search))
+ if(word in emojis)
+ final += lowertext(copytext(text, pos, search + length(text[search])))
+ pos = search + length(text[search])
+ continue
+ break
+ return final
diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm
index 8b410130cb..418b75e1ce 100644
--- a/code/modules/error_handler/error_handler.dm
+++ b/code/modules/error_handler/error_handler.dm
@@ -12,7 +12,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
return ..()
//this is snowflake because of a byond bug (ID:2306577), do not attempt to call non-builtin procs in this if
- if(copytext(E.name,1,32) == "Maximum recursion level reached")
+ if(copytext(E.name, 1, 32) == "Maximum recursion level reached")//32 == length() of that string + 1
//log to world while intentionally triggering the byond bug.
log_world("runtime error: [E.name]\n[E.desc]")
//if we got to here without silently ending, the byond bug has been fixed.
@@ -102,7 +102,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
usrinfo = null
continue // Our usr info is better, replace it
- if(copytext(line, 1, 3) != " ")
+ if(copytext(line, 1, 3) != " ")//3 == length(" ") + 1
desclines += (" " + line) // Pad any unpadded lines, so they look pretty
else
desclines += line
diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm
index a1a82ea5f7..6ecc1d9d42 100644
--- a/code/modules/events/meteor_wave.dm
+++ b/code/modules/events/meteor_wave.dm
@@ -18,6 +18,7 @@
announceWhen = 1
var/list/wave_type
var/wave_name = "normal"
+ var/direction
/datum/round_event/meteor_wave/setup()
announceWhen = 1
@@ -26,7 +27,6 @@
startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE)
endWhen = startWhen + 60
-
/datum/round_event/meteor_wave/New()
..()
if(!wave_type)
@@ -38,6 +38,8 @@
"normal" = 50,
"threatening" = 40,
"catastrophic" = 10))
+ if(!direction)
+ direction = pick(GLOB.cardinals)
switch(wave_name)
if("normal")
wave_type = GLOB.meteors_normal
@@ -59,11 +61,24 @@
kill()
/datum/round_event/meteor_wave/announce(fake)
- priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", "meteors")
+ priority_announce(generateMeteorString(startWhen,TRUE,direction), "Meteor Alert", "meteors")
+
+/proc/generateMeteorString(startWhen,syndiealert,direction)
+ var/directionstring
+ switch(direction)
+ if(NORTH)
+ directionstring = " towards the fore"
+ if(SOUTH)
+ directionstring = " towards the aft"
+ if(EAST)
+ directionstring = " towards starboard"
+ if(WEST)
+ directionstring = " towards port"
+ return "Meteors have been detected on a collision course with the station[directionstring]. Estimated time until impact: [round((startWhen * SSevents.wait) / 10, 0.1)] seconds.[GLOB.singularity_counter && syndiealert ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]"
/datum/round_event/meteor_wave/tick()
if(ISMULTIPLE(activeFor, 3))
- spawn_meteors(5, wave_type) //meteor list types defined in gamemode/meteor/meteors.dm
+ spawn_meteors(5, wave_type, direction) //meteor list types defined in gamemode/meteor/meteors.dm
/datum/round_event_control/meteor_wave/threatening
name = "Meteor Wave: Threatening"
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index f006f2b358..c585961604 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -133,7 +133,7 @@
shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate/ranged/infiltrator)
if(RUSKY_PARTY)
- var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/misc/party]
+ var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/party]
pack.generate(pick_n_take(empty_shuttle_turfs))
shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian)
diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm
index c59a8004ca..56abef8cd6 100644
--- a/code/modules/fields/timestop.dm
+++ b/code/modules/fields/timestop.dm
@@ -9,7 +9,7 @@
pixel_x = -64
pixel_y = -64
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- var/list/immune = list() // the one who creates the timestop is immune
+ var/list/immune = list() // the one who creates the timestop is immune, which includes wizards and the dead slime you murdered to make this chronofield
var/turf/target
var/freezerange = 2
var/duration = 140
@@ -27,10 +27,10 @@
for(var/A in immune_atoms)
immune[A] = TRUE
for(var/mob/living/L in GLOB.player_list)
- if(locate(/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) in L.mind.spell_list) //People who can stop time are immune to its effects
+ if(locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in L.mind.spell_list) //People who can stop time are immune to its effects
immune[L] = TRUE
for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.parasites)
- if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune.
+ if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune.
immune[G] = TRUE
if(start)
timestop()
@@ -46,9 +46,8 @@
chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy))
QDEL_IN(src, duration)
-/obj/effect/timestop/wizard
+/obj/effect/timestop/magic
check_anti_magic = TRUE
- duration = 100
/datum/proximity_monitor/advanced/timestop
name = "chronofield"
@@ -56,9 +55,10 @@
field_shape = FIELD_SHAPE_RADIUS_SQUARE
requires_processing = TRUE
var/list/immune = list()
- var/list/mob/living/frozen_mobs = list()
- var/list/obj/item/projectile/frozen_projectiles = list()
- var/list/atom/movable/frozen_throws = list()
+ var/list/frozen_things = list()
+ var/list/frozen_mobs = list() //cached separately for processing
+ var/list/frozen_structures = list() //Also machinery, and only frozen aestethically
+ var/list/frozen_turfs = list() //Only aesthetically
var/check_anti_magic = FALSE
var/check_holy = FALSE
@@ -74,85 +74,125 @@
/datum/proximity_monitor/advanced/timestop/proc/freeze_atom(atom/movable/A)
if(immune[A] || global_frozen_atoms[A] || !istype(A))
return FALSE
- if(A.throwing)
- freeze_throwing(A)
+ if(ismob(A))
+ var/mob/M = A
+ if(M.anti_magic_check(check_anti_magic, check_holy))
+ immune[A] = TRUE
+ return
+ var/frozen = TRUE
if(isliving(A))
freeze_mob(A)
else if(istype(A, /obj/item/projectile))
freeze_projectile(A)
+ else if(istype(A, /obj/mecha))
+ freeze_mecha(A)
+ else if((ismachinery(A) && !istype(A, /obj/machinery/light)) || isstructure(A)) //Special exception for light fixtures since recoloring causes them to change light
+ freeze_structure(A)
else
- return FALSE
+ frozen = FALSE
+ if(A.throwing)
+ freeze_throwing(A)
+ frozen = TRUE
+ if(!frozen)
+ return
+ frozen_things[A] = A.move_resist
+ A.move_resist = INFINITY
+ global_frozen_atoms[A] = src
into_the_negative_zone(A)
+ RegisterSignal(A, COMSIG_MOVABLE_PRE_MOVE, .proc/unfreeze_atom)
+ RegisterSignal(A, COMSIG_ITEM_PICKUP, .proc/unfreeze_atom)
return TRUE
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_all()
- for(var/i in frozen_projectiles)
- unfreeze_projectile(i)
- for(var/i in frozen_mobs)
- unfreeze_mob(i)
- for(var/i in frozen_throws)
- unfreeze_throw(i)
+ for(var/i in frozen_things)
+ unfreeze_atom(i)
+ for(var/T in frozen_turfs)
+ unfreeze_turf(T)
+
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_atom(atom/movable/A)
+ if(A.throwing)
+ unfreeze_throwing(A)
+ if(isliving(A))
+ unfreeze_mob(A)
+ else if(istype(A, /obj/item/projectile))
+ unfreeze_projectile(A)
+ else if(istype(A, /obj/mecha))
+ unfreeze_mecha(A)
+
+ UnregisterSignal(A, COMSIG_MOVABLE_PRE_MOVE)
+ UnregisterSignal(A, COMSIG_ITEM_PICKUP)
+ escape_the_negative_zone(A)
+ A.move_resist = frozen_things[A]
+ frozen_things -= A
+ global_frozen_atoms -= A
+
+/datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/mecha/M)
+ M.completely_disabled = TRUE
+
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/mecha/M)
+ M.completely_disabled = FALSE
/datum/proximity_monitor/advanced/timestop/proc/freeze_throwing(atom/movable/AM)
var/datum/thrownthing/T = AM.throwing
T.paused = TRUE
- frozen_throws[AM] = T
- global_frozen_atoms[AM] = TRUE
-/datum/proximity_monitor/advanced/timestop/proc/unfreeze_throw(atom/movable/AM)
- var/datum/thrownthing/T = frozen_throws[AM]
- T.paused = FALSE
- frozen_throws -= AM
- global_frozen_atoms -= AM
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_throwing(atom/movable/AM)
+ var/datum/thrownthing/T = AM.throwing
+ if(T)
+ T.paused = FALSE
+
+/datum/proximity_monitor/advanced/timestop/proc/freeze_turf(turf/T)
+ into_the_negative_zone(T)
+ frozen_turfs += T
+
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_turf(turf/T)
+ escape_the_negative_zone(T)
+
+/datum/proximity_monitor/advanced/timestop/proc/freeze_structure(obj/O)
+ into_the_negative_zone(O)
+ frozen_structures += O
+
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_structure(obj/O)
+ escape_the_negative_zone(O)
/datum/proximity_monitor/advanced/timestop/process()
for(var/i in frozen_mobs)
var/mob/living/m = i
- if(get_dist(get_turf(m), get_turf(host)) > current_range)
- unfreeze_mob(m)
- else
- m.Stun(20, 1, 1)
+ m.Stun(20, 1, 1)
/datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T)
for(var/i in T.contents)
freeze_atom(i)
+ freeze_turf(T)
return ..()
-/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P)
- escape_the_negative_zone(P)
- frozen_projectiles -= P
- P.paused = FALSE
- global_frozen_atoms -= P
-
/datum/proximity_monitor/advanced/timestop/proc/freeze_projectile(obj/item/projectile/P)
- frozen_projectiles[P] = TRUE
P.paused = TRUE
- global_frozen_atoms[P] = TRUE
+
+/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P)
+ P.paused = FALSE
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
- if(L.anti_magic_check(check_anti_magic, check_holy))
- immune += L
- return
+ frozen_mobs += L
L.Stun(20, 1, 1)
- frozen_mobs[L] = L.anchored
- L.anchored = TRUE
- global_frozen_atoms[L] = TRUE
- if(ishostile(L))
- var/mob/living/simple_animal/hostile/H = L
- H.toggle_ai(AI_OFF)
- H.LoseTarget()
+ ADD_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT)
+ walk(L, 0) //stops them mid pathing even if they're stunimmune
+ if(isanimal(L))
+ var/mob/living/simple_animal/S = L
+ S.toggle_ai(AI_OFF)
+ if(ishostile(L))
+ var/mob/living/simple_animal/hostile/H = L
+ H.LoseTarget()
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L)
- escape_the_negative_zone(L)
L.AdjustStun(-20, 1, 1)
- L.anchored = frozen_mobs[L]
+ REMOVE_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT)
frozen_mobs -= L
- global_frozen_atoms -= L
- if(ishostile(L))
- var/mob/living/simple_animal/hostile/H = L
- H.toggle_ai(initial(H.AIStatus))
+ if(isanimal(L))
+ var/mob/living/simple_animal/S = L
+ S.toggle_ai(initial(S.AIStatus))
//you don't look quite right, is something the matter?
/datum/proximity_monitor/advanced/timestop/proc/into_the_negative_zone(atom/A)
@@ -160,4 +200,4 @@
//let's put some colour back into your cheeks
/datum/proximity_monitor/advanced/timestop/proc/escape_the_negative_zone(atom/A)
- A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
\ No newline at end of file
+ A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 83dbad0246..150f066886 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -895,7 +895,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
SEND_SOUND(target, get_announcer_sound("aimalf"))
if("meteors") //Meteors inbound!
to_chat(target, "
Meteor Alert
")
- to_chat(target, "
Meteors have been detected on collision course with the station. Estimated time until impact: [round(rand(180,360)/60)] minutes.