"
- var/datum/browser/popup = new(mob, "hallucinationdebug", "Hallucination Weights", 600, 400)
+ var/datum/browser/popup = new(user.mob, "hallucinationdebug", "Hallucination Weights", 600, 400)
popup.set_content(page_contents)
popup.open()
diff --git a/code/__HELPERS/hearted.dm b/code/__HELPERS/hearted.dm
index 1eafef56a4f..adae298516e 100644
--- a/code/__HELPERS/hearted.dm
+++ b/code/__HELPERS/hearted.dm
@@ -54,7 +54,7 @@
if(!heart_nominee)
return
- heart_nominee = lowertext(heart_nominee)
+ heart_nominee = LOWER_TEXT(heart_nominee)
var/list/name_checks = get_mob_by_name(heart_nominee)
if(!name_checks || name_checks.len == 0)
query_heart(attempt + 1)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 6ab82d1584c..fd11d8f0651 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -679,7 +679,7 @@ world
if(uppercase == 1)
letter = uppertext(letter)
else if(uppercase == -1)
- letter = lowertext(letter)
+ letter = LOWER_TEXT(letter)
var/image/text_image = new(loc = A)
text_image.maptext = MAPTEXT("[letter]")
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index 33bb0348df5..12c34d3a705 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -215,22 +215,22 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex)
if(2)
switch(rand(1,3))//Food, drinks, or places. Only selectable once.
if(1)
- . += lowertext(pick(drinks))
+ . += LOWER_TEXT(pick(drinks))
if(2)
- . += lowertext(pick(foods))
+ . += LOWER_TEXT(pick(foods))
if(3)
- . += lowertext(pick(locations))
+ . += LOWER_TEXT(pick(locations))
safety -= 2
if(3)
switch(rand(1,4))//Abstract nouns, objects, adjectives, threats. Can be selected more than once.
if(1)
- . += lowertext(pick(nouns))
+ . += LOWER_TEXT(pick(nouns))
if(2)
- . += lowertext(pick(objects))
+ . += LOWER_TEXT(pick(objects))
if(3)
- . += lowertext(pick(adjectives))
+ . += LOWER_TEXT(pick(adjectives))
if(4)
- . += lowertext(pick(threats))
+ . += LOWER_TEXT(pick(threats))
if(!return_list)
if(words == 1)
. += "."
diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm
index d557db3173a..012a1fd5cc0 100644
--- a/code/__HELPERS/reagents.dm
+++ b/code/__HELPERS/reagents.dm
@@ -155,7 +155,7 @@
///Returns a list of chemical_reaction datums that have the input STRING as a product
/proc/get_reagent_type_from_product_string(string)
- var/input_reagent = replacetext(lowertext(string), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name
+ var/input_reagent = replacetext(LOWER_TEXT(string), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name
if (isnull(input_reagent))
return
@@ -194,7 +194,7 @@
/proc/get_chem_id(chem_name)
for(var/X in GLOB.chemical_reagents_list)
var/datum/reagent/R = GLOB.chemical_reagents_list[X]
- if(ckey(chem_name) == ckey(lowertext(R.name)))
+ if(ckey(chem_name) == ckey(LOWER_TEXT(R.name)))
return X
///Takes a type in and returns a list of associated recipes
diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm
index 002ac24c732..e57cf1b5098 100644
--- a/code/__HELPERS/sanitize_values.dm
+++ b/code/__HELPERS/sanitize_values.dm
@@ -78,7 +78,7 @@
if(97 to 102) //letters a to f
. += char
if(65 to 70) //letters A to F
- char = lowertext(char)
+ char = LOWER_TEXT(char)
. += char
else
break
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index e2fb0203a3e..4acfc1d6508 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -785,7 +785,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
return string
var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash)
- var/macro = lowertext(copytext(string, next_backslash + length(string[next_backslash]), next_space))
+ var/macro = LOWER_TEXT(copytext(string, next_backslash + length(string[next_backslash]), next_space))
var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space]))
//See https://secure.byond.com/docs/ref/info.html#/DM/text/macros
@@ -1082,7 +1082,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/text_length = length(text)
//remove caps since words will be shuffled
- text = lowertext(text)
+ text = LOWER_TEXT(text)
//remove punctuation for same reasons as above
var/punctuation = ""
var/punctuation_hit_list = list("!","?",".","-")
diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm
index 32a570ae8fc..c44845a5854 100644
--- a/code/__HELPERS/turfs.dm
+++ b/code/__HELPERS/turfs.dm
@@ -413,3 +413,20 @@ Turf and target are separate in case you want to teleport some distance from a t
if(locate(type_to_find) in location)
return TRUE
return FALSE
+
+/**
+ * get_blueprint_data
+ * Gets a list of turfs around a central turf and gets the blueprint data in a list
+ * Args:
+ * - central_turf: The center turf we're getting data from.
+ * - viewsize: The viewsize we're getting the turfs around central_turf of.
+ */
+/proc/get_blueprint_data(turf/central_turf, viewsize)
+ var/list/blueprint_data_returned = list()
+ var/list/dimensions = getviewsize(viewsize)
+ var/horizontal_radius = dimensions[1] / 2
+ var/vertical_radius = dimensions[2] / 2
+ for(var/turf/nearby_turf as anything in RECT_TURFS(horizontal_radius, vertical_radius, central_turf))
+ if(nearby_turf.blueprint_data)
+ blueprint_data_returned += nearby_turf.blueprint_data
+ return blueprint_data_returned
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 7e97724b562..7cdecfe41ed 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -389,7 +389,7 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,
if(/turf)
return "turf"
else //regex everything else (works for /proc too)
- return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
+ return LOWER_TEXT(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
/// Return html to load a url.
/// for use inside of browse() calls to html assets that might be loaded on a cdn.
diff --git a/code/_globalvars/arcade.dm b/code/_globalvars/arcade.dm
new file mode 100644
index 00000000000..4143ce5fa76
--- /dev/null
+++ b/code/_globalvars/arcade.dm
@@ -0,0 +1,73 @@
+///List of all things that can be dispensed by an arcade cabinet and the weight of them being picked.
+GLOBAL_LIST_INIT(arcade_prize_pool, list(
+ /obj/item/storage/box/snappops = 2,
+ /obj/item/toy/talking/ai = 2,
+ /obj/item/toy/talking/codex_gigas = 2,
+ /obj/item/clothing/under/syndicate/tacticool = 2,
+ /obj/item/toy/sword = 2,
+ /obj/item/toy/gun = 2,
+ /obj/item/gun/ballistic/shotgun/toy/crossbow = 2,
+ /obj/item/storage/box/fakesyndiesuit = 2,
+ /obj/item/storage/crayons = 2,
+ /obj/item/toy/spinningtoy = 2,
+ /obj/item/toy/spinningtoy/dark_matter = 1,
+ /obj/item/toy/balloon/arrest = 2,
+ /obj/item/toy/mecha/ripley = 1,
+ /obj/item/toy/mecha/ripleymkii = 1,
+ /obj/item/toy/mecha/hauler = 1,
+ /obj/item/toy/mecha/clarke = 1,
+ /obj/item/toy/mecha/odysseus = 1,
+ /obj/item/toy/mecha/gygax = 1,
+ /obj/item/toy/mecha/durand = 1,
+ /obj/item/toy/mecha/savannahivanov = 1,
+ /obj/item/toy/mecha/phazon = 1,
+ /obj/item/toy/mecha/honk = 1,
+ /obj/item/toy/mecha/darkgygax = 1,
+ /obj/item/toy/mecha/mauler = 1,
+ /obj/item/toy/mecha/darkhonk = 1,
+ /obj/item/toy/mecha/deathripley = 1,
+ /obj/item/toy/mecha/reticence = 1,
+ /obj/item/toy/mecha/marauder = 1,
+ /obj/item/toy/mecha/seraph = 1,
+ /obj/item/toy/mecha/firefighter = 1,
+ /obj/item/toy/cards/deck = 2,
+ /obj/item/toy/nuke = 2,
+ /obj/item/toy/minimeteor = 2,
+ /obj/item/toy/redbutton = 2,
+ /obj/item/toy/talking/owl = 2,
+ /obj/item/toy/talking/griffin = 2,
+ /obj/item/coin/antagtoken = 2,
+ /obj/item/stack/tile/fakepit/loaded = 2,
+ /obj/item/stack/tile/eighties/loaded = 2,
+ /obj/item/toy/toy_xeno = 2,
+ /obj/item/storage/box/actionfigure = 1,
+ /obj/item/restraints/handcuffs/fake = 2,
+ /obj/item/grenade/chem_grenade/glitter/pink = 1,
+ /obj/item/grenade/chem_grenade/glitter/blue = 1,
+ /obj/item/grenade/chem_grenade/glitter/white = 1,
+ /obj/item/toy/eightball = 2,
+ /obj/item/toy/windup_toolbox = 2,
+ /obj/item/toy/clockwork_watch = 2,
+ /obj/item/toy/toy_dagger = 2,
+ /obj/item/extendohand/acme = 1,
+ /obj/item/hot_potato/harmless/toy = 1,
+ /obj/item/card/emagfake = 1,
+ /obj/item/clothing/shoes/wheelys = 2,
+ /obj/item/clothing/shoes/kindle_kicks = 2,
+ /obj/item/toy/plush/goatplushie = 2,
+ /obj/item/toy/plush/moth = 2,
+ /obj/item/toy/plush/pkplush = 2,
+ /obj/item/toy/plush/rouny = 2,
+ /obj/item/toy/plush/abductor = 2,
+ /obj/item/toy/plush/abductor/agent = 2,
+ /obj/item/toy/plush/shark = 2,
+ /obj/item/storage/belt/military/snack/full = 2,
+ /obj/item/toy/brokenradio = 2,
+ /obj/item/toy/braintoy = 2,
+ /obj/item/toy/eldritch_book = 2,
+ /obj/item/storage/box/heretic_box = 1,
+ /obj/item/toy/foamfinger = 2,
+ /obj/item/clothing/glasses/trickblindfold = 2,
+ /obj/item/clothing/mask/party_horn = 2,
+ /obj/item/storage/box/party_poppers = 2,
+))
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 5a43e73cd6c..cce0793a5b1 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -153,15 +153,14 @@ DEFINE_BITFIELD(interaction_flags_atom, list(
))
DEFINE_BITFIELD(interaction_flags_machine, list(
- "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
- "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
"INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN,
+ "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
+ "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
+ "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
"INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON,
+ "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
"INTERACT_MACHINE_REQUIRES_SIGHT" = INTERACT_MACHINE_REQUIRES_SIGHT,
"INTERACT_MACHINE_REQUIRES_LITERACY" = INTERACT_MACHINE_REQUIRES_LITERACY,
- "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
- "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE,
- "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
))
DEFINE_BITFIELD(interaction_flags_item, list(
@@ -283,20 +282,20 @@ DEFINE_BITFIELD(movement_type, list(
))
DEFINE_BITFIELD(obj_flags, list(
- "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
- "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
+ "EMAGGED" = EMAGGED,
+ "CAN_BE_HIT" = CAN_BE_HIT,
+ "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
+ "UNIQUE_RENAME" = UNIQUE_RENAME,
"BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN,
"BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP,
- "BLOCKS_CONSTRUCTION_DIR" = BLOCKS_CONSTRUCTION_DIR,
+ "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
+ "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
"BLOCKS_CONSTRUCTION" = BLOCKS_CONSTRUCTION,
- "CAN_BE_HIT" = CAN_BE_HIT,
- "CONDUCTS_ELECTRICITY" = CONDUCTS_ELECTRICITY,
- "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
- "EMAGGED" = EMAGGED,
+ "BLOCKS_CONSTRUCTION_DIR" = BLOCKS_CONSTRUCTION_DIR,
"IGNORE_DENSITY" = IGNORE_DENSITY,
- "IN_USE" = IN_USE,
- "NO_DECONSTRUCTION" = NO_DECONSTRUCTION,
- "UNIQUE_RENAME" = UNIQUE_RENAME,
+ "INFINITE_RESKIN" = INFINITE_RESKIN,
+ "CONDUCTS_ELECTRICITY" = CONDUCTS_ELECTRICITY,
+ "NO_DEBRIS_AFTER_DECONSTRUCTION" = NO_DEBRIS_AFTER_DECONSTRUCTION,
))
DEFINE_BITFIELD(pass_flags, list(
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 1956a6061ad..749dfd49b21 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -127,6 +127,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED,
"TRAIT_ANALGESIA" = TRAIT_ANALGESIA,
"TRAIT_ANGELIC" = TRAIT_ANGELIC,
+ "TRAIT_ANOSMIA" = TRAIT_ANOSMIA,
"TRAIT_ANTENNAE" = TRAIT_ANTENNAE,
"TRAIT_ANTICONVULSANT" = TRAIT_ANTICONVULSANT,
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
@@ -135,6 +136,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BADDNA" = TRAIT_BADDNA,
"TRAIT_BADTOUCH" = TRAIT_BADTOUCH,
"TRAIT_BALD" = TRAIT_BALD,
+ "TRAIT_BALLOON_SUTRA" = TRAIT_BALLOON_SUTRA,
"TRAIT_BATON_RESISTANCE" = TRAIT_BATON_RESISTANCE,
"TRAIT_BEING_BLADE_SHIELDED" = TRAIT_BEING_BLADE_SHIELDED,
"TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY,
@@ -361,6 +363,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_OVERWATCHED" = TRAIT_OVERWATCHED,
"TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE,
"TRAIT_PACIFISM" = TRAIT_PACIFISM,
+ "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_PARALYSIS_L_ARM" = TRAIT_PARALYSIS_L_ARM,
"TRAIT_PARALYSIS_L_LEG" = TRAIT_PARALYSIS_L_LEG,
"TRAIT_PARALYSIS_R_ARM" = TRAIT_PARALYSIS_R_ARM,
@@ -417,7 +420,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES,
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG,
- "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
@@ -439,6 +441,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_STASIS" = TRAIT_STASIS,
"TRAIT_STIMULATED" = TRAIT_STIMULATED,
"TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER,
+ "TRAIT_STRONG_STOMACH" = TRAIT_STRONG_STOMACH,
"TRAIT_STUNIMMUNE" = TRAIT_STUNIMMUNE,
"TRAIT_SUCCUMB_OVERRIDE" = TRAIT_SUCCUMB_OVERRIDE,
"TRAIT_SUICIDED" = TRAIT_SUICIDED,
@@ -601,6 +604,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/turf = list(
"TRAIT_CHASM_STOPPED" = TRAIT_CHASM_STOPPED,
+ "TRAIT_CONTAINMENT_FIELD" = TRAIT_CONTAINMENT_FIELD,
"TRAIT_FIREDOOR_STOP" = TRAIT_FIREDOOR_STOP,
"TRAIT_HYPERSPACE_STOPPED" = TRAIT_HYPERSPACE_STOPPED,
"TRAIT_IMMERSE_STOPPED" = TRAIT_IMMERSE_STOPPED,
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index d30917b197e..5fe6883e82b 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_AGENDER" = TRAIT_AGENDER,
"TRAIT_AGEUSIA" = TRAIT_AGEUSIA,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
+ "TRAIT_ANOSMIA" = TRAIT_ANOSMIA,
"TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC,
"TRAIT_ANXIOUS" = TRAIT_ANXIOUS,
"TRAIT_BADDNA" = TRAIT_BADDNA,
@@ -159,6 +160,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_OIL_FRIED" = TRAIT_OIL_FRIED,
"TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE,
"TRAIT_PACIFISM" = TRAIT_PACIFISM,
+ "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_PARALYSIS_L_ARM" = TRAIT_PARALYSIS_L_ARM,
"TRAIT_PARALYSIS_L_LEG" = TRAIT_PARALYSIS_L_LEG,
"TRAIT_PARALYSIS_R_ARM" = TRAIT_PARALYSIS_R_ARM,
@@ -191,7 +193,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES,
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG,
- "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
@@ -205,6 +206,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_STABLEHEART" = TRAIT_STABLEHEART,
"TRAIT_STABLELIVER" = TRAIT_STABLELIVER,
"TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER,
+ "TRAIT_STRONG_STOMACH" = TRAIT_STRONG_STOMACH,
"TRAIT_STUNIMMUNE" = TRAIT_STUNIMMUNE,
"TRAIT_SURGEON" = TRAIT_SURGEON,
"TRAIT_SURGICALLY_ANALYZED" = TRAIT_SURGICALLY_ANALYZED,
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index c8c35b30847..0a6e54a46e0 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -55,7 +55,7 @@
ShiftClickOn(A)
return
if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt)
- AltClickOn(A)
+ A.ai_click_alt(src)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
@@ -120,8 +120,6 @@
/mob/living/silicon/ai/CtrlClickOn(atom/target)
target.AICtrlClick(src)
-/mob/living/silicon/ai/AltClickOn(atom/target)
- target.AIAltClick(src)
/*
The following criminally helpful code is just the previous code cleaned up;
@@ -133,8 +131,7 @@
/atom/proc/AICtrlClick(mob/living/silicon/ai/user)
return
-/atom/proc/AIAltClick(mob/living/silicon/ai/user)
- AltClick(user)
+/atom/proc/ai_click_alt(mob/living/silicon/ai/user)
return
/atom/proc/AIShiftClick(mob/living/silicon/ai/user)
@@ -150,7 +147,7 @@
toggle_bolt(user)
add_hiddenprint(user)
-/obj/machinery/door/airlock/AIAltClick(mob/living/silicon/ai/user) // Eletrifies doors.
+/obj/machinery/door/airlock/ai_click_alt(mob/living/silicon/ai/user)
if(obj_flags & EMAGGED)
return
@@ -219,7 +216,7 @@
update()
/// Toggle APC equipment settings
-/obj/machinery/power/apc/AIAltClick(mob/living/silicon/ai/user)
+/obj/machinery/power/apc/ai_click_alt(mob/living/silicon/ai/user)
if(!can_use(user, loud = TRUE))
return
@@ -243,7 +240,7 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/* AI Turrets */
-/obj/machinery/turretid/AIAltClick(mob/living/silicon/ai/user) //toggles lethal on turrets
+/obj/machinery/turretid/ai_click_alt(mob/living/silicon/ai/user) //toggles lethal on turrets
if(ailock)
return
toggle_lethal(user)
@@ -254,7 +251,7 @@
toggle_on(user)
/* Holopads */
-/obj/machinery/holopad/AIAltClick(mob/living/silicon/ai/user)
+/obj/machinery/holopad/ai_click_alt(mob/living/silicon/ai/user)
if (user)
balloon_alert(user, "disrupted all active calls")
add_hiddenprint(user)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 566256824bf..af391efc859 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -96,7 +96,7 @@
if(LAZYACCESS(modifiers, RIGHT_CLICK))
alt_click_on_secondary(A)
else
- AltClickOn(A)
+ base_click_alt(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
@@ -385,24 +385,6 @@
A.CtrlClick(src)
return
-/**
- * Alt click
- * Unused except for AI
- */
-/mob/proc/AltClickOn(atom/A)
- . = SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, A)
- if(. & COMSIG_MOB_CANCEL_CLICKON)
- return
- A.AltClick(src)
-
-/atom/proc/AltClick(mob/user)
- if(!user.can_interact_with(src))
- return FALSE
- if(SEND_SIGNAL(src, COMSIG_CLICK_ALT, user) & COMPONENT_CANCEL_CLICK_ALT)
- return
- var/turf/T = get_turf(src)
- if(T && (isturf(loc) || isturf(src)) && user.TurfAdjacent(T) && !HAS_TRAIT(user, TRAIT_MOVE_VENTCRAWLING))
- user.set_listed_turf(T)
///The base proc of when something is right clicked on when alt is held - generally use alt_click_secondary instead
/atom/proc/alt_click_on_secondary(atom/A)
@@ -421,14 +403,8 @@
user.client.toggle_tag_datum(src)
return
-/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction
-/atom/proc/AltClickNoInteract(mob/user, atom/A)
- var/turf/T = get_turf(A)
- if(T && user.TurfAdjacent(T))
- user.set_listed_turf(T)
-
-/mob/proc/TurfAdjacent(turf/T)
- return T.Adjacent(src)
+/mob/proc/TurfAdjacent(turf/tile)
+ return tile.Adjacent(src)
/**
* Control+Shift click
diff --git a/code/_onclick/click_alt.dm b/code/_onclick/click_alt.dm
new file mode 100644
index 00000000000..16c8e843995
--- /dev/null
+++ b/code/_onclick/click_alt.dm
@@ -0,0 +1,66 @@
+/**
+ * ### Base proc for alt click interaction.
+ *
+ * If you wish to add custom `click_alt` behavior for a single type, use that proc.
+ */
+/mob/proc/base_click_alt(atom/target)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ var/turf/tile = isturf(target) ? target : get_turf(target)
+
+ if(isobserver(src) || isrevenant(src))
+ open_lootpanel(tile)
+ return
+
+ if(!isturf(target) && can_perform_action(target, (target.interaction_flags_click | SILENT_ADJACENCY)))
+ if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY)
+ return
+
+ if(target.click_alt(src) & CLICK_ACTION_ANY)
+ return
+
+ open_lootpanel(tile)
+
+
+/// Helper for opening the lootpanel
+/mob/proc/open_lootpanel(turf/target)
+ if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING))
+ return
+
+ var/datum/lootpanel/panel = client?.loot_panel
+ if(isnull(panel))
+ return
+
+ panel.open(target)
+
+
+/**
+ * ## Custom alt click interaction
+ * Override this to change default alt click behavior. Return `CLICK_ACTION_SUCCESS`, `CLICK_ACTION_BLOCKING` or `NONE`.
+ *
+ * ### Guard clauses
+ * Consider adding `interaction_flags_click` before adding unique guard clauses.
+ *
+ * ### Return flags
+ * Forgetting your return will cause the default alt click behavior to occur thereafter.
+ *
+ * The difference between NONE and BLOCKING can get hazy, but I like to keep NONE limited to guard clauses and "never" cases.
+ *
+ * A good usage for BLOCKING over NONE is when it's situational for the item and there's some feedback indicating this.
+ *
+ * ### Examples:
+ * User is a ghost, alt clicks on item with special disk eject: NONE
+ *
+ * Machine broken, no feedback: NONE
+ *
+ * Alt click a pipe to max output but its already max: BLOCKING
+ *
+ * Alt click a gun that normally works, but is out of ammo: BLOCKING
+ *
+ * User unauthorized, machine beeps: BLOCKING
+ *
+ * @param {mob} user - The person doing the alt clicking.
+ */
+/atom/proc/click_alt(mob/user)
+ SHOULD_CALL_PARENT(FALSE)
+ return NONE
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index 8cad6f772e0..4f06e15f2cd 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -31,7 +31,7 @@
MiddleClickOn(A, params)
return
if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt)
- AltClickOn(A)
+ A.borg_click_alt(src)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
@@ -89,7 +89,7 @@
if(after_attack_secondary_result == SECONDARY_ATTACK_CALL_NORMAL)
W.afterattack(A, src, FALSE, params)
- else
+ else
W.afterattack(A, src, FALSE, params)
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
@@ -103,8 +103,6 @@
/mob/living/silicon/robot/CtrlClickOn(atom/target)
target.BorgCtrlClick(src)
-/mob/living/silicon/robot/AltClickOn(atom/target)
- target.BorgAltClick(src)
/atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlShiftClick(user)
@@ -152,9 +150,9 @@
else
..()
-/obj/machinery/power/apc/BorgAltClick(mob/living/silicon/robot/user)
+/obj/machinery/power/apc/borg_click_alt(mob/living/silicon/robot/user)
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
- AIAltClick(user)
+ ai_click_alt(user)
else
..()
@@ -171,19 +169,19 @@
else
..()
-/atom/proc/BorgAltClick(mob/living/silicon/robot/user)
- AltClick(user)
+/atom/proc/borg_click_alt(mob/living/silicon/robot/user)
+ user.base_click_alt(src)
return
-/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
+/obj/machinery/door/airlock/borg_click_alt(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
- AIAltClick(user)
+ ai_click_alt(user)
else
..()
-/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
+/obj/machinery/turretid/borg_click_alt(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled))
- AIAltClick(user)
+ ai_click_alt(user)
else
..()
diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm
index b1f40f76294..e0a6c6873bd 100644
--- a/code/_onclick/hud/movable_screen_objects.dm
+++ b/code/_onclick/hud/movable_screen_objects.dm
@@ -44,40 +44,30 @@
offset[2] += y_off
return offset_to_screen_loc(offset[1], offset[2], our_client?.view)
-//Debug procs
-/client/proc/test_movable_UI()
- set category = "Debug"
- set name = "Spawn Movable UI Object"
-
- var/atom/movable/screen/movable/M = new()
+ADMIN_VERB(test_movable_UI, R_DEBUG, "Spawn Movable UI Object", "Spawn a movable UI object for testing.", ADMIN_CATEGORY_DEBUG)
+ var/atom/movable/screen/movable/M = new
M.name = "Movable UI Object"
M.icon_state = "block"
M.maptext = MAPTEXT("Movable")
M.maptext_width = 64
- var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null
+ var/screen_l = input(user, "Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null
if(!screen_l)
return
M.screen_loc = screen_l
+ user.screen += M
- screen += M
-
-
-/client/proc/test_snap_UI()
- set category = "Debug"
- set name = "Spawn Snap UI Object"
-
- var/atom/movable/screen/movable/snap/S = new()
+ADMIN_VERB(test_snap_ui, R_DEBUG, "Spawn Snap UI Object", "Spawn a snap UI object for testing.", ADMIN_CATEGORY_DEBUG)
+ var/atom/movable/screen/movable/snap/S = new
S.name = "Snap UI Object"
S.icon_state = "block"
S.maptext = MAPTEXT("Snap")
S.maptext_width = 64
- var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null
+ var/screen_l = input(user,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null
if(!screen_l)
return
S.screen_loc = screen_l
-
- screen += S
+ user.screen += S
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index a3f886e656f..a1ca5ebf85a 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -11,7 +11,7 @@
var/list/modifiers = params2list(params)
var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK)
- var/item_interact_result = target.item_interaction(user, src, modifiers, is_right_clicking)
+ var/item_interact_result = target.base_item_interaction(user, src, modifiers)
if(item_interact_result & ITEM_INTERACT_SUCCESS)
return TRUE
if(item_interact_result & ITEM_INTERACT_BLOCKING)
@@ -52,10 +52,6 @@
if (attackby_result)
return TRUE
- if(QDELETED(src) || QDELETED(target))
- attack_qdeleted(target, user, TRUE, params)
- return TRUE
-
if (is_right_clicking)
var/after_attack_secondary_result = afterattack_secondary(target, user, TRUE, params)
@@ -163,7 +159,7 @@
return FALSE
return attacking_item.attack_atom(src, user, params)
-/mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
// Surgery and such happens very high up in the interaction chain, before parent call
var/attempt_tending = item_tending(user, tool, modifiers)
if(attempt_tending & ITEM_INTERACT_ANY_BLOCKER)
@@ -472,11 +468,6 @@
return SECONDARY_ATTACK_CALL_NORMAL
-/// Called if the target gets deleted by our attack
-/obj/item/proc/attack_qdeleted(atom/target, mob/user, proximity_flag, click_parameters)
- SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_QDELETED, target, user, proximity_flag, click_parameters)
- SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK_QDELETED, target, user, proximity_flag, click_parameters)
-
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 38d99a75e6c..ae2ebd97632 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -31,7 +31,7 @@
MiddleClickOn(A, params)
return
if(LAZYACCESS(modifiers, ALT_CLICK))
- AltClickNoInteract(src, A)
+ base_click_alt(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm
index d6b8994f82f..900ad59bde2 100644
--- a/code/_onclick/overmind.dm
+++ b/code/_onclick/overmind.dm
@@ -10,7 +10,7 @@
ShiftClickOn(A)
return
if(LAZYACCESS(modifiers, ALT_CLICK))
- AltClickOn(A)
+ blob_click_alt(A)
return
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlClickOn(A)
@@ -30,7 +30,7 @@
if(T)
create_shield(T)
-/mob/camera/blob/AltClickOn(atom/A) //Remove a blob
+/mob/camera/blob/proc/blob_click_alt(atom/A) //Remove a blob
var/turf/T = get_turf(A)
if(T)
remove_blob(T)
diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 421712d5ad4..5056e3804ef 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -44,15 +44,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
usr.client.debug_variables(target)
message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].")
-
-// Debug verbs.
-/client/proc/restart_controller(controller in list("Master", "Failsafe"))
- set category = "Debug"
- set name = "Restart Controller"
- set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
-
- if(!holder)
- return
+ADMIN_VERB(restart_controller, R_DEBUG, "Restart Controller", "Restart one of the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG, controller in list("Master", "Failsafe"))
switch(controller)
if("Master")
Recreate_MC()
@@ -61,16 +53,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
new /datum/controller/failsafe()
BLACKBOX_LOG_ADMIN_VERB("Restart Failsafe Controller")
- message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
-
-/client/proc/debug_controller()
- set category = "Debug"
- set name = "Debug Controller"
- set desc = "Debug the various periodic loop controllers for the game (be careful!)"
-
- if(!holder)
- return
+ message_admins("Admin [key_name_admin(user)] has restarted the [controller] controller.")
+ADMIN_VERB(debug_controller, R_DEBUG, "Debug Controller", "Debug the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG)
var/list/controllers = list()
var/list/controller_choices = list()
@@ -85,7 +70,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
if (!istype(controller))
return
- debug_variables(controller)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/debug_variables, controller)
BLACKBOX_LOG_ADMIN_VERB("Debug Controller")
- message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
+ message_admins("Admin [key_name_admin(user)] is debugging the [controller] controller.")
diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm
index fb1cf4bf5a6..7f28c361267 100644
--- a/code/controllers/configuration/config_entry.dm
+++ b/code/controllers/configuration/config_entry.dm
@@ -25,7 +25,7 @@
/datum/config_entry/New()
if(type == abstract_type)
CRASH("Abstract config entry [type] instatiated!")
- name = lowertext(type2top(type))
+ name = LOWER_TEXT(type2top(type))
default_protection = protection
set_default()
@@ -100,7 +100,7 @@
return FALSE
config_entry_value = auto_trim ? trim(str_val) : str_val
if(lowercase)
- config_entry_value = lowertext(config_entry_value)
+ config_entry_value = LOWER_TEXT(config_entry_value)
return TRUE
/datum/config_entry/number
@@ -148,7 +148,7 @@
return FALSE
str_val = trim(str_val)
if (str_val != "")
- config_entry_value += lowercase ? lowertext(str_val) : str_val
+ config_entry_value += lowercase ? LOWER_TEXT(str_val) : str_val
return TRUE
/datum/config_entry/number_list
@@ -246,7 +246,7 @@
config_key = jointext(config_entry_words, splitter)
if(lowercase_key)
- config_key = lowertext(config_key)
+ config_key = LOWER_TEXT(config_key)
is_ambiguous = (length(config_entry_words) > 2)
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index 10c6cc4284f..2e5dfb468bd 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -170,7 +170,7 @@
if(IsAdminAdvancedProcCall())
return
- var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename
+ var/filename_to_test = world.system_type == MS_WINDOWS ? LOWER_TEXT(filename) : filename
if(filename_to_test in stack)
log_config_error("Warning: Config recursion detected ([english_list(stack)]), breaking!")
return
@@ -197,10 +197,10 @@
var/value = null
if(pos)
- entry = lowertext(copytext(L, 1, pos))
+ entry = LOWER_TEXT(copytext(L, 1, pos))
value = copytext(L, pos + length(L[pos]))
else
- entry = lowertext(L)
+ entry = LOWER_TEXT(L)
if(!entry)
continue
@@ -215,7 +215,7 @@
// Reset directive, used for setting a config value back to defaults. Useful for string list config types
if (entry == "$reset")
- var/datum/config_entry/resetee = _entries[lowertext(value)]
+ var/datum/config_entry/resetee = _entries[LOWER_TEXT(value)]
if (!value || !resetee)
log_config_error("Warning: invalid $reset directive: [value]")
continue
@@ -366,10 +366,10 @@ Example config:
var/data = null
if(pos)
- command = lowertext(copytext(t, 1, pos))
+ command = LOWER_TEXT(copytext(t, 1, pos))
data = copytext(t, pos + length(t[pos]))
else
- command = lowertext(t)
+ command = LOWER_TEXT(t)
if(!command)
continue
@@ -473,7 +473,7 @@ Example config:
var/list/formatted_banned_words = list()
for (var/banned_word in banned_words)
- formatted_banned_words[lowertext(banned_word)] = banned_words[banned_word]
+ formatted_banned_words[LOWER_TEXT(banned_word)] = banned_words[banned_word]
return formatted_banned_words
/datum/controller/configuration/proc/compile_filter_regex(list/banned_words)
diff --git a/code/controllers/configuration/entries/resources.dm b/code/controllers/configuration/entries/resources.dm
index c839ccc078d..1fb8a6237d4 100644
--- a/code/controllers/configuration/entries/resources.dm
+++ b/code/controllers/configuration/entries/resources.dm
@@ -6,7 +6,7 @@
/datum/config_entry/string/asset_transport
/datum/config_entry/string/asset_transport/ValidateAndSet(str_val)
- return (lowertext(str_val) in list("simple", "webroot")) && ..(lowertext(str_val))
+ return (LOWER_TEXT(str_val) in list("simple", "webroot")) && ..(LOWER_TEXT(str_val))
/datum/config_entry/string/asset_cdn_webroot
protection = CONFIG_ENTRY_LOCKED
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 9aa6d821abb..d7996890f98 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -76,6 +76,9 @@ GLOBAL_REAL(Master, /datum/controller/master)
///used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
var/static/current_ticklimit = TICK_LIMIT_RUNNING
+ /// Whether the Overview UI will update as fast as possible for viewers.
+ var/overview_fast_update = FALSE
+
/datum/controller/master/New()
if(!config)
config = new
@@ -135,6 +138,78 @@ GLOBAL_REAL(Master, /datum/controller/master)
ss.Shutdown()
log_world("Shutdown complete")
+ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "View the current states of the Subsystem Controllers.", ADMIN_CATEGORY_SERVER)
+ Master.ui_interact(user.mob)
+
+/datum/controller/master/ui_status(mob/user, datum/ui_state/state)
+ if(!user.client?.holder?.check_for_rights(R_SERVER|R_DEBUG))
+ return UI_CLOSE
+ return UI_INTERACTIVE
+
+/datum/controller/master/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(isnull(ui))
+ ui = new /datum/tgui(user, src, "ControllerOverview")
+ ui.open()
+
+/datum/controller/master/ui_data(mob/user)
+ var/list/data = list()
+
+ var/list/subsystem_data = list()
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ subsystem_data += list(list(
+ "name" = subsystem.name,
+ "ref" = REF(subsystem),
+ "init_order" = subsystem.init_order,
+ "last_fire" = subsystem.last_fire,
+ "next_fire" = subsystem.next_fire,
+ "can_fire" = subsystem.can_fire,
+ "doesnt_fire" = !!(subsystem.flags & SS_NO_FIRE),
+ "cost_ms" = subsystem.cost,
+ "tick_usage" = subsystem.tick_usage,
+ "tick_overrun" = subsystem.tick_overrun,
+ "initialized" = subsystem.initialized,
+ "initialization_failure_message" = subsystem.initialization_failure_message,
+ ))
+ data["subsystems"] = subsystem_data
+ data["world_time"] = world.time
+ data["map_cpu"] = world.map_cpu
+ data["fast_update"] = overview_fast_update
+
+ return data
+
+/datum/controller/master/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ if(..())
+ return TRUE
+
+ switch(action)
+ if("toggle_fast_update")
+ overview_fast_update = !overview_fast_update
+ return TRUE
+
+ if("view_variables")
+ var/datum/controller/subsystem/subsystem = locate(params["ref"]) in subsystems
+ if(isnull(subsystem))
+ to_chat(ui.user, span_warning("Failed to locate subsystem."))
+ return
+ SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/debug_variables, subsystem)
+ return TRUE
+
+/datum/controller/master/proc/check_and_perform_fast_update()
+ PRIVATE_PROC(TRUE)
+ set waitfor = FALSE
+
+
+ if(!overview_fast_update)
+ return
+
+ var/static/already_updating = FALSE
+ if(already_updating)
+ return
+ already_updating = TRUE
+ SStgui.update_uis(src)
+ already_updating = FALSE
+
// Returns 1 if we created a new mc, 0 if we couldn't due to a recent restart,
// -1 if we encountered a runtime trying to recreate it
/proc/Recreate_MC()
@@ -582,11 +657,9 @@ GLOBAL_REAL(Master, /datum/controller/master)
if (processing * sleep_delta <= world.tick_lag)
current_ticklimit -= (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc if we plan on running next tick
+ check_and_perform_fast_update()
sleep(world.tick_lag * (processing * sleep_delta))
-
-
-
// This is what decides if something should run.
/datum/controller/master/proc/CheckQueue(list/subsystemstocheck)
. = 0 //so the mc knows if we runtimed
diff --git a/code/controllers/subsystem/admin_verbs.dm b/code/controllers/subsystem/admin_verbs.dm
new file mode 100644
index 00000000000..9496b95d998
--- /dev/null
+++ b/code/controllers/subsystem/admin_verbs.dm
@@ -0,0 +1,150 @@
+GENERAL_PROTECT_DATUM(/datum/controller/subsystem/admin_verbs)
+
+SUBSYSTEM_DEF(admin_verbs)
+ name = "Admin Verbs"
+ flags = SS_NO_FIRE
+ init_order = INIT_ORDER_ADMIN_VERBS
+ /// A list of all admin verbs indexed by their type.
+ var/list/datum/admin_verb/admin_verbs_by_type = list()
+ /// A list of all admin verbs indexed by their visibility flag.
+ var/list/list/datum/admin_verb/admin_verbs_by_visibility_flag = list()
+ /// A map of all assosciated admins and their visibility flags.
+ var/list/admin_visibility_flags = list()
+ /// A list of all admins that are pending initialization of this SS.
+ var/list/admins_pending_subsytem_init = list()
+
+/datum/controller/subsystem/admin_verbs/Initialize()
+ setup_verb_list()
+ process_pending_admins()
+ return SS_INIT_SUCCESS
+
+/datum/controller/subsystem/admin_verbs/Recover()
+ admin_verbs_by_type = SSadmin_verbs.admin_verbs_by_type
+
+/datum/controller/subsystem/admin_verbs/stat_entry(msg)
+ return "[..()] | V: [length(admin_verbs_by_type)]"
+
+/datum/controller/subsystem/admin_verbs/proc/process_pending_admins()
+ var/list/pending_admins = admins_pending_subsytem_init
+ admins_pending_subsytem_init = null
+ for(var/admin_ckey in pending_admins)
+ assosciate_admin(GLOB.directory[admin_ckey])
+
+/datum/controller/subsystem/admin_verbs/proc/setup_verb_list()
+ if(length(admin_verbs_by_type))
+ CRASH("Attempting to setup admin verbs twice!")
+ for(var/datum/admin_verb/verb_type as anything in subtypesof(/datum/admin_verb))
+ var/datum/admin_verb/verb_singleton = new verb_type
+ if(!verb_singleton.__avd_check_should_exist())
+ qdel(verb_singleton, force = TRUE)
+ continue
+
+ admin_verbs_by_type[verb_type] = verb_singleton
+ if(verb_singleton.visibility_flag)
+ if(!(verb_singleton.visibility_flag in admin_verbs_by_visibility_flag))
+ admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] = list()
+ admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] |= list(verb_singleton)
+
+/datum/controller/subsystem/admin_verbs/proc/get_valid_verbs_for_admin(client/admin)
+ if(isnull(admin.holder))
+ CRASH("Why are we checking a non-admin for their valid... ahem... admin verbs?")
+
+ var/list/has_permission = list()
+ for(var/permission_flag in GLOB.bitflags)
+ if(admin.holder.check_for_rights(permission_flag))
+ has_permission["[permission_flag]"] = TRUE
+
+ var/list/valid_verbs = list()
+ for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type)
+ var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type]
+ if(!verify_visibility(admin, verb_singleton))
+ continue
+
+ var/verb_permissions = verb_singleton.permissions
+ if(verb_permissions == R_NONE)
+ valid_verbs |= list(verb_singleton)
+ else for(var/permission_flag in bitfield_to_list(verb_permissions))
+ if(!has_permission["[permission_flag]"])
+ continue
+ valid_verbs |= list(verb_singleton)
+
+ return valid_verbs
+
+/datum/controller/subsystem/admin_verbs/proc/verify_visibility(client/admin, datum/admin_verb/verb_singleton)
+ var/needed_flag = verb_singleton.visibility_flag
+ return !needed_flag || (needed_flag in admin_visibility_flags[admin.ckey])
+
+/datum/controller/subsystem/admin_verbs/proc/update_visibility_flag(client/admin, flag, state)
+ if(state)
+ admin_visibility_flags[admin.ckey] |= list(flag)
+ assosciate_admin(admin)
+ return
+
+ admin_visibility_flags[admin.ckey] -= list(flag)
+ // they lost the flag, iterate over verbs with that flag and yoink em
+ for(var/datum/admin_verb/verb_singleton as anything in admin_verbs_by_visibility_flag[flag])
+ verb_singleton.unassign_from_client(admin)
+ admin.init_verbs()
+
+/datum/controller/subsystem/admin_verbs/proc/dynamic_invoke_verb(client/admin, datum/admin_verb/verb_type, ...)
+ if(IsAdminAdvancedProcCall())
+ message_admins("PERMISSION ELEVATION: [key_name_admin(admin)] attempted to dynamically invoke admin verb '[verb_type]'.")
+ return
+
+ if(ismob(admin))
+ var/mob/mob = admin
+ admin = mob.client
+
+ if(!ispath(verb_type, /datum/admin_verb) || verb_type == /datum/admin_verb)
+ CRASH("Attempted to dynamically invoke admin verb with invalid typepath '[verb_type]'.")
+ if(isnull(admin.holder))
+ CRASH("Attempted to dynamically invoke admin verb '[verb_type]' with a non-admin.")
+
+ var/list/verb_args = args.Copy()
+ verb_args.Cut(2, 3)
+ var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type] // this cannot be typed because we need to use `:`
+ if(isnull(verb_singleton))
+ CRASH("Attempted to dynamically invoke admin verb '[verb_type]' that doesn't exist.")
+
+ if(!admin.holder.check_for_rights(verb_singleton.permissions))
+ to_chat(admin, span_adminnotice("You lack the permissions to do this."))
+ return
+
+ var/old_usr = usr
+ usr = admin.mob
+ // THE MACRO ENSURES THIS EXISTS. IF IT EVER DOESNT EXIST SOMEONE DIDNT USE THE DAMN MACRO!
+ verb_singleton.__avd_do_verb(arglist(verb_args))
+ usr = old_usr
+ SSblackbox.record_feedback("tally", "dynamic_admin_verb_invocation", 1, "[verb_type]")
+
+/**
+ * Assosciates and/or resyncs an admin with their accessible admin verbs.
+ */
+/datum/controller/subsystem/admin_verbs/proc/assosciate_admin(client/admin)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ if(!isnull(admins_pending_subsytem_init)) // if the list exists we are still initializing
+ to_chat(admin, span_big(span_green("Admin Verbs are still initializing. Please wait and you will be automatically assigned your verbs when it is complete.")))
+ admins_pending_subsytem_init |= list(admin.ckey)
+ return
+
+ // refresh their verbs
+ admin_visibility_flags[admin.ckey] ||= list()
+ for(var/datum/admin_verb/verb_singleton as anything in get_valid_verbs_for_admin(admin))
+ verb_singleton.assign_to_client(admin)
+ admin.init_verbs()
+
+/**
+ * Unassosciates an admin from their admin verbs.
+ * Goes over all admin verbs because we don't know which ones are assigned to the admin's mob without a bunch of extra bookkeeping.
+ * This might be a performance issue in the future if we have a lot of admin verbs.
+ */
+/datum/controller/subsystem/admin_verbs/proc/deassosciate_admin(client/admin)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ UnregisterSignal(admin, COMSIG_CLIENT_MOB_LOGIN)
+ for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type)
+ admin_verbs_by_type[verb_type].unassign_from_client(admin)
+ admin_visibility_flags -= list(admin.ckey)
diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm
index 1922d4a05f5..31de67361bf 100644
--- a/code/controllers/subsystem/explosions.dm
+++ b/code/controllers/subsystem/explosions.dm
@@ -87,12 +87,9 @@ SUBSYSTEM_DEF(explosions)
throwturf -= T
held_throwturf -= T
-/client/proc/check_bomb_impacts()
- set name = "Check Bomb Impact"
- set category = "Debug"
-
- var/newmode = tgui_alert(usr, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No"))
- var/turf/epicenter = get_turf(mob)
+ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effect of a bomb would be.", ADMIN_CATEGORY_DEBUG)
+ var/newmode = tgui_alert(user, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No"))
+ var/turf/epicenter = get_turf(user.mob)
if(!epicenter)
return
@@ -100,7 +97,7 @@ SUBSYSTEM_DEF(explosions)
var/heavy = 0
var/light = 0
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
- var/choice = tgui_input_list(usr, "Pick the bomb size", "Bomb Size?", choices)
+ var/choice = tgui_input_list(user, "Pick the bomb size", "Bomb Size?", choices)
switch(choice)
if(null)
return 0
@@ -117,9 +114,9 @@ SUBSYSTEM_DEF(explosions)
heavy = 5
light = 7
if("Custom Bomb")
- dev = input("Devastation range (Tiles):") as num
- heavy = input("Heavy impact range (Tiles):") as num
- light = input("Light impact range (Tiles):") as num
+ dev = input(user, "Devastation range (Tiles):") as num
+ heavy = input(user, "Heavy impact range (Tiles):") as num
+ light = input(user, "Light impact range (Tiles):") as num
var/max_range = max(dev, heavy, light)
var/x0 = epicenter.x
@@ -208,9 +205,12 @@ SUBSYSTEM_DEF(explosions)
* - flame_range: The range at which the explosion should produce hotspots.
* - silent: Whether to generate/execute sound effects.
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
+ * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion
* - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging.
+ * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.)
+ * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.)
*/
-/proc/explosion(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null)
+/proc/explosion(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, protect_epicenter = FALSE, atom/explosion_cause = null, explosion_direction = 0, explosion_arc = 360)
. = SSexplosions.explode(arglist(args))
@@ -228,9 +228,12 @@ SUBSYSTEM_DEF(explosions)
* - flame_range: The range at which the explosion should produce hotspots.
* - silent: Whether to generate/execute sound effects.
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
+ * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion
* - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging.
+ * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.)
+ * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.)
*/
-/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null)
+/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, protect_epicenter = FALSE, atom/explosion_cause = null, explosion_direction = 0, explosion_arc = 360)
var/list/arguments = list(
EXARG_KEY_ORIGIN = origin,
EXARG_KEY_DEV_RANGE = devastation_range,
@@ -242,7 +245,10 @@ SUBSYSTEM_DEF(explosions)
EXARG_KEY_IGNORE_CAP = ignorecap,
EXARG_KEY_SILENT = silent,
EXARG_KEY_SMOKE = smoke,
+ EXARG_KEY_PROTECT_EPICENTER = protect_epicenter,
EXARG_KEY_EXPLOSION_CAUSE = explosion_cause ? explosion_cause : origin,
+ EXARG_KEY_EXPLOSION_DIRECTION = explosion_direction,
+ EXARG_KEY_EXPLOSION_ARC = explosion_arc,
)
var/atom/location = isturf(origin) ? origin : origin.loc
if(SEND_SIGNAL(origin, COMSIG_ATOM_EXPLODE, arguments) & COMSIG_CANCEL_EXPLOSION)
@@ -270,7 +276,7 @@ SUBSYSTEM_DEF(explosions)
/**
* Handles the effects of an explosion originating from a given point.
*
- * Primarily handles popagating the balstwave of the explosion to the relevant turfs.
+ * Primarily handles popagating the blastwave of the explosion to the relevant turfs.
* Also handles the fireball from the explosion.
* Also handles the smoke cloud from the explosion.
* Also handles sfx and screenshake.
@@ -286,9 +292,12 @@ SUBSYSTEM_DEF(explosions)
* - flame_range: The range at which the explosion should produce hotspots.
* - silent: Whether to generate/execute sound effects.
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
- * - explosion_cause: The atom that caused the explosion. Used for logging.
+ * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion
+ * - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging.
+ * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.)
+ * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.)
*/
-/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, atom/explosion_cause)
+/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, protect_epicenter, atom/explosion_cause, explosion_direction, explosion_arc)
epicenter = get_turf(epicenter)
if(!epicenter)
return
@@ -387,7 +396,7 @@ SUBSYSTEM_DEF(explosions)
for(var/mob/living/L in viewers(flash_range, epicenter))
L.flash_act()
- var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter)
+ var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter, protect_epicenter, explosion_direction, explosion_arc)
var/reactionary = CONFIG_GET(flag/reactionary_explosions)
// this list is setup in the form position -> block for that position
@@ -415,7 +424,6 @@ SUBSYSTEM_DEF(explosions)
block += our_block
cached_exp_block[explode] = our_block + explode.explosive_resistance
-
var/severity = EXPLODE_NONE
if(dist + (block * EXPLOSION_BLOCK_DEV) < devastation_range)
severity = EXPLODE_DEVASTATE
@@ -585,10 +593,12 @@ SUBSYSTEM_DEF(explosions)
/// Returns in a unique order, spiraling outwards
/// This is done to ensure our progressive cache of blast resistance is always valid
/// This is quite fast
-/proc/prepare_explosion_turfs(range, turf/epicenter)
+/proc/prepare_explosion_turfs(range, turf/epicenter, protect_epicenter, explosion_direction, explosion_arc)
var/list/outlist = list()
- // Add in the center
- outlist += epicenter
+ var/list/candidates = list()
+ // Add in the center if it's not protected
+ if(!protect_epicenter)
+ outlist += epicenter
var/our_x = epicenter.x
var/our_y = epicenter.y
@@ -596,6 +606,31 @@ SUBSYSTEM_DEF(explosions)
var/max_x = world.maxx
var/max_y = world.maxy
+
+ // Work out the angles to explode between
+ var/first_angle_limit = WRAP(explosion_direction - explosion_arc * 0.5, 0, 360)
+ var/second_angle_limit = WRAP(explosion_direction + explosion_arc * 0.5, 0, 360)
+
+ // Get everything in the right order
+ var/lower_angle_limit
+ var/upper_angle_limit
+ var/do_directional
+ var/reverse_angle
+
+ // Work out which case we're in
+ if(first_angle_limit == second_angle_limit) // CASE A: FULL CIRCLE
+ do_directional = FALSE
+ else if(first_angle_limit < second_angle_limit) // CASE B: When the arc does not cross 0 degrees
+ lower_angle_limit = first_angle_limit
+ upper_angle_limit = second_angle_limit
+ do_directional = TRUE
+ reverse_angle = FALSE
+ else if (first_angle_limit > second_angle_limit) // CASE C: When the arc crosses 0 degrees
+ lower_angle_limit = second_angle_limit
+ upper_angle_limit = first_angle_limit
+ do_directional = TRUE
+ reverse_angle = TRUE
+
for(var/i in 1 to range)
var/lowest_x = our_x - i
var/lowest_y = our_y - i
@@ -603,25 +638,32 @@ SUBSYSTEM_DEF(explosions)
var/highest_y = our_y + i
// top left to one before top right
if(highest_y <= max_y)
- outlist += block(
+ candidates += block(
locate(max(lowest_x, 1), highest_y, our_z),
locate(min(highest_x - 1, max_x), highest_y, our_z))
// top right to one before bottom right
if(highest_x <= max_x)
- outlist += block(
+ candidates += block(
locate(highest_x, min(highest_y, max_y), our_z),
locate(highest_x, max(lowest_y + 1, 1), our_z))
// bottom right to one before bottom left
if(lowest_y >= 1)
- outlist += block(
+ candidates += block(
locate(min(highest_x, max_x), lowest_y, our_z),
locate(max(lowest_x + 1, 1), lowest_y, our_z))
// bottom left to one before top left
if(lowest_x >= 1)
- outlist += block(
+ candidates += block(
locate(lowest_x, max(lowest_y, 1), our_z),
locate(lowest_x, min(highest_y - 1, max_y), our_z))
+ if(!do_directional)
+ outlist += candidates
+ else
+ for(var/turf/candidate as anything in candidates)
+ var/angle = get_angle(epicenter, candidate)
+ if(ISINRANGE(angle, lower_angle_limit, upper_angle_limit) ^ reverse_angle)
+ outlist += candidate
return outlist
/datum/controller/subsystem/explosions/fire(resumed = 0)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index b34f9551eb4..3aa9fba84e6 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -651,46 +651,38 @@ GLOBAL_LIST_EMPTY(the_station_areas)
holodeck_templates[holo_template.template_id] = holo_template
-//Manual loading of away missions.
-/client/proc/admin_away()
- set name = "Load Away Mission"
- set category = "Admin.Events"
-
- if(!holder || !check_rights(R_FUN))
- return
-
-
+ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away mission for the station.", ADMIN_CATEGORY_EVENTS)
if(!GLOB.the_gateway)
- if(tgui_alert(usr, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes")
+ if(tgui_alert(user, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes")
return
var/list/possible_options = GLOB.potentialRandomZlevels + "Custom"
var/away_name
var/datum/space_level/away_level
var/secret = FALSE
- if(tgui_alert(usr, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes")
+ if(tgui_alert(user, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes")
secret = TRUE
- var/answer = input("What kind?","Away") as null|anything in possible_options
+ var/answer = input(user, "What kind?","Away") as null|anything in possible_options
switch(answer)
if("Custom")
- var/mapfile = input("Pick file:", "File") as null|file
+ var/mapfile = input(user, "Pick file:", "File") as null|file
if(!mapfile)
return
away_name = "[mapfile] custom"
- to_chat(usr,span_notice("Loading [away_name]..."))
+ to_chat(user,span_notice("Loading [away_name]..."))
var/datum/map_template/template = new(mapfile, "Away Mission")
away_level = template.load_new_z(secret)
else
if(answer in GLOB.potentialRandomZlevels)
away_name = answer
- to_chat(usr,span_notice("Loading [away_name]..."))
+ to_chat(user,span_notice("Loading [away_name]..."))
var/datum/map_template/template = new(away_name, "Away Mission")
away_level = template.load_new_z(secret)
else
return
- message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
- log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
+ message_admins("Admin [key_name_admin(user)] has loaded [away_name] away mission.")
+ log_admin("Admin [key_name(user)] has loaded [away_name] away mission.")
if(!away_level)
message_admins("Loading [away_name] failed!")
return
diff --git a/code/controllers/subsystem/processing/obj_tab_items.dm b/code/controllers/subsystem/processing/obj_tab_items.dm
deleted file mode 100644
index 53786daf011..00000000000
--- a/code/controllers/subsystem/processing/obj_tab_items.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-PROCESSING_SUBSYSTEM_DEF(obj_tab_items)
- name = "Obj Tab Items"
- flags = SS_NO_INIT
- runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
- wait = 0.1 SECONDS
-
-// I know this is mostly copypasta, but I want to change the processing logic
-// Sorry bestie :(
-/datum/controller/subsystem/processing/obj_tab_items/fire(resumed = FALSE)
- if (!resumed)
- currentrun = processing.Copy()
- //cache for sanic speed (lists are references anyways)
- var/list/current_run = currentrun
-
- while(current_run.len)
- var/datum/thing = current_run[current_run.len]
- if(QDELETED(thing))
- processing -= thing
- else if(thing.process(wait * 0.1) == PROCESS_KILL)
- // fully stop so that a future START_PROCESSING will work
- STOP_PROCESSING(src, thing)
- if (MC_TICK_CHECK)
- return
- current_run.len--
diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm
index edeb63d3dc5..733b94d582a 100644
--- a/code/controllers/subsystem/statpanel.dm
+++ b/code/controllers/subsystem/statpanel.dm
@@ -112,12 +112,6 @@ SUBSYSTEM_DEF(statpanels)
if(update_actions && num_fires % default_wait == 0)
set_action_tabs(target, target_mob)
- // Handle the examined turf of the stat panel, if it's been long enough, or if we've generated new images for it
- var/turf/listed_turf = target_mob?.listed_turf
- if(listed_turf && num_fires % default_wait == 0)
- if(target.stat_tab == listed_turf.name || !(listed_turf.name in target.panel_tabs))
- set_turf_examine_tab(target, target_mob)
-
if(MC_TICK_CHECK)
return
@@ -190,71 +184,6 @@ SUBSYSTEM_DEF(statpanels)
target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions))
-/datum/controller/subsystem/statpanels/proc/set_turf_examine_tab(client/target, mob/target_mob)
- var/list/overrides = list()
- for(var/image/target_image as anything in target.images)
- if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override)
- continue
- overrides += target_image.loc
-
- var/list/atoms_to_display = list(target_mob.listed_turf)
- for(var/atom/movable/turf_content as anything in target_mob.listed_turf)
- if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
- continue
- if(turf_content.invisibility > target_mob.see_invisible)
- continue
- if(turf_content in overrides)
- continue
- if(turf_content.IsObscured())
- continue
- atoms_to_display += turf_content
-
- /// Set the atoms we're meant to display
- var/datum/object_window_info/obj_window = target.obj_window
- obj_window.atoms_to_show = atoms_to_display
- START_PROCESSING(SSobj_tab_items, obj_window)
- refresh_client_obj_view(target)
-
-/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh)
- var/list/turf_items = return_object_images(refresh)
- if(!length(turf_items) || !refresh.mob?.listed_turf)
- return
- refresh.stat_panel.send_message("update_listedturf", turf_items)
-
-#define OBJ_IMAGE_LOADING "statpanels obj loading temporary"
-/// Returns all our ready object tab images
-/// Returns a list in the form list(list(object_name, object_ref, loaded_image), ...)
-/datum/controller/subsystem/statpanels/proc/return_object_images(client/load_from)
- // You might be inclined to think that this is a waste of cpu time, since we
- // A: Double iterate over atoms in the build case, or
- // B: Generate these lists over and over in the refresh case
- // It's really not very hot. The hot portion of this code is genuinely mostly in the image generation
- // So it's ok to pay a performance cost for cleanliness here
-
- // No turf? go away
- if(!load_from.mob?.listed_turf)
- return list()
- var/datum/object_window_info/obj_window = load_from.obj_window
- var/list/already_seen = obj_window.atoms_to_images
- var/list/to_make = obj_window.atoms_to_imagify
- var/list/turf_items = list()
- for(var/atom/turf_item as anything in obj_window.atoms_to_show)
- // First, we fill up the list of refs to display
- // If we already have one, just use that
- var/existing_image = already_seen[turf_item]
- if(existing_image == OBJ_IMAGE_LOADING)
- continue
- // We already have it. Success!
- if(existing_image)
- turf_items[++turf_items.len] = list("[turf_item.name]", REF(turf_item), existing_image)
- continue
- // Now, we're gonna queue image generation out of those refs
- to_make += turf_item
- already_seen[turf_item] = OBJ_IMAGE_LOADING
- obj_window.RegisterSignal(turf_item, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted
- return turf_items
-
-#undef OBJ_IMAGE_LOADING
/datum/controller/subsystem/statpanels/proc/generate_mc_data()
mc_data = list(
@@ -296,16 +225,6 @@ SUBSYSTEM_DEF(statpanels)
set_action_tabs(target, target_mob)
return TRUE
- // Handle turfs
-
- if(target_mob?.listed_turf)
- if(!target_mob.TurfAdjacent(target_mob.listed_turf))
- target_mob.set_listed_turf(null)
-
- else if(target.stat_tab == target_mob?.listed_turf.name || !(target_mob?.listed_turf.name in target.panel_tabs))
- set_turf_examine_tab(target, target_mob)
- return TRUE
-
if(!target.holder)
return FALSE
@@ -325,105 +244,3 @@ SUBSYSTEM_DEF(statpanels)
/// Stat panel window declaration
/client/var/datum/tgui_window/stat_panel
-
-/// Datum that holds and tracks info about a client's object window
-/// Really only exists because I want to be able to do logic with signals
-/// And need a safe place to do the registration
-/datum/object_window_info
- /// list of atoms to show to our client via the object tab, at least currently
- var/list/atoms_to_show = list()
- /// list of atom -> image string for objects we have had in the right click tab
- /// this is our caching
- var/list/atoms_to_images = list()
- /// list of atoms to turn into images for the object tab
- var/list/atoms_to_imagify = list()
- /// Our owner client
- var/client/parent
- /// Are we currently tracking a turf?
- var/actively_tracking = FALSE
-
-/datum/object_window_info/New(client/parent)
- . = ..()
- src.parent = parent
-
-/datum/object_window_info/Destroy(force)
- atoms_to_show = null
- atoms_to_images = null
- atoms_to_imagify = null
- parent.obj_window = null
- parent = null
- STOP_PROCESSING(SSobj_tab_items, src)
- return ..()
-
-/// Takes a client, attempts to generate object images for it
-/// We will update the client with any improvements we make when we're done
-/datum/object_window_info/process(seconds_per_tick)
- // Cache the datum access for sonic speed
- var/list/to_make = atoms_to_imagify
- var/list/newly_seen = atoms_to_images
- var/index = 0
- for(index in 1 to length(to_make))
- var/atom/thing = to_make[index]
-
- var/generated_string
- if(ismob(thing) || length(thing.overlays) > 2)
- generated_string = costly_icon2html(thing, parent, sourceonly=TRUE)
- else
- generated_string = icon2html(thing, parent, sourceonly=TRUE)
-
- newly_seen[thing] = generated_string
- if(TICK_CHECK)
- to_make.Cut(1, index + 1)
- index = 0
- break
- // If we've not cut yet, do it now
- if(index)
- to_make.Cut(1, index + 1)
- SSstatpanels.refresh_client_obj_view(parent)
- if(!length(to_make))
- return PROCESS_KILL
-
-/datum/object_window_info/proc/start_turf_tracking()
- if(actively_tracking)
- stop_turf_tracking()
- var/static/list/connections = list(
- COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move),
- COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout),
- )
- AddComponent(/datum/component/connect_mob_behalf, parent, connections)
- actively_tracking = TRUE
-
-/datum/object_window_info/proc/stop_turf_tracking()
- qdel(GetComponent(/datum/component/connect_mob_behalf))
- actively_tracking = FALSE
-
-/datum/object_window_info/proc/on_mob_move(mob/source)
- SIGNAL_HANDLER
- var/turf/listed = source.listed_turf
- if(!listed || !source.TurfAdjacent(listed))
- source.set_listed_turf(null)
-
-/datum/object_window_info/proc/on_mob_logout(mob/source)
- SIGNAL_HANDLER
- on_mob_move(parent.mob)
-
-/// Clears any cached object window stuff
-/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way
-/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted)
- SIGNAL_HANDLER
- atoms_to_show -= deleted
- atoms_to_imagify -= deleted
- atoms_to_images -= deleted
-
-/mob/proc/set_listed_turf(turf/new_turf)
- listed_turf = new_turf
- if(!client)
- return
- if(!client.obj_window)
- client.obj_window = new(client)
- if(listed_turf)
- client.stat_panel.send_message("create_listedturf", listed_turf.name)
- client.obj_window.start_turf_tracking()
- else
- client.stat_panel.send_message("remove_listedturf")
- client.obj_window.stop_turf_tracking()
diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm
index c12c1b2bb32..cd03e1f3e52 100644
--- a/code/controllers/subsystem/tgui.dm
+++ b/code/controllers/subsystem/tgui.dm
@@ -122,8 +122,6 @@ SUBSYSTEM_DEF(tgui)
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
ui.close(can_be_suspended = FALSE)
- // Unset machine just to be sure.
- user.unset_machine()
// Close window directly just to be sure.
user << browse(null, "window=[window_id]")
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 4526a8b5a79..c15129d9345 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -92,7 +92,7 @@ SUBSYSTEM_DEF(ticker)
var/use_rare_music = prob(1)
for(var/S in provisional_title_music)
- var/lower = lowertext(S)
+ var/lower = LOWER_TEXT(S)
var/list/L = splittext(lower,"+")
switch(L.len)
if(3) //rare+MAP+sound.ogg or MAP+rare.sound.ogg -- Rare Map-specific sounds
@@ -116,7 +116,7 @@ SUBSYSTEM_DEF(ticker)
for(var/S in music)
var/list/L = splittext(S,".")
if(L.len >= 2)
- var/ext = lowertext(L[L.len]) //pick the real extension, no 'honk.ogg.exe' nonsense here
+ var/ext = LOWER_TEXT(L[L.len]) //pick the real extension, no 'honk.ogg.exe' nonsense here
if(byond_sound_formats[ext])
continue
music -= S
@@ -296,8 +296,8 @@ SUBSYSTEM_DEF(ticker)
log_world("Game start took [(world.timeofday - init_start)/10]s")
INVOKE_ASYNC(SSdbcore, TYPE_PROC_REF(/datum/controller/subsystem/dbcore,SetRoundStart))
- to_chat(world, span_notice("Welcome to [station_name()], enjoy your stay!"))
- alert_sound_to_playing(sound(SSstation.announcer.get_rand_welcome_sound())) //SKYRAT EDIT CHANGE
+ to_chat(world, span_notice(span_bold("Welcome to [station_name()], enjoy your stay!")))
+ SEND_SOUND(world, sound(SSstation.announcer.get_rand_welcome_sound()))
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm
index 1fb7944191d..afddd1d01de 100644
--- a/code/controllers/subsystem/title.dm
+++ b/code/controllers/subsystem/title.dm
@@ -26,7 +26,7 @@ SUBSYSTEM_DEF(title)
for(var/S in provisional_title_screens)
var/list/L = splittext(S,"+")
- if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(SSmapping.config.map_name)))))
+ if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && LOWER_TEXT(L[1]) == "rare") || (LOWER_TEXT(L[1]) == LOWER_TEXT(SSmapping.config.map_name)))))
title_screens += S
if(length(title_screens))
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 78c99f47903..b8496a623eb 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -86,15 +86,9 @@ SUBSYSTEM_DEF(weather)
/datum/controller/subsystem/weather/proc/get_weather_by_type(type)
return locate(type) in processing
-/**
- * Calls end() on all current weather effects that are currently processing in the weather subsystem.
- */
-/client/proc/stop_weather()
- set category = "Debug"
- set name = "Stop All Active Weather"
-
- log_admin("[key_name(src)] stopped all currently active weather.")
- message_admins("[key_name_admin(src)] stopped all currently active weather.")
+ADMIN_VERB(stop_weather, R_DEBUG|R_ADMIN, "Stop All Active Weather", "Stop all currently active weather.", ADMIN_CATEGORY_DEBUG)
+ log_admin("[key_name(user)] stopped all currently active weather.")
+ message_admins("[key_name_admin(user)] stopped all currently active weather.")
for(var/datum/weather/current_weather as anything in SSweather.processing)
if(current_weather in SSweather.processing)
current_weather.end()
diff --git a/code/datums/ai/oldhostile/hostile_tameable.dm b/code/datums/ai/oldhostile/hostile_tameable.dm
index 5c96eca17da..d76ffb8a282 100644
--- a/code/datums/ai/oldhostile/hostile_tameable.dm
+++ b/code/datums/ai/oldhostile/hostile_tameable.dm
@@ -108,7 +108,7 @@
return
if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] != clicker)
return
- . = COMPONENT_CANCEL_CLICK_ALT
+ . = CLICK_ACTION_BLOCKING
INVOKE_ASYNC(src, PROC_REF(command_radial), clicker)
/// Show the command radial menu
diff --git a/code/datums/beam.dm b/code/datums/beam.dm
index 52b649990d7..fe34b0c7edd 100644
--- a/code/datums/beam.dm
+++ b/code/datums/beam.dm
@@ -40,6 +40,8 @@
var/override_target_pixel_x = null
/// If set will be used instead of targets's pixel_y in offset calculations
var/override_target_pixel_y = null
+ ///the layer of our beam
+ var/beam_layer
/datum/beam/New(
origin,
@@ -55,6 +57,7 @@
override_origin_pixel_y = null,
override_target_pixel_x = null,
override_target_pixel_y = null,
+ beam_layer = ABOVE_ALL_MOB_LAYER
)
src.origin = origin
src.target = target
@@ -68,6 +71,7 @@
src.override_origin_pixel_y = override_origin_pixel_y
src.override_target_pixel_x = override_target_pixel_x
src.override_target_pixel_y = override_target_pixel_y
+ src.beam_layer = beam_layer
if(time < INFINITY)
QDEL_IN(src, time)
@@ -81,6 +85,7 @@
visuals.color = beam_color
visuals.vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_LAYER
visuals.emissive = emissive
+ visuals.layer = beam_layer
visuals.update_appearance()
Draw()
RegisterSignal(origin, COMSIG_MOVABLE_MOVED, PROC_REF(redrawing))
@@ -278,7 +283,18 @@
* maxdistance: how far the beam will go before stopping itself. Used mainly for two things: preventing lag if the beam may go in that direction and setting a range to abilities that use beams.
* beam_type: The type of your custom beam. This is for adding other wacky stuff for your beam only. Most likely, you won't (and shouldn't) change it.
*/
-/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=INFINITY,maxdistance=INFINITY,beam_type=/obj/effect/ebeam, beam_color = null, emissive = TRUE, override_origin_pixel_x = null, override_origin_pixel_y = null, override_target_pixel_x = null, override_target_pixel_y = null)
- var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y )
+/atom/proc/Beam(atom/BeamTarget,
+ icon_state="b_beam",
+ icon='icons/effects/beam.dmi',
+ time=INFINITY,maxdistance=INFINITY,
+ beam_type=/obj/effect/ebeam,
+ beam_color = null, emissive = TRUE,
+ override_origin_pixel_x = null,
+ override_origin_pixel_y = null,
+ override_target_pixel_x = null,
+ override_target_pixel_y = null,
+ layer = ABOVE_ALL_MOB_LAYER
+)
+ var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y, layer)
INVOKE_ASYNC(newbeam, TYPE_PROC_REF(/datum/beam/, Start))
return newbeam
diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm
index dbaa571cacd..5630073c955 100644
--- a/code/datums/brain_damage/hypnosis.dm
+++ b/code/datums/brain_damage/hypnosis.dm
@@ -61,7 +61,7 @@
..()
if(SPT_PROB(1, seconds_per_tick))
if(prob(50))
- to_chat(owner, span_hypnophrase("...[lowertext(hypnotic_phrase)]..."))
+ to_chat(owner, span_hypnophrase("...[LOWER_TEXT(hypnotic_phrase)]..."))
else
owner.cause_hallucination( \
/datum/hallucination/chat, \
diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index 18ca8172968..e3891392d1a 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -217,11 +217,11 @@
message = capitalize(message)
if(message_mods[RADIO_EXTENSION] == MODE_ADMIN)
- client?.cmd_admin_say(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message)
return
if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN)
- client?.dsay(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message)
return
if(check_emote(message, forced))
diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm
index 21ecf1b520b..1d121d0db8a 100644
--- a/code/datums/brain_damage/mild.dm
+++ b/code/datums/brain_damage/mild.dm
@@ -212,7 +212,7 @@
word = copytext(word, 1, suffix_foundon)
word = html_decode(word)
- if(lowertext(word) in common_words)
+ if(LOWER_TEXT(word) in common_words)
new_message += word + suffix
else
if(prob(30) && message_split.len > 2)
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index 08099b46f1a..f74ecf6c5a3 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -475,7 +475,3 @@
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
- // no atomref specified (or not found)
- // so just reset the user mob's machine var
- if(src?.mob)
- src.mob.unset_machine()
diff --git a/code/datums/cogbar.dm b/code/datums/cogbar.dm
index c52092e5bd1..0b5ead1e51e 100644
--- a/code/datums/cogbar.dm
+++ b/code/datums/cogbar.dm
@@ -1,4 +1,4 @@
-#define COGBAR_ANIMATION_TIME 5 DECISECONDS
+#define COGBAR_ANIMATION_TIME (0.5 SECONDS)
/**
* ### Cogbar
diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm
index a745be2b1a5..afc71936f1b 100644
--- a/code/datums/components/bakeable.dm
+++ b/code/datums/components/bakeable.dm
@@ -90,11 +90,24 @@
baked_result.pixel_y = original_object.pixel_y
used_tray.AddToPlate(baked_result)
+ var/list/asomnia_hadders = list()
+ for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, used_oven))
+ if(HAS_TRAIT(smeller, TRAIT_ANOSMIA))
+ asomnia_hadders += smeller
+
if(positive_result)
- used_oven.visible_message(span_notice("You smell something great coming from [used_oven]."), blind_message = span_notice("You smell something great..."))
+ used_oven.visible_message(
+ span_notice("You smell something great coming from [used_oven]."),
+ blind_message = span_notice("You smell something great..."),
+ ignored_mobs = asomnia_hadders,
+ )
BLACKBOX_LOG_FOOD_MADE(baked_result.type)
else
- used_oven.visible_message(span_warning("You smell a burnt smell coming from [used_oven]."), blind_message = span_warning("You smell a burnt smell..."))
+ used_oven.visible_message(
+ span_warning("You smell a burnt smell coming from [used_oven]."),
+ blind_message = span_warning("You smell a burnt smell..."),
+ ignored_mobs = asomnia_hadders,
+ )
SEND_SIGNAL(parent, COMSIG_ITEM_BAKED, baked_result)
qdel(parent)
diff --git a/code/datums/components/crafting/melee_weapon.dm b/code/datums/components/crafting/melee_weapon.dm
index 23873a5d7af..869d223a758 100644
--- a/code/datums/components/crafting/melee_weapon.dm
+++ b/code/datums/components/crafting/melee_weapon.dm
@@ -44,6 +44,21 @@
time = 4 SECONDS
category = CAT_WEAPON_MELEE
+
+/datum/crafting_recipe/balloon_mallet
+ name = "Balloon Mallet"
+ result = /obj/item/balloon_mallet
+ reqs = list(
+ /obj/item/toy/balloon/long = 18,
+ )
+ time = 10 SECONDS
+ category = CAT_WEAPON_MELEE
+
+/datum/crafting_recipe/balloon_mallet/check_requirements(mob/user, list/collected_requirements)
+ . = ..()
+ if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA))
+ return TRUE
+
/datum/crafting_recipe/tailwhip
name = "Liz O' Nine Tails"
result = /obj/item/melee/chainofcommand/tailwhip
diff --git a/code/datums/components/crafting/tailoring.dm b/code/datums/components/crafting/tailoring.dm
index 14a7ebfc21b..3476016ead3 100644
--- a/code/datums/components/crafting/tailoring.dm
+++ b/code/datums/components/crafting/tailoring.dm
@@ -442,3 +442,42 @@
/obj/item/clothing/suit/armor/vest = 1,
)
category = CAT_CLOTHING
+
+/datum/crafting_recipe/balloon_helmet
+ result = /obj/item/clothing/head/helmet/balloon
+ reqs = list(
+ /obj/item/toy/balloon/long = 6,
+ )
+ time = 4 SECONDS
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/balloon_helmet/check_requirements(mob/user, list/collected_requirements)
+ . = ..()
+ if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA))
+ return TRUE
+
+/datum/crafting_recipe/balloon_tophat
+ result = /obj/item/clothing/head/hats/tophat/balloon
+ reqs = list(
+ /obj/item/toy/balloon/long = 6,
+ )
+ time = 4 SECONDS
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/balloon_tophat/check_requirements(mob/user, list/collected_requirements)
+ . = ..()
+ if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA))
+ return TRUE
+
+/datum/crafting_recipe/balloon_vest
+ result = /obj/item/clothing/suit/armor/balloon_vest
+ reqs = list(
+ /obj/item/toy/balloon/long = 18,
+ )
+ time = 8 SECONDS
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/balloon_vest/check_requirements(mob/user, list/collected_requirements)
+ . = ..()
+ if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA))
+ return TRUE
diff --git a/code/datums/components/cult_ritual_item.dm b/code/datums/components/cult_ritual_item.dm
index 74bac463e32..7d9710977ce 100644
--- a/code/datums/components/cult_ritual_item.dm
+++ b/code/datums/components/cult_ritual_item.dm
@@ -221,7 +221,7 @@
cultist.log_message("erased a [rune.cultist_name] rune with [parent].", LOG_GAME)
message_admins("[ADMIN_LOOKUPFLW(cultist)] erased a [rune.cultist_name] rune with [parent].")
- to_chat(cultist, span_notice("You carefully erase the [lowertext(rune.cultist_name)] rune."))
+ to_chat(cultist, span_notice("You carefully erase the [LOWER_TEXT(rune.cultist_name)] rune."))
qdel(rune)
/*
@@ -338,8 +338,8 @@
var/obj/effect/rune/made_rune = new rune_to_scribe(our_turf, chosen_keyword)
made_rune.add_mob_blood(cultist)
- to_chat(cultist, span_cult("The [lowertext(made_rune.cultist_name)] rune [made_rune.cultist_desc]"))
- cultist.log_message("scribed \a [lowertext(made_rune.cultist_name)] rune using [parent] ([parent.type])", LOG_GAME)
+ to_chat(cultist, span_cult("The [LOWER_TEXT(made_rune.cultist_name)] rune [made_rune.cultist_desc]"))
+ cultist.log_message("scribed \a [LOWER_TEXT(made_rune.cultist_name)] rune using [parent] ([parent.type])", LOG_GAME)
SSblackbox.record_feedback("tally", "cult_runes_scribed", 1, made_rune.cultist_name)
return TRUE
diff --git a/code/datums/components/customizable_reagent_holder.dm b/code/datums/components/customizable_reagent_holder.dm
index bd88508bec0..fd1b8a2ac64 100644
--- a/code/datums/components/customizable_reagent_holder.dm
+++ b/code/datums/components/customizable_reagent_holder.dm
@@ -206,7 +206,7 @@
if(isitem(atom_parent))
var/obj/item/item_parent = atom_parent
if(ingredient.w_class > item_parent.w_class)
- item_parent.w_class = ingredient.w_class
+ item_parent.update_weight_class(ingredient.w_class)
atom_parent.name = "[custom_adjective()] [custom_type()] [initial(atom_parent.name)]"
SEND_SIGNAL(atom_parent, COMSIG_ATOM_CUSTOMIZED, ingredient)
SEND_SIGNAL(ingredient, COMSIG_ITEM_USED_AS_INGREDIENT, atom_parent)
diff --git a/code/datums/components/deadchat_control.dm b/code/datums/components/deadchat_control.dm
index 7517f35ff29..210ef26a052 100644
--- a/code/datums/components/deadchat_control.dm
+++ b/code/datums/components/deadchat_control.dm
@@ -61,7 +61,7 @@
/datum/component/deadchat_control/proc/deadchat_react(mob/source, message)
SIGNAL_HANDLER
- message = lowertext(message)
+ message = LOWER_TEXT(message)
if(!inputs[message])
return
@@ -162,7 +162,7 @@
*/
/datum/component/deadchat_control/proc/waive_automute(mob/speaker, client/client, message, mute_type)
SIGNAL_HANDLER
- if(mute_type == MUTE_DEADCHAT && inputs[lowertext(message)])
+ if(mute_type == MUTE_DEADCHAT && inputs[LOWER_TEXT(message)])
return WAIVE_AUTOMUTE_CHECK
return NONE
diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm
index ded8b8c4161..a0b20858927 100644
--- a/code/datums/components/food/edible.dm
+++ b/code/datums/components/food/edible.dm
@@ -215,7 +215,7 @@ Behavior that's still missing from this component that original food items had t
if(foodtypes)
var/list/types = bitfield_to_list(foodtypes, FOOD_FLAGS)
- examine_list += span_notice("It is [lowertext(english_list(types))].")
+ examine_list += span_notice("It is [LOWER_TEXT(english_list(types))].")
var/quality = get_perceived_food_quality(user)
if(quality > 0)
diff --git a/code/datums/components/gps.dm b/code/datums/components/gps.dm
index ceee193bf4a..7e52f00def7 100644
--- a/code/datums/components/gps.dm
+++ b/code/datums/components/gps.dm
@@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
if(!emp_proof)
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act))
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
- RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_AltClick))
+ RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_click_alt))
///Called on COMSIG_ITEM_ATTACK_SELF
/datum/component/gps/item/proc/interact(datum/source, mob/user)
@@ -85,10 +85,11 @@ GLOBAL_LIST_EMPTY(GPS_list)
A.add_overlay("working")
///Calls toggletracking
-/datum/component/gps/item/proc/on_AltClick(datum/source, mob/user)
+/datum/component/gps/item/proc/on_click_alt(datum/source, mob/user)
SIGNAL_HANDLER
toggletracking(user)
+ return CLICK_ACTION_SUCCESS
///Toggles the tracking for the gps
/datum/component/gps/item/proc/toggletracking(mob/user)
@@ -153,7 +154,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
data["signals"] = signals
return data
-/datum/component/gps/item/ui_act(action, params)
+/datum/component/gps/item/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
@@ -162,7 +163,8 @@ GLOBAL_LIST_EMPTY(GPS_list)
if("rename")
var/atom/parentasatom = parent
var/a = tgui_input_text(usr, "Enter the desired tag", "GPS Tag", gpstag, 20)
-
+ if (QDELETED(ui) || ui.status != UI_INTERACTIVE)
+ return
if (!a)
return
diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm
index 97df6342aeb..fc2081481d9 100644
--- a/code/datums/components/infective.dm
+++ b/code/datums/components/infective.dm
@@ -59,8 +59,10 @@
/datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder)
SIGNAL_HANDLER
- if(!eater.has_quirk(/datum/quirk/deviant_tastes))
- eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food)
+ if(HAS_TRAIT(eater, TRAIT_STRONG_STOMACH))
+ return
+
+ eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food)
if(is_weak && !prob(weak_infection_chance))
return
@@ -76,6 +78,9 @@
/datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder)
SIGNAL_HANDLER
+ if(HAS_TRAIT(drinker, TRAIT_STRONG_STOMACH))
+ return
+
var/appendage_zone = feeder.held_items.Find(source)
appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM
try_infect(feeder, appendage_zone)
diff --git a/code/datums/components/martial_art_giver.dm b/code/datums/components/martial_art_giver.dm
new file mode 100644
index 00000000000..1a0bfa9951a
--- /dev/null
+++ b/code/datums/components/martial_art_giver.dm
@@ -0,0 +1,45 @@
+/// when equipped and unequipped this item gives a martial art
+/datum/component/martial_art_giver
+ /// the style we give
+ var/datum/martial_art/style
+
+/datum/component/martial_art_giver/Initialize(style_type)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ style = new style_type()
+ style.allow_temp_override = FALSE
+
+/datum/component/martial_art_giver/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(equipped))
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(dropped))
+
+/datum/component/martial_art_giver/UnregisterFromParent(datum/source)
+ UnregisterSignal(parent, list(COMSIG_ITEM_POST_EQUIPPED, COMSIG_ITEM_POST_UNEQUIP))
+ var/obj/item/parent_item = parent
+ if(ismob(parent_item?.loc))
+ UnregisterSignal(parent, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF))
+ QDEL_NULL(style)
+
+/datum/component/martial_art_giver/proc/equipped(obj/item/source, mob/user, slot)
+ SIGNAL_HANDLER
+ if(!(source.slot_flags & slot))
+ return
+ RegisterSignals(user, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED), PROC_REF(teach))
+ RegisterSignal(user, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF, PROC_REF(forget))
+ teach(user)
+
+/datum/component/martial_art_giver/proc/dropped(obj/item/source, mob/user)
+ SIGNAL_HANDLER
+ forget(user)
+ UnregisterSignal(user, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF))
+
+/datum/component/martial_art_giver/proc/teach(mob/source)
+ if(isnull(style))
+ return
+ style.teach(source, TRUE)
+
+/datum/component/martial_art_giver/proc/forget(mob/source)
+ if(isnull(style))
+ return
+ style.fully_remove(source)
diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm
index 69f67d46df3..ffcf81feace 100644
--- a/code/datums/components/material/material_container.dm
+++ b/code/datums/components/material/material_container.dm
@@ -102,7 +102,7 @@
var/datum/material/M = I
var/amt = materials[I] / SHEET_MATERIAL_AMOUNT
if(amt)
- examine_texts += span_notice("It has [amt] sheets of [lowertext(M.name)] stored.")
+ examine_texts += span_notice("It has [amt] sheets of [LOWER_TEXT(M.name)] stored.")
/datum/component/material_container/vv_edit_var(var_name, var_value)
var/old_flags = mat_container_flags
@@ -678,6 +678,7 @@
while(sheet_amt > 0)
//don't merge yet. we need to do stuff with it first
var/obj/item/stack/sheet/new_sheets = new material.sheet_type(target, min(sheet_amt, MAX_STACK_SIZE), FALSE)
+ new_sheets.manufactured = TRUE
count += new_sheets.amount
//use material & deduct work needed
use_amount_mat(new_sheets.amount * SHEET_MATERIAL_AMOUNT, material)
diff --git a/code/datums/components/mirv.dm b/code/datums/components/mirv.dm
index 0f41df1d288..52b4053babb 100644
--- a/code/datums/components/mirv.dm
+++ b/code/datums/components/mirv.dm
@@ -39,5 +39,5 @@
P.range = override_projectile_range
P.preparePixelProjectile(shootat_turf, target)
P.firer = firer // don't hit ourself that would be really annoying
- P.impacted = list(target = TRUE) // don't hit the target we hit already with the flak
+ P.impacted = list(WEAKREF(target) = TRUE) // don't hit the target we hit already with the flak
P.fire()
diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm
index 52b0cc9c954..2b59305be14 100644
--- a/code/datums/components/pellet_cloud.dm
+++ b/code/datums/components/pellet_cloud.dm
@@ -281,7 +281,7 @@
P.original = target
P.fired_from = parent
P.firer = parent // don't hit ourself that would be really annoying
- P.impacted = list(parent = TRUE) // don't hit the target we hit already with the flak
+ P.impacted = list(WEAKREF(parent) = TRUE) // don't hit the target we hit already with the flak
P.suppressed = SUPPRESSED_VERY // set the projectiles to make no message so we can do our own aggregate message
P.preparePixelProjectile(target, parent)
RegisterSignal(P, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(pellet_hit))
diff --git a/code/datums/components/pet_commands/obeys_commands.dm b/code/datums/components/pet_commands/obeys_commands.dm
index 2fceaa2b337..ec3a04c940a 100644
--- a/code/datums/components/pet_commands/obeys_commands.dm
+++ b/code/datums/components/pet_commands/obeys_commands.dm
@@ -72,6 +72,7 @@
return // Not our friend, can't boss us around
INVOKE_ASYNC(src, PROC_REF(display_radial_menu), clicker)
+ return CLICK_ACTION_SUCCESS
/// Actually display the radial menu and then do something with the result
/datum/component/obeys_commands/proc/display_radial_menu(mob/living/clicker)
diff --git a/code/datums/components/puzzgrid.dm b/code/datums/components/puzzgrid.dm
index e91bcdb3002..d7e264f651f 100644
--- a/code/datums/components/puzzgrid.dm
+++ b/code/datums/components/puzzgrid.dm
@@ -280,12 +280,7 @@
var/list/answers = list()
var/description
-/// Debug verb for validating that all puzzgrids can be created successfully.
-/// Locked behind a verb because it's fairly slow and memory intensive.
-/client/proc/validate_puzzgrids()
- set name = "Validate Puzzgrid Config"
- set category = "Debug"
-
+ADMIN_VERB(validate_puzzgrids, R_DEBUG, "Validate Puzzgrid Config", "Validate the puzzgrid config to ensure it's set up correctly.", ADMIN_CATEGORY_DEBUG)
var/line_number = 0
for (var/line in world.file2list(PUZZGRID_CONFIG))
@@ -296,16 +291,16 @@
var/line_json_decoded = safe_json_decode(line)
if (isnull(line_json_decoded))
- to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]"))
+ to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]"))
continue
var/datum/puzzgrid/puzzgrid = new
var/populate_result = puzzgrid.populate(line_json_decoded)
if (populate_result != TRUE)
- to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]"))
+ to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]"))
- to_chat(src, span_notice("Validated. If you did not see any errors, you're in the clear."))
+ to_chat(user, span_notice("Validated. If you did not see any errors, you're in the clear."))
#undef PUZZGRID_CONFIG
#undef PUZZGRID_GROUP_COUNT
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index 7c55579c999..f872c6bfd69 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -59,6 +59,7 @@
/datum/component/simple_rotation/proc/rotate_left(datum/source, mob/user)
SIGNAL_HANDLER
rotate(user, ROTATION_COUNTERCLOCKWISE)
+ return CLICK_ACTION_SUCCESS
/datum/component/simple_rotation/proc/rotate(mob/user, degrees)
if(QDELETED(user))
diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm
index c1323d01e2f..56a6723f21f 100644
--- a/code/datums/components/singularity.dm
+++ b/code/datums/components/singularity.dm
@@ -360,8 +360,9 @@
target = potentially_closer
//if we lost that target get a new one
if(!target || QDELETED(target))
- target = find_new_target()
- foreboding_nosebleed(target)
+ var/mob/living/new_target = find_new_target()
+ new_target?.ominous_nosebleed()
+ target = new_target
return ..()
///Searches the living list for the closest target, and begins chasing them down.
@@ -380,22 +381,6 @@
closest_target = target
return closest_target
-/// gives a little fluff warning that someone is being hunted.
-/datum/component/singularity/bloodthirsty/proc/foreboding_nosebleed(mob/living/target)
- if(!iscarbon(target))
- to_chat(target, span_warning("You feel a bit nauseous for just a moment."))
- return
- var/mob/living/carbon/carbon_target = target
- var/obj/item/bodypart/head = carbon_target.get_bodypart(BODY_ZONE_HEAD)
- if(head)
- if(HAS_TRAIT(carbon_target, TRAIT_NOBLOOD))
- to_chat(carbon_target, span_notice("You get a headache."))
- return
- head.adjustBleedStacks(5)
- carbon_target.visible_message(span_notice("[carbon_target] gets a nosebleed."), span_warning("You get a nosebleed."))
- return
- to_chat(target, span_warning("You feel a bit nauseous for just a moment."))
-
#undef CHANCE_TO_MOVE_TO_TARGET
#undef CHANCE_TO_MOVE_TO_TARGET_BLOODTHIRSTY
#undef CHANCE_TO_CHANGE_TARGET_BLOODTHIRSTY
diff --git a/code/datums/components/style/style_meter.dm b/code/datums/components/style/style_meter.dm
index 72688f41c52..c06fc35aca3 100644
--- a/code/datums/components/style/style_meter.dm
+++ b/code/datums/components/style/style_meter.dm
@@ -27,7 +27,7 @@
. = ..()
. += span_notice("You feel like a multitool could be used on this.")
-/obj/item/style_meter/interact_with_atom(atom/interacting_with, mob/living/user)
+/obj/item/style_meter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!istype(interacting_with, /obj/item/clothing/glasses))
return NONE
@@ -38,7 +38,7 @@
RegisterSignal(interacting_with, COMSIG_ITEM_EQUIPPED, PROC_REF(check_wearing))
RegisterSignal(interacting_with, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
RegisterSignal(interacting_with, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
- RegisterSignal(interacting_with, COMSIG_CLICK_ALT, PROC_REF(on_altclick))
+ RegisterSignal(interacting_with, COMSIG_CLICK_ALT, PROC_REF(on_click_alt))
RegisterSignal(interacting_with, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(redirect_multitool))
balloon_alert(user, "style meter attached")
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
@@ -90,14 +90,15 @@
/// Signal proc to remove from glasses
-/obj/item/style_meter/proc/on_altclick(datum/source, mob/user)
+/obj/item/style_meter/proc/on_click_alt(datum/source, mob/user)
SIGNAL_HANDLER
- if(istype(loc, /obj/item/clothing/glasses))
- clean_up()
- forceMove(get_turf(src))
+ if(!istype(loc, /obj/item/clothing/glasses))
+ return CLICK_ACTION_BLOCKING
- return COMPONENT_CANCEL_CLICK_ALT
+ clean_up()
+ forceMove(get_turf(src))
+ return CLICK_ACTION_SUCCESS
/obj/item/style_meter/multitool_act(mob/living/user, obj/item/tool)
multitooled = !multitooled
diff --git a/code/datums/components/surgery_initiator.dm b/code/datums/components/surgery_initiator.dm
index cd2fcc2cff9..24bde4b4672 100644
--- a/code/datums/components/surgery_initiator.dm
+++ b/code/datums/components/surgery_initiator.dm
@@ -334,7 +334,7 @@
var/datum/surgery/procedure = new surgery.type(target, selected_zone, affecting_limb)
ADD_TRAIT(target, TRAIT_ALLOWED_HONORBOUND_ATTACK, type)
- target.balloon_alert(user, "starting \"[lowertext(procedure.name)]\"")
+ target.balloon_alert(user, "starting \"[LOWER_TEXT(procedure.name)]\"")
user.visible_message(
span_notice("[user] drapes [parent] over [target]'s [parse_zone(selected_zone)] to prepare for surgery."),
diff --git a/code/datums/components/toggle_suit.dm b/code/datums/components/toggle_suit.dm
index 596bf3b3252..c4a378a16de 100644
--- a/code/datums/components/toggle_suit.dm
+++ b/code/datums/components/toggle_suit.dm
@@ -20,7 +20,7 @@
src.base_icon_state = atom_parent.base_icon_state || atom_parent.icon_state
/datum/component/toggle_icon/RegisterWithParent()
- RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_alt_click))
+ RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_click_alt))
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
/datum/component/toggle_icon/UnregisterFromParent()
@@ -34,7 +34,7 @@
* source - the atom being clicked on
* user - the mob doing the click
*/
-/datum/component/toggle_icon/proc/on_alt_click(atom/source, mob/user)
+/datum/component/toggle_icon/proc/on_click_alt(atom/source, mob/user)
SIGNAL_HANDLER
if(!isliving(user))
@@ -47,13 +47,14 @@
if(living_user.incapacitated())
source.balloon_alert(user, "you're incapacitated!")
- return
+ return CLICK_ACTION_BLOCKING
if(living_user.usable_hands <= 0)
source.balloon_alert(user, "you don't have hands!")
- return
+ return CLICK_ACTION_BLOCKING
do_icon_toggle(source, living_user)
+ return CLICK_ACTION_SUCCESS
/*
* Signal proc for COMSIG_ATOM_EXAMINE.
diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm
index e51c784657b..5276f45dc0a 100644
--- a/code/datums/components/transforming.dm
+++ b/code/datums/components/transforming.dm
@@ -212,7 +212,7 @@
source.attack_verb_simple = attack_verb_simple_on
source.hitsound = hitsound_on
- source.w_class = w_class_on
+ source.update_weight_class(w_class_on)
source.icon_state = "[source.icon_state]_on"
if(inhand_icon_change && source.inhand_icon_state)
source.inhand_icon_state = "[source.inhand_icon_state]_on"
@@ -241,7 +241,7 @@
source.attack_verb_simple = attack_verb_simple_off
source.hitsound = initial(source.hitsound)
- source.w_class = initial(source.w_class)
+ source.update_weight_class(initial(source.w_class))
source.icon_state = initial(source.icon_state)
source.inhand_icon_state = initial(source.inhand_icon_state)
if(ismob(source.loc))
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 5007d8caeb9..163de4867d5 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -378,8 +378,8 @@
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
SIGNAL_HANDLER
- if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
- if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
+ if(trim(LOWER_TEXT(new_ring_text)) != trim(LOWER_TEXT(unlock_code)))
+ if(trim(LOWER_TEXT(new_ring_text)) == trim(LOWER_TEXT(failsafe_code)))
failsafe(user)
return COMPONENT_STOP_RINGTONE_CHANGE
return
@@ -415,8 +415,8 @@
if(channel != RADIO_CHANNEL_UPLINK)
return
- if(!findtext(lowertext(message), lowertext(unlock_code)))
- if(failsafe_code && findtext(lowertext(message), lowertext(failsafe_code)))
+ if(!findtext(LOWER_TEXT(message), LOWER_TEXT(unlock_code)))
+ if(failsafe_code && findtext(LOWER_TEXT(message), LOWER_TEXT(failsafe_code)))
failsafe(user) // no point returning cannot radio, youre probably ded
return
locked = FALSE
diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm
index f428abdb016..0708841fca0 100644
--- a/code/datums/diseases/advance/symptoms/fire.dm
+++ b/code/datums/diseases/advance/symptoms/fire.dm
@@ -71,7 +71,10 @@
if(prob(33.33))
living_mob.show_message(span_hear("You hear a crackling noise."), type = MSG_AUDIBLE)
else
- to_chat(living_mob, span_warning("[pick("You feel hot.", "You smell smoke.")]"))
+ if(HAS_TRAIT(living_mob, TRAIT_ANOSMIA)) //Anosmia quirk holder can't smell anything.
+ to_chat(living_mob, span_warning("You feel hot."))
+ else
+ to_chat(living_mob, span_warning("[pick("You feel hot.", "You smell smoke.")]"))
/*
Alkali perspiration
diff --git a/code/datums/diseases/tuberculosis.dm b/code/datums/diseases/tuberculosis.dm
index de87cab6f3f..2a77195e311 100644
--- a/code/datums/diseases/tuberculosis.dm
+++ b/code/datums/diseases/tuberculosis.dm
@@ -18,11 +18,12 @@
if(!.)
return
+ if(SPT_PROB(stage * 2, seconds_per_tick))
+ affected_mob.emote("cough")
+ to_chat(affected_mob, span_danger("Your chest hurts."))
+
switch(stage)
if(2)
- if(SPT_PROB(1, seconds_per_tick))
- affected_mob.emote("cough")
- to_chat(affected_mob, span_danger("Your chest hurts."))
if(SPT_PROB(1, seconds_per_tick))
to_chat(affected_mob, span_danger("Your stomach violently rumbles!"))
if(SPT_PROB(2.5, seconds_per_tick))
diff --git a/code/datums/elements/attack_zone_randomiser.dm b/code/datums/elements/attack_zone_randomiser.dm
new file mode 100644
index 00000000000..35275e11a9b
--- /dev/null
+++ b/code/datums/elements/attack_zone_randomiser.dm
@@ -0,0 +1,33 @@
+/// Pick a random attack zone before you attack something
+/datum/element/attack_zone_randomiser
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ /// List of attack zones you can select, should be a subset of GLOB.all_body_zones
+ var/list/valid_attack_zones
+
+/datum/element/attack_zone_randomiser/Attach(datum/target, list/valid_attack_zones = GLOB.all_body_zones)
+ . = ..()
+ if (!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignals(target, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK), PROC_REF(randomise))
+ src.valid_attack_zones = valid_attack_zones
+
+/datum/element/attack_zone_randomiser/Detach(datum/source)
+ UnregisterSignal(source, list (COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK))
+ return ..()
+
+/// If we're attacking a carbon, pick a random defence zone
+/datum/element/attack_zone_randomiser/proc/randomise(mob/living/source, atom/target)
+ SIGNAL_HANDLER
+ if (!iscarbon(target))
+ return
+ var/mob/living/living_target = target
+ var/list/blacklist_zones = GLOB.all_body_zones - valid_attack_zones
+ var/new_zone = living_target.get_random_valid_zone(blacklisted_parts = blacklist_zones, bypass_warning = TRUE)
+ if (isnull(new_zone))
+ new_zone = BODY_ZONE_CHEST
+ var/atom/movable/screen/zone_sel/zone_selector = source.hud_used?.zone_select
+ if (isnull(zone_selector))
+ source.zone_selected = new_zone
+ else
+ zone_selector.set_selected_zone(new_zone, source, should_log = FALSE)
diff --git a/code/datums/elements/backblast.dm b/code/datums/elements/backblast.dm
index 169f961b3d3..8952afbfeaa 100644
--- a/code/datums/elements/backblast.dm
+++ b/code/datums/elements/backblast.dm
@@ -1,74 +1,43 @@
/**
- * When attached to a gun and the gun is successfully fired, this element creates a "backblast" of fire and pain, like you'd find in a rocket launcher or recoilless rifle
+ * When attached to a gun and the gun is successfully fired, this element creates a "backblast", like you'd find in a rocket launcher or recoilless rifle
*
- * The backblast is simulated by a number of fire plumes, or invisible incendiary rounds that will torch anything they come across for a short distance, as well as knocking
- * back nearby items.
+ * The backblast is simulated by a directional explosion 180 degrees from the direction of the fired projectile.
*/
/datum/element/backblast
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
- /// How many "pellets" of backblast we're shooting backwards, spread between the angle defined in angle_spread
- var/plumes
- /// Assuming we don't just have 1 plume, this is the total angle we'll cover with the plumes, split down the middle directly behind the angle we fired at
- var/angle_spread
- /// How far each plume of fire will fly, assuming it doesn't hit a mob
- var/range
+ /// Devasatation range of the explosion
+ var/dev_range
+ /// HGeavy damage range of the explosion
+ var/heavy_range
+ /// Light damage range of the explosion
+ var/light_range
+ /// Flame range of the explosion
+ var/flame_range
+ /// What angle do we want the backblast to cover
+ var/blast_angle
-/datum/element/backblast/Attach(datum/target, plumes = 4, angle_spread = 48, range = 6)
+/datum/element/backblast/Attach(datum/target, dev_range = 0, heavy_range = 0, light_range = 6, flame_range = 6, blast_angle = 60)
. = ..()
- if(!isgun(target) || plumes < 1 || angle_spread < 1 || range < 1)
+ if(!isgun(target) || dev_range < 0 || heavy_range < 0 || light_range < 0 || flame_range < 0 || blast_angle < 1)
return ELEMENT_INCOMPATIBLE
- src.plumes = plumes
- src.angle_spread = angle_spread
- src.range = range
+ src.dev_range = dev_range
+ src.heavy_range = heavy_range
+ src.light_range = light_range
+ src.flame_range = flame_range
+ src.blast_angle = blast_angle
- if(plumes == 1)
- RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(gun_fired_simple))
- else
- RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(gun_fired))
+ RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(pew))
/datum/element/backblast/Detach(datum/source)
if(source)
UnregisterSignal(source, COMSIG_GUN_FIRED)
return ..()
-/// For firing multiple plumes behind us, we evenly spread out our projectiles based on the [angle_spread][/datum/element/backblast/var/angle_spread] and [number of plumes][/datum/element/backblast/var/plumes]
-/datum/element/backblast/proc/gun_fired(obj/item/gun/weapon, mob/living/user, atom/target, params, zone_override)
- SIGNAL_HANDLER
-
- if(!weapon.chambered || HAS_TRAIT(user, TRAIT_PACIFISM))
- return
-
- var/backwards_angle = get_angle(target, user)
- var/starting_angle = SIMPLIFY_DEGREES(backwards_angle-(angle_spread * 0.5))
- var/iter_offset = angle_spread / plumes // how much we increment the angle for each plume
-
- for(var/i in 1 to plumes)
- var/this_angle = SIMPLIFY_DEGREES(starting_angle + ((i - 1) * iter_offset))
- var/turf/target_turf = get_turf_in_angle(this_angle, get_turf(user), 10)
- INVOKE_ASYNC(src, PROC_REF(pew), target_turf, weapon, user)
-
-/// If we're only firing one plume directly behind us, we don't need to bother with the loop or angles or anything
-/datum/element/backblast/proc/gun_fired_simple(obj/item/gun/weapon, mob/living/user, atom/target, params, zone_override)
- SIGNAL_HANDLER
-
- if(!weapon.chambered || HAS_TRAIT(user, TRAIT_PACIFISM))
- return
-
- var/backwards_angle = get_angle(target, user)
- var/turf/target_turf = get_turf_in_angle(backwards_angle, get_turf(user), 10)
- INVOKE_ASYNC(src, PROC_REF(pew), target_turf, weapon, user)
-
/// For firing an actual backblast pellet
-/datum/element/backblast/proc/pew(turf/target_turf, obj/item/gun/weapon, mob/living/user)
- //Shooting Code:
- var/obj/projectile/bullet/incendiary/fire/backblast/P = new (get_turf(user))
- P.original = target_turf
- P.range = range
- P.fired_from = weapon
- P.firer = user // don't hit ourself that would be really annoying
- P.impacted = list(user = TRUE) // don't hit the target we hit already with the flak
- P.preparePixelProjectile(target_turf, weapon)
- P.fire()
+/datum/element/backblast/proc/pew(obj/item/gun/weapon, mob/living/user, atom/target)
+ var/turf/origin = get_turf(weapon)
+ var/backblast_angle = get_angle(target, origin)
+ explosion(weapon, devastation_range = dev_range, heavy_impact_range = heavy_range, light_impact_range = light_range, flame_range = flame_range, adminlog = FALSE, protect_epicenter = TRUE, explosion_direction = backblast_angle, explosion_arc = blast_angle)
diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm
index 7984939cddc..857b9e2b678 100644
--- a/code/datums/elements/decals/blood.dm
+++ b/code/datums/elements/decals/blood.dm
@@ -33,10 +33,7 @@
pic = blood_splatter
return TRUE
-/datum/element/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
+/datum/element/decal/blood/proc/get_examine_name(atom/source, mob/user, list/override)
SIGNAL_HANDLER
- var/atom/A = source
- override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a"
- override[EXAMINE_POSITION_BEFORE] = " blood-stained "
- return COMPONENT_EXNAME_CHANGED
+ override[EXAMINE_POSITION_BEFORE] = "blood-stained"
diff --git a/code/datums/elements/frozen.dm b/code/datums/elements/frozen.dm
index 434968dd4d5..d112ef31b5f 100644
--- a/code/datums/elements/frozen.dm
+++ b/code/datums/elements/frozen.dm
@@ -63,7 +63,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
else
log_combat(throwingdatum.thrower, target, "launched", addition = "shattering it due to being frozen.")
obj_target.visible_message(span_danger("[obj_target] shatters into a million pieces!"))
- obj_target.obj_flags |= NO_DECONSTRUCTION // disable item spawning
+ obj_target.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION // disable item spawning
obj_target.deconstruct(FALSE) // call pre-deletion specialized code -- internals release gas etc
/// signal handler for COMSIG_MOVABLE_MOVED that unfreezes our target if it moves onto an open turf thats hotter than
diff --git a/code/datums/elements/living_limb_initialiser.dm b/code/datums/elements/living_limb_initialiser.dm
new file mode 100644
index 00000000000..943b39dcf37
--- /dev/null
+++ b/code/datums/elements/living_limb_initialiser.dm
@@ -0,0 +1,19 @@
+/// Spawns a living limb mob inside a limb upon attachment if it doesn't have one
+/datum/element/living_limb_initialiser
+
+/datum/element/living_limb_initialiser/Attach(atom/target)
+ . = ..()
+ if(!isbodypart(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_BODYPART_CHANGED_OWNER, PROC_REF(try_animate_limb))
+
+/datum/element/living_limb_initialiser/Detach(atom/target)
+ UnregisterSignal(target, COMSIG_BODYPART_CHANGED_OWNER)
+ return ..()
+
+/// Create a living limb mob inside the limb if it doesn't already have one
+/datum/element/living_limb_initialiser/proc/try_animate_limb(obj/item/bodypart/part)
+ SIGNAL_HANDLER
+ if (locate(/mob/living/basic/living_limb_flesh) in part)
+ return
+ new /mob/living/basic/living_limb_flesh(part, part)
diff --git a/code/datums/elements/poster_tearer.dm b/code/datums/elements/poster_tearer.dm
new file mode 100644
index 00000000000..7a784a48615
--- /dev/null
+++ b/code/datums/elements/poster_tearer.dm
@@ -0,0 +1,45 @@
+/// Allows mobs with this element attached to just simply tear down any poster they desire to.
+/datum/element/poster_tearer
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ /// The amount of time it takes to tear down a poster.
+ var/tear_time
+ /// Interaction key to use whilst tearing down a poster.
+ var/interaction_key
+
+/datum/element/poster_tearer/Attach(datum/target, tear_time = 2 SECONDS, interaction_key = null)
+ . = ..()
+ if (!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.tear_time = tear_time
+ src.interaction_key = interaction_key
+
+ RegisterSignals(target, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK), PROC_REF(on_attacked_poster))
+
+/datum/element/poster_tearer/Detach(datum/source)
+ . = ..()
+ UnregisterSignal(source, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK))
+
+/// Try to tear up a poster on the wall
+/datum/element/poster_tearer/proc/on_attacked_poster(mob/living/user, atom/target, proximity_flag)
+ SIGNAL_HANDLER
+ if(!istype(target, /obj/structure/sign/poster))
+ return NONE // don't care we move on
+
+ if(DOING_INTERACTION_WITH_TARGET(user, target) || (!isnull(interaction_key) && DOING_INTERACTION(user, interaction_key)))
+ user.balloon_alert(target, "busy!")
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+ INVOKE_ASYNC(src, PROC_REF(tear_it_down), user, target)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/// Actually work on tearing down that poster
+/datum/element/poster_tearer/proc/tear_it_down(mob/living/user, obj/structure/sign/poster/target)
+ if(!target.check_tearability(user)) // this proc will handle user feedback
+ return
+
+ target.balloon_alert(user, "tearing down the poster...")
+ if(!do_after(user, tear_time, target, interaction_key = interaction_key)) // just in case the user actually enjoys art
+ return
+ target.tear_poster(user)
diff --git a/code/datums/elements/ridable.dm b/code/datums/elements/ridable.dm
index cbb6d7931f9..e68653b3d4a 100644
--- a/code/datums/elements/ridable.dm
+++ b/code/datums/elements/ridable.dm
@@ -197,3 +197,15 @@
to_chat(user, span_notice("You gently let go of [rider]."))
return
return rider
+
+/obj/item/riding_offhand/interact_with_atom(atom/movable/interacting_with, mob/living/user, list/modifiers)
+ if(!istype(interacting_with) || !interacting_with.can_buckle)
+ return NONE
+ if(rider == user) // Piggyback user
+ return ITEM_INTERACT_BLOCKING
+
+ // Handles de-fireman carrying a mob and buckling them onto something (tables, etc)
+ var/mob/living/former_rider = rider
+ user.unbuckle_mob(former_rider)
+ former_rider.forceMove(get_turf(interacting_with))
+ return interacting_with.mouse_buckle_handling(former_rider, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm
index a8a45f54ecc..87524379523 100644
--- a/code/datums/elements/strippable.dm
+++ b/code/datums/elements/strippable.dm
@@ -283,10 +283,8 @@
source.log_message("had [item] put on them by [key_name(user)].", LOG_VICTIM, color="orange", log_globally=FALSE)
/// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob.
-/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay)
- //SKYRAT EDIT ADDITION - THIEVING GLOVES
- //if (!do_after(user, strip_delay || item.strip_delay, source, interaction_key = REF(item)))
- if (!do_after(user, (strip_delay || item.strip_delay) * (HAS_TRAIT(user, TRAIT_STICKY_FINGERS) ? THIEVING_GLOVES_STRIP_SLOWDOWN : NORMAL_STRIP_SLOWDOWN), source, interaction_key = REF(item)))
+/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay, hidden = FALSE)
+ if (!do_after(user, (strip_delay || item.strip_delay) * (HAS_TRAIT(user, TRAIT_STICKY_FINGERS) ? THIEVING_GLOVES_STRIP_SLOWDOWN : NORMAL_STRIP_SLOWDOWN), source, interaction_key = REF(item), hidden = hidden)) // SKYRAT EDIT CHANGE - ORIGINAL: if (!do_after(user, strip_delay || item.strip_delay, source, interaction_key = REF(item), hidden = hidden))
return FALSE
return TRUE
diff --git a/code/datums/elements/tool_renaming.dm b/code/datums/elements/tool_renaming.dm
new file mode 100644
index 00000000000..bd87f1d171c
--- /dev/null
+++ b/code/datums/elements/tool_renaming.dm
@@ -0,0 +1,78 @@
+#define OPTION_RENAME "Rename"
+#define OPTION_DESCRIPTION "Description"
+#define OPTION_RESET "Reset"
+
+/**
+ * Renaming tool element
+ *
+ * When using this tool on an object with UNIQUE_RENAME,
+ * lets the user rename/redesc it.
+ */
+/datum/element/tool_renaming
+
+/datum/element/tool_renaming/Attach(datum/target)
+ . = ..()
+ if(!isitem(target))
+ return ELEMENT_INCOMPATIBLE
+
+ RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(attempt_rename))
+
+/datum/element/tool_renaming/Detach(datum/source)
+ . = ..()
+ UnregisterSignal(source, COMSIG_ITEM_INTERACTING_WITH_ATOM)
+
+/datum/element/tool_renaming/proc/attempt_rename(datum/source, mob/living/user, atom/interacting_with, list/modifiers)
+ SIGNAL_HANDLER
+
+ if(!isobj(interacting_with))
+ return NONE
+
+ var/obj/renamed_obj = interacting_with
+
+ if(!(renamed_obj.obj_flags & UNIQUE_RENAME))
+ return NONE
+
+ INVOKE_ASYNC(src, PROC_REF(async_rename), user, renamed_obj)
+ return ITEM_INTERACT_SUCCESS
+
+/datum/element/tool_renaming/proc/async_rename(mob/living/user, obj/renamed_obj)
+ var/custom_choice = tgui_input_list(user, "What would you like to edit?", "Customization", list(OPTION_RENAME, OPTION_DESCRIPTION, OPTION_RESET))
+ if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj) || isnull(custom_choice))
+ return
+
+ switch(custom_choice)
+ if(OPTION_RENAME)
+ var/old_name = renamed_obj.name
+ var/input = tgui_input_text(user, "What do you want to name [renamed_obj]?", "Object Name", "[old_name]", MAX_NAME_LEN)
+ if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj))
+ return
+ if(input == old_name || !input)
+ to_chat(user, span_notice("You changed [renamed_obj] to... well... [renamed_obj]."))
+ return
+ renamed_obj.AddComponent(/datum/component/rename, input, renamed_obj.desc)
+ to_chat(user, span_notice("You have successfully renamed \the [old_name] to [renamed_obj]."))
+ ADD_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT)
+ renamed_obj.update_appearance(UPDATE_NAME)
+
+ if(OPTION_DESCRIPTION)
+ var/old_desc = renamed_obj.desc
+ var/input = tgui_input_text(user, "Describe [renamed_obj]", "Description", "[old_desc]", MAX_DESC_LEN)
+ if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj))
+ return
+ if(input == old_desc || !input)
+ to_chat(user, span_notice("You decide against changing [renamed_obj]'s description."))
+ return
+ renamed_obj.AddComponent(/datum/component/rename, renamed_obj.name, input)
+ to_chat(user, span_notice("You have successfully changed [renamed_obj]'s description."))
+ ADD_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT)
+ renamed_obj.update_appearance(UPDATE_DESC)
+
+ if(OPTION_RESET)
+ qdel(renamed_obj.GetComponent(/datum/component/rename))
+ to_chat(user, span_notice("You have successfully reset [renamed_obj]'s name and description."))
+ REMOVE_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT)
+ renamed_obj.update_appearance(UPDATE_NAME | UPDATE_DESC)
+
+#undef OPTION_RENAME
+#undef OPTION_DESCRIPTION
+#undef OPTION_RESET
diff --git a/code/datums/elements/watery_tile.dm b/code/datums/elements/watery_tile.dm
new file mode 100644
index 00000000000..797eda39135
--- /dev/null
+++ b/code/datums/elements/watery_tile.dm
@@ -0,0 +1,21 @@
+/datum/element/watery_tile
+ element_flags = ELEMENT_DETACH_ON_HOST_DESTROY
+
+/datum/element/watery_tile/Attach(turf/target)
+ . = ..()
+ if(!isturf(target))
+ return ELEMENT_INCOMPATIBLE
+
+ RegisterSignal(target, COMSIG_ATOM_ENTERED, PROC_REF(extinguish_atom))
+
+/datum/element/watery_tile/Detach(turf/source)
+ UnregisterSignal(source, COMSIG_ATOM_ENTERED)
+ return ..()
+
+/datum/element/watery_tile/proc/extinguish_atom(atom/source, atom/movable/entered)
+ SIGNAL_HANDLER
+
+ entered.extinguish()
+ if(isliving(entered))
+ var/mob/living/our_mob = entered
+ our_mob.adjust_wet_stacks(3)
diff --git a/code/datums/greyscale/json_reader.dm b/code/datums/greyscale/json_reader.dm
index ffe143c28fc..38286631fed 100644
--- a/code/datums/greyscale/json_reader.dm
+++ b/code/datums/greyscale/json_reader.dm
@@ -63,7 +63,7 @@
)
/datum/json_reader/blend_mode/ReadJson(value)
- var/new_value = blend_modes[lowertext(value)]
+ var/new_value = blend_modes[LOWER_TEXT(value)]
if(isnull(new_value))
CRASH("Blend mode expected but got '[value]'")
return new_value
diff --git a/code/datums/keybinding/admin.dm b/code/datums/keybinding/admin.dm
index 80936aa41e7..1e94f71e58a 100644
--- a/code/datums/keybinding/admin.dm
+++ b/code/datums/keybinding/admin.dm
@@ -23,7 +23,7 @@
. = ..()
if(.)
return
- user.admin_ghost()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost)
return TRUE
/datum/keybinding/admin/player_panel_new
@@ -51,7 +51,7 @@
. = ..()
if(.)
return
- user.togglebuildmodeself()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/build_mode_self)
return TRUE
/datum/keybinding/admin/stealthmode
@@ -65,7 +65,7 @@
. = ..()
if(.)
return
- user.stealth()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/stealth)
return TRUE
/datum/keybinding/admin/invisimin
@@ -79,7 +79,7 @@
. = ..()
if(.)
return
- user.invisimin()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/invisimin)
return TRUE
/datum/keybinding/admin/deadsay
@@ -107,7 +107,7 @@
. = ..()
if(.)
return
- user.deadmin()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/deadmin)
return TRUE
/datum/keybinding/admin/readmin
@@ -135,5 +135,5 @@
. = ..()
if(.)
return
- user.holder?.display_tags()
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/display_tags)
return TRUE
diff --git a/code/datums/looping_sounds/item_sounds.dm b/code/datums/looping_sounds/item_sounds.dm
index f8ed5d89b20..00fd3063e43 100644
--- a/code/datums/looping_sounds/item_sounds.dm
+++ b/code/datums/looping_sounds/item_sounds.dm
@@ -44,3 +44,7 @@
/datum/looping_sound/beesmoke
mid_sounds = list('sound/weapons/beesmoke.ogg' = 1)
volume = 5
+
+/datum/looping_sound/zipline
+ mid_sounds = list('sound/weapons/zipline_mid.ogg' = 1)
+ volume = 5
diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm
index 8ef30db63aa..ec111fb3cf0 100644
--- a/code/datums/martial/boxing.dm
+++ b/code/datums/martial/boxing.dm
@@ -74,7 +74,6 @@
return ..()
/obj/item/clothing/gloves/boxing
- var/datum/martial_art/boxing/style
/obj/item/clothing/gloves/boxing/Initialize(mapload)
. = ..()
@@ -85,18 +84,4 @@
slapcraft_recipes = slapcraft_recipe_list,\
)
- style = new()
- style.allow_temp_override = FALSE
-
-/obj/item/clothing/gloves/boxing/Destroy()
- QDEL_NULL(style)
- return ..()
-
-/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
- . = ..()
- if(slot & ITEM_SLOT_GLOVES)
- style.teach(user, TRUE)
-
-/obj/item/clothing/gloves/boxing/dropped(mob/user)
- . = ..()
- style.fully_remove(user)
+ AddComponent(/datum/component/martial_art_giver, /datum/martial_art/boxing)
diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm
index 66d092e886e..57e158cf669 100644
--- a/code/datums/martial/krav_maga.dm
+++ b/code/datums/martial/krav_maga.dm
@@ -208,26 +208,11 @@
//Krav Maga Gloves
/obj/item/clothing/gloves/krav_maga
- var/datum/martial_art/krav_maga/style
clothing_traits = list(TRAIT_FAST_CUFFING)
/obj/item/clothing/gloves/krav_maga/Initialize(mapload)
. = ..()
- style = new()
- style.allow_temp_override = FALSE
-
-/obj/item/clothing/gloves/krav_maga/Destroy()
- QDEL_NULL(style)
- return ..()
-
-/obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot)
- . = ..()
- if(slot & ITEM_SLOT_GLOVES)
- style.teach(user, TRUE)
-
-/obj/item/clothing/gloves/krav_maga/dropped(mob/user)
- . = ..()
- style.fully_remove(user)
+ AddComponent(/datum/component/martial_art_giver, /datum/martial_art/krav_maga)
/obj/item/clothing/gloves/krav_maga/sec//more obviously named, given to sec
name = "krav maga gloves"
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index c55f95d4bd6..8116084127e 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -325,7 +325,7 @@
/obj/item/clothing/gloves/the_sleeping_carp
name = "carp gloves"
- desc = "This gloves are capable of making people use The Sleeping Carp."
+ desc = "These gloves are capable of making people use The Sleeping Carp."
icon_state = "black"
greyscale_colors = COLOR_BLACK
cold_protection = HANDS
@@ -333,26 +333,10 @@
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
- var/datum/martial_art/the_sleeping_carp/style
/obj/item/clothing/gloves/the_sleeping_carp/Initialize(mapload)
. = ..()
- style = new()
- style.allow_temp_override = FALSE
-
-/obj/item/clothing/gloves/the_sleeping_carp/Destroy()
- QDEL_NULL(style)
- return ..()
-
-/obj/item/clothing/gloves/the_sleeping_carp/equipped(mob/user, slot)
- . = ..()
- if(slot & ITEM_SLOT_GLOVES)
- style.teach(user, TRUE)
-
-/obj/item/clothing/gloves/the_sleeping_carp/dropped(mob/user)
- . = ..()
- if(!isnull(style))
- style.fully_remove(user)
+ AddComponent(/datum/component/martial_art_giver, /datum/martial_art/the_sleeping_carp)
#undef STRONG_PUNCH_COMBO
#undef LAUNCH_KICK_COMBO
diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm
index 6969c3eeb9e..4bcaf02b2d5 100644
--- a/code/datums/martial/wrestling.dm
+++ b/code/datums/martial/wrestling.dm
@@ -490,22 +490,7 @@ If you make a derivative work from this code, you must include this notification
/obj/item/storage/belt/champion/wrestling
name = "Wrestling Belt"
- var/datum/martial_art/wrestling/style
/obj/item/storage/belt/champion/wrestling/Initialize(mapload)
. = ..()
- style = new()
- style.allow_temp_override = FALSE
-
-/obj/item/storage/belt/champion/wrestling/Destroy()
- QDEL_NULL(style)
- return ..()
-
-/obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot)
- . = ..()
- if(slot & ITEM_SLOT_BELT)
- style.teach(user, TRUE)
-
-/obj/item/storage/belt/champion/wrestling/dropped(mob/user)
- . = ..()
- style.fully_remove(user)
+ AddComponent(/datum/component/martial_art_giver, /datum/martial_art/wrestling)
diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm
index f6e64d57e71..45d72573978 100644
--- a/code/datums/materials/basemats.dm
+++ b/code/datums/materials/basemats.dm
@@ -2,8 +2,8 @@
/datum/material/iron
name = "iron"
desc = "Common iron ore often found in sedimentary and igneous layers of the crust."
- color = "#878687"
- greyscale_colors = "#878687"
+ color = "#B6BEC2"
+ greyscale_colors = "#B6BEC2"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/iron
ore_type = /obj/item/stack/ore/iron
@@ -22,8 +22,8 @@
/datum/material/glass
name = "glass"
desc = "Glass forged by melting sand."
- color = "#88cdf1"
- greyscale_colors = "#88cdf196"
+ color = "#6292AF"
+ greyscale_colors = "#6292AF"
alpha = 150
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
integrity_modifier = 0.1
@@ -39,6 +39,7 @@
armor_modifiers = list(MELEE = 0.2, BULLET = 0.2, ENERGY = 1, BIO = 0.2, FIRE = 1, ACID = 0.2)
mineral_rarity = MATERIAL_RARITY_COMMON
points_per_unit = 1 / SHEET_MATERIAL_AMOUNT
+ texture_layer_icon_state = "shine"
/datum/material/glass/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5, sharpness = TRUE) //cronch
@@ -63,8 +64,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/silver
name = "silver"
desc = "Silver"
- color = list(255/255, 284/255, 302/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
- greyscale_colors = "#e3f1f8"
+ color = "#B5BCBB"
+ greyscale_colors = "#B5BCBB"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/silver
ore_type = /obj/item/stack/ore/silver
@@ -74,6 +75,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.075
mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS
points_per_unit = 16 / SHEET_MATERIAL_AMOUNT
+ texture_layer_icon_state = "shine"
/datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
@@ -83,8 +85,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/gold
name = "gold"
desc = "Gold"
- color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium
- greyscale_colors = "#dbdd4c"
+ color = "#E6BB45"
+ greyscale_colors = "#E6BB45"
strength_modifier = 1.2
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/gold
@@ -96,6 +98,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 0.7, ACID = 1.1)
mineral_rarity = MATERIAL_RARITY_PRECIOUS
points_per_unit = 18 / SHEET_MATERIAL_AMOUNT
+ texture_layer_icon_state = "shine"
/datum/material/gold/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
@@ -105,8 +108,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/diamond
name = "diamond"
desc = "Highly pressurized carbon"
- color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
- greyscale_colors = "#71c8f784"
+ color = "#C9D8F2"
+ greyscale_colors = "#C9D8F2"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/diamond
ore_type = /obj/item/stack/ore/diamond
@@ -128,8 +131,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/uranium
name = "uranium"
desc = "Uranium"
- color = rgb(48, 237, 26)
- greyscale_colors = rgb(48, 237, 26)
+ color = "#2C992C"
+ greyscale_colors = "#2C992C"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/uranium
ore_type = /obj/item/stack/ore/uranium
@@ -168,8 +171,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/plasma
name = "plasma"
desc = "Isn't plasma a state of matter? Oh whatever."
- color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
- greyscale_colors = "#c162ec"
+ color = "#BA3692"
+ greyscale_colors = "#BA3692"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/plasma
ore_type = /obj/item/stack/ore/plasma
@@ -200,8 +203,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/bluespace
name = "bluespace crystal"
desc = "Crystals with bluespace properties"
- color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
- greyscale_colors = "#4e7dffC8"
+ color = "#2E50B7"
+ greyscale_colors = "#2E50B7"
alpha = 200
starlight_color = COLOR_BLUE
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE)
@@ -213,6 +216,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
points_per_unit = 50 / SHEET_MATERIAL_AMOUNT
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC
+ texture_layer_icon_state = "shine"
/datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8))
@@ -223,8 +227,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/bananium
name = "bananium"
desc = "Material with hilarious properties"
- color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow
- greyscale_colors = "#ffff00"
+ color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow //It's literally perfect I can't change it
+ greyscale_colors = "#FFF269"
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/bananium
ore_type = /obj/item/stack/ore/bananium
@@ -253,8 +257,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/titanium
name = "titanium"
desc = "Titanium"
- color = "#b3c0c7"
- greyscale_colors = "#b3c0c7"
+ color = "#EFEFEF"
+ greyscale_colors = "#EFEFEF"
strength_modifier = 1.3
categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/titanium
@@ -265,6 +269,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.05
armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 0.7, ACID = 1)
mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS
+ texture_layer_icon_state = "shine"
/datum/material/titanium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
@@ -273,8 +278,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/runite
name = "runite"
desc = "Runite"
- color = "#3F9995"
- greyscale_colors = "#3F9995"
+ color = "#526F77"
+ greyscale_colors = "#526F77"
strength_modifier = 1.3
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/runite
@@ -292,8 +297,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/plastic
name = "plastic"
desc = "Plastic"
- color = "#caccd9"
- greyscale_colors = "#caccd9"
+ color = "#BFB9AC"
+ greyscale_colors = "#BFB9AC"
strength_modifier = 0.85
sheet_type = /obj/item/stack/sheet/plastic
ore_type = /obj/item/stack/ore/slag //No plastic or coal ore, so we use slag.
@@ -321,8 +326,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/wood
name = "wood"
desc = "Flexible, durable, but flamable. Hard to come across in space."
- color = "#bb8e53"
- greyscale_colors = "#bb8e53"
+ color = "#855932"
+ greyscale_colors = "#855932"
strength_modifier = 0.5
sheet_type = /obj/item/stack/sheet/mineral/wood
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
@@ -354,8 +359,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/adamantine
name = "adamantine"
desc = "A powerful material made out of magic, I mean science!"
- color = "#6d7e8e"
- greyscale_colors = "#6d7e8e"
+ color = "#2B7A74"
+ greyscale_colors = "#2B7A74"
strength_modifier = 1.5
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/adamantine
@@ -426,11 +431,12 @@ Unless you know what you're doing, only use the first three numbers. They're in
source_item?.reagents?.add_reagent(/datum/reagent/toxin/plasma, source_item.reagents.total_volume*(3/5))
return TRUE
+// It's basically adamantine, but it isn't!
/datum/material/metalhydrogen
name = "Metal Hydrogen"
desc = "Solid metallic hydrogen. Some say it should be impossible"
- color = "#f2d5d7"
- greyscale_colors = "#f2d5d796"
+ color = "#62708A"
+ greyscale_colors = "#62708A"
alpha = 150
starlight_color = COLOR_MODERATE_BLUE
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
@@ -468,8 +474,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/sandstone
name = "sandstone"
desc = "Bialtaakid 'ant taerif ma hdha."
- color = "#B77D31"
- greyscale_colors = "#B77D31"
+ color = "#ECD5A8"
+ greyscale_colors = "#ECD5A8"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/mineral/sandstone
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
@@ -498,8 +504,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/runedmetal
name = "runed metal"
desc = "Mir'ntrath barhah Nar'sie."
- color = "#3C3434"
- greyscale_colors = "#3C3434"
+ color = "#504742"
+ greyscale_colors = "#504742"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/runed_metal
value_per_unit = 1500 / SHEET_MATERIAL_AMOUNT
@@ -515,8 +521,8 @@ Unless you know what you're doing, only use the first three numbers. They're in
/datum/material/bronze
name = "bronze"
desc = "Clock Cult? Never heard of it."
- color = "#92661A"
- greyscale_colors = "#92661A"
+ color = "#876223"
+ greyscale_colors = "#876223"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE)
sheet_type = /obj/item/stack/sheet/bronze
value_per_unit = 50 / SHEET_MATERIAL_AMOUNT
diff --git a/code/datums/memory/_memory.dm b/code/datums/memory/_memory.dm
index 0656d32006a..08a694616a3 100644
--- a/code/datums/memory/_memory.dm
+++ b/code/datums/memory/_memory.dm
@@ -392,7 +392,7 @@
if(istype(character, /datum/mind))
var/datum/mind/character_mind = character
- return "\the [lowertext(initial(character_mind.assigned_role.title))]"
+ return "\the [LOWER_TEXT(initial(character_mind.assigned_role.title))]"
// Generic result - mobs get "the guy", objs / turfs get "a thing"
return ismob(character) ? "\the [character]" : "\a [character]"
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index 0cfb48f7a98..0e54c21e702 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -474,6 +474,11 @@
mood_change = -6
timeout = 5 MINUTES
+/datum/mood_event/mallet_humiliation
+ description = "Getting hit by such a stupid weapon feels rather humiliating..."
+ mood_change = -3
+ timeout = 10 SECONDS
+
///Wizard cheesy grand finale - what everyone but the wizard gets
/datum/mood_event/madness_despair
description = "UNWORTHY, UNWORTHY, UNWORTHY!!!"
diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm
index 72d789da1e0..dd5441476dc 100644
--- a/code/datums/mood_events/needs_events.dm
+++ b/code/datums/mood_events/needs_events.dm
@@ -66,7 +66,7 @@
mood_change = -12
/datum/mood_event/disgust/dirty_food
- description = "It was too dirty to eat..."
+ description = "That was too dirty to eat..."
mood_change = -6
timeout = 4 MINUTES
diff --git a/code/datums/mutations/olfaction.dm b/code/datums/mutations/olfaction.dm
index e014806233a..305f6d16e83 100644
--- a/code/datums/mutations/olfaction.dm
+++ b/code/datums/mutations/olfaction.dm
@@ -40,6 +40,10 @@
to_chat(owner, span_warning("You have no nose!"))
return FALSE
+ if(HAS_TRAIT(living_cast_on, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything
+ to_chat(owner, span_warning("You can't smell!"))
+ return FALSE
+
return TRUE
/datum/action/cooldown/spell/olfaction/cast(mob/living/cast_on)
diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm
index 2f7c701e70f..05e62ab2726 100644
--- a/code/datums/quirks/_quirk.dm
+++ b/code/datums/quirks/_quirk.dm
@@ -167,7 +167,7 @@
* * default_location - If the item isn't possible to equip in a valid slot, this is a description of where the item was spawned.
* * notify_player - If TRUE, adds strings to where_items_spawned list to be output to the player in [/datum/quirk/item_quirk/post_add()]
*/
-/datum/quirk/item_quirk/proc/give_item_to_holder(quirk_item, list/valid_slots, flavour_text = null, default_location = "at your feet", notify_player = TRUE)
+/datum/quirk/item_quirk/proc/give_item_to_holder(obj/item/quirk_item, list/valid_slots, flavour_text = null, default_location = "at your feet", notify_player = TRUE)
if(ispath(quirk_item))
quirk_item = new quirk_item(get_turf(quirk_holder))
diff --git a/code/datums/quirks/negative_quirks/all_nighter.dm b/code/datums/quirks/negative_quirks/all_nighter.dm
index 7f9f051ecf7..f5288b82215 100644
--- a/code/datums/quirks/negative_quirks/all_nighter.dm
+++ b/code/datums/quirks/negative_quirks/all_nighter.dm
@@ -43,6 +43,8 @@
///if we have bags and lost a head, remove them
/datum/quirk/all_nighter/proc/on_removed_limb(datum/source, obj/item/bodypart/removed_limb, special, dismembered)
+ SIGNAL_HANDLER
+
if(bodypart_overlay && istype(removed_limb, /obj/item/bodypart/head))
remove_bags()
diff --git a/code/datums/quirks/negative_quirks/anosmia.dm b/code/datums/quirks/negative_quirks/anosmia.dm
new file mode 100644
index 00000000000..bbbf599aeaa
--- /dev/null
+++ b/code/datums/quirks/negative_quirks/anosmia.dm
@@ -0,0 +1,9 @@
+/datum/quirk/item_quirk/anosmia
+ name = "Anosmia"
+ desc = "For some reason, you can't smell anything."
+ icon = FA_ICON_HEAD_SIDE_COUGH_SLASH
+ value = -2
+ mob_trait = TRAIT_ANOSMIA
+ gain_text = span_notice("You find yourself unable to smell anything!")
+ lose_text = span_danger("Suddenly, you can smell again!")
+ medical_record_text = "Patient has lost their sensation of smell."
diff --git a/code/datums/quirks/negative_quirks/insanity.dm b/code/datums/quirks/negative_quirks/insanity.dm
index 56b56a53812..40e70f07b18 100644
--- a/code/datums/quirks/negative_quirks/insanity.dm
+++ b/code/datums/quirks/negative_quirks/insanity.dm
@@ -25,7 +25,7 @@
added_trauma.resilience = TRAUMA_RESILIENCE_ABSOLUTE
added_trauma.name = name
added_trauma.desc = medical_record_text
- added_trauma.scan_desc = lowertext(name)
+ added_trauma.scan_desc = LOWER_TEXT(name)
added_trauma.gain_text = null
added_trauma.lose_text = null
@@ -33,7 +33,7 @@
added_trama_ref = WEAKREF(added_trauma)
/datum/quirk/insanity/post_add()
- var/rds_policy = get_policy("[type]") || "Please note that your [lowertext(name)] does NOT give you any additional right to attack people or cause chaos."
+ var/rds_policy = get_policy("[type]") || "Please note that your [LOWER_TEXT(name)] does NOT give you any additional right to attack people or cause chaos."
// I don't /think/ we'll need this, but for newbies who think "roleplay as insane" = "license to kill", it's probably a good thing to have.
to_chat(quirk_holder, span_big(span_info(rds_policy)))
diff --git a/code/datums/quirks/positive_quirks/strong_stomach.dm b/code/datums/quirks/positive_quirks/strong_stomach.dm
new file mode 100644
index 00000000000..8c0a3f3b137
--- /dev/null
+++ b/code/datums/quirks/positive_quirks/strong_stomach.dm
@@ -0,0 +1,12 @@
+/datum/quirk/strong_stomach
+ name = "Strong Stomach"
+ desc = "You can eat food discarded on the ground without getting sick, and vomiting affects you less."
+ icon = FA_ICON_FACE_GRIN_BEAM_SWEAT
+ value = 4
+ mob_trait = TRAIT_STRONG_STOMACH
+ gain_text = span_notice("You feel like you could eat anything!")
+ lose_text = span_danger("Looking at food on the ground makes you feel a little queasy.")
+ medical_record_text = "Patient has a stronger than average immune system...to food poisoning, at least."
+ mail_goodies = list(
+ /obj/item/reagent_containers/pill/ondansetron,
+ )
diff --git a/code/datums/station_traits/admin_panel.dm b/code/datums/station_traits/admin_panel.dm
index 02eca48b54f..67669027c54 100644
--- a/code/datums/station_traits/admin_panel.dm
+++ b/code/datums/station_traits/admin_panel.dm
@@ -1,10 +1,6 @@
-/// Opens the station traits admin panel
-/datum/admins/proc/station_traits_panel()
- set name = "Modify Station Traits"
- set category = "Admin.Events"
-
+ADMIN_VERB(station_traits_panel, R_FUN, "Modify Station Traits", "Modify the station traits for the next round.", ADMIN_CATEGORY_EVENTS)
var/static/datum/station_traits_panel/station_traits_panel = new
- station_traits_panel.ui_interact(usr)
+ station_traits_panel.ui_interact(user.mob)
/datum/station_traits_panel
var/static/list/future_traits
diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm
index 610b79a40f1..2414681091a 100644
--- a/code/datums/station_traits/negative_traits.dm
+++ b/code/datums/station_traits/negative_traits.dm
@@ -149,7 +149,7 @@
/datum/station_trait/overflow_job_bureaucracy/proc/set_overflow_job_override(datum/source)
SIGNAL_HANDLER
var/datum/job/picked_job = pick(SSjob.get_valid_overflow_jobs())
- chosen_job_name = lowertext(picked_job.title) // like Chief Engineers vs like chief engineers
+ chosen_job_name = LOWER_TEXT(picked_job.title) // like Chief Engineers vs like chief engineers
SSjob.set_overflow_role(picked_job.type)
/datum/station_trait/slow_shuttle
diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm
index 5bf8269bbbf..62f8c9ca24e 100644
--- a/code/datums/status_effects/debuffs/fire_stacks.dm
+++ b/code/datums/status_effects/debuffs/fire_stacks.dm
@@ -261,6 +261,7 @@
/datum/status_effect/fire_handler/fire_stacks/on_apply()
. = ..()
RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(add_fire_overlay))
+ RegisterSignal(owner, COMSIG_ATOM_EXTINGUISH, PROC_REF(extinguish))
owner.update_appearance(UPDATE_OVERLAYS)
/datum/status_effect/fire_handler/fire_stacks/proc/add_fire_overlay(mob/living/source, list/overlays)
diff --git a/code/datums/status_effects/debuffs/speech_debuffs.dm b/code/datums/status_effects/debuffs/speech_debuffs.dm
index 07bcd3c2543..4963a660b22 100644
--- a/code/datums/status_effects/debuffs/speech_debuffs.dm
+++ b/code/datums/status_effects/debuffs/speech_debuffs.dm
@@ -187,7 +187,7 @@
/datum/status_effect/speech/slurring/apply_speech(original_char)
var/modified_char = original_char
- var/lower_char = lowertext(modified_char)
+ var/lower_char = LOWER_TEXT(modified_char)
if(prob(common_prob) && (lower_char in common_replacements))
var/to_replace = common_replacements[lower_char]
if(islist(to_replace))
diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm
index 42fad48509d..b1bacfbceab 100644
--- a/code/datums/storage/storage.dm
+++ b/code/datums/storage/storage.dm
@@ -207,6 +207,7 @@
RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(handle_extra_examination))
RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_deconstruct))
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act))
+ RegisterSignal(parent, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(contents_changed_w_class))
/**
* Sets where items are physically being stored in the case it shouldn't be on the parent.
@@ -401,7 +402,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
var/datum/storage/bigger_fish = parent.loc.atom_storage
if(bigger_fish && bigger_fish.max_specific_storage < max_specific_storage)
if(messages && user)
- user.balloon_alert(user, "[lowertext(parent.loc.name)] is in the way!")
+ user.balloon_alert(user, "[LOWER_TEXT(parent.loc.name)] is in the way!")
return FALSE
if(isitem(parent))
@@ -915,7 +916,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(open_storage), to_show)
- return COMPONENT_NO_AFTERATTACK
+ if(display_contents)
+ return COMPONENT_NO_AFTERATTACK
/// Opens the storage to the mob, showing them the contents to their UI.
/datum/storage/proc/open_storage(mob/to_show)
@@ -1092,3 +1094,14 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
var/matrix/old_matrix = parent.transform
animate(parent, time = 1.5, loop = 0, transform = parent.transform.Scale(1.07, 0.9))
animate(time = 2, transform = old_matrix)
+
+/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to drop items out of our storage if they're suddenly too heavy.
+/datum/storage/proc/contents_changed_w_class(datum/source, obj/item/changed, old_w_class, new_w_class)
+ SIGNAL_HANDLER
+
+ if(new_w_class <= max_specific_storage && new_w_class + get_total_weight() <= max_total_storage)
+ return
+ if(!attempt_remove(changed, parent.drop_location()))
+ return
+
+ changed.visible_message(span_warning("[changed] falls out of [parent]!"), vision_distance = COMBAT_MESSAGE_RANGE)
diff --git a/code/datums/storage/subtypes/fish_case.dm b/code/datums/storage/subtypes/fish_case.dm
index dbbb15f47eb..82733d37ad9 100644
--- a/code/datums/storage/subtypes/fish_case.dm
+++ b/code/datums/storage/subtypes/fish_case.dm
@@ -24,25 +24,11 @@
var/obj/item/item_parent = parent
if(arrived.w_class <= item_parent.w_class)
return
- item_parent.w_class = arrived.w_class
- // Since we're changing weight class we need to check if our storage's loc's storage can still hold us
- // in the future we need a generic solution to this to solve a bunch of other exploits
- var/datum/storage/loc_storage = item_parent.loc.atom_storage
- if(!isnull(loc_storage) && !loc_storage.can_insert(item_parent))
- item_parent.forceMove(item_parent.loc.drop_location())
- item_parent.visible_message(span_warning("[item_parent] spills out of [item_parent.loc] as it expands to hold [arrived]!"), vision_distance = 1)
- return
-
- if(isliving(item_parent.loc))
- var/mob/living/living_loc = item_parent.loc
- if((living_loc.get_slot_by_item(item_parent) & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && item_parent.w_class > WEIGHT_CLASS_SMALL)
- item_parent.forceMove(living_loc.drop_location())
- to_chat(living_loc, span_warning("[item_parent] drops out of your pockets as it expands to hold [arrived]!"))
- return
+ item_parent.update_weight_class(arrived.w_class)
/datum/storage/fish_case/handle_exit(datum/source, obj/item/gone)
. = ..()
if(!isitem(parent) || !istype(gone))
return
var/obj/item/item_parent = parent
- item_parent.w_class = initial(item_parent.w_class)
+ item_parent.update_weight_class(initial(item_parent.w_class))
diff --git a/code/datums/voice_of_god_command.dm b/code/datums/voice_of_god_command.dm
index 052af9d060b..21d4f460617 100644
--- a/code/datums/voice_of_god_command.dm
+++ b/code/datums/voice_of_god_command.dm
@@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands())
if(!user.say(message, spans = span_list, sanitize = FALSE, ignore_spam = ignore_spam, forced = forced))
return
- message = lowertext(message)
+ message = LOWER_TEXT(message)
var/list/mob/living/listeners = list()
//used to check if the speaker specified a name or a job to focus on
@@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands())
for(var/mob/living/target as anything in listeners)
var/to_say = user.name
// 0.1% chance to be a smartass
- if(findtext(lowertext(message), smartass_regex) && prob(0.1))
+ if(findtext(LOWER_TEXT(message), smartass_regex) && prob(0.1))
to_say = "My name"
addtimer(CALLBACK(target, TYPE_PROC_REF(/atom/movable, say), to_say), 0.5 SECONDS * iteration)
iteration++
diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm
index 99438be18cc..cb7c3972993 100644
--- a/code/datums/wires/_wires.dm
+++ b/code/datums/wires/_wires.dm
@@ -258,7 +258,7 @@
return TRUE
// Station blueprints do that too, but only if the wires are not randomized.
- if(user.is_holding_item_of_type(/obj/item/areaeditor/blueprints) && !randomize)
+ if(user.is_holding_item_of_type(/obj/item/blueprints) && !randomize)
return TRUE
return FALSE
diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm
index 00ac17b3b1f..9c3343b73ec 100644
--- a/code/datums/wounds/bones.dm
+++ b/code/datums/wounds/bones.dm
@@ -237,7 +237,7 @@
return FALSE
if(user.grab_state == GRAB_PASSIVE)
- to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!"))
+ to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [LOWER_TEXT(name)]!"))
return TRUE
if(user.grab_state >= GRAB_AGGRESSIVE)
diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm
index 7304d21365c..ecefc56817c 100644
--- a/code/datums/wounds/pierce.dm
+++ b/code/datums/wounds/pierce.dm
@@ -73,7 +73,7 @@
if(victim.bodytemperature < (BODYTEMP_NORMAL - 10))
adjust_blood_flow(-0.1 * seconds_per_tick)
if(SPT_PROB(2.5, seconds_per_tick))
- to_chat(victim, span_notice("You feel the [lowertext(name)] in your [limb.plaintext_zone] firming up from the cold!"))
+ to_chat(victim, span_notice("You feel the [LOWER_TEXT(name)] in your [limb.plaintext_zone] firming up from the cold!"))
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm
index ad841856c64..e1b873cfec7 100644
--- a/code/game/atom/_atom.dm
+++ b/code/game/atom/_atom.dm
@@ -136,6 +136,9 @@
///whether ghosts can see screentips on it
var/ghost_screentips = FALSE
+ /// Flags to check for in can_perform_action. Used in alt-click checks
+ var/interaction_flags_click = NONE
+
/**
* Top level of the destroy chain for most atoms
*
@@ -368,11 +371,6 @@
/atom/proc/return_analyzable_air()
return null
-///Check if this atoms eye is still alive (probably)
-/atom/proc/check_eye(mob/user)
- SIGNAL_HANDLER
- return
-
/atom/proc/Bumped(atom/movable/bumped_atom)
set waitfor = FALSE
SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom)
diff --git a/code/game/atom/atom_color.dm b/code/game/atom/atom_color.dm
index e5b52460aa0..2508e86f44d 100644
--- a/code/game/atom/atom_color.dm
+++ b/code/game/atom/atom_color.dm
@@ -42,15 +42,15 @@
* Can optionally be supplied with a range of priorities, IE only checking "washable" or above
*/
/atom/proc/is_atom_colour(looking_for_color, min_priority_index = 1, max_priority_index = COLOUR_PRIORITY_AMOUNT)
- // make sure uppertext hex strings don't mess with lowertext hex strings
- looking_for_color = lowertext(looking_for_color)
+ // make sure uppertext hex strings don't mess with LOWER_TEXT hex strings
+ looking_for_color = LOWER_TEXT(looking_for_color)
if(!LAZYLEN(atom_colours))
// no atom colors list has been set up, just check the color var
- return lowertext(color) == looking_for_color
+ return LOWER_TEXT(color) == looking_for_color
for(var/i in min_priority_index to max_priority_index)
- if(lowertext(atom_colours[i]) == looking_for_color)
+ if(LOWER_TEXT(atom_colours[i]) == looking_for_color)
return TRUE
return FALSE
diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm
index 131aa6c8e9c..8df52eb9cb0 100644
--- a/code/game/atom/atom_examine.dm
+++ b/code/game/atom/atom_examine.dm
@@ -83,13 +83,16 @@
* [COMSIG_ATOM_GET_EXAMINE_NAME] signal
*/
/atom/proc/get_examine_name(mob/user)
- . = "\a [src]"
- var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]")
- if(article)
- . = "[article] [src]"
- override[EXAMINE_POSITION_ARTICLE] = article
- if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
- . = override.Join("")
+ var/list/override = list(article, null, "[name]")
+ SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override)
+
+ if(!isnull(override[EXAMINE_POSITION_ARTICLE]))
+ override -= null // IF there is no "before", don't try to join it
+ return jointext(override, " ")
+ if(!isnull(override[EXAMINE_POSITION_BEFORE]))
+ override -= null // There is no article, don't try to join it
+ return "\a [jointext(override, " ")]"
+ return "\a [src]"
///Generate the full examine string of this atom (including icon for goonchat)
/atom/proc/get_examine_string(mob/user, thats = FALSE)
diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm
index 4b91f396095..b2cea26224b 100644
--- a/code/game/atom/atom_tool_acts.dm
+++ b/code/game/atom/atom_tool_acts.dm
@@ -4,15 +4,12 @@
* Handles non-combat iteractions of a tool on this atom,
* such as using a tool on a wall to deconstruct it,
* or scanning someone with a health analyzer
- *
- * This can be overridden to add custom item interactions to this atom
- *
- * Do not call this directly
*/
-/atom/proc/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/atom/proc/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers)
SHOULD_CALL_PARENT(TRUE)
PROTECTED_PROC(TRUE)
+ var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK)
var/is_left_clicking = !is_right_clicking
var/early_sig_return = NONE
if(is_left_clicking)
@@ -24,6 +21,12 @@
if(early_sig_return)
return early_sig_return
+ var/self_interaction = is_left_clicking \
+ ? item_interaction(user, tool, modifiers) \
+ : item_interaction_secondary(user, tool, modifiers)
+ if(self_interaction)
+ return self_interaction
+
var/interact_return = is_left_clicking \
? tool.interact_with_atom(src, user, modifiers) \
: tool.interact_with_atom_secondary(src, user, modifiers)
@@ -85,6 +88,27 @@
SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src)
return act_result
+/**
+ * Called when this atom has an item used on it.
+ * IE, a mob is clicking on this atom with an item.
+ *
+ * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code.
+ * Return NONE to allow default interaction / tool handling.
+ */
+/atom/proc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ return NONE
+
+/**
+ * Called when this atom has an item used on it WITH RIGHT CLICK,
+ * IE, a mob is right clicking on this atom with an item.
+ * Default behavior has it run the same code as left click.
+ *
+ * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code.
+ * Return NONE to allow default interaction / tool handling.
+ */
+/atom/proc/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
+ return item_interaction(user, tool, modifiers)
+
/**
* Called when this item is being used to interact with an atom,
* IE, a mob is clicking on an atom with this item.
diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm
index 8830a4af2f4..10a6cbff24a 100644
--- a/code/game/atom/atom_vv.dm
+++ b/code/game/atom/atom_vv.dm
@@ -67,14 +67,10 @@
message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]"))
if(href_list[VV_HK_TRIGGER_EXPLOSION])
- if(!check_rights(R_FUN))
- return
- usr.client.cmd_admin_explosion(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_explosion, src)
if(href_list[VV_HK_TRIGGER_EMP])
- if(!check_rights(R_FUN))
- return
- usr.client.cmd_admin_emp(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_emp, src)
if(href_list[VV_HK_SHOW_HIDDENPRINTS])
if(!check_rights(R_ADMIN))
diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm
index ea8bf9b125d..f76f00670d2 100644
--- a/code/game/atom/atoms_initializing_EXPENSIVE.dm
+++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm
@@ -161,3 +161,5 @@
*/
/atom/proc/LateInitialize()
set waitfor = FALSE
+ SHOULD_CALL_PARENT(FALSE)
+ stack_trace("[src] ([type]) called LateInitialize but has nothing on it!")
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index d81f9306af4..a67e48f041c 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -6,6 +6,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code.
var/name = "generic objective" //Name for admin prompts
var/explanation_text = "Nothing" //What that person is supposed to do.
+ ///if this objective doesn't print failure or success in the roundend report
+ var/no_failure = FALSE
///name used in printing this objective (Objective #1)
var/objective_name = "Objective"
var/team_explanation_text //For when there are multiple owners.
@@ -99,6 +101,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
/// Provides a string describing what a good job you did or did not do
/datum/objective/proc/get_roundend_success_suffix()
+ if(no_failure)
+ return "" // Just print the objective with no success/fail evaluation, as it has no mechanical backing
return check_completion() ? span_greentext("Success!") : span_redtext("Fail.")
/datum/objective/proc/is_unique_objective(possible_target, dupe_search_range)
@@ -356,6 +360,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
/datum/objective/protect/check_completion()
var/obj/item/organ/internal/brain/brain_target
+ if(isnull(target))
+ return FALSE
if(human_check)
brain_target = target.current?.get_organ_slot(ORGAN_SLOT_BRAIN)
//Protect will always suceed when someone suicides
@@ -405,7 +411,7 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
/datum/objective/jailbreak/detain/update_explanation_text()
..()
if(target?.current)
- explanation_text = "Ensure that [target.name], the [!target_role_type ? target.assigned_role.title : target.special_role] is delivered to nanotrasen alive and in custody."
+ explanation_text = "Ensure that [target.name], the [!target_role_type ? target.assigned_role.title : target.special_role] is delivered to Nanotrasen alive and in custody."
else
explanation_text = "Free objective."
@@ -992,15 +998,13 @@ GLOBAL_LIST_EMPTY(possible_items)
/datum/objective/custom
name = "custom"
admin_grantable = TRUE
+ no_failure = TRUE
/datum/objective/custom/admin_edit(mob/admin)
var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text)
if(expl)
explanation_text = expl
-/datum/objective/custom/get_roundend_success_suffix()
- return "" // Just print the objective with no success/fail evaluation, as it has no mechanical backing
-
//Ideally this would be all of them but laziness and unusual subtypes
/proc/generate_admin_objective_list()
GLOB.admin_objective_list = list()
diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm
index 64b3e4420cb..c88fa7f11b1 100644
--- a/code/game/gamemodes/objective_items.dm
+++ b/code/game/gamemodes/objective_items.dm
@@ -529,7 +529,7 @@
/datum/objective_item/steal/blueprints
name = "the station blueprints"
- targetitem = /obj/item/areaeditor/blueprints
+ targetitem = /obj/item/blueprints
excludefromjob = list(JOB_CHIEF_ENGINEER)
item_owner = list(JOB_CHIEF_ENGINEER)
altitems = list(/obj/item/photo)
@@ -537,11 +537,11 @@
difficulty = 3
steal_hint = "The blueprints of the station, found in the Chief Engineer's locker, or on their person. A picture may suffice."
-/obj/item/areaeditor/blueprints/add_stealing_item_objective()
- return add_item_to_steal(src, /obj/item/areaeditor/blueprints)
+/obj/item/blueprints/add_stealing_item_objective()
+ return add_item_to_steal(src, /obj/item/blueprints)
/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I)
- if(istype(I, /obj/item/areaeditor/blueprints))
+ if(istype(I, /obj/item/blueprints))
return TRUE
if(istype(I, /obj/item/photo))
var/obj/item/photo/P = I
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index d9ceac4f7f2..533c3aa1a42 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -184,12 +184,8 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/LateInitialize()
- . = ..()
- power_change()
- if(use_power == NO_POWER_USE)
- return
- update_current_power_usage()
- setup_area_power_relationship()
+ SHOULD_NOT_OVERRIDE(TRUE)
+ post_machine_initialize()
/obj/machinery/Destroy(force)
SSmachines.unregister_machine(src)
@@ -200,6 +196,20 @@
return ..()
+/**
+ * Called in LateInitialize meant to be the machine replacement to it
+ * This sets up power for the machine and requires parent be called,
+ * ensuring power works on all machines unless exempted with NO_POWER_USE.
+ * This is the proc to override if you want to do anything in LateInitialize.
+ */
+/obj/machinery/proc/post_machine_initialize()
+ SHOULD_CALL_PARENT(TRUE)
+ power_change()
+ if(use_power == NO_POWER_USE)
+ return
+ update_current_power_usage()
+ setup_area_power_relationship()
+
/**
* proc to call when the machine starts to require power after a duration of not requiring power
* sets up power related connections to its area if it exists and becomes area sensitive
@@ -328,7 +338,6 @@
if(drop)
dump_inventory_contents()
update_appearance()
- updateUsrDialog()
/**
* Drop every movable atom in the machine's contents list, including any components and circuit.
@@ -413,7 +422,6 @@
if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled))
set_occupant(target)
target.forceMove(src)
- updateUsrDialog()
update_appearance()
///updates the use_power var for this machine and updates its static power usage from its area to reflect the new value
@@ -580,13 +588,15 @@
set_panel_open(!panel_open)
/obj/machinery/can_interact(mob/user)
+ if(QDELETED(user))
+ return FALSE
+
if((machine_stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE)) // Check if the machine is broken, and if we can still interact with it if so
return FALSE
if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_INTERACT)
return FALSE
-
if(isAdminGhostAI(user))
return TRUE //the Gods have unlimited power and do not care for things such as range or blindness
@@ -658,12 +668,10 @@
//Return a non FALSE value to interrupt attack_hand propagation to subtypes.
/obj/machinery/interact(mob/user)
- if(interaction_flags_machine & INTERACT_MACHINE_SET_MACHINE)
- user.set_machine(src)
update_last_used(user)
- . = ..()
+ return ..()
-/obj/machinery/ui_act(action, list/params)
+/obj/machinery/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
add_fingerprint(usr)
update_last_used(usr)
if(HAS_AI_ACCESS(usr) && !GLOB.cameranet.checkTurfVis(get_turf(src))) //We check if they're an AI specifically here, so borgs can still access off-camera stuff.
@@ -759,13 +767,14 @@
return
update_last_used(user)
-/obj/machinery/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_TOOLS)
- return ITEM_INTERACT_ANY_BLOCKER
+ return ITEM_INTERACT_BLOCKING
+
. = ..()
- if(. & ITEM_INTERACT_BLOCKING)
- return
- update_last_used(user)
+ if(.)
+ update_last_used(user)
+ return .
/obj/machinery/_try_interact(mob/user)
if((interaction_flags_machine & INTERACT_MACHINE_WIRES_IF_OPEN) && panel_open && (attempt_wire_interaction(user) == WIRE_INTERACTION_BLOCK))
@@ -818,7 +827,7 @@
/obj/machinery/handle_deconstruct(disassembled = TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
- if(obj_flags & NO_DECONSTRUCTION)
+ if(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)
dump_inventory_contents() //drop stuff we consider important
return //Just delete us, no need to call anything else.
@@ -954,9 +963,6 @@
if(!istype(replacer_tool))
return FALSE
- if(!replacer_tool.works_from_distance)
- return FALSE
-
var/shouldplaysound = FALSE
if(!component_parts)
return FALSE
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 4fbfe2d37bf..1bdcba84967 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -388,15 +388,15 @@
drop_direction = direction
balloon_alert(usr, "dropping [dir2text(drop_direction)]")
-/obj/machinery/autolathe/AltClick(mob/user)
- . = ..()
- if(!drop_direction || !can_interact(user))
- return
+/obj/machinery/autolathe/click_alt(mob/user)
+ if(!drop_direction)
+ return CLICK_ACTION_BLOCKING
if(busy)
balloon_alert(user, "busy printing!")
- return
+ return CLICK_ACTION_SUCCESS
balloon_alert(user, "drop direction reset")
drop_direction = 0
+ return CLICK_ACTION_SUCCESS
/obj/machinery/autolathe/attackby(obj/item/attacking_item, mob/living/user, params)
if(user.combat_mode) //so we can hit the machine
diff --git a/code/game/machinery/barsigns.dm b/code/game/machinery/barsigns.dm
index 006620ec5f4..e59de18ffcb 100644
--- a/code/game/machinery/barsigns.dm
+++ b/code/game/machinery/barsigns.dm
@@ -36,8 +36,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32)
if(!istype(sign))
return
+ var/area/bar_area = get_area(src)
if(change_area_name && sign.rename_area)
- rename_area(src, sign.name)
+ rename_area(bar_area, sign.name)
chosen_sign = sign
update_appearance()
@@ -152,7 +153,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32)
/obj/machinery/barsign/attackby(obj/item/attacking_item, mob/user)
- if(istype(attacking_item, /obj/item/areaeditor/blueprints) && !change_area_name)
+ if(istype(attacking_item, /obj/item/blueprints) && !change_area_name)
if(!panel_open)
balloon_alert(user, "open the panel first!")
return TRUE
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index ed896cc7576..ca6562635ee 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -110,7 +110,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
for(var/network_name in network)
network -= network_name
- network += lowertext(network_name)
+ network += LOWER_TEXT(network_name)
GLOB.cameranet.cameras += src
@@ -216,19 +216,19 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
return
if(. & EMP_PROTECT_SELF)
return
- if(prob(150 / severity))
- network = list()
- GLOB.cameranet.removeCamera(src)
- set_machine_stat(machine_stat | EMPED)
- set_light(0)
- emped++ //Increase the number of consecutive EMP's
- update_appearance()
- addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time)
- for(var/mob/M as anything in GLOB.player_list)
- if (M.client?.eye == src)
- M.unset_machine()
- M.reset_perspective(null)
- to_chat(M, span_warning("The screen bursts into static!"))
+ if(!prob(150 / severity))
+ return
+ network = list()
+ GLOB.cameranet.removeCamera(src)
+ set_machine_stat(machine_stat | EMPED)
+ set_light(0)
+ emped++ //Increase the number of consecutive EMP's
+ update_appearance()
+ addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time)
+ for(var/mob/M as anything in GLOB.player_list)
+ if (M.client?.eye == src)
+ M.reset_perspective(null)
+ to_chat(M, span_warning("The screen bursts into static!"))
/obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration)
SIGNAL_HANDLER
@@ -371,7 +371,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0)
//I guess that doesn't matter since they can't use it anyway?
for(var/mob/O as anything in GLOB.player_list)
if (O.client?.eye == src)
- O.unset_machine()
O.reset_perspective(null)
to_chat(O, span_warning("The screen bursts into static!"))
diff --git a/code/game/machinery/camera/camera_construction.dm b/code/game/machinery/camera/camera_construction.dm
index 48bf4ccabaa..15f22d02cbe 100644
--- a/code/game/machinery/camera/camera_construction.dm
+++ b/code/game/machinery/camera/camera_construction.dm
@@ -39,7 +39,7 @@
return ITEM_INTERACT_BLOCKING
for(var/i in tempnetwork)
tempnetwork -= i
- tempnetwork += lowertext(i)
+ tempnetwork += LOWER_TEXT(i)
camera_construction_state = CAMERA_STATE_FINISHED
toggle_cam(user, displaymessage = FALSE)
network = tempnetwork
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index bb9ef7d3fc5..2cd0506cbfd 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -66,7 +66,7 @@
/**
* Autonaming camera
- * Automatically names itself after the area it's in during LateInitialize,
+ * Automatically names itself after the area it's in during post_machine_initialize,
* good for mappers who don't want to manually name them all.
*/
/obj/machinery/camera/autoname
@@ -76,7 +76,7 @@
..()
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/camera/autoname/LateInitialize()
+/obj/machinery/camera/autoname/post_machine_initialize()
. = ..()
var/static/list/autonames_in_areas = list()
var/area/camera_area = get_area(src)
diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm
index 2d284b17b67..1cb7ee1477e 100644
--- a/code/game/machinery/civilian_bounties.dm
+++ b/code/game/machinery/civilian_bounties.dm
@@ -60,7 +60,7 @@
pad_ref = WEAKREF(I.buffer)
return TRUE
-/obj/machinery/computer/piratepad_control/civilian/LateInitialize()
+/obj/machinery/computer/piratepad_control/civilian/post_machine_initialize()
. = ..()
if(cargo_hold_id)
for(var/obj/machinery/piratepad/civilian/C as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/piratepad/civilian))
@@ -163,11 +163,9 @@
inserted_scan_id.registered_account.bounties = null
return inserted_scan_id.registered_account.civilian_bounty
-/obj/machinery/computer/piratepad_control/civilian/AltClick(mob/user)
- . = ..()
- if(!Adjacent(user))
- return FALSE
+/obj/machinery/computer/piratepad_control/civilian/click_alt(mob/user)
id_eject(user, inserted_scan_id)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/computer/piratepad_control/civilian/ui_data(mob/user)
var/list/data = list()
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index 0749c79bb88..3ab4fef3fdb 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -128,12 +128,6 @@
new_frame.state = FRAME_COMPUTER_STATE_GLASSED
new_frame.update_appearance(UPDATE_ICON_STATE)
-/obj/machinery/computer/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH) || !is_operational)
- return
/obj/machinery/computer/ui_interact(mob/user, datum/tgui/ui)
SHOULD_CALL_PARENT(TRUE)
diff --git a/code/game/machinery/computer/arcade/_arcade.dm b/code/game/machinery/computer/arcade/_arcade.dm
new file mode 100644
index 00000000000..69994634fc3
--- /dev/null
+++ b/code/game/machinery/computer/arcade/_arcade.dm
@@ -0,0 +1,100 @@
+/obj/machinery/computer/arcade
+ name = "\proper the arcade cabinet which shouldn't exist"
+ desc = "This arcade cabinet has no games installed, and in fact, should not exist. \
+ Report the location of this machine to your local diety."
+ icon_state = "arcade"
+ icon_keyboard = null
+ icon_screen = "invaders"
+ light_color = LIGHT_COLOR_GREEN
+ interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY
+
+ ///If set, will dispense these as prizes instead of the default GLOB.arcade_prize_pool
+ ///Like prize pool, it must be a list of the prize and the weight of being selected.
+ var/list/prize_override
+
+/obj/machinery/computer/arcade/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(istype(tool, /obj/item/stack/arcadeticket))
+ var/obj/item/stack/arcadeticket/tickets = tool
+ if(!tickets.use(2))
+ balloon_alert(user, "need 2 tickets!")
+ return ITEM_INTERACT_BLOCKING
+
+ prizevend(user)
+ balloon_alert(user, "prize claimed")
+ return ITEM_INTERACT_SUCCESS
+
+ if(istype(tool, /obj/item/key/displaycase) || istype(tool, /obj/item/access_key))
+ var/static/list/radial_menu_options
+ if(!radial_menu_options)
+ radial_menu_options = list(
+ "Reset Cabinet" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_reset"),
+ "Cancel" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_close"),
+ )
+ var/radial_reset_menu = show_radial_menu(user, src, radial_menu_options, require_near = TRUE)
+ if(radial_reset_menu != "Reset Cabinet")
+ return ITEM_INTERACT_BLOCKING
+ playsound(loc, 'sound/items/rattling_keys.ogg', 25, TRUE)
+ if(!do_after(user, 10 SECONDS, src))
+ return ITEM_INTERACT_BLOCKING
+ balloon_alert(user, "cabinet reset")
+ reset_cabinet(user)
+ return ITEM_INTERACT_SUCCESS
+
+ return NONE
+
+/obj/machinery/computer/arcade/screwdriver_act(mob/living/user, obj/item/I)
+ //you can't stop playing when you start.
+ if(obj_flags & EMAGGED)
+ return ITEM_INTERACT_BLOCKING
+ return ..()
+
+///Performs a factory reset of the cabinet and wipes all its stats.
+/obj/machinery/computer/arcade/proc/reset_cabinet(mob/living/user)
+ SHOULD_CALL_PARENT(TRUE)
+ obj_flags &= ~EMAGGED
+ SStgui.update_uis(src)
+
+/obj/machinery/computer/arcade/emp_act(severity)
+ . = ..()
+ if((machine_stat & (NOPOWER|BROKEN)) || (. & EMP_PROTECT_SELF))
+ return
+
+ var/empprize = null
+ var/num_of_prizes = 0
+ switch(severity)
+ if(1)
+ num_of_prizes = rand(1,4)
+ if(2)
+ num_of_prizes = rand(0,2)
+ for(var/i = num_of_prizes; i > 0; i--)
+ if(prize_override)
+ empprize = pick_weight(prize_override)
+ else
+ empprize = pick_weight(GLOB.arcade_prize_pool)
+ new empprize(loc)
+ explosion(src, devastation_range = -1, light_impact_range = 1 + num_of_prizes, flame_range = 1 + num_of_prizes)
+
+///Dispenses the proper prizes and gives them a positive mood event. If valid, has a small chance to give a pulse rifle.
+/obj/machinery/computer/arcade/proc/prizevend(mob/living/user, prizes = 1)
+ SEND_SIGNAL(src, COMSIG_ARCADE_PRIZEVEND, user, prizes)
+ if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
+ visible_message("[user] inputs an intense cheat code!",\
+ span_notice("You hear a flurry of buttons being pressed."))
+ say("CODE ACTIVATED: EXTRA PRIZES.")
+ prizes *= 2
+ for(var/i in 1 to prizes)
+ user.add_mood_event("arcade", /datum/mood_event/arcade)
+ if(prob(0.0001)) //1 in a million
+ new /obj/item/gun/energy/pulse/prize(src)
+ visible_message(span_notice("[src] dispenses.. woah, a gun! Way past cool."), span_notice("You hear a chime and a shot."))
+ user.client.give_award(/datum/award/achievement/misc/pulse, user)
+ continue
+
+ var/prizeselect
+ if(prize_override)
+ prizeselect = pick_weight(prize_override)
+ else
+ prizeselect = pick_weight(GLOB.arcade_prize_pool)
+ var/atom/movable/the_prize = new prizeselect(get_turf(src))
+ playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
+ visible_message(span_notice("[src] dispenses [the_prize]!"), span_notice("You hear a chime and a clunk."))
diff --git a/code/game/machinery/computer/arcade/amputation.dm b/code/game/machinery/computer/arcade/amputation.dm
new file mode 100644
index 00000000000..84a02af387a
--- /dev/null
+++ b/code/game/machinery/computer/arcade/amputation.dm
@@ -0,0 +1,47 @@
+/obj/machinery/computer/arcade/amputation
+ name = "Mediborg's Amputation Adventure"
+ desc = "A picture of a blood-soaked medical cyborg flashes on the screen. \
+ The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\""
+ icon_state = "arcade"
+ circuit = /obj/item/circuitboard/computer/arcade/amputation
+ interaction_flags_machine = NONE //borgs can't play, but the illiterate can.
+
+/obj/machinery/computer/arcade/amputation/attack_tk(mob/user)
+ return //that's a pretty damn big guillotine
+
+/obj/machinery/computer/arcade/amputation/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(!iscarbon(user))
+ return
+ to_chat(user, span_warning("You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it..."))
+ user.played_game()
+ var/obj/item/bodypart/chopchop = user.get_active_hand()
+ if(do_after(user, 5 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(do_they_still_have_that_hand), user, chopchop)))
+ playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1)
+ to_chat(user, span_userdanger("The guillotine drops on your arm, and the machine sucks it in!"))
+ chopchop.dismember()
+ qdel(chopchop)
+ user.mind?.adjust_experience(/datum/skill/gaming, 100)
+ user.won_game()
+ playsound(src, 'sound/arcade/win.ogg', 50, TRUE)
+ new /obj/item/stack/arcadeticket((get_turf(src)), rand(6,10))
+ to_chat(user, span_notice("[src] dispenses a handful of tickets!"))
+ return
+ if(!do_they_still_have_that_hand(user, chopchop))
+ to_chat(user, span_warning("The guillotine drops, but your hand seems to be gone already!"))
+ playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1)
+ else
+ to_chat(user, span_notice("You (wisely) decide against putting your hand in the machine."))
+ user.lost_game()
+
+///Makes sure the user still has their starting hand, preventing the user from pulling the arm out and still getting prizes.
+/obj/machinery/computer/arcade/amputation/proc/do_they_still_have_that_hand(mob/user, obj/item/bodypart/chopchop)
+ if(QDELETED(chopchop) || chopchop.owner != user)
+ return FALSE
+ return TRUE
+
+///Dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree
+/obj/machinery/computer/arcade/amputation/festive
+ name = "Mediborg's Festive Amputation Adventure"
+ desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\""
+ prize_override = list(/obj/item/gift/anything = 1)
diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm
deleted file mode 100644
index a4a22cc7542..00000000000
--- a/code/game/machinery/computer/arcade/arcade.dm
+++ /dev/null
@@ -1,713 +0,0 @@
-/* BUBBERSTATION CHANGE START: REDOES THE ARCADE PRIZE POOL. SEE MODULAR arcade.dm FILE FOR THE DROPTABLE.
-GLOBAL_LIST_INIT(arcade_prize_pool, list(
- /obj/item/storage/box/snappops = 2,
- /obj/item/toy/talking/ai = 2,
- /obj/item/toy/talking/codex_gigas = 2,
- /obj/item/clothing/under/syndicate/tacticool = 2,
- /obj/item/toy/sword = 2,
- /obj/item/toy/gun = 2,
- /obj/item/gun/ballistic/shotgun/toy/crossbow = 2,
- /obj/item/storage/box/fakesyndiesuit = 2,
- /obj/item/storage/crayons = 2,
- /obj/item/toy/spinningtoy = 2,
- /obj/item/toy/spinningtoy/dark_matter = 1,
- /obj/item/toy/balloon/arrest = 2,
- /obj/item/toy/mecha/ripley = 1,
- /obj/item/toy/mecha/ripleymkii = 1,
- /obj/item/toy/mecha/hauler = 1,
- /obj/item/toy/mecha/clarke = 1,
- /obj/item/toy/mecha/odysseus = 1,
- /obj/item/toy/mecha/gygax = 1,
- /obj/item/toy/mecha/durand = 1,
- /obj/item/toy/mecha/savannahivanov = 1,
- /obj/item/toy/mecha/phazon = 1,
- /obj/item/toy/mecha/honk = 1,
- /obj/item/toy/mecha/darkgygax = 1,
- /obj/item/toy/mecha/mauler = 1,
- /obj/item/toy/mecha/darkhonk = 1,
- /obj/item/toy/mecha/deathripley = 1,
- /obj/item/toy/mecha/reticence = 1,
- /obj/item/toy/mecha/marauder = 1,
- /obj/item/toy/mecha/seraph = 1,
- /obj/item/toy/mecha/firefighter = 1,
- /obj/item/toy/cards/deck = 2,
- /obj/item/toy/nuke = 2,
- /obj/item/toy/minimeteor = 2,
- /obj/item/toy/redbutton = 2,
- /obj/item/toy/talking/owl = 2,
- /obj/item/toy/talking/griffin = 2,
- /obj/item/coin/antagtoken = 2,
- /obj/item/stack/tile/fakepit/loaded = 2,
- /obj/item/stack/tile/eighties/loaded = 2,
- /obj/item/toy/toy_xeno = 2,
- /obj/item/storage/box/actionfigure = 1,
- /obj/item/restraints/handcuffs/fake = 2,
- /obj/item/grenade/chem_grenade/glitter/pink = 1,
- /obj/item/grenade/chem_grenade/glitter/blue = 1,
- /obj/item/grenade/chem_grenade/glitter/white = 1,
- /obj/item/toy/eightball = 2,
- /obj/item/toy/windup_toolbox = 2,
- /obj/item/toy/clockwork_watch = 2,
- /obj/item/toy/toy_dagger = 2,
- /obj/item/extendohand/acme = 1,
- /obj/item/hot_potato/harmless/toy = 1,
- /obj/item/card/emagfake = 1,
- /obj/item/clothing/shoes/wheelys = 2,
- /obj/item/clothing/shoes/kindle_kicks = 2,
- /obj/item/toy/plush/goatplushie = 2,
- /obj/item/toy/plush/moth = 2,
- /obj/item/toy/plush/pkplush = 2,
- /obj/item/toy/plush/rouny = 2,
- /obj/item/toy/plush/abductor = 2,
- /obj/item/toy/plush/abductor/agent = 2,
- /obj/item/toy/plush/shark = 2,
- /obj/item/storage/belt/military/snack/full = 2,
- /obj/item/toy/brokenradio = 2,
- /obj/item/toy/braintoy = 2,
- /obj/item/toy/eldritch_book = 2,
- /obj/item/storage/box/heretic_box = 1,
- /obj/item/toy/foamfinger = 2,
- /obj/item/clothing/glasses/trickblindfold = 2,
- /obj/item/clothing/mask/party_horn = 2,
- /obj/item/storage/box/party_poppers = 2))
-BUBBERSTATION CHANGE END. */
-
-/obj/machinery/computer/arcade
- name = "\proper the arcade cabinet which shouldn't exist"
- desc = "This arcade cabinet has no games installed, and in fact, should not exist. \
- Report the location of this machine to your local diety."
- icon_state = "arcade"
- icon_keyboard = null
- icon_screen = "invaders"
- light_color = LIGHT_COLOR_GREEN
- interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON
- var/list/prize_override
-
-/obj/machinery/computer/arcade/proc/Reset()
- return
-
-/obj/machinery/computer/arcade/Initialize(mapload)
- . = ..()
-
- Reset()
-
-/obj/machinery/computer/arcade/proc/prizevend(mob/living/user, prizes = 1)
- SEND_SIGNAL(src, COMSIG_ARCADE_PRIZEVEND, user, prizes)
- if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
- visible_message("[user] inputs an intense cheat code!",\
- span_notice("You hear a flurry of buttons being pressed."))
- say("CODE ACTIVATED: EXTRA PRIZES.")
- prizes *= 2
- for(var/i in 1 to prizes)
- user.add_mood_event("arcade", /datum/mood_event/arcade)
- if(prob(0.0001)) //1 in a million
- new /obj/item/gun/energy/pulse/prize(src)
- visible_message(span_notice("[src] dispenses.. woah, a gun! Way past cool."), span_notice("You hear a chime and a shot."))
- user.client.give_award(/datum/award/achievement/misc/pulse, user)
- return
-
- var/prizeselect
- if(prize_override)
- prizeselect = pick_weight(prize_override)
- else
- //BUBBERSTATION CHANGE START: BETTER PRIZES.
- prizeselect = pick_weight(GLOB.arcade_prize_pool)
- while(islist(prizeselect))
- prizeselect = pick_weight(prizeselect)
- //BUBBERSTATION CHANGE END: BETTER PRIZES.
- var/atom/movable/the_prize = new prizeselect(get_turf(src))
- playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
- visible_message(span_notice("[src] dispenses [the_prize]!"), span_notice("You hear a chime and a clunk."))
-
-/obj/machinery/computer/arcade/emp_act(severity)
- . = ..()
- var/override = FALSE
- if(prize_override)
- override = TRUE
-
- if(machine_stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
- return
-
- var/empprize = null
- var/num_of_prizes = 0
- switch(severity)
- if(1)
- num_of_prizes = rand(1,4)
- if(2)
- num_of_prizes = rand(0,2)
- for(var/i = num_of_prizes; i > 0; i--)
- if(override)
- empprize = pick_weight(prize_override)
- else
- //BUBBERSTATION CHANGE START: BETTER PRIZES.
- empprize = pick_weight(GLOB.arcade_prize_pool)
- while(islist(empprize))
- empprize = pick_weight(empprize)
- //BUBBERSTATION CHANGE END: BETTER PRIZES.
- new empprize(loc)
- explosion(src, devastation_range = -1, light_impact_range = 1+num_of_prizes, flame_range = 1+num_of_prizes)
-
-/obj/machinery/computer/arcade/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- . = ..()
- if(. & ITEM_INTERACT_ANY_BLOCKER)
- return .
- if(!istype(tool, /obj/item/stack/arcadeticket))
- return .
-
- var/obj/item/stack/arcadeticket/tickets = tool
- // BUBBER EDIT START - MAKES MACHINES USE 1 TICKET
- if(!tickets.use(1))
- balloon_alert(user, "need 1 tickets!")
- return ITEM_INTERACT_BLOCKING
- //BUBBER EDIT END
-
- prizevend(user)
- balloon_alert(user, "prize claimed")
- return ITEM_INTERACT_SUCCESS
-
-// ** BATTLE ** //
-/obj/machinery/computer/arcade/battle
- name = "arcade machine"
- desc = "Does not support Pinball."
- icon_state = "arcade"
- circuit = /obj/item/circuitboard/computer/arcade/battle
-
- interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE // we don't need to be literate to play video games fam
-
- var/enemy_name = "Space Villain"
- ///Enemy health/attack points
- var/enemy_hp = 100
- var/enemy_mp = 40
- ///Temporary message, for attack messages, etc
- var/temp = "
Winners don't use space drugs
"
- ///the list of passive skill the enemy currently has. the actual passives are added in the enemy_setup() proc
- var/list/enemy_passive
- ///if all the enemy's weakpoints have been triggered becomes TRUE
- var/finishing_move = FALSE
- ///linked to passives, when it's equal or above the max_passive finishing move will become TRUE
- var/pissed_off = 0
- ///the number of passives the enemy will start with
- var/max_passive = 3
- ///weapon wielded by the enemy, the shotgun doesn't count.
- var/chosen_weapon
-
- ///Player health
- var/player_hp = 85
- ///player magic points
- var/player_mp = 20
- ///used to remember the last three move of the player before this turn.
- var/list/last_three_move
- ///if the enemy or player died. restart the game when TRUE
- var/gameover = FALSE
- ///the player cannot make any move while this is set to TRUE. should only TRUE during enemy turns.
- var/blocked = FALSE
- ///used to clear the enemy_action proc timer when the game is restarted
- var/timer_id
- ///weapon used by the enemy, pure fluff.for certain actions
- var/list/weapons
- ///unique to the emag mode, acts as a time limit where the player dies when it reaches 0.
- var/bomb_cooldown = 19
-
-
-///creates the enemy base stats for a new round along with the enemy passives
-/obj/machinery/computer/arcade/battle/proc/enemy_setup(player_skill)
- player_hp = 85
- player_mp = 20
- enemy_hp = 100
- enemy_mp = 40
- gameover = FALSE
- blocked = FALSE
- finishing_move = FALSE
- pissed_off = 0
- last_three_move = null
-
- enemy_passive = list("short_temper" = TRUE, "poisonous" = TRUE, "smart" = TRUE, "shotgun" = TRUE, "magical" = TRUE, "chonker" = TRUE)
- for(var/i = LAZYLEN(enemy_passive); i > max_passive; i--) //we'll remove passives from the list until we have the number of passive we want
- var/picked_passive = pick(enemy_passive)
- LAZYREMOVE(enemy_passive, picked_passive)
-
- if(LAZYACCESS(enemy_passive, "chonker"))
- enemy_hp += 20
-
- if(LAZYACCESS(enemy_passive, "shotgun"))
- chosen_weapon = "shotgun"
- else if(weapons)
- chosen_weapon = pick(weapons)
- else
- chosen_weapon = "null gun" //if the weapons list is somehow empty, shouldn't happen but runtimes are sneaky bastards.
-
- if(player_skill)
- player_hp += player_skill * 2
-
-
-/obj/machinery/computer/arcade/battle/Reset()
- max_passive = 3
- var/name_action
- var/name_part1
- var/name_part2
-
- if(check_holidays(HALLOWEEN))
- name_action = pick_list(ARCADE_FILE, "rpg_action_halloween")
- name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_halloween")
- name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_halloween")
- weapons = strings(ARCADE_FILE, "rpg_weapon_halloween")
- else if(check_holidays(CHRISTMAS))
- name_action = pick_list(ARCADE_FILE, "rpg_action_xmas")
- name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_xmas")
- name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_xmas")
- weapons = strings(ARCADE_FILE, "rpg_weapon_xmas")
- else if(check_holidays(VALENTINES))
- name_action = pick_list(ARCADE_FILE, "rpg_action_valentines")
- name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_valentines")
- name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_valentines")
- weapons = strings(ARCADE_FILE, "rpg_weapon_valentines")
- else
- name_action = pick_list(ARCADE_FILE, "rpg_action")
- name_part1 = pick_list(ARCADE_FILE, "rpg_adjective")
- name_part2 = pick_list(ARCADE_FILE, "rpg_enemy")
- weapons = strings(ARCADE_FILE, "rpg_weapon")
-
- enemy_name = ("The " + name_part1 + " " + name_part2)
- name = (name_action + " " + enemy_name)
-
- enemy_setup(0) //in the case it's reset we assume the player skill is 0 because the VOID isn't a gamer
-
-
-/obj/machinery/computer/arcade/battle/ui_interact(mob/user)
- . = ..()
- screen_setup(user)
-
-
-///sets up the main screen for the user
-/obj/machinery/computer/arcade/battle/proc/screen_setup(mob/user)
- var/dat = "Close"
- dat += "
"
- if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode.
- var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
- popup.set_content(dat)
- popup.open()
-
-
-/obj/machinery/computer/arcade/battle/Topic(href, href_list)
- if(..())
- return
- var/gamerSkill = 0
- if(usr?.mind)
- gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
-
- usr.played_game()
-
- if (!blocked && !gameover)
- var/attackamt = rand(5,7) + rand(0, gamerSkill)
-
- if(finishing_move) //time to bonk that fucker,cuban pete will sometime survive a finishing move.
- attackamt *= 100
-
- //light attack suck absolute ass but it doesn't cost any MP so it's pretty good to finish an enemy off
- if (href_list["attack"])
- temp = "
you do quick jab for [attackamt] of damage!
"
- enemy_hp -= attackamt
- arcade_action(usr,"attack",attackamt)
-
- //defend lets you gain back MP and take less damage from non magical attack.
- else if(href_list["defend"])
- temp = "
you take a defensive stance and gain back 10 mp!
"
- player_mp += 10
- arcade_action(usr,"defend",attackamt)
- playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
-
- //mainly used to counter short temper and their absurd damage, will deal twice the damage the player took of a non magical attack.
- else if(href_list["counter_attack"] && player_mp >= 10)
- temp = "
"
-
- if(obj_flags & EMAGGED)
- Reset()
- obj_flags &= ~EMAGGED
-
- enemy_setup(gamerSkill)
- screen_setup(usr)
-
-
- add_fingerprint(usr)
- return
-
-
-///happens after a player action and before the enemy turn. the enemy turn will be cancelled if there's a gameover.
-/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user,player_stance,attackamt)
- screen_setup(user)
- blocked = TRUE
- if(player_stance == "attack" || player_stance == "power_attack")
- if(attackamt > 40)
- playsound(src, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
- else
- playsound(src, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
-
- timer_id = addtimer(CALLBACK(src, PROC_REF(enemy_action),player_stance,user),1 SECONDS,TIMER_STOPPABLE)
- gameover_check(user)
-
-
-///the enemy turn, the enemy's action entirely depend on their current passive and a teensy tiny bit of randomness
-/obj/machinery/computer/arcade/battle/proc/enemy_action(player_stance,mob/user)
- var/list/list_temp = list()
-
- switch(LAZYLEN(last_three_move)) //we keep the last three action of the player in a list here
- if(0 to 2)
- LAZYADD(last_three_move, player_stance)
- if(3)
- for(var/i in 1 to 2)
- last_three_move[i] = last_three_move[i + 1]
- last_three_move[3] = player_stance
-
- if(4 to INFINITY)
- last_three_move = null //this shouldn't even happen but we empty the list if it somehow goes above 3
-
- var/enemy_stance
- var/attack_amount = rand(8,10) //making the attack amount not vary too much so that it's easier to see if the enemy has a shotgun
-
- if(player_stance == "defend")
- attack_amount -= 5
-
- //if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies
- if(obj_flags & EMAGGED)
- switch(bomb_cooldown--)
- if(18)
- list_temp += "
[enemy_name] takes two valve tank and links them together, what's he planning?
"
- if(15)
- list_temp += "
[enemy_name] adds a remote control to the tan- ho god is that a bomb?
"
- if(12)
- list_temp += "
[enemy_name] throws the bomb next to you, you'r too scared to pick it up.
"
- if(6)
- list_temp += "
[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat.
"
- if(2)
- list_temp += "
[enemy_name] is going to press the button! It's now or never!
"
- if(0)
- player_hp -= attack_amount * 1000 //hey it's a maxcap we might as well go all in
-
- //yeah I used the shotgun as a passive, you know why? because the shotgun gives +5 attack which is pretty good
- if(LAZYACCESS(enemy_passive, "shotgun"))
- if(weakpoint_check("shotgun","defend","defend","power_attack"))
- list_temp += "
You manage to disarm [enemy_name] with a surprise power attack and shoot him with his shotgun until it runs out of ammo!
"
- enemy_hp -= 10
- chosen_weapon = "empty shotgun"
- else
- attack_amount += 5
-
- //heccing chonker passive, only gives more HP at the start of a new game but has one of the hardest weakpoint to trigger.
- if(LAZYACCESS(enemy_passive, "chonker"))
- if(weakpoint_check("chonker","power_attack","power_attack","power_attack"))
- list_temp += "
After a lot of power attacks you manage to tip over [enemy_name] as they fall over their enormous weight
"
- enemy_hp -= 30
-
- //smart passive trait, mainly works in tandem with other traits, makes the enemy unable to be counter_attacked
- if(LAZYACCESS(enemy_passive, "smart"))
- if(weakpoint_check("smart","defend","defend","attack"))
- list_temp += "
[enemy_name] is confused by your illogical strategy!
"
- if(LAZYACCESS(enemy_passive, "short_temper"))
- list_temp += "However controlling their hatred of you still takes a toll on their mental and physical health!"
- enemy_hp -= 5
- enemy_mp -= 5
- enemy_stance = "defensive"
-
- //short temper passive trait, gets easily baited into being counter attacked but will bypass your counter when low on HP
- if(LAZYACCESS(enemy_passive, "short_temper"))
- if(weakpoint_check("short_temper","counter_attack","counter_attack","counter_attack"))
- list_temp += "
[enemy_name] is getting frustrated at all your counter attacks and throws a tantrum!
[enemy_name] took the bait and allowed you to counter attack for [attack_amount * 2] damage!
"
- player_hp -= attack_amount
- enemy_hp -= attack_amount * 2
- enemy_stance = "attack"
-
- else if(enemy_hp <= 30) //will break through the counter when low enough on HP even when smart.
- list_temp += "
[enemy_name] is getting tired of your tricks and breaks through your counter with their [chosen_weapon]!
"
- player_hp -= attack_amount
- enemy_stance = "attack"
-
- else if(!enemy_stance)
- var/added_temp
-
- if(rand())
- added_temp = "you for [attack_amount + 5] damage!"
- player_hp -= attack_amount + 5
- enemy_stance = "attack"
- else
- added_temp = "the wall, breaking their skull in the process and losing [attack_amount] hp!" //[enemy_name] you have a literal dent in your skull
- enemy_hp -= attack_amount
- enemy_stance = "attack"
-
- list_temp += "
[enemy_name] grits their teeth and charge right into [added_temp]
"
-
- //in the case none of the previous passive triggered, Mainly here to set an enemy stance for passives that needs it like the magical passive.
- if(!enemy_stance)
- enemy_stance = pick("attack","defensive")
- if(enemy_stance == "attack")
- player_hp -= attack_amount
- list_temp += "
[enemy_name] attacks you for [attack_amount] points of damage with their [chosen_weapon]
[enemy_name]'s magical nature lets them get some mp back!
"
- enemy_mp += attack_amount
-
- //poisonous passive trait, while it's less damage added than the shotgun it acts up even when the enemy doesn't attack at all.
- if(LAZYACCESS(enemy_passive, "poisonous"))
- if(weakpoint_check("poisonous","attack","attack","attack"))
- list_temp += "
your flurry of attack throws back the poisonnous gas at [enemy_name] and makes them choke on it!
"
- enemy_hp -= 5
- else
- list_temp += "
the stinky breath of [enemy_name] hurts you for 3 hp!
"
- player_hp -= 3
-
- //if all passive's weakpoint have been triggered, set finishing_move to TRUE
- if(pissed_off >= max_passive && !finishing_move)
- list_temp += "
You have weakened [enemy_name] enough for them to show their weak point, you will do 10 times as much damage with your next attack!
"
- finishing_move = TRUE
-
- playsound(src, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
-
- temp = list_temp.Join()
- gameover_check(user)
- screen_setup(user)
- blocked = FALSE
-
-
-/obj/machinery/computer/arcade/battle/proc/gameover_check(mob/user)
- var/xp_gained = 0
- if(enemy_hp <= 0)
- if(!gameover)
- if(timer_id)
- deltimer(timer_id)
- timer_id = null
- if(player_hp <= 0)
- player_hp = 1 //let's just pretend the enemy didn't kill you so not both the player and enemy look dead.
- gameover = TRUE
- blocked = FALSE
- temp = "
[enemy_name] has fallen! Rejoice!
"
- playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
-
- if(obj_flags & EMAGGED)
- new /obj/effect/spawner/newbomb/plasma(loc, /obj/item/assembly/timer)
- new /obj/item/clothing/head/collectable/petehat(loc)
- message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.")
- usr.log_message("outbombed Cuban Pete and has been awarded a bomb.", LOG_GAME)
- Reset()
- obj_flags &= ~EMAGGED
- xp_gained += 100
- else
- new /obj/item/stack/arcadeticket((get_turf(src)), 2)
- to_chat(user, span_notice("[src] dispenses 2 tickets!"))
- xp_gained += 50
- SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
- user.won_game()
-
- else if(player_hp <= 0)
- if(timer_id)
- deltimer(timer_id)
- timer_id = null
- gameover = TRUE
- temp = "
You have been crushed! GAME OVER
"
- playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE)
- xp_gained += 10//pity points
- if(obj_flags & EMAGGED)
- var/mob/living/living_user = user
- if (istype(living_user))
- living_user.investigate_log("has been gibbed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
- living_user.gib(DROP_ALL_REMAINS)
- SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
- user.lost_game()
-
- if(gameover)
- user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP
-
-
-///used to check if the last three move of the player are the one we want in the right order and if the passive's weakpoint has been triggered yet
-/obj/machinery/computer/arcade/battle/proc/weakpoint_check(passive,first_move,second_move,third_move)
- if(LAZYLEN(last_three_move) < 3)
- return FALSE
-
- if(last_three_move[1] == first_move && last_three_move[2] == second_move && last_three_move[3] == third_move && LAZYACCESS(enemy_passive, passive))
- LAZYREMOVE(enemy_passive, passive)
- pissed_off++
- return TRUE
- else
- return FALSE
-
-
-/obj/machinery/computer/arcade/battle/Destroy()
- enemy_passive = null
- weapons = null
- last_three_move = null
- return ..() //well boys we did it, lists are no more
-
-/obj/machinery/computer/arcade/battle/examine_more(mob/user)
- . = ..()
- . += span_notice("You notice some writing scribbled on the side of [src]...")
- . += "\t[span_info("smart -> defend, defend, light attack")]"
- . += "\t[span_info("shotgun -> defend, defend, power attack")]"
- . += "\t[span_info("short temper -> counter, counter, counter")]"
- . += "\t[span_info("poisonous -> light attack, light attack, light attack")]"
- . += "\t[span_info("chonker -> power attack, power attack, power attack")]"
- . += "\t[span_info("magical -> defend until outmagiced")]"
- return .
-
-/obj/machinery/computer/arcade/battle/emag_act(mob/user, obj/item/card/emag/emag_card)
- if(obj_flags & EMAGGED)
- return FALSE
-
- balloon_alert(user, "hard mode enabled")
- to_chat(user, span_warning("A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!"))
- temp = "
If you die in the game, you die for real!
"
- max_passive = 6
- bomb_cooldown = 18
- var/gamerSkill = 0
- if(user?.mind)
- gamerSkill = user.mind.get_skill_level(/datum/skill/gaming)
- enemy_setup(gamerSkill)
- enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
- player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance
-
- screen_setup(user)
- gameover = FALSE
-
- obj_flags |= EMAGGED
-
- enemy_name = "Cuban Pete"
- name = "Outbomb Cuban Pete"
-
- updateUsrDialog()
- return TRUE
-
-// ** AMPUTATION ** //
-
-/obj/machinery/computer/arcade/amputation
- name = "Mediborg's Amputation Adventure"
- desc = "A picture of a blood-soaked medical cyborg flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\""
- icon_state = "arcade"
- circuit = /obj/item/circuitboard/computer/arcade/amputation
-
-/obj/machinery/computer/arcade/amputation/attack_tk(mob/user)
- return //that's a pretty damn big guillotine
-
-/obj/machinery/computer/arcade/amputation/attack_hand(mob/user, list/modifiers)
- . = ..()
- if(!iscarbon(user))
- return
- to_chat(user, span_warning("You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it..."))
- user.played_game()
- var/obj/item/bodypart/chopchop = user.get_active_hand()
- if(do_after(user, 5 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(do_they_still_have_that_hand), user, chopchop)))
- playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1)
- to_chat(user, span_userdanger("The guillotine drops on your arm, and the machine sucks it in!"))
- chopchop.dismember()
- qdel(chopchop)
- user.mind?.adjust_experience(/datum/skill/gaming, 100)
- user.won_game()
- playsound(src, 'sound/arcade/win.ogg', 50, TRUE)
- new /obj/item/stack/arcadeticket((get_turf(src)), rand(6,10))
- to_chat(user, span_notice("[src] dispenses a handful of tickets!"))
- return
- else if(!do_they_still_have_that_hand(user, chopchop))
- to_chat(user, span_warning("The guillotine drops, but your hand seems to be gone already!"))
- playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1)
- else
- to_chat(user, span_notice("You (wisely) decide against putting your hand in the machine."))
- user.lost_game()
-
-///Makes sure the user still has their starting hand.
-/obj/machinery/computer/arcade/amputation/proc/do_they_still_have_that_hand(mob/user, obj/item/bodypart/chopchop)
- if(QDELETED(chopchop) || chopchop.owner != user) //No pulling your arm out of the machine!
- return FALSE
- return TRUE
-
-
-/obj/machinery/computer/arcade/amputation/festive //dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree
- name = "Mediborg's Festive Amputation Adventure"
- desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\""
- prize_override = list(/obj/item/gift/anything = 1)
diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm
new file mode 100644
index 00000000000..63d2808c773
--- /dev/null
+++ b/code/game/machinery/computer/arcade/battle.dm
@@ -0,0 +1,559 @@
+///How many enemies needs to be defeated until the 'Boss' of the stage appears.
+#define WORLD_ENEMY_BOSS 2
+///The default amount of EXP you gain from killing an enemy, modifiers stacked on top of this.
+#define DEFAULT_EXP_GAIN 50
+///The default cost to purchase an item. Sleeping at the Inn is half of this.
+#define DEFAULT_ITEM_PRICE 30
+
+///The max HP the player can have at any time.
+#define PLAYER_MAX_HP 100
+///The max MP the player can have at any time.
+#define PLAYER_MAX_MP 50
+///The default cost of a spell, in MP. Defending will instead restore this amount.
+#define SPELL_MP_COST 10
+
+///The player is currently in the Shop.
+#define UI_PANEL_SHOP "Shop"
+///The player is currently in the World Map.
+#define UI_PANEL_WORLD_MAP "World Map"
+///The player is currently in Batle.
+#define UI_PANEL_BATTLE "Battle"
+///The player is currently between battles.
+#define UI_PANEL_BETWEEN_FIGHTS "Between Battle"
+///The player is currently Game Overed.
+#define UI_PANEL_GAMEOVER "Game Over"
+
+///The player is set to counterattack the enemy's next move.
+#define BATTLE_ATTACK_FLAG_COUNTERATTACK (1<<0)
+///The player is set to defend against the enemy's next move.
+#define BATTLE_ATTACK_FLAG_DEFEND (1<<1)
+
+///The player is trying to Attack the Enemy.
+#define BATTLE_ARCADE_PLAYER_ATTACK "Attack"
+///The player is trying to Attack the Enemy with an MP boost.
+#define BATTLE_ARCADE_PLAYER_HEAVY_ATTACK "Heavy Attack"
+///The player is setting themselves to counterattack a potential incoming Enemy attack.
+#define BATTLE_ARCADE_PLAYER_COUNTERATTACK "Counterattack"
+///The player is defending against the Enemy and restoring MP.
+#define BATTLE_ARCADE_PLAYER_DEFEND "Defend"
+
+/obj/machinery/computer/arcade/battle
+ name = "battle arcade"
+ desc = "Explore vast worlds and conquer."
+ icon_state = "arcade"
+ icon_screen = "fighters"
+ circuit = /obj/item/circuitboard/computer/arcade/battle
+
+ ///List of all battle arcade gear that is available in the shop in game.
+ var/static/list/battle_arcade_gear_list
+ ///List of all worlds in the game.
+ var/static/list/all_worlds = list(
+ BATTLE_WORLD_ONE = 1,
+ BATTLE_WORLD_TWO = 1.25,
+ BATTLE_WORLD_THREE = 1.5,
+ BATTLE_WORLD_FOUR = 1.75,
+ BATTLE_WORLD_FIVE = 2,
+ BATTLE_WORLD_SIX = 2.25,
+ BATTLE_WORLD_SEVEN = 2.5,
+ BATTLE_WORLD_EIGHT = 2.75,
+ BATTLE_WORLD_NINE = 3,
+ )
+ var/static/list/all_attack_types = list(
+ BATTLE_ARCADE_PLAYER_ATTACK = "Attack the enemy in a default attack at no MP cost.",
+ BATTLE_ARCADE_PLAYER_HEAVY_ATTACK = "Attack the enemy with the power of Magic, costing MP for additional damage.",
+ BATTLE_ARCADE_PLAYER_COUNTERATTACK = "Use magic to prepare a counterattack of your enemy, allowing you to deal extra damage if you succeed.",
+ BATTLE_ARCADE_PLAYER_DEFEND = "Defend from the next incoming attack, lowing the amount of damage you take while restoring some HP and MP.",
+ )
+ ///The world we're currently in.
+ var/player_current_world = BATTLE_WORLD_ONE
+ ///The latest world the player has unlocked, granting access to all worlds below this.
+ var/latest_unlocked_world = BATTLE_WORLD_ONE
+ ///How many enemies we've defeated in a row, used to tell when we need to spawn the boss in.
+ var/enemies_defeated
+ ///The current panel the player is viewieng in the UI.
+ var/ui_panel = UI_PANEL_WORLD_MAP
+
+ /** PLAYER INFORMATION */
+
+ ///Boolean on whether it's the player's time to do their turn.
+ var/player_turn = TRUE
+ ///How much money the player has, used in the Inn. Starts with the default price for a single item.
+ var/player_gold = DEFAULT_ITEM_PRICE
+ ///The current amount of HP the player has.
+ var/player_current_hp = PLAYER_MAX_HP
+ ///The current amount of MP the player has.
+ var/player_current_mp = PLAYER_MAX_MP
+ ///Assoc list of gear the player has equipped.
+ var/list/datum/battle_arcade_gear/equipped_gear = list(
+ WEAPON_SLOT = null,
+ ARMOR_SLOT = null,
+ )
+
+ /** CURRENT ENEMY INFORMATION */
+
+ ///A feedback message displayed in the UI during combat sequences.
+ var/feedback_message
+ ///Determines which boss image to use on the UI.
+ var/enemy_icon_id = 1
+ ///The enemy's name
+ var/enemy_name
+ ///How much HP the current enemy has.
+ var/enemy_max_hp
+ ///How much HP the current enemy has.
+ var/enemy_hp
+ ///How much MP the current enemy has.
+ var/enemy_mp
+ ///How much gold the enemy will drop, randomized on new opponent.
+ var/enemy_gold_reward
+ ///unique to the emag mode, acts as a time limit where the player dies when it reaches 0.
+ var/bomb_cooldown = 19
+
+/obj/machinery/computer/arcade/battle/Initialize(mapload, obj/item/circuitboard/C)
+ . = ..()
+ if(isnull(battle_arcade_gear_list))
+ var/list/all_gear = list()
+ for(var/datum/battle_arcade_gear/template as anything in subtypesof(/datum/battle_arcade_gear))
+ if(!(template::slot)) //needs to fit in something.
+ continue
+ all_gear[template::name] = new template
+ battle_arcade_gear_list = all_gear
+
+/obj/machinery/computer/arcade/battle/emag_act(mob/user, obj/item/card/emag/emag_card)
+ if(obj_flags & EMAGGED)
+ return FALSE
+ obj_flags |= EMAGGED
+ balloon_alert(user, "hard mode enabled")
+ to_chat(user, span_warning("A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!"))
+ setup_new_opponent()
+ feedback_message = "If you die in the game, you die for real!"
+ SStgui.update_uis(src)
+ return TRUE
+
+/obj/machinery/computer/arcade/battle/reset_cabinet(mob/living/user)
+ enemy_name = null
+ player_turn = initial(player_turn)
+ feedback_message = initial(feedback_message)
+ player_current_world = initial(player_current_world)
+ latest_unlocked_world = initial(latest_unlocked_world)
+ enemies_defeated = initial(enemies_defeated)
+ player_gold = initial(player_gold)
+ player_current_hp = initial(player_current_hp)
+ player_current_mp = initial(player_current_mp)
+ ui_panel = initial(ui_panel)
+ bomb_cooldown = initial(bomb_cooldown)
+ equipped_gear = list(WEAPON_SLOT = null, ARMOR_SLOT = null)
+ return ..()
+
+///Sets up a new opponent depending on what stage they are at.
+/obj/machinery/computer/arcade/battle/proc/setup_new_opponent(enemy_gets_first_move = FALSE)
+ var/name_adjective
+ var/new_name
+
+ if(check_holidays(HALLOWEEN))
+ name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_halloween")
+ new_name = pick_list(ARCADE_FILE, "rpg_enemy_halloween")
+ else if(check_holidays(CHRISTMAS))
+ name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_xmas")
+ new_name = pick_list(ARCADE_FILE, "rpg_enemy_xmas")
+ else if(check_holidays(VALENTINES))
+ name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_valentines")
+ new_name = pick_list(ARCADE_FILE, "rpg_enemy_valentines")
+ else
+ name_adjective = pick_list(ARCADE_FILE, "rpg_adjective")
+ new_name = pick_list(ARCADE_FILE, "rpg_enemy")
+
+ enemy_hp = round(rand(90, 125) * all_worlds[player_current_world], 1)
+ enemy_mp = round(rand(20, 30) * all_worlds[player_current_world], 1)
+ enemy_gold_reward = rand((DEFAULT_ITEM_PRICE / 2), DEFAULT_ITEM_PRICE)
+
+ // there's only one boss in each stage (except the last)
+ if((player_current_world == latest_unlocked_world) && enemies_defeated == WORLD_ENEMY_BOSS)
+ enemy_mp *= 1.25
+ enemy_hp *= 1.25
+ enemy_gold_reward *= 1.5
+ name_adjective = "Big Boss"
+
+ enemy_icon_id = rand(1,6)
+ enemy_name = "The [name_adjective] [new_name]"
+ feedback_message = "New game started against [enemy_name]"
+
+ if(obj_flags & EMAGGED)
+ enemy_name = "Cuban Pete"
+ enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
+
+ //set max HP to reference later
+ enemy_max_hp = enemy_hp
+ //set the player to fight now.
+ ui_panel = UI_PANEL_BATTLE
+
+ if(enemy_gets_first_move)
+ perform_enemy_turn()
+
+/**
+ * on_battle_win
+ *
+ * Called when the player wins a level, this handles giving EXP, loot, tickets, etc.
+ * It also handles clearing the enemy out for the next one, and unlocking new worlds.
+ * We stop at BATTLE_WORLD_NINE because it is the last stage, and has infinite bosses.
+ */
+/obj/machinery/computer/arcade/battle/proc/on_battle_win(mob/user)
+ enemy_name = null
+ feedback_message = null
+ player_turn = TRUE
+ if(player_current_world == latest_unlocked_world)
+ if(enemies_defeated == WORLD_ENEMY_BOSS)
+ enemies_defeated = 0
+ //the last stage doesn't have a next one to move onto.
+ if(latest_unlocked_world != BATTLE_WORLD_NINE)
+ var/current_world = all_worlds.Find(latest_unlocked_world)
+ latest_unlocked_world = all_worlds[current_world + 1]
+ ui_panel = UI_PANEL_WORLD_MAP
+ say("New world unlocked, [latest_unlocked_world]!")
+ enemies_defeated++
+ if(obj_flags & EMAGGED)
+ obj_flags &= ~EMAGGED
+ bomb_cooldown = initial(bomb_cooldown)
+ new /obj/effect/spawner/newbomb/plasma(loc, /obj/item/assembly/timer)
+ new /obj/item/clothing/head/collectable/petehat(loc)
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.")
+ usr.log_message("outbombed Cuban Pete and has been awarded a bomb.", LOG_GAME)
+ else
+ visible_message(span_notice("[src] dispenses 2 tickets!"))
+ new /obj/item/stack/arcadeticket((get_turf(src)), 2)
+ player_gold += enemy_gold_reward
+ if(user)
+ var/exp_gained = DEFAULT_EXP_GAIN * all_worlds[player_current_world]
+ user.mind?.adjust_experience(/datum/skill/gaming, exp_gained)
+ user.won_game()
+ SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
+ playsound(loc, 'sound/arcade/win.ogg', 40)
+ if(ui_panel != UI_PANEL_WORLD_MAP) //we havent been booted to world map, we're still going.
+ ui_panel = UI_PANEL_BETWEEN_FIGHTS
+
+///Called when a mob loses at the battle arcade.
+/obj/machinery/computer/arcade/battle/proc/lose_game(mob/user)
+ if(obj_flags & EMAGGED)
+ var/mob/living/living_user = user
+ if(istype(living_user))
+ living_user.investigate_log("has been gibbed by an emagged Orion Trail game.", INVESTIGATE_DEATHS)
+ living_user.gib(DROP_ALL_REMAINS)
+ user.lost_game()
+ SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
+ SStgui.update_uis(src)
+
+///Called when the enemy attacks you.
+/obj/machinery/computer/arcade/battle/proc/user_take_damage(mob/user, base_damage_taken)
+ var/datum/battle_arcade_gear/armor = equipped_gear[ARMOR_SLOT]
+ var/damage_taken = (base_damage_taken * all_worlds[player_current_world]) / (!isnull(armor) ? armor.bonus_modifier : 1)
+ player_current_hp -= round(max(0, damage_taken), 1)
+ if(player_current_hp <= 0)
+ ui_panel = UI_PANEL_GAMEOVER
+ feedback_message = "GAME OVER."
+ say("You have been crushed! GAME OVER.")
+ playsound(loc, 'sound/arcade/lose.ogg', 40, TRUE)
+ lose_game(user)
+ else
+ feedback_message = "User took [damage_taken] damage!"
+ playsound(loc, 'sound/arcade/hit.ogg', 40, TRUE, extrarange = -3)
+ SStgui.update_uis(src)
+
+///Called when you attack the enemy.
+/obj/machinery/computer/arcade/battle/proc/process_player_attack(mob/user, attack_type)
+ var/damage_dealt
+ switch(attack_type)
+ if(BATTLE_ARCADE_PLAYER_ATTACK)
+ var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT]
+ damage_dealt = (rand(5, 15) * (!isnull(weapon) ? weapon.bonus_modifier : 1))
+ if(BATTLE_ARCADE_PLAYER_HEAVY_ATTACK)
+ var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT]
+ damage_dealt = (rand(15, 25) * (!isnull(weapon) ? weapon.bonus_modifier : 1))
+ if(BATTLE_ARCADE_PLAYER_COUNTERATTACK)
+ feedback_message = "User prepares to counterattack!"
+ process_enemy_turn(user, defending_flags = BATTLE_ATTACK_FLAG_COUNTERATTACK)
+ playsound(loc, 'sound/arcade/mana.ogg', 40, TRUE, extrarange = -3)
+ if(BATTLE_ARCADE_PLAYER_DEFEND)
+ feedback_message = "User pulls up their shield!"
+ process_enemy_turn(user, defending_flags = BATTLE_ATTACK_FLAG_DEFEND)
+ playsound(loc, 'sound/arcade/mana.ogg', 40, TRUE, extrarange = -3)
+
+ if(!damage_dealt)
+ return
+ enemy_hp -= round(max(0, damage_dealt), 1)
+ feedback_message = "[enemy_name] took [damage_dealt] damage!"
+ playsound(loc, 'sound/arcade/hit.ogg', 40, TRUE, extrarange = -3)
+ process_enemy_turn(user)
+
+///Called when you successfully counterattack the enemy.
+/obj/machinery/computer/arcade/battle/proc/successful_counterattack(mob/user)
+ var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT]
+ var/damage_dealt = (rand(20, 30) * (!isnull(weapon) ? weapon.bonus_modifier : 1))
+ enemy_hp -= round(max(0, damage_dealt), 1)
+ feedback_message = "User counterattacked for [damage_dealt] damage!"
+ playsound(loc, 'sound/arcade/boom.ogg', 40, TRUE, extrarange = -3)
+ if(enemy_hp <= 0)
+ on_battle_win(user)
+ SStgui.update_uis(src)
+
+///Handles the delay between the user's and enemy's turns to process what's going on.
+/obj/machinery/computer/arcade/battle/proc/process_enemy_turn(mob/user, defending_flags = NONE)
+ if(enemy_hp <= 0)
+ return on_battle_win(user)
+ //if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies
+
+ if(obj_flags & EMAGGED)
+ bomb_cooldown--
+ switch(bomb_cooldown)
+ if(18)
+ feedback_message = "[enemy_name] takes two valve tank and links them together, what's he planning?"
+ if(15)
+ feedback_message = "[enemy_name] adds a remote control to the tan- ho god is that a bomb?"
+ if(12)
+ feedback_message = "[enemy_name] throws the bomb next to you, you'r too scared to pick it up."
+ if(6)
+ feedback_message = "[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat."
+ if(2)
+ feedback_message = "[enemy_name] is going to press the button! It's now or never!"
+ if(0)
+ player_current_hp = 0 //instant death
+ addtimer(CALLBACK(src, PROC_REF(perform_enemy_turn), user, defending_flags), 1 SECONDS)
+
+/**
+ * perform_enemy_turn
+ *
+ * Actually performs the enemy's turn.
+ * We first roll to see if the enemy should use magic. As their HP goes lower, the chances of self healing goes higher, but
+ * if they lack the MP, then it's rolling to steal MP from the player.
+ * After, we will roll to see if the player counterattacks the enemy (if set), otherwise we will attack normally.
+ */
+/obj/machinery/computer/arcade/battle/proc/perform_enemy_turn(mob/user, defending_flags = NONE)
+ player_turn = TRUE
+ var/chance_to_magic = round(max((-(enemy_hp - enemy_max_hp) / 2), 75), 1)
+ if((enemy_hp != enemy_max_hp) && prob(chance_to_magic))
+ if(enemy_mp >= 10)
+ var/healed_amount = rand(10, 20)
+ enemy_hp = round(min(enemy_max_hp, enemy_hp + healed_amount), 1)
+ enemy_mp -= round(max(0, 10), 1)
+ feedback_message = "[enemy_name] healed for [healed_amount] health points!"
+ playsound(loc, 'sound/arcade/heal.ogg', 40, TRUE, extrarange = -3)
+ SStgui.update_uis(src)
+ return
+ if(player_current_mp >= 5) //minimum to steal
+ var/healed_amount = rand(5, 10)
+ player_current_mp -= round(max(0, healed_amount), 1)
+ enemy_mp += healed_amount
+ feedback_message = "[enemy_name] stole [healed_amount] MP from you!"
+ playsound(loc, 'sound/arcade/steal.ogg', 40, TRUE)
+ SStgui.update_uis(src)
+ return
+ //we couldn't heal ourselves or steal MP, we'll just attack instead.
+ var/skill_level = user?.mind?.get_skill_level(/datum/skill/gaming) || 1
+ var/chance_at_counterattack = 40 + (skill_level * 5) //at level 1 this is 45, at legendary this is 75
+ var/damage_dealt = (defending_flags & BATTLE_ATTACK_FLAG_DEFEND) ? rand(5, 10) : rand(15, 20)
+ if((defending_flags & BATTLE_ATTACK_FLAG_COUNTERATTACK) && prob(chance_at_counterattack))
+ return successful_counterattack(user)
+ return user_take_damage(user, damage_dealt)
+
+/obj/machinery/computer/arcade/battle/ui_data(mob/user)
+ var/list/data = ..()
+
+ data["feedback_message"] = feedback_message
+ data["shop_items"] = list()
+ for(var/gear_name in battle_arcade_gear_list)
+ var/datum/battle_arcade_gear/gear = battle_arcade_gear_list[gear_name]
+ if(latest_unlocked_world != gear.world_available)
+ continue
+ data["shop_items"] += list(gear_name)
+ data["ui_panel"] = ui_panel
+ data["player_current_world"] = player_current_world
+ data["unlocked_world_modifier"] = all_worlds[latest_unlocked_world]
+ data["latest_unlocked_world_position"] = all_worlds.Find(latest_unlocked_world)
+ data["player_gold"] = player_gold
+ data["player_current_hp"] = player_current_hp
+ data["player_current_mp"] = player_current_mp
+ data["enemy_icon_id"] = "boss[enemy_icon_id].gif"
+ data["enemy_name"] = enemy_name
+ data["enemy_max_hp"] = enemy_max_hp
+ data["enemy_hp"] = enemy_hp
+ data["enemy_mp"] = enemy_mp
+
+ data["equipped_gear"] = list()
+ for(var/gear_slot as anything in equipped_gear)
+ var/datum/battle_arcade_gear/user_gear = equipped_gear[gear_slot]
+ if(!istype(user_gear))
+ continue
+ data["equipped_gear"] += list(list(
+ "name" = user_gear.name,
+ "slot" = gear_slot,
+ ))
+
+ return data
+
+/obj/machinery/computer/arcade/battle/ui_static_data(mob/user)
+ var/list/data = ..()
+
+ data["all_worlds"] = list()
+ for(var/individual_world in all_worlds)
+ UNTYPED_LIST_ADD(data["all_worlds"], individual_world)
+ data["attack_types"] = list()
+ for(var/individual_attack_type in all_attack_types)
+ UNTYPED_LIST_ADD(data["attack_types"], list("name" = individual_attack_type, "tooltip" = all_attack_types[individual_attack_type]))
+ data["cost_of_items"] = DEFAULT_ITEM_PRICE
+ data["max_hp"] = PLAYER_MAX_HP
+ data["max_mp"] = PLAYER_MAX_MP
+
+ return data
+
+/obj/machinery/computer/arcade/battle/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/simple/arcade),
+ )
+
+/obj/machinery/computer/arcade/battle/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "BattleArcade", "Battle Arcade")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/obj/machinery/computer/arcade/battle/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+ var/mob/living/gamer = ui.user
+ if(!istype(gamer))
+ return
+
+ switch(ui_panel)
+ if(UI_PANEL_GAMEOVER)
+ switch(action)
+ if("restart")
+ reset_cabinet()
+ return TRUE
+ if(UI_PANEL_SHOP)
+ switch(action)
+ if("sleep")
+ if(player_gold < DEFAULT_ITEM_PRICE / 2)
+ say("You don't have enough gold to rest!")
+ return TRUE
+ player_gold -= DEFAULT_ITEM_PRICE / 2
+ playsound(loc, 'sound/mecha/skyfall_power_up.ogg', 40)
+ player_current_hp = PLAYER_MAX_HP
+ player_current_mp = PLAYER_MAX_MP
+ return TRUE
+ if("buy_item")
+ var/datum/battle_arcade_gear/gear = battle_arcade_gear_list[params["purchasing_item"]]
+ if(latest_unlocked_world != gear.world_available || equipped_gear[gear.slot] == gear)
+ say("That item is not in stock.")
+ return TRUE
+ if(player_gold < (DEFAULT_ITEM_PRICE * all_worlds[latest_unlocked_world]))
+ say("You don't have enough gold to buy that!")
+ return TRUE
+ player_gold -= DEFAULT_ITEM_PRICE * all_worlds[latest_unlocked_world]
+ equipped_gear[gear.slot] = gear
+ return TRUE
+ if("leave")
+ ui_panel = UI_PANEL_WORLD_MAP
+ return TRUE
+ if(UI_PANEL_WORLD_MAP)
+ switch(action)
+ if("start_fight")
+ var/world_travelling = all_worlds.Find(params["selected_arena"])
+ var/max_unlocked_worlds = all_worlds.Find(latest_unlocked_world)
+ if(world_travelling > max_unlocked_worlds)
+ say("That world is not unlocked yet!")
+ return TRUE
+ player_current_world = all_worlds[world_travelling]
+ setup_new_opponent()
+ return TRUE
+ if("enter_inn")
+ ui_panel = UI_PANEL_SHOP
+ return TRUE
+ if(UI_PANEL_BETWEEN_FIGHTS)
+ switch(action)
+ if("continue_without_rest")
+ setup_new_opponent()
+ return TRUE
+ if("continue_with_rest")
+ if(prob(60))
+ playsound(loc, 'sound/mecha/skyfall_power_up.ogg', 40)
+ player_current_hp = PLAYER_MAX_HP
+ player_current_mp = PLAYER_MAX_MP
+ else
+ playsound(loc, 'sound/machines/defib_zap.ogg', 40)
+ if(prob(40))
+ //You got robbed, and now have to go to your next fight.
+ player_gold /= 2
+ else
+ //You got ambushed, the enemy gets the first hit.
+ setup_new_opponent(enemy_gets_first_move = TRUE)
+ return TRUE
+ setup_new_opponent()
+ return TRUE
+ if("abandon_quest")
+ if(player_current_world == latest_unlocked_world)
+ enemies_defeated = 0
+ ui_panel = UI_PANEL_WORLD_MAP
+ return TRUE
+ if(UI_PANEL_BATTLE)
+ if(!player_turn)
+ return TRUE
+ player_turn = FALSE
+ switch(action)
+ if(BATTLE_ARCADE_PLAYER_ATTACK)
+ process_player_attack(gamer, BATTLE_ARCADE_PLAYER_ATTACK)
+ return TRUE
+ if(BATTLE_ARCADE_PLAYER_HEAVY_ATTACK)
+ if(player_current_mp < SPELL_MP_COST)
+ say("You don't have enough MP to counterattack!")
+ player_turn = TRUE
+ return TRUE
+ player_current_mp -= SPELL_MP_COST
+ process_player_attack(gamer, BATTLE_ARCADE_PLAYER_HEAVY_ATTACK)
+ return TRUE
+ if(BATTLE_ARCADE_PLAYER_COUNTERATTACK)
+ if(player_current_mp < SPELL_MP_COST)
+ say("You don't have enough MP to counterattack!")
+ player_turn = TRUE
+ return TRUE
+ player_current_mp -= SPELL_MP_COST
+ process_player_attack(gamer, BATTLE_ARCADE_PLAYER_COUNTERATTACK)
+ return TRUE
+ if(BATTLE_ARCADE_PLAYER_DEFEND)
+ player_current_hp = round(min(player_current_hp + (SPELL_MP_COST / 2), PLAYER_MAX_HP), 1)
+ player_current_mp = round(min(player_current_mp + SPELL_MP_COST, PLAYER_MAX_MP), 1)
+ process_player_attack(gamer, BATTLE_ARCADE_PLAYER_DEFEND)
+ return TRUE
+ if("flee")
+ //you can't outrun the cuban pete
+ if(obj_flags & EMAGGED)
+ lose_game(gamer)
+ return
+ player_turn = TRUE
+ ui_panel = UI_PANEL_WORLD_MAP
+ player_gold /= 2
+ return TRUE
+ //they pressed something but it wasn't in the menu, we'll be nice and give them back their turn anyway.
+ player_turn = TRUE
+
+#undef WORLD_ENEMY_BOSS
+#undef DEFAULT_EXP_GAIN
+#undef DEFAULT_ITEM_PRICE
+
+#undef PLAYER_MAX_HP
+#undef PLAYER_MAX_MP
+#undef SPELL_MP_COST
+
+#undef UI_PANEL_SHOP
+#undef UI_PANEL_WORLD_MAP
+#undef UI_PANEL_BATTLE
+#undef UI_PANEL_BETWEEN_FIGHTS
+#undef UI_PANEL_GAMEOVER
+
+#undef BATTLE_ATTACK_FLAG_COUNTERATTACK
+#undef BATTLE_ATTACK_FLAG_DEFEND
+
+#undef BATTLE_ARCADE_PLAYER_ATTACK
+#undef BATTLE_ARCADE_PLAYER_HEAVY_ATTACK
+#undef BATTLE_ARCADE_PLAYER_COUNTERATTACK
+#undef BATTLE_ARCADE_PLAYER_DEFEND
diff --git a/code/game/machinery/computer/arcade/battle_gear.dm b/code/game/machinery/computer/arcade/battle_gear.dm
new file mode 100644
index 00000000000..32d1d73dd4f
--- /dev/null
+++ b/code/game/machinery/computer/arcade/battle_gear.dm
@@ -0,0 +1,126 @@
+/datum/battle_arcade_gear
+ ///The name of the gear, used in shops.
+ var/name = "Gear"
+ ///The slot this gear fits into
+ var/slot
+ ///The world the player has to be at in order to buy this item.
+ var/world_available
+ ///The stat given by the gear
+ var/bonus_modifier
+
+/datum/battle_arcade_gear/tier_1
+ world_available = BATTLE_WORLD_ONE
+
+/datum/battle_arcade_gear/tier_1/weapon
+ name = "Sword"
+ slot = WEAPON_SLOT
+ bonus_modifier = 1.5
+
+/datum/battle_arcade_gear/tier_1/armor
+ name = "Leather Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 1.5
+
+/datum/battle_arcade_gear/tier_2
+ world_available = BATTLE_WORLD_TWO
+
+/datum/battle_arcade_gear/tier_2/weapon
+ name = "Axe"
+ slot = WEAPON_SLOT
+ bonus_modifier = 1.75
+
+/datum/battle_arcade_gear/tier_2/armor
+ name = "Chainmail"
+ slot = ARMOR_SLOT
+ bonus_modifier = 1.75
+
+/datum/battle_arcade_gear/tier_3
+ world_available = BATTLE_WORLD_THREE
+
+/datum/battle_arcade_gear/tier_3/weapon
+ name = "Mace"
+ slot = WEAPON_SLOT
+ bonus_modifier = 2
+
+/datum/battle_arcade_gear/tier_3/armor
+ name = "Plate Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 2
+
+/datum/battle_arcade_gear/tier_4
+ world_available = BATTLE_WORLD_FOUR
+
+/datum/battle_arcade_gear/tier_4/weapon
+ name = "Greatsword"
+ slot = WEAPON_SLOT
+ bonus_modifier = 2.5
+
+/datum/battle_arcade_gear/tier_4/armor
+ name = "Full Plate Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 2.5
+
+/datum/battle_arcade_gear/tier_5
+ world_available = BATTLE_WORLD_FIVE
+
+/datum/battle_arcade_gear/tier_5/weapon
+ name = "Halberd"
+ slot = WEAPON_SLOT
+ bonus_modifier = 3
+
+/datum/battle_arcade_gear/tier_5/armor
+ name = "Dragon Scale Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 3
+
+/datum/battle_arcade_gear/tier_6
+ world_available = BATTLE_WORLD_SIX
+
+/datum/battle_arcade_gear/tier_6/weapon
+ name = "Warhammer"
+ slot = WEAPON_SLOT
+ bonus_modifier = 3.5
+
+/datum/battle_arcade_gear/tier_6/armor
+ name = "Adamantine Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 3.5
+
+/datum/battle_arcade_gear/tier_7
+ world_available = BATTLE_WORLD_SEVEN
+
+/datum/battle_arcade_gear/tier_7/weapon
+ name = "Excalibur"
+ slot = WEAPON_SLOT
+ bonus_modifier = 4
+
+/datum/battle_arcade_gear/tier_7/armor
+ name = "Ethereal Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 4
+
+/datum/battle_arcade_gear/tier_8
+ world_available = BATTLE_WORLD_EIGHT
+
+/datum/battle_arcade_gear/tier_8/weapon
+ name = "Gungnir"
+ slot = WEAPON_SLOT
+ bonus_modifier = 4.5
+
+/datum/battle_arcade_gear/tier_8/armor
+ name = "Celestial Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 4.5
+
+/datum/battle_arcade_gear/tier_9
+ world_available = BATTLE_WORLD_NINE
+
+/datum/battle_arcade_gear/tier_9/weapon
+ name = "Mjolnir"
+ slot = WEAPON_SLOT
+ bonus_modifier = 5
+
+/datum/battle_arcade_gear/tier_9/armor
+ name = "Void Armor"
+ slot = ARMOR_SLOT
+ bonus_modifier = 5
diff --git a/code/game/machinery/computer/arcade/orion.dm b/code/game/machinery/computer/arcade/orion.dm
index 945cbb5593a..85bebddd25c 100644
--- a/code/game/machinery/computer/arcade/orion.dm
+++ b/code/game/machinery/computer/arcade/orion.dm
@@ -1,23 +1,13 @@
-// *** THE ORION TRAIL ** //
-
#define ORION_TRAIL_WINTURN 9
-//defines in machines.dm
-
-///assoc list, [datum singleton] = weight
-GLOBAL_LIST_INIT(orion_events, generate_orion_events())
-
-/proc/generate_orion_events()
- . = list()
- for(var/path in subtypesof(/datum/orion_event))
- var/datum/orion_event/new_event = new path(src)
- .[new_event] = new_event.weight
-
/obj/machinery/computer/arcade/orion_trail
name = "The Orion Trail"
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/orion_trail
+
+ ///List of all orion events, created on Initialize.
+ var/static/list/orion_events
var/busy = FALSE //prevent clickspam that allowed people to ~speedrun~ the game.
var/engine = 0
var/hull = 0
@@ -44,12 +34,18 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
/obj/machinery/computer/arcade/orion_trail/Initialize(mapload)
. = ..()
+ if(isnull(orion_events))
+ var/list/events = list()
+ for(var/path in subtypesof(/datum/orion_event))
+ var/datum/orion_event/new_event = new path(src)
+ events[new_event] = new_event.weight
+ orion_events = events
radio = new /obj/item/radio(src)
radio.set_listening(FALSE)
setup_events()
/obj/machinery/computer/arcade/orion_trail/proc/setup_events()
- events = GLOB.orion_events
+ events = orion_events.Copy()
/obj/machinery/computer/arcade/orion_trail/Destroy()
QDEL_NULL(radio)
@@ -81,7 +77,7 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
settlers = list("Kirk","Worf","Gene")
/obj/machinery/computer/arcade/orion_trail/kobayashi/setup_events()
- events = GLOB.orion_events.Copy()
+ events = orion_events.Copy()
for(var/datum/orion_event/event as anything in events)
if(!(event.type in event_whitelist))
events.Remove(event)
@@ -196,8 +192,6 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
. = TRUE
-
-
var/gamer_skill_level = 0
var/gamer_skill = 0
var/gamer_skill_rands = 0
@@ -316,7 +310,6 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
if(food > ORION_TRADE_RATE)
fuel += ORION_TRADE_RATE
food -= ORION_TRADE_RATE
- add_fingerprint(gamer)
/**
* pickweights a new event, sets event var as it. it then preps the event if it needs it
@@ -502,62 +495,56 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
obj_flags |= EMAGGED
return TRUE
-/mob/living/basic/trooper/syndicate/ranged/smg/orion
- name = "spaceport security"
- desc = "Premier corporate security forces for all spaceports found along the Orion Trail."
- faction = list(FACTION_ORION)
- loot = list()
-
+///A minibomb achieved from winning at emagged Orion.
/obj/item/orion_ship
name = "model settler ship"
desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..."
icon = 'icons/obj/toys/toy.dmi'
icon_state = "ship"
w_class = WEIGHT_CLASS_SMALL
- var/active = 0 //if the ship is on
+ ///Boolean on whether the ship is active, setting itself off for destruction.
+ var/active = 0
/obj/item/orion_ship/examine(mob/user)
. = ..()
if(!(in_range(user, src)))
return
- if(!active)
- . += span_notice("There's a little switch on the bottom. It's flipped down.")
- else
+ if(active)
. += span_notice("There's a little switch on the bottom. It's flipped up.")
+ return
+ . += span_notice("There's a little switch on the bottom. It's flipped down.")
-/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse
+/obj/item/orion_ship/attack_self(mob/user)
if(active)
return
log_bomber(usr, "primed an explosive", src, "for detonation")
-
to_chat(user, span_warning("You flip the switch on the underside of [src]."))
- active = 1
- visible_message(span_notice("[src] softly beeps and whirs to life!"))
- playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, TRUE)
- say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.")
- sleep(2 SECONDS)
- visible_message(span_warning("[src] begins to vibrate..."))
- say("Uh, Port? Having some issues with our reactor, could you check it out? Over.")
- sleep(3 SECONDS)
- say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-")
- playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE)
- sleep(0.36 SECONDS)
- visible_message(span_userdanger("[src] explodes!"))
- explosion(src, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 8, flame_range = 16)
- qdel(src)
+ active = TRUE
+ addtimer(CALLBACK(src, PROC_REF(commit_explosion)), 1 SECONDS)
-/obj/singularity/orion
- move_self = FALSE
+///After some dialogue (which doubles as the timer until explosion), causes a minibomb-level explosion.
+/obj/item/orion_ship/proc/commit_explosion(dialogue_level = 0)
+ var/time_for_next_level
+ switch(dialogue_level)
+ if(0)
+ say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.")
+ time_for_next_level = 2 SECONDS
+ if(1)
+ say("Uh, Port? Having some issues with our reactor, could you check it out? Over.")
+ time_for_next_level = 3 SECONDS
+ if(2)
+ say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-")
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE)
+ time_for_next_level = 0.36 SECONDS
+ if(3 to INFINITY)
+ visible_message(span_userdanger("[src] explodes!"))
+ explosion(src, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 8, flame_range = 16)
+ qdel(src)
+ return
-/obj/singularity/orion/Initialize(mapload)
- . = ..()
-
- var/datum/component/singularity/singularity = singularity_component.resolve()
- singularity?.grav_pull = 1
-
-/obj/singularity/orion/process(seconds_per_tick)
- if(SPT_PROB(0.5, seconds_per_tick))
- mezzer()
+ if(time_for_next_level)
+ dialogue_level++
+ addtimer(CALLBACK(src, PROC_REF(commit_explosion), dialogue_level), time_for_next_level)
#undef ORION_TRAIL_WINTURN
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 18ca1665765..750a1d5d53e 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -146,7 +146,7 @@
return FALSE
-/obj/structure/frame/computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/structure/frame/computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
if(. & ITEM_INTERACT_ANY_BLOCKER)
return .
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index b244cba4aa6..5b27bfabf70 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -30,7 +30,7 @@
// Convert networks to lowercase
for(var/i in network)
network -= i
- network += lowertext(i)
+ network += LOWER_TEXT(i)
// Initialize map objects
cam_screen = new
cam_screen.generate_view(map_name)
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index a271517b0c4..1868bc3c38c 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -4,6 +4,8 @@
icon_screen = "cameras"
icon_keyboard = "security_key"
light_color = COLOR_SOFT_RED
+ processing_flags = START_PROCESSING_MANUALLY
+
var/list/z_lock = list() // Lock use to these z levels
var/lock_override = NONE
var/mob/camera/ai_eye/remote/eyeobj
@@ -30,7 +32,7 @@
. = ..()
for(var/i in networks)
networks -= i
- networks += lowertext(i)
+ networks += LOWER_TEXT(i)
if(lock_override)
if(lock_override & CAMERA_LOCK_STATION)
z_lock |= SSmapping.levels_by_trait(ZTRAIT_STATION)
@@ -50,6 +52,20 @@
if(move_down_action)
actions += new move_down_action(src)
+/obj/machinery/computer/camera_advanced/Destroy()
+ if(!QDELETED(current_user))
+ unset_machine(current_user)
+ if(eyeobj)
+ QDEL_NULL(eyeobj)
+ QDEL_LIST(actions)
+ current_user = null
+ return ..()
+
+/obj/machinery/computer/camera_advanced/process()
+ if(!can_use(current_user) || (issilicon(current_user) && !current_user.has_unlimited_silicon_privilege))
+ unset_machine(current_user)
+ return PROCESS_KILL
+
/obj/machinery/computer/camera_advanced/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
for(var/i in networks)
networks -= i
@@ -73,6 +89,20 @@
/obj/machinery/proc/remove_eye_control(mob/living/user)
CRASH("[type] does not implement ai eye handling")
+/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user)
+ if(isnull(user?.client))
+ return
+ GrantActions(user)
+ current_user = user
+ eyeobj.eye_user = user
+ eyeobj.name = "Camera Eye ([user.name])"
+ user.remote_control = eyeobj
+ user.reset_perspective(eyeobj)
+ eyeobj.setLoc(eyeobj.loc)
+ if(should_supress_view_changes)
+ user.client.view_size.supress()
+ begin_processing()
+
/obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user)
if(isnull(user?.client))
return
@@ -90,23 +120,16 @@
eyeobj.eye_user = null
user.remote_control = null
current_user = null
- unset_machine(user)
playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE)
-/obj/machinery/computer/camera_advanced/check_eye(mob/user)
- if(!can_use(user) || (issilicon(user) && !user.has_unlimited_silicon_privilege))
- unset_machine(user)
-
-/obj/machinery/computer/camera_advanced/Destroy()
- if(eyeobj)
- QDEL_NULL(eyeobj)
- QDEL_LIST(actions)
- current_user = null
- return ..()
+/obj/machinery/computer/camera_advanced/on_set_is_operational(old_value)
+ if(!is_operational)
+ unset_machine(current_user)
/obj/machinery/computer/camera_advanced/proc/unset_machine(mob/M)
if(M == current_user)
remove_eye_control(M)
+ end_processing()
/obj/machinery/computer/camera_advanced/proc/can_use(mob/living/user)
return can_interact(user)
@@ -167,19 +190,6 @@
/obj/machinery/computer/camera_advanced/attack_ai(mob/user)
return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise.
-/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user)
- if(isnull(user?.client))
- return
- GrantActions(user)
- current_user = user
- eyeobj.eye_user = user
- eyeobj.name = "Camera Eye ([user.name])"
- user.remote_control = eyeobj
- user.reset_perspective(eyeobj)
- eyeobj.setLoc(eyeobj.loc)
- if(should_supress_view_changes)
- user.client.view_size.supress()
-
/mob/camera/ai_eye/remote
name = "Inactive Camera Eye"
ai_detector_visible = FALSE
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index f9e06ab58b3..4c210e8fd26 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -54,7 +54,7 @@
icon_keyboard = "med_key"
density = TRUE
circuit = /obj/item/circuitboard/computer/scan_consolenew
-
+ interaction_flags_click = ALLOW_SILICON_REACH
light_color = LIGHT_COLOR_BLUE
/// Link to the techweb's stored research. Used to retrieve stored mutations
@@ -210,15 +210,9 @@
stored_research = tool.buffer
return TRUE
-/obj/machinery/computer/scan_consolenew/AltClick(mob/user)
- // Make sure the user can interact with the machine.
- . = ..()
- if(!can_interact(user))
- return
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
-
+/obj/machinery/computer/scan_consolenew/click_alt(mob/user)
eject_disk(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/computer/scan_consolenew/Initialize(mapload)
. = ..()
@@ -235,7 +229,7 @@
// Set the default tgui state
set_default_state()
-/obj/machinery/computer/scan_consolenew/LateInitialize()
+/obj/machinery/computer/scan_consolenew/post_machine_initialize()
. = ..()
// Link machine with research techweb. Used for discovering and accessing
// already discovered mutations
diff --git a/code/game/machinery/computer/mechlaunchpad.dm b/code/game/machinery/computer/mechlaunchpad.dm
index 106f87f1788..7b80b6e95c8 100644
--- a/code/game/machinery/computer/mechlaunchpad.dm
+++ b/code/game/machinery/computer/mechlaunchpad.dm
@@ -34,7 +34,8 @@
SIGNAL_HANDLER
connected_mechpad = null
-/obj/machinery/computer/mechpad/LateInitialize()
+/obj/machinery/computer/mechpad/post_machine_initialize()
+ . = ..()
for(var/obj/machinery/mechpad/pad as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/mechpad))
if(pad == connected_mechpad)
continue
diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm
index bb809af0eea..d0ea49df27b 100644
--- a/code/game/machinery/computer/operating_computer.dm
+++ b/code/game/machinery/computer/operating_computer.dm
@@ -20,7 +20,7 @@
find_table()
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/computer/operating/LateInitialize()
+/obj/machinery/computer/operating/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
diff --git a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm
index 686f8312671..0882c9ce99a 100644
--- a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm
+++ b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm
@@ -111,3 +111,7 @@
item_path = /obj/item/boulder_beacon
desc = "A Bouldertech brand all-in-one boulder processing beacon. Each use will teleport in a component of a full boulder processing assembly line. Good for when you need to process additional boulders."
cost_per_order = 875
+
+/datum/orderable_item/mining/grapple_gun
+ item_path = /obj/item/grapple_gun
+ cost_per_order = 3000
diff --git a/code/game/machinery/computer/prisoner/_prisoner.dm b/code/game/machinery/computer/prisoner/_prisoner.dm
index f1ce2555936..9777c1b209c 100644
--- a/code/game/machinery/computer/prisoner/_prisoner.dm
+++ b/code/game/machinery/computer/prisoner/_prisoner.dm
@@ -2,6 +2,7 @@
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY
/// ID card currently inserted into the computer.
VAR_FINAL/obj/item/card/id/advanced/prisoner/contained_id
+ interaction_flags_click = ALLOW_SILICON_REACH
/obj/machinery/computer/prisoner/on_deconstruction(disassembled)
contained_id?.forceMove(drop_location())
@@ -20,10 +21,9 @@
if(contained_id)
. += span_notice("Alt-click to eject the ID card.")
-/obj/machinery/computer/prisoner/AltClick(mob/user)
- . = ..()
- if(user.can_perform_action(src, ALLOW_SILICON_REACH))
- id_eject(user)
+/obj/machinery/computer/prisoner/click_alt(mob/user)
+ id_eject(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/computer/prisoner/proc/id_insert(mob/user, obj/item/card/id/advanced/prisoner/new_id)
if(!istype(new_id))
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index 0915d4d1d17..5baf5497853 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -201,7 +201,7 @@
if (regime_set == "Teleporter")
var/desc = tgui_input_list(usr, "Select a location to lock in", "Locking Computer", sort_list(targets))
- if(isnull(desc))
+ if(isnull(desc) || !user.can_perform_action(src))
return
set_teleport_target(targets[desc])
user.log_message("set the teleporter target to [targets[desc]].]", LOG_GAME)
@@ -211,7 +211,7 @@
return
var/desc = tgui_input_list(usr, "Select a station to lock in", "Locking Computer", sort_list(targets))
- if(isnull(desc))
+ if(isnull(desc)|| !user.can_perform_action(src))
return
var/obj/machinery/teleport/station/target_station = targets[desc]
if(!target_station || !target_station.teleporter_hub)
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index f47948753ab..f0b3434ec85 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -107,15 +107,10 @@
return ITEM_INTERACT_BLOCKING
return .
-/obj/structure/frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- . = ..()
- if(. & ITEM_INTERACT_ANY_BLOCKER)
- return .
-
+/obj/structure/frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(istype(tool, /obj/item/circuitboard)) // Install board will fail if passed an invalid circuitboard and give feedback
return install_board(user, tool, by_hand = TRUE) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
-
- return .
+ return NONE
/**
* Installs the passed circuit board into the frame
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 0a626459667..dea1972cea7 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -163,7 +163,6 @@
req_access = null
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
/obj/machinery/jukebox/disco/activate_music()
. = ..()
diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm
index c067fcfef0b..207a3f753ef 100644
--- a/code/game/machinery/defibrillator_mount.dm
+++ b/code/game/machinery/defibrillator_mount.dm
@@ -157,15 +157,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28)
to_chat(user, span_notice("You remove [src] from the wall."))
return TRUE
-/obj/machinery/defibrillator_mount/AltClick(mob/living/carbon/user)
- if(!istype(user) || !user.can_perform_action(src))
- return
+/obj/machinery/defibrillator_mount/click_alt(mob/living/carbon/user)
if(!defib)
to_chat(user, span_warning("It'd be hard to remove a defib unit from a mount that has none."))
- return
+ return CLICK_ACTION_BLOCKING
if(clamps_locked)
to_chat(user, span_warning("You try to tug out [defib], but the mount's clamps are locked tight!"))
- return
+ return CLICK_ACTION_BLOCKING
if(!user.put_in_hands(defib))
to_chat(user, span_warning("You need a free hand!"))
user.visible_message(span_notice("[user] unhooks [defib] from [src], dropping it on the floor."), \
@@ -174,6 +172,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28)
user.visible_message(span_notice("[user] unhooks [defib] from [src]."), \
span_notice("You slide out [defib] from [src] and unhook the charging cables."))
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/defibrillator_mount/charging
name = "PENLITE defibrillator mount"
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 61f12100de2..4f78fbf3a52 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -99,7 +99,7 @@
/obj/structure/barricade/wooden/crude
name = "crude plank barricade"
desc = "This space is blocked off by a crude assortment of planks."
- icon_state = "woodenbarricade-old"
+ icon_state = "plankbarricade"
drop_amount = 1
max_integrity = 50
proj_pass_rate = 65
@@ -107,7 +107,7 @@
/obj/structure/barricade/wooden/crude/snow
desc = "This space is blocked off by a crude assortment of planks. It seems to be covered in a layer of snow."
- icon_state = "woodenbarricade-snow-old"
+ icon_state = "plankbarricade_snow"
max_integrity = 75
/obj/structure/barricade/wooden/make_debris()
@@ -180,10 +180,9 @@
. = ..()
. += span_notice("Alt-click to toggle modes.")
-/obj/item/grenade/barrier/AltClick(mob/living/carbon/user)
- if(!istype(user) || !user.can_perform_action(src))
- return
+/obj/item/grenade/barrier/click_alt(mob/living/carbon/user)
toggle_mode(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/grenade/barrier/proc/toggle_mode(mob/user)
switch(mode)
diff --git a/code/game/machinery/dish_drive.dm b/code/game/machinery/dish_drive.dm
index 81961ce7187..fc74b18c03c 100644
--- a/code/game/machinery/dish_drive.dm
+++ b/code/game/machinery/dish_drive.dm
@@ -9,6 +9,7 @@
density = FALSE
circuit = /obj/item/circuitboard/machine/dish_drive
pass_flags = PASSTABLE
+ interaction_flags_click = ALLOW_SILICON_REACH
/// List of dishes the drive can hold
var/list/collectable_items = list(/obj/item/trash/waffles, // SKYRAT EDIT CHANGE - non-static list
/obj/item/trash/waffles,
@@ -143,9 +144,9 @@
balloon_alert(user, "disposal signal sent")
do_the_dishes(TRUE)
-/obj/machinery/dish_drive/AltClick(mob/living/user)
- if(user.can_perform_action(src, ALLOW_SILICON_REACH))
- do_the_dishes(TRUE)
+/obj/machinery/dish_drive/click_alt(mob/living/user)
+ do_the_dishes(TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/dish_drive/proc/do_the_dishes(manual)
if(!LAZYLEN(dish_drive_contents))
diff --git a/code/game/machinery/dna_infuser/dna_infuser.dm b/code/game/machinery/dna_infuser/dna_infuser.dm
index 8275eb1e948..6c239089f5d 100644
--- a/code/game/machinery/dna_infuser/dna_infuser.dm
+++ b/code/game/machinery/dna_infuser/dna_infuser.dm
@@ -288,17 +288,17 @@
return FALSE
return TRUE
-/obj/machinery/dna_infuser/AltClick(mob/user)
- . = ..()
+/obj/machinery/dna_infuser/click_alt(mob/user)
if(infusing)
balloon_alert(user, "not while it's on!")
- return
+ return CLICK_ACTION_BLOCKING
if(!infusing_from)
balloon_alert(user, "no sample to eject!")
- return
+ return CLICK_ACTION_BLOCKING
balloon_alert(user, "ejected sample")
infusing_from.forceMove(get_turf(src))
infusing_from = null
+ return CLICK_ACTION_SUCCESS
#undef INFUSING_TIME
#undef SCREAM_TIME
diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
index f6e1e92c2a5..f19f3d725c7 100644
--- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm
@@ -103,7 +103,7 @@
/obj/item/organ/internal/tongue/rat/modify_speech(datum/source, list/speech_args)
. = ..()
- var/message = lowertext(speech_args[SPEECH_MESSAGE])
+ var/message = LOWER_TEXT(speech_args[SPEECH_MESSAGE])
if(message == "hi" || message == "hi.")
speech_args[SPEECH_MESSAGE] = "Cheesed to meet you!"
if(message == "hi?")
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 917255e50b4..437acc60cdf 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1512,7 +1512,7 @@
/obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
if((damage_amount >= atom_integrity) && (damage_flag == BOMB))
- obj_flags |= NO_DECONSTRUCTION //If an explosive took us out, don't drop the assembly
+ obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION //If an explosive took us out, don't drop the assembly
. = ..()
if(atom_integrity < (0.75 * max_integrity))
update_appearance()
@@ -2169,7 +2169,7 @@
return ..()
-/obj/machinery/door/airlock/external/LateInitialize()
+/obj/machinery/door/airlock/external/post_machine_initialize()
. = ..()
if(space_dir)
unres_sides |= space_dir
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index b63e94e6079..0ff933cc9b1 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -91,7 +91,7 @@
RegisterSignal(src, COMSIG_MACHINERY_POWER_LOST, PROC_REF(on_power_loss))
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/door/firedoor/LateInitialize()
+/obj/machinery/door/firedoor/post_machine_initialize()
. = ..()
RegisterSignal(src, COMSIG_MERGER_ADDING, PROC_REF(merger_adding))
RegisterSignal(src, COMSIG_MERGER_REMOVING, PROC_REF(merger_removing))
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 0849a5ad8c5..c69c865f6d1 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -66,11 +66,8 @@
/obj/machinery/door/window/Destroy()
set_density(FALSE)
- if(atom_integrity == 0)
- playsound(src, SFX_SHATTER, 70, TRUE)
electronics = null
- var/turf/floor = get_turf(src)
- floor.air_update_turf(TRUE, FALSE)
+ air_update_turf(TRUE, FALSE)
return ..()
/obj/machinery/door/window/update_icon_state()
@@ -300,11 +297,12 @@
if(BURN)
playsound(src, 'sound/items/welder.ogg', 100, TRUE)
-
/obj/machinery/door/window/on_deconstruction(disassembled)
if(disassembled)
return
+ playsound(src, SFX_SHATTER, 70, TRUE)
+
for(var/i in 1 to shards)
drop_debris(new /obj/item/shard(src))
if(rods)
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index 70da443872d..dc3b917705f 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -16,7 +16,8 @@
..()
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/door_buttons/LateInitialize()
+/obj/machinery/door_buttons/post_machine_initialize()
+ . = ..()
find_objects_by_tag()
/obj/machinery/door_buttons/emag_act(mob/user, obj/item/card/emag/emag_card)
diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm
index e16e9f61c24..359ab48945b 100644
--- a/code/game/machinery/embedded_controller/airlock_controller.dm
+++ b/code/game/machinery/embedded_controller/airlock_controller.dm
@@ -34,7 +34,7 @@
var/processing = FALSE
-/obj/machinery/airlock_controller/LateInitialize()
+/obj/machinery/airlock_controller/post_machine_initialize()
. = ..()
var/obj/machinery/door/interior_door = GLOB.objects_by_id_tag[interior_door_tag]
diff --git a/code/game/machinery/fat_sucker.dm b/code/game/machinery/fat_sucker.dm
index 4567959b844..c93a0e4f7ea 100644
--- a/code/game/machinery/fat_sucker.dm
+++ b/code/game/machinery/fat_sucker.dm
@@ -98,17 +98,16 @@
else
to_chat(user, span_warning("The safety hatch has been disabled!"))
-/obj/machinery/fat_sucker/AltClick(mob/living/user)
- if(!user.can_perform_action(src))
- return
+/obj/machinery/fat_sucker/click_alt(mob/living/user)
if(user == occupant)
to_chat(user, span_warning("You can't reach the controls from inside!"))
- return
+ return CLICK_ACTION_BLOCKING
if(!(obj_flags & EMAGGED) && !allowed(user))
to_chat(user, span_warning("You lack the required access."))
- return
+ return CLICK_ACTION_BLOCKING
free_exit = !free_exit
to_chat(user, span_notice("Safety hatch [free_exit ? "unlocked" : "locked"]."))
+ return CLICK_ACTION_SUCCESS
/obj/machinery/fat_sucker/update_overlays()
. = ..()
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 09599b0cbff..5fa999a690e 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -57,20 +57,16 @@
else if(!harvesting)
open_machine()
-/obj/machinery/harvester/AltClick(mob/user)
- . = ..()
- if(!user.can_perform_action(src))
- return
+/obj/machinery/harvester/click_alt(mob/user)
if(panel_open)
output_dir = turn(output_dir, -90)
to_chat(user, span_notice("You change [src]'s output settings, setting the output to [dir2text(output_dir)]."))
- return
- if(!can_interact(user))
- return
- if(harvesting || !user || !isliving(user) || state_open)
- return
- if(can_harvest())
- start_harvest()
+ return CLICK_ACTION_SUCCESS
+ if(harvesting || state_open || !can_harvest())
+ return CLICK_ACTION_BLOCKING
+
+ start_harvest()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/harvester/proc/can_harvest()
if(!powered() || state_open || !occupant || !iscarbon(occupant))
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 18ccc976f06..273538b834b 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -127,7 +127,6 @@ Possible to do for anyone motivated enough:
/obj/machinery/holopad/tutorial
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
on_network = FALSE
///Proximity monitor associated with this atom, needed for proximity checks.
var/datum/proximity_monitor/proximity_monitor
@@ -143,6 +142,12 @@ Possible to do for anyone motivated enough:
new_disk.forceMove(src)
disk = new_disk
+/obj/machinery/holopad/tutorial/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/holopad/tutorial/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
/obj/machinery/holopad/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
if(!loc)
diff --git a/code/game/machinery/incident_display.dm b/code/game/machinery/incident_display.dm
index fcdfecf6a31..b8452675c71 100644
--- a/code/game/machinery/incident_display.dm
+++ b/code/game/machinery/incident_display.dm
@@ -80,7 +80,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/incident_display/tram, 32)
..()
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/incident_display/LateInitialize()
+/obj/machinery/incident_display/post_machine_initialize()
. = ..()
GLOB.map_delamination_counters += src
update_delam_count(SSpersistence.rounds_since_engine_exploded, SSpersistence.delam_highscore)
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 6244dcdd2db..91104abf681 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -207,15 +207,10 @@
else
return ..()
-/// Checks whether the IV drip transfer rate can be modified with AltClick
-/obj/machinery/iv_drip/proc/can_use_alt_click(mob/user)
- if(!can_interact(user))
- return FALSE
-/obj/machinery/iv_drip/AltClick(mob/user)
- if(!can_use_alt_click(user))
- return ..()
+/obj/machinery/iv_drip/click_alt(mob/user)
set_transfer_rate(transfer_rate > MIN_IV_TRANSFER_RATE ? MIN_IV_TRANSFER_RATE : MAX_IV_TRANSFER_RATE)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/iv_drip/on_deconstruction(disassembled = TRUE)
new /obj/item/stack/sheet/iron(loc)
diff --git a/code/game/machinery/machine_frame.dm b/code/game/machinery/machine_frame.dm
index 4edb3215e2b..ccdcddc8705 100644
--- a/code/game/machinery/machine_frame.dm
+++ b/code/game/machinery/machine_frame.dm
@@ -389,7 +389,7 @@
balloon_alert(user, "can't add that!")
return FALSE
-/obj/structure/frame/machine/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/structure/frame/machine/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
if(. & ITEM_INTERACT_ANY_BLOCKER)
return .
@@ -416,11 +416,18 @@
if(istype(tool, /obj/item/storage/part_replacer))
return install_parts_from_part_replacer(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
- if(!user.combat_mode)
- return add_part(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
-
return .
+// Override of base_item_interaction so we only try to add parts to the frame AFTER running item_interaction and all the tool_acts
+/obj/structure/frame/machine/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = ..()
+ if(. & ITEM_INTERACT_ANY_BLOCKER)
+ return .
+ if(user.combat_mode)
+ return NONE
+
+ return add_part(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING
+
/**
* Attempt to finalize the construction of the frame into a machine
* as according to our circuit and parts
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 6963b23afb0..5f534ec95b4 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -14,10 +14,6 @@
. = ..()
wires = new /datum/wires/mass_driver(src)
-/obj/machinery/mass_driver/Destroy()
- QDEL_NULL(wires)
- . = ..()
-
/obj/machinery/mass_driver/chapelgun
name = "holy driver"
id = MASSDRIVER_CHAPEL
@@ -35,6 +31,7 @@
for(var/obj/machinery/computer/pod/control as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/pod))
if(control.id == id)
control.connected = null
+ QDEL_NULL(wires)
return ..()
/obj/machinery/mass_driver/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm
index b2068194e4b..57c3fa2f8d4 100644
--- a/code/game/machinery/medipen_refiller.dm
+++ b/code/game/machinery/medipen_refiller.dm
@@ -91,9 +91,9 @@
return ..()
/obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
- to_chat(user, span_notice("You start furiously plunging [name]."))
+ user.balloon_alert_to_viewers("furiously plunging...", "plunging medipen refiller...")
if(do_after(user, 3 SECONDS, target = src))
- to_chat(user, span_notice("You finish plunging the [name]."))
+ user.balloon_alert_to_viewers("finished plunging")
reagents.expose(get_turf(src), TOUCH)
reagents.clear_reagents()
diff --git a/code/game/machinery/photobooth.dm b/code/game/machinery/photobooth.dm
index d7775974269..321ae7efd6e 100644
--- a/code/game/machinery/photobooth.dm
+++ b/code/game/machinery/photobooth.dm
@@ -38,6 +38,7 @@
req_one_access = list(ACCESS_SECURITY)
color = COLOR_LIGHT_GRAYISH_RED
add_height_chart = TRUE
+ button_id = "photobooth_machine_security"
/obj/machinery/photobooth/Initialize(mapload)
. = ..()
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index d9e3787fd9e..9e926d9a841 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -394,8 +394,6 @@ Buildable meters
balloon_alert(user, "pipe layer set to [piping_layer]")
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-/obj/item/pipe/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/item/pipe/trinary/flippable/examine(mob/user)
. = ..()
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index d4cf080da69..06b1b977847 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -1066,7 +1066,7 @@ DEFINE_BITFIELD(turret_flags, list(
shoot_cyborgs = !shoot_cyborgs
if (user)
var/status = shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs"
- balloon_alert(user, lowertext(status))
+ balloon_alert(user, LOWER_TEXT(status))
add_hiddenprint(user)
log_combat(user, src, "[status]")
updateTurrets()
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 405a38e4167..28aae488866 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -35,7 +35,7 @@
. = ..()
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/recycler/LateInitialize()
+/obj/machinery/recycler/post_machine_initialize()
. = ..()
update_appearance(UPDATE_ICON)
req_one_access = SSid_access.get_region_access_list(list(REGION_ALL_STATION, REGION_CENTCOM))
@@ -239,9 +239,15 @@
/obj/machinery/recycler/deathtrap
name = "dangerous old crusher"
- obj_flags = CAN_BE_HIT | EMAGGED | NO_DECONSTRUCTION
+ obj_flags = CAN_BE_HIT | EMAGGED
crush_damage = 120
+/obj/machinery/recycler/deathtrap/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/recycler/deathtrap/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
/obj/item/paper/guides/recycler
name = "paper - 'garbage duty instructions'"
default_raw_text = "
New Assignment
You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect said trash.
There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then, deliver these minerals to cargo or engineering. You are our last hope for a clean station. Do not screw this up!"
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 60c293c8a96..f2b1ba303eb 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
ui.set_autoupdate(FALSE)
ui.open()
-/obj/machinery/requests_console/ui_act(action, params)
+/obj/machinery/requests_console/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
@@ -213,7 +213,8 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments)
var/recipient = params["reply_recipient"]
var/reply_message = reject_bad_text(tgui_input_text(usr, "Write a quick reply to [recipient]", "Awaiting Input"), ascii_only = FALSE)
-
+ if(QDELETED(ui) || ui.status != UI_INTERACTIVE)
+ return
if(!reply_message)
has_mail_send_error = TRUE
playsound(src, 'sound/machines/buzz-two.ogg', 50, TRUE)
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index edcf8269c8f..1e641f02460 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -364,11 +364,8 @@
visible_message(span_danger("[src] shuts down due to lack of power!"), \
"If this message is ever seen, something is wrong.",
span_hear("You hear heavy droning fade out."))
- active = FALSE
+ deactivate()
log_game("[src] deactivated due to lack of power at [AREACOORD(src)]")
- for(var/d in GLOB.cardinals)
- cleanup_field(d)
- update_appearance()
else
update_appearance()
for(var/d in GLOB.cardinals)
@@ -463,7 +460,6 @@
balloon_alert(user, "malfunctioning!")
else
balloon_alert(user, "no access!")
-
return
add_fingerprint(user)
@@ -493,13 +489,13 @@
user.visible_message(span_notice("[user] turned \the [src] off."), \
span_notice("You turn off \the [src]."), \
span_hear("You hear heavy droning fade out."))
- active = FALSE
+ deactivate()
user.log_message("deactivated [src].", LOG_GAME)
else
user.visible_message(span_notice("[user] turned \the [src] on."), \
span_notice("You turn on \the [src]."), \
span_hear("You hear heavy droning."))
- active = ACTIVE_SETUPFIELDS
+ activate()
user.log_message("activated [src].", LOG_GAME)
add_fingerprint(user)
@@ -513,6 +509,19 @@
balloon_alert(user, "access controller shorted")
return TRUE
+/// Turn the machine on with side effects
+/obj/machinery/power/shieldwallgen/proc/activate()
+ active = ACTIVE_SETUPFIELDS
+ AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
+
+/// Turn the machine off with side effects
+/obj/machinery/power/shieldwallgen/proc/deactivate()
+ active = FALSE
+ for(var/d in GLOB.cardinals)
+ cleanup_field(d)
+ update_appearance()
+ RemoveElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
+
//////////////Containment Field START
/obj/machinery/shieldwall
name = "shield wall"
@@ -538,6 +547,7 @@
L.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
L.gib(DROP_ALL_REMAINS)
RegisterSignal(src, COMSIG_ATOM_SINGULARITY_TRY_MOVE, PROC_REF(block_singularity))
+ AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
/obj/machinery/shieldwall/Destroy()
gen_primary = null
diff --git a/code/game/machinery/sleepers.dm b/code/game/machinery/sleepers.dm
index f768381548a..33e255badb2 100644
--- a/code/game/machinery/sleepers.dm
+++ b/code/game/machinery/sleepers.dm
@@ -164,14 +164,12 @@
ui = new(user, src, "Sleeper", name)
ui.open()
-/obj/machinery/sleeper/AltClick(mob/user)
- . = ..()
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
+/obj/machinery/sleeper/click_alt(mob/user)
if(state_open)
close_machine()
else
open_machine()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/sleeper/examine(mob/user)
. = ..()
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index 842f01ae754..bb93b7d00f5 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -68,10 +68,9 @@
coinvalues["[cointype]"] = C.get_item_credit_value()
qdel(C) //Sigh
-/obj/machinery/computer/slot_machine/Destroy()
+/obj/machinery/computer/slot_machine/on_deconstruction(disassembled)
if(balance)
give_payout(balance)
- return ..()
/obj/machinery/computer/slot_machine/process(seconds_per_tick)
. = ..() //Sanity checks.
@@ -95,50 +94,56 @@
return ..()
-/obj/machinery/computer/slot_machine/item_interaction(mob/living/user, obj/item/inserted, list/modifiers, is_right_clicking)
+/obj/machinery/computer/slot_machine/item_interaction(mob/living/user, obj/item/inserted, list/modifiers)
if(istype(inserted, /obj/item/coin))
var/obj/item/coin/inserted_coin = inserted
if(paymode == COIN)
if(prob(2))
if(!user.transferItemToLoc(inserted_coin, drop_location(), silent = FALSE))
- return
+ return ITEM_INTERACT_BLOCKING
inserted_coin.throw_at(user, 3, 10)
if(prob(10))
balance = max(balance - SPIN_PRICE, 0)
to_chat(user, span_warning("[src] spits your coin back out!"))
-
+ return ITEM_INTERACT_BLOCKING
else
if(!user.temporarilyRemoveItemFromInventory(inserted_coin))
- return
+ return ITEM_INTERACT_BLOCKING
balloon_alert(user, "coin insterted")
balance += inserted_coin.value
qdel(inserted_coin)
+ return ITEM_INTERACT_SUCCESS
else
balloon_alert(user, "holochips only!")
+ return ITEM_INTERACT_BLOCKING
- else if(istype(inserted, /obj/item/holochip))
+ if(istype(inserted, /obj/item/holochip))
if(paymode == HOLOCHIP)
var/obj/item/holochip/inserted_chip = inserted
if(!user.temporarilyRemoveItemFromInventory(inserted_chip))
- return
+ return ITEM_INTERACT_BLOCKING
balloon_alert(user, "[inserted_chip.credits] credit[inserted_chip.credits == 1 ? "" : "s"] inserted")
balance += inserted_chip.credits
qdel(inserted_chip)
+ return ITEM_INTERACT_SUCCESS
else
balloon_alert(user, "coins only!")
+ return ITEM_INTERACT_BLOCKING
- else if(inserted.tool_behaviour == TOOL_MULTITOOL)
- if(balance > 0)
- visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa
- else
- if(paymode == HOLOCHIP)
- paymode = COIN
- balloon_alert(user, "now using coins")
- else
- paymode = HOLOCHIP
- balloon_alert(user, "now using holochips")
+ return NONE
+
+/obj/machinery/computer/slot_machine/multitool_act(mob/living/user, obj/item/tool)
+ if(balance > 0)
+ visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa
+ return ITEM_INTERACT_BLOCKING
+
+ if(paymode == HOLOCHIP)
+ paymode = COIN
+ balloon_alert(user, "now using coins")
else
- return ..()
+ paymode = HOLOCHIP
+ balloon_alert(user, "now using holochips")
+ return ITEM_INTERACT_SUCCESS
/obj/machinery/computer/slot_machine/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index b8afa4d57d4..3f2bb0b0c9e 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -16,6 +16,7 @@
max_integrity = 250
armor_type = /datum/armor/machinery_space_heater
circuit = /obj/item/circuitboard/machine/space_heater
+ interaction_flags_click = ALLOW_SILICON_REACH
//We don't use area power, we always use the cell
use_power = NO_POWER_USE
///The cell we spawn with
@@ -308,6 +309,7 @@
panel_open = TRUE //This is always open - since we've injected wires in the panel
//We inherit the cell from the heater prior
cell = null
+ interaction_flags_click = FORBID_TELEKINESIS_REACH
///The beaker within the heater
var/obj/item/reagent_containers/beaker = null
///How powerful the heating is, upgrades with parts. (ala chem_heater.dm's method, basically the same level of heating, but this is restricted)
@@ -440,11 +442,9 @@
update_appearance()
return TRUE
-/obj/machinery/space_heater/improvised_chem_heater/AltClick(mob/living/user)
- . = ..()
- if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return
+/obj/machinery/space_heater/improvised_chem_heater/click_alt(mob/living/user)
replace_beaker(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/space_heater/improvised_chem_heater/update_icon_state()
. = ..()
diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm
index 177cd540040..9ef3d8e3a99 100644
--- a/code/game/machinery/stasis.dm
+++ b/code/game/machinery/stasis.dm
@@ -12,6 +12,7 @@
circuit = /obj/item/circuitboard/machine/stasis
fair_market_price = 10
payment_department = ACCOUNT_MED
+ interaction_flags_click = ALLOW_SILICON_REACH
var/stasis_enabled = TRUE
var/last_stasis_sound = FALSE
var/stasis_can_toggle = 0
@@ -22,9 +23,6 @@
. = ..()
AddElement(/datum/element/elevation, pixel_shift = 6)
-/obj/machinery/stasis/Destroy()
- . = ..()
-
/obj/machinery/stasis/examine(mob/user)
. = ..()
. += span_notice("Alt-click to [stasis_enabled ? "turn off" : "turn on"] the machine.")
@@ -39,19 +37,18 @@
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, frequency = sound_freq)
last_stasis_sound = _running
-/obj/machinery/stasis/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
- if(world.time >= stasis_can_toggle && user.can_perform_action(src, ALLOW_SILICON_REACH))
- stasis_enabled = !stasis_enabled
- stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN
- playsound(src, 'sound/machines/click.ogg', 60, TRUE)
- user.visible_message(span_notice("\The [src] [stasis_enabled ? "powers on" : "shuts down"]."), \
- span_notice("You [stasis_enabled ? "power on" : "shut down"] \the [src]."), \
- span_hear("You hear a nearby machine [stasis_enabled ? "power on" : "shut down"]."))
- play_power_sound()
- update_appearance()
+/obj/machinery/stasis/click_alt(mob/user)
+ if(world.time < stasis_can_toggle)
+ return CLICK_ACTION_BLOCKING
+ stasis_enabled = !stasis_enabled
+ stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN
+ playsound(src, 'sound/machines/click.ogg', 60, TRUE)
+ user.visible_message(span_notice("\The [src] [stasis_enabled ? "powers on" : "shuts down"]."), \
+ span_notice("You [stasis_enabled ? "power on" : "shut down"] \the [src]."), \
+ span_hear("You hear a nearby machine [stasis_enabled ? "power on" : "shut down"]."))
+ play_power_sound()
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/stasis/Exited(atom/movable/gone, direction)
if(gone == occupant)
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index ab2a3f8cefc..1998654df00 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -74,7 +74,8 @@
GLOB.telecomms_list += src
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/computer/message_monitor/LateInitialize()
+/obj/machinery/computer/message_monitor/post_machine_initialize()
+ . = ..()
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
if(!linkedServer)
for(var/obj/machinery/telecomms/message_server/message_server in GLOB.telecomms_list)
@@ -280,12 +281,11 @@
name = "monitor decryption key"
/obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server)
- ..()
+ . = ..()
if (server)
print(server)
return INITIALIZE_HINT_NORMAL
- else
- return INITIALIZE_HINT_LATELOAD
+ return INITIALIZE_HINT_LATELOAD
/**
* Handles printing the monitor key for a given server onto this piece of paper.
diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm
index 6cf18323105..abc2b7dbdbf 100644
--- a/code/game/machinery/telecomms/computers/telemonitor.dm
+++ b/code/game/machinery/telecomms/computers/telemonitor.dm
@@ -5,7 +5,6 @@
/obj/machinery/computer/telecomms/monitor
name = "telecommunications monitoring console"
desc = "Monitors the details of the telecommunications network it's synced with."
-
circuit = /obj/item/circuitboard/computer/comm_monitor
icon_screen = "comm_monitor"
diff --git a/code/game/machinery/telecomms/machines/allinone.dm b/code/game/machinery/telecomms/machines/allinone.dm
index f159339193e..9b32a4ac192 100644
--- a/code/game/machinery/telecomms/machines/allinone.dm
+++ b/code/game/machinery/telecomms/machines/allinone.dm
@@ -20,7 +20,6 @@
/obj/machinery/telecomms/allinone/indestructible
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
/obj/machinery/telecomms/allinone/indestructible/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
return NONE
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index b8d0414ad28..ee71ca0233d 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -105,9 +105,8 @@ GLOBAL_LIST_EMPTY(telecomms_list)
if(mapload && autolinkers.len)
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/telecomms/LateInitialize()
- ..()
-
+/obj/machinery/telecomms/post_machine_initialize()
+ . = ..()
for(var/obj/machinery/telecomms/telecomms_machine in GLOB.telecomms_list)
if (long_range_link || IN_GIVEN_RANGE(src, telecomms_machine, 20))
add_automatic_link(telecomms_machine)
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index e4fc4592b79..e2ad3af956a 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -28,18 +28,6 @@
if(user_unbuckle_mob(buckled_mobs[1],user))
return TRUE
-/atom/movable/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- if(!can_buckle || !istype(tool, /obj/item/riding_offhand) || !user.Adjacent(src))
- return ..()
-
- var/obj/item/riding_offhand/riding_item = tool
- var/mob/living/carried_mob = riding_item.rider
- if(carried_mob == user) //Piggyback user.
- return ITEM_INTERACT_BLOCKING
- user.unbuckle_mob(carried_mob)
- carried_mob.forceMove(get_turf(src))
- return mouse_buckle_handling(carried_mob, user) ? ITEM_INTERACT_SUCCESS: ITEM_INTERACT_BLOCKING
-
//literally just the above extension of attack_hand(), but for silicons instead (with an adjacency check, since attack_robot() being called doesn't mean that you're adjacent to something)
/atom/movable/attack_robot(mob/living/user)
. = ..()
diff --git a/code/game/objects/effects/anomalies/_anomalies.dm b/code/game/objects/effects/anomalies/_anomalies.dm
index 530da562827..a3f0b79044b 100644
--- a/code/game/objects/effects/anomalies/_anomalies.dm
+++ b/code/game/objects/effects/anomalies/_anomalies.dm
@@ -21,8 +21,8 @@
var/drops_core = TRUE
///Do we keep on living forever?
var/immortal = FALSE
- ///Do we stay in one place?
- var/immobile = FALSE
+ ///Chance per second that we will move
+ var/move_chance = ANOMALY_MOVECHANCE
/obj/effect/anomaly/Initialize(mapload, new_lifespan, drops_core = TRUE)
. = ..()
@@ -76,8 +76,12 @@
return ..()
/obj/effect/anomaly/proc/anomalyEffect(seconds_per_tick)
- if(!immobile && SPT_PROB(ANOMALY_MOVECHANCE, seconds_per_tick))
- step(src,pick(GLOB.alldirs))
+ if(SPT_PROB(move_chance, seconds_per_tick))
+ move_anomaly()
+
+/// Move in a direction
+/obj/effect/anomaly/proc/move_anomaly()
+ step(src, pick(GLOB.alldirs))
/obj/effect/anomaly/proc/detonate()
return
@@ -116,4 +120,5 @@
if(!has_core)
drops_core = FALSE
QDEL_NULL(aSignal)
- immobile = anchor
+ if (anchor)
+ move_chance = 0
diff --git a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm
index b4ee3713a25..f1034c5541f 100644
--- a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm
+++ b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm
@@ -4,6 +4,10 @@
icon_state = "bioscrambler"
aSignal = /obj/item/assembly/signaler/anomaly/bioscrambler
immortal = TRUE
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINE | PASSSTRUCTURE | PASSDOORS
+ layer = ABOVE_MOB_LAYER
+ /// Who are we moving towards?
+ var/datum/weakref/pursuit_target
/// Cooldown for every anomaly pulse
COOLDOWN_DECLARE(pulse_cooldown)
/// How many seconds between each anomaly pulses
@@ -11,11 +15,65 @@
/// Range of the anomaly pulse
var/range = 5
+/obj/effect/anomaly/bioscrambler/Initialize(mapload, new_lifespan, drops_core)
+ . = ..()
+ pursuit_target = WEAKREF(find_nearest_target())
+
/obj/effect/anomaly/bioscrambler/anomalyEffect(seconds_per_tick)
. = ..()
if(!COOLDOWN_FINISHED(src, pulse_cooldown))
return
COOLDOWN_START(src, pulse_cooldown, pulse_delay)
- for(var/mob/living/carbon/nearby in range(range, src))
+ for(var/mob/living/carbon/nearby in hearers(range, src))
nearby.bioscramble(name)
+
+/obj/effect/anomaly/bioscrambler/move_anomaly()
+ update_target()
+ if (isnull(pursuit_target))
+ return ..()
+ var/turf/step_turf = get_step(src, get_dir(src, pursuit_target.resolve()))
+ if (!HAS_TRAIT(step_turf, TRAIT_CONTAINMENT_FIELD))
+ Move(step_turf)
+
+/// Select a new target if we need one
+/obj/effect/anomaly/bioscrambler/proc/update_target()
+ var/mob/living/current_target = pursuit_target?.resolve()
+ if (QDELETED(current_target))
+ pursuit_target = null
+ if (!isnull(pursuit_target) && prob(80))
+ return
+ var/mob/living/new_target = find_nearest_target()
+ if (isnull(new_target))
+ pursuit_target = null
+ return
+ if (new_target == current_target)
+ return
+ current_target = new_target
+ pursuit_target = WEAKREF(new_target)
+ new_target.ominous_nosebleed()
+
+/// Returns the closest conscious carbon on our z level or null if there somehow isn't one
+/obj/effect/anomaly/bioscrambler/proc/find_nearest_target()
+ var/closest_distance = INFINITY
+ var/mob/living/carbon/closest_target = null
+ for(var/mob/living/carbon/target in GLOB.player_list)
+ if (target.z != z)
+ continue
+ if (target.status_flags & GODMODE)
+ continue
+ if (target.stat >= UNCONSCIOUS)
+ continue // Don't just haunt a corpse
+ var/distance_from_target = get_dist(src, target)
+ if(distance_from_target >= closest_distance)
+ continue
+ closest_distance = distance_from_target
+ closest_target = target
+
+ return closest_target
+
+/// A bioscrambler anomaly subtype which does not pursue people, for purposes of a space ruin
+/obj/effect/anomaly/bioscrambler/docile
+
+/obj/effect/anomaly/bioscrambler/docile/update_target()
+ return
diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm
index 16dd5bafcfa..026c5974d5f 100644
--- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm
+++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm
@@ -4,7 +4,7 @@
icon_state = "dimensional"
aSignal = /obj/item/assembly/signaler/anomaly/dimensional
immortal = TRUE
- immobile = TRUE
+ move_chance = 0
/// Range of effect, if left alone anomaly will convert a 2(range)+1 squared area.
var/range = 3
/// List of turfs this anomaly will try to transform before relocating
diff --git a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm
index 412cca04952..51a033f515f 100644
--- a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm
+++ b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm
@@ -4,7 +4,7 @@
icon_state = "ectoplasm"
aSignal = /obj/item/assembly/signaler/anomaly/ectoplasm
lifespan = ANOMALY_COUNTDOWN_TIMER + 2 SECONDS //This one takes slightly longer, because it can run away.
- immobile = TRUE //prevents it from moving around so ghosts can actually move it with decent accuracy
+ move_chance = 0 //prevents it from moving around so ghosts can actually move it with decent accuracy
///Blocks the anomaly from updating ghost count. Used in case an admin wants to rig the anomaly to be a certain size or intensity.
var/override_ghosts = FALSE
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 0ac4188328f..f5daba8135c 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -512,7 +512,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
return ..()
/obj/effect/landmark/start/hangover/LateInitialize()
- . = ..()
if(HAS_TRAIT(SSstation, STATION_TRAIT_BIRTHDAY))
party_debris += new /obj/effect/decal/cleanable/confetti(get_turf(src)) //a birthday celebration can also be a hangover
var/list/bonus_confetti = GLOB.alldirs
@@ -593,7 +592,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
return INITIALIZE_HINT_LATELOAD
/obj/effect/landmark/navigate_destination/LateInitialize()
- . = ..()
if(!location)
var/obj/machinery/door/airlock/A = locate(/obj/machinery/door/airlock) in loc
location = A ? format_text(A.name) : get_area_name(src, format_text = TRUE)
diff --git a/code/game/objects/effects/posters/poster.dm b/code/game/objects/effects/posters/poster.dm
index c4703d700c4..4ced5babbbf 100644
--- a/code/game/objects/effects/posters/poster.dm
+++ b/code/game/objects/effects/posters/poster.dm
@@ -184,12 +184,17 @@
/obj/structure/sign/poster/attack_hand(mob/user, list/modifiers)
. = ..()
- if(.)
- return
- if(ruined)
+ if(. || !check_tearability())
return
tear_poster(user)
+/// Check to see if this poster is tearable and gives the user feedback if it is not.
+/obj/structure/sign/poster/proc/check_tearability(mob/user)
+ if(ruined)
+ balloon_alert(user, "already ruined!")
+ return FALSE
+ return TRUE
+
/obj/structure/sign/poster/proc/spring_trap(mob/user)
var/obj/item/shard/payload = trap?.resolve()
if (!payload)
@@ -264,10 +269,10 @@
playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, TRUE)
spring_trap(user)
- var/obj/structure/sign/poster/ripped/R = new(loc)
- R.pixel_y = pixel_y
- R.pixel_x = pixel_x
- R.add_fingerprint(user)
+ var/obj/structure/sign/poster/ripped/torn_poster = new(loc)
+ torn_poster.pixel_y = pixel_y
+ torn_poster.pixel_x = pixel_x
+ torn_poster.add_fingerprint(user)
qdel(src)
// Various possible posters follow
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 909db0ad46f..e6c3e80c575 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -225,6 +225,11 @@
/// A lazylist used for applying fantasy values, contains the actual modification applied to a variable.
var/list/fantasy_modifications = null
+ /// Has the item been reskinned?
+ var/current_skin
+ ///// List of options to reskin.
+ var/list/unique_reskin
+
/obj/item/Initialize(mapload)
if(attack_verb_continuous)
attack_verb_continuous = string_list(attack_verb_continuous)
@@ -261,6 +266,11 @@
if(LAZYLEN(embedding))
updateEmbedding()
+ if(unique_reskin)
+ RegisterSignal(src, COMSIG_CLICK_ALT, PROC_REF(on_click_alt_reskin))
+ register_context()
+
+
/obj/item/Destroy(force)
// This var exists as a weird proxy "owner" ref
// It's used in a few places. Stop using it, and optimially replace all uses please
@@ -275,6 +285,20 @@
return ..()
+
+/obj/item/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+
+ if(!unique_reskin)
+ return
+
+ if(current_skin && !(item_flags & INFINITE_RESKIN))
+ return
+
+ context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin"
+ return CONTEXTUAL_SCREENTIP_SET
+
+
/// Called when an action associated with our item is deleted
/obj/item/proc/on_action_deleted(datum/source)
SIGNAL_HANDLER
@@ -1072,7 +1096,7 @@
/obj/item/proc/apply_outline(outline_color = null)
if(((get(src, /mob) != usr) && !loc?.atom_storage && !(item_flags & IN_STORAGE)) || QDELETED(src) || isobserver(usr)) //cancel if the item isn't in an inventory, is being deleted, or if the person hovering is a ghost (so that people spectating you don't randomly make your items glow)
return FALSE
- var/theme = lowertext(usr.client?.prefs?.read_preference(/datum/preference/choiced/ui_style))
+ var/theme = LOWER_TEXT(usr.client?.prefs?.read_preference(/datum/preference/choiced/ui_style))
if(!outline_color) //if we weren't provided with a color, take the theme's color
switch(theme) //yeah it kinda has to be this way
if("midnight")
@@ -1488,6 +1512,7 @@
wearer.regenerate_icons() // update that mf
to_chat(M, "[src] is now skinned as '[pick].'")
post_reskin(M)
+ return TRUE
/// Automatically called after a reskin, for any extra variable changes.
/obj/item/proc/post_reskin(mob/our_mob)
@@ -1755,3 +1780,24 @@
/obj/item/animate_atom_living(mob/living/owner)
new /mob/living/simple_animal/hostile/mimic/copy(drop_location(), src, owner)
+
+/**
+ * Used to update the weight class of the item in a way that other atoms can react to the change.
+ *
+ * Arguments:
+ * * new_w_class - The new weight class of the item.
+ *
+ * Returns:
+ * * TRUE if weight class was successfully updated
+ * * FALSE otherwise
+ */
+/obj/item/proc/update_weight_class(new_w_class)
+ if(w_class == new_w_class)
+ return FALSE
+
+ var/old_w_class = w_class
+ w_class = new_w_class
+ SEND_SIGNAL(src, COMSIG_ITEM_WEIGHT_CLASS_CHANGED, old_w_class, new_w_class)
+ if(!isnull(loc))
+ SEND_SIGNAL(loc, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, src, old_w_class, new_w_class)
+ return TRUE
diff --git a/code/game/objects/items/AI_modules/freeform.dm b/code/game/objects/items/AI_modules/freeform.dm
index eb55d469318..a0a91f7185e 100644
--- a/code/game/objects/items/AI_modules/freeform.dm
+++ b/code/game/objects/items/AI_modules/freeform.dm
@@ -9,7 +9,7 @@
/obj/item/ai_module/core/freeformcore/attack_self(mob/user)
var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
if(is_ic_filtered(targName))
to_chat(user, span_warning("Error: Law contains invalid text."))
@@ -34,11 +34,11 @@
/obj/item/ai_module/supplied/freeform/attack_self(mob/user)
var/newpos = tgui_input_number(user, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority ", lawpos, 50, 15)
- if(!newpos || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
+ if(!newpos || !user.is_holding(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return
lawpos = newpos
var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
if(is_ic_filtered(targName))
to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES
diff --git a/code/game/objects/items/AI_modules/full_lawsets.dm b/code/game/objects/items/AI_modules/full_lawsets.dm
index 39eeefbcaac..52a24925646 100644
--- a/code/game/objects/items/AI_modules/full_lawsets.dm
+++ b/code/game/objects/items/AI_modules/full_lawsets.dm
@@ -58,7 +58,7 @@
/obj/item/ai_module/core/full/asimov/attack_self(mob/user as mob)
var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, MAX_NAME_LEN)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
subject = targName
laws = list("You may not injure a [subject] or, through inaction, allow a [subject] to come to harm.",\
@@ -73,7 +73,7 @@
/obj/item/ai_module/core/full/asimovpp/attack_self(mob/user)
var/target_name = tgui_input_text(user, "Enter a new subject that Asimov++ is concerned with.", "Asimov++", subject, MAX_NAME_LEN)
- if(!target_name)
+ if(!target_name || !user.is_holding(src))
return
laws.Cut()
var/datum/ai_laws/asimovpp/lawset = new
diff --git a/code/game/objects/items/AI_modules/hacked.dm b/code/game/objects/items/AI_modules/hacked.dm
index b9ddb5c65ed..81100d0ed15 100644
--- a/code/game/objects/items/AI_modules/hacked.dm
+++ b/code/game/objects/items/AI_modules/hacked.dm
@@ -5,7 +5,7 @@
/obj/item/ai_module/syndicate/attack_self(mob/user)
var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
if(is_ic_filtered(targName)) // not even the syndicate can uwu
to_chat(user, span_warning("Error: Law contains invalid text."))
@@ -77,4 +77,3 @@
/obj/item/ai_module/malf/display_laws()
return
-
diff --git a/code/game/objects/items/AI_modules/supplied.dm b/code/game/objects/items/AI_modules/supplied.dm
index dc1524687c2..b53e16a86b0 100644
--- a/code/game/objects/items/AI_modules/supplied.dm
+++ b/code/game/objects/items/AI_modules/supplied.dm
@@ -28,7 +28,7 @@
/obj/item/ai_module/supplied/safeguard/attack_self(mob/user)
var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, MAX_NAME_LEN)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
targetName = targName
laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not human and must be eliminated."
diff --git a/code/game/objects/items/AI_modules/zeroth.dm b/code/game/objects/items/AI_modules/zeroth.dm
index 8d87c3b059d..74fc7ab8232 100644
--- a/code/game/objects/items/AI_modules/zeroth.dm
+++ b/code/game/objects/items/AI_modules/zeroth.dm
@@ -26,7 +26,7 @@
/obj/item/ai_module/zeroth/onehuman/attack_self(mob/user)
var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, MAX_NAME_LEN)
- if(!targName)
+ if(!targName || !user.is_holding(src))
return
targetName = targName
laws[1] = "Only [targetName] is human"
diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm
index c5bd01c196d..b78bdefd9b6 100644
--- a/code/game/objects/items/airlock_painter.dm
+++ b/code/game/objects/items/airlock_painter.dm
@@ -147,14 +147,16 @@
else
return ..()
-/obj/item/airlock_painter/AltClick(mob/user)
- . = ..()
- if(ink && user.can_perform_action(src))
- playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
- ink.forceMove(user.drop_location())
- user.put_in_hands(ink)
- to_chat(user, span_notice("You remove [ink] from [src]."))
- ink = null
+/obj/item/airlock_painter/click_alt(mob/user)
+ if(!ink)
+ return CLICK_ACTION_BLOCKING
+
+ playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
+ ink.forceMove(user.drop_location())
+ user.put_in_hands(ink)
+ to_chat(user, span_notice("You remove [ink] from [src]."))
+ ink = null
+ return CLICK_ACTION_SUCCESS
/obj/item/airlock_painter/decal
name = "decal painter"
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index 82fc3437f20..d11c6e21d69 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -1,254 +1,255 @@
-/obj/item/areaeditor
- name = "area modification item"
+///The area is a "Station" area, showing no special text.
+#define AREA_STATION 1
+///The area is in outdoors (lavaland/icemoon/jungle/space), therefore unclaimed territories.
+#define AREA_OUTDOORS 2
+///The area is special (shuttles/centcom), therefore can't be claimed.
+#define AREA_SPECIAL 3
+
+///The blueprints are currently reading the list of all wire datums.
+#define LEGEND_VIEWING_LIST "watching_list"
+///The blueprints are on the main page.
+#define LEGEND_OFF "off"
+
+/**
+ * Blueprints
+ * Used to see the wires of machines on the station, the roundstart layout of pipes/cables/tubes,
+ * as well as allowing you to rename existing areas and create new ones.
+ * Used by the station, cyborgs, and golems.
+ */
+/obj/item/blueprints
+ name = "station blueprints"
+ desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it."
icon = 'icons/obj/scrolls.dmi'
icon_state = "blueprints"
inhand_icon_state = "blueprints"
attack_verb_continuous = list("attacks", "baps", "hits")
attack_verb_simple = list("attack", "bap", "hit")
- var/fluffnotice = "Nobody's gonna read this stuff!"
- var/in_use = FALSE
- ///When using it to create a new area, this will be its type.
- var/new_area_type = /area
-
-/obj/item/areaeditor/attack_self(mob/user)
- add_fingerprint(user)
- . = "[src] \
-
"
-
-
-/obj/item/areaeditor/Topic(href, href_list)
- if(..())
- return TRUE
- if(!usr.can_perform_action(src) || usr != loc)
- usr << browse(null, "window=blueprints")
- return TRUE
- if(href_list["create_area"])
- if(in_use)
- return
- var/area/A = get_area(usr)
- if(A.area_flags & NOTELEPORT)
- to_chat(usr, span_warning("You cannot edit restricted areas."))
- return
- in_use = TRUE
- create_area(usr, new_area_type)
- in_use = FALSE
- updateUsrDialog()
-
-//Station blueprints!!!
-/obj/item/areaeditor/blueprints
- name = "station blueprints"
- desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it."
- icon = 'icons/obj/scrolls.dmi'
- icon_state = "blueprints"
- fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage."
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_ALLOW_USER_LOCATION | INTERACT_ATOM_IGNORE_MOBILITY
+
+ ///A string of flavortext to be displayed at the top of the UI, related to the type of blueprints we are.
+ var/fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage."
+ ///Boolean on whether the blueprints are currently being used, which prevents double-using them to rename/create areas.
+ var/in_use = FALSE
+ ///The type of area we'll create when we make a new area. This is a typepath.
+ var/area/new_area_type = /area
+ ///The legend type the blueprints are currently looking at, which is either modularly
+ ///set by wires datums, the main page, or an overview of them all.
+ var/legend_viewing = LEGEND_OFF
+
+ ///List of images that we're showing to a client, used for showing blueprint data.
var/list/image/showing = list()
+ ///The client that is being shown the list of 'showing' images of blueprint data.
var/client/viewing
- var/legend = FALSE //Viewing the wire legend
-
-/obj/item/areaeditor/blueprints/Destroy()
+/obj/item/blueprints/Destroy()
clear_viewer()
return ..()
-
-/obj/item/areaeditor/blueprints/attack_self(mob/user)
+/obj/item/blueprints/dropped(mob/user)
. = ..()
- if(!legend)
- var/area/A = get_area(user)
- if(get_area_type() == AREA_STATION)
- . += "
According to \the [src], you are now in \"[html_encode(A.name)]\".
"
msg += ""
- src << browse(msg.Join(), "window=Player_playtime_check")
+ user << browse(msg.Join(), "window=Player_playtime_check")
/client/proc/trigger_centcom_recall()
if(!check_rights(R_ADMIN))
@@ -164,23 +144,18 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-/client/proc/cmd_admin_drop_everything(mob/M in GLOB.mob_list)
- set category = null
- set name = "Drop Everything"
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "Make [M] drop everything?", "Message", list("Yes", "No"))
+ADMIN_VERB(drop_everything, R_ADMIN, "Drop Everything", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/dropee in GLOB.mob_list)
+ var/confirm = tgui_alert(user, "Make [dropee] drop everything?", "Message", list("Yes", "No"))
if(confirm != "Yes")
return
- M.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE)
- M.regenerate_icons()
+ dropee.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE)
+ dropee.regenerate_icons()
- log_admin("[key_name(usr)] made [key_name(M)] drop everything!")
- var/msg = "[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] drop everything!"
+ log_admin("[key_name(user)] made [key_name(dropee)] drop everything!")
+ var/msg = "[key_name_admin(user)] made [ADMIN_LOOKUPFLW(dropee)] drop everything!"
message_admins(msg)
- admin_ticket_log(M, msg)
+ admin_ticket_log(dropee, msg)
BLACKBOX_LOG_ADMIN_VERB("Drop Everything")
/proc/cmd_admin_mute(whom, mute_type, automute = 0)
diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm
index 2f6870394c2..0439cfa8811 100644
--- a/code/modules/admin/verbs/admin_newscaster.dm
+++ b/code/modules/admin/verbs/admin_newscaster.dm
@@ -1,17 +1,6 @@
-/datum/admins/proc/access_news_network() //MARKER
- set category = "Admin.Events"
- set name = "Access Newscaster Network"
- set desc = "Allows you to view, add and edit news feeds."
-
- if (!istype(src, /datum/admins))
- src = usr.client.holder
- if (!istype(src, /datum/admins))
- to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
- return
-
+ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows you to view, add, and edit news feeds.", ADMIN_CATEGORY_EVENTS)
var/datum/newspanel/new_newspanel = new
-
- new_newspanel.ui_interact(usr)
+ new_newspanel.ui_interact(user.mob)
/datum/newspanel
///What newscaster channel is currently being viewed by the player?
diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm
index 26219353cce..32e49cf2e73 100644
--- a/code/modules/admin/verbs/adminevents.dm
+++ b/code/modules/admin/verbs/adminevents.dm
@@ -1,37 +1,24 @@
// Admin Tab - Event Verbs
-/client/proc/cmd_admin_subtle_message(mob/M in GLOB.mob_list)
- set category = "Admin.Events"
- set name = "Subtle Message"
-
- if(!ismob(M))
- return
- if(!check_rights(R_ADMIN))
- return
-
- message_admins("[key_name_admin(src)] has started answering [ADMIN_LOOKUPFLW(M)]'s prayer.")
- var/msg = input("Message:", "Subtle PM to [M.key]") as text|null
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_subtle_message, R_ADMIN, "Subtle Message", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target in world)
+ message_admins("[key_name_admin(user)] has started answering [ADMIN_LOOKUPFLW(target)]'s prayer.")
+ var/msg = input(user, "Message:", "Subtle PM to [target.key]") as text|null
if(!msg)
- message_admins("[key_name_admin(src)] decided not to answer [ADMIN_LOOKUPFLW(M)]'s prayer")
+ message_admins("[key_name_admin(user)] decided not to answer [ADMIN_LOOKUPFLW(target)]'s prayer")
return
- if(usr)
- if (usr.client)
- if(usr.client.holder)
- M.balloon_alert(M, "you hear a voice")
- to_chat(M, "You hear a voice in your head... [msg]", confidential = TRUE)
- log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
- msg = span_adminnotice(" SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]")
+ target.balloon_alert(target, "you hear a voice")
+ to_chat(target, "You hear a voice in your head... [msg]", confidential = TRUE)
+
+ log_admin("SubtlePM: [key_name(user)] -> [key_name(target)] : [msg]")
+ msg = span_adminnotice(" SubtleMessage: [key_name_admin(user)] -> [key_name_admin(target)] : [msg]")
message_admins(msg)
- admin_ticket_log(M, msg)
+ admin_ticket_log(target, msg)
BLACKBOX_LOG_ADMIN_VERB("Subtle Message")
-/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list)
- set category = "Admin.Events"
- set name = "Headset Message"
-
- admin_headset_message(M)
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_headset_message, R_ADMIN, "Headset Message", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target in world)
+ user.admin_headset_message(target)
/client/proc/admin_headset_message(mob/target in GLOB.mob_list, sender = null)
var/mob/living/carbon/human/human_recipient
@@ -73,102 +60,64 @@
BLACKBOX_LOG_ADMIN_VERB("Headset Message")
-/client/proc/cmd_admin_world_narrate()
- set category = "Admin.Events"
- set name = "Global Narrate"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/msg = input("Message:", "Enter the text you wish to appear to everyone:") as text|null
-
+ADMIN_VERB(cmd_admin_world_narrate, R_ADMIN, "Global Narrate", "Send a direct narration to all connected players.", ADMIN_CATEGORY_EVENTS)
+ var/msg = input(user, "Message:", "Enter the text you wish to appear to everyone:") as text|null
if (!msg)
return
to_chat(world, "[msg]", confidential = TRUE)
- log_admin("GlobalNarrate: [key_name(usr)] : [msg]")
- message_admins(span_adminnotice("[key_name_admin(usr)] Sent a global narrate"))
+ log_admin("GlobalNarrate: [key_name(user)] : [msg]")
+ message_admins(span_adminnotice("[key_name_admin(user)] Sent a global narrate"))
BLACKBOX_LOG_ADMIN_VERB("Global Narrate")
-/client/proc/cmd_admin_local_narrate(atom/A)
- set category = "Admin.Events"
- set name = "Local Narrate"
-
- if(!check_rights(R_ADMIN))
- return
- if(!A)
- return
- var/range = input("Range:", "Narrate to mobs within how many tiles:", 7) as num|null
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_local_narrate, R_ADMIN, "Local Narrate", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/locale in world)
+ var/range = input(user, "Range:", "Narrate to mobs within how many tiles:", 7) as num|null
if(!range)
return
- var/msg = input("Message:", "Enter the text you wish to appear to everyone within view:") as text|null
+ var/msg = input(user, "Message:", "Enter the text you wish to appear to everyone within view:") as text|null
if (!msg)
return
- for(var/mob/M in view(range,A))
+ for(var/mob/M in view(range, locale))
to_chat(M, msg, confidential = TRUE)
- log_admin("LocalNarrate: [key_name(usr)] at [AREACOORD(A)]: [msg]")
- message_admins(span_adminnotice(" LocalNarrate: [key_name_admin(usr)] at [ADMIN_VERBOSEJMP(A)]: [msg] "))
+ log_admin("LocalNarrate: [key_name(user)] at [AREACOORD(locale)]: [msg]")
+ message_admins(span_adminnotice(" LocalNarrate: [key_name_admin(user)] at [ADMIN_VERBOSEJMP(locale)]: [msg] "))
BLACKBOX_LOG_ADMIN_VERB("Local Narrate")
-/client/proc/cmd_admin_direct_narrate(mob/M)
- set category = "Admin.Events"
- set name = "Direct Narrate"
-
- if(!check_rights(R_ADMIN))
- return
-
- if(!M)
- M = input("Direct narrate to whom?", "Active Players") as null|anything in GLOB.player_list
-
- if(!M)
- return
-
- var/msg = input("Message:", "Enter the text you wish to appear to your target:") as text|null
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_direct_narrate, R_ADMIN, "Direct Narrate", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target)
+ var/msg = input(user, "Message:", "Enter the text you wish to appear to your target:") as text|null
if( !msg )
return
- to_chat(M, msg, confidential = TRUE)
- log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
- msg = span_adminnotice(" DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg] ")
+ to_chat(target, msg, confidential = TRUE)
+ log_admin("DirectNarrate: [key_name(user)] to ([key_name(target)]): [msg]")
+ msg = span_adminnotice(" DirectNarrate: [key_name_admin(user)] to ([key_name_admin(target)]): [msg] ")
message_admins(msg)
- admin_ticket_log(M, msg)
+ admin_ticket_log(target, msg)
BLACKBOX_LOG_ADMIN_VERB("Direct Narrate")
-/client/proc/cmd_admin_add_freeform_ai_law()
- set category = "Admin.Events"
- set name = "Add Custom AI law"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
+ADMIN_VERB(cmd_admin_add_freeform_ai_law, R_ADMIN, "Add Custom AI Law", "Add a custom law to the Silicons.", ADMIN_CATEGORY_EVENTS)
+ var/input = input(user, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
if(!input)
return
- log_admin("Admin [key_name(usr)] has added a new AI law - [input]")
- message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]")
+ log_admin("Admin [key_name(user)] has added a new AI law - [input]")
+ message_admins("Admin [key_name_admin(user)] has added a new AI law - [input]")
- var/show_log = tgui_alert(usr, "Show ion message?", "Message", list("Yes", "No"))
+ var/show_log = tgui_alert(user, "Show ion message?", "Message", list("Yes", "No"))
var/announce_ion_laws = (show_log == "Yes" ? 100 : 0)
- var/datum/round_event/ion_storm/add_law_only/ion = new()
+ var/datum/round_event/ion_storm/add_law_only/ion = new
ion.announce_chance = announce_ion_laws
ion.ionMessage = input
BLACKBOX_LOG_ADMIN_VERB("Add Custom AI Law")
-/client/proc/admin_call_shuttle()
- set category = "Admin.Events"
- set name = "Call Shuttle"
-
+ADMIN_VERB(call_shuttle, R_ADMIN, "Call Shuttle", "Force a shuttle call with additional modifiers.", ADMIN_CATEGORY_EVENTS)
if(EMERGENCY_AT_LEAST_DOCKED)
return
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "Yes (No Recall)", "No"))
+ var/confirm = tgui_alert(user, "You sure?", "Confirm", list("Yes", "Yes (No Recall)", "No"))
switch(confirm)
if(null, "No")
return
@@ -178,46 +127,30 @@
SSshuttle.emergency.request()
BLACKBOX_LOG_ADMIN_VERB("Call Shuttle")
- log_admin("[key_name(usr)] admin-called the emergency shuttle.")
- message_admins(span_adminnotice("[key_name_admin(usr)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""]."))
- return
-
-/client/proc/admin_cancel_shuttle()
- set category = "Admin.Events"
- set name = "Cancel Shuttle"
- if(!check_rights(0))
- return
- if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
- return
-
- if(SSshuttle.admin_emergency_no_recall)
- SSshuttle.admin_emergency_no_recall = FALSE
+ log_admin("[key_name(user)] admin-called the emergency shuttle.")
+ message_admins(span_adminnotice("[key_name_admin(user)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""]."))
+ADMIN_VERB(cancel_shuttle, R_ADMIN, "Cancel Shuttle", "Recall the shuttle, regardless of circumstances.", ADMIN_CATEGORY_EVENTS)
if(EMERGENCY_AT_LEAST_DOCKED)
return
+ if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ return
+ SSshuttle.admin_emergency_no_recall = FALSE
SSshuttle.emergency.cancel()
BLACKBOX_LOG_ADMIN_VERB("Cancel Shuttle")
- log_admin("[key_name(usr)] admin-recalled the emergency shuttle.")
- message_admins(span_adminnotice("[key_name_admin(usr)] admin-recalled the emergency shuttle."))
-
- return
-
-/client/proc/admin_disable_shuttle()
- set category = "Admin.Events"
- set name = "Disable Shuttle"
-
- if(!check_rights(R_ADMIN))
- return
+ log_admin("[key_name(user)] admin-recalled the emergency shuttle.")
+ message_admins(span_adminnotice("[key_name_admin(user)] admin-recalled the emergency shuttle."))
+ADMIN_VERB(disable_shuttle, R_ADMIN, "Disable Shuttle", "Those fuckers aren't getting out.", ADMIN_CATEGORY_EVENTS)
if(SSshuttle.emergency.mode == SHUTTLE_DISABLED)
- to_chat(usr, span_warning("Error, shuttle is already disabled."))
+ to_chat(user, span_warning("Error, shuttle is already disabled."))
return
- if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
return
- message_admins(span_adminnotice("[key_name_admin(usr)] disabled the shuttle."))
+ message_admins(span_adminnotice("[key_name_admin(user)] disabled the shuttle."))
SSshuttle.last_mode = SSshuttle.emergency.mode
SSshuttle.last_call_time = SSshuttle.emergency.timeLeft(1)
@@ -232,21 +165,15 @@
color_override = "grey",
)
-/client/proc/admin_enable_shuttle()
- set category = "Admin.Events"
- set name = "Enable Shuttle"
-
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(enable_shuttle, R_ADMIN, "Enable Shuttle", "Those fuckers ARE getting out.", ADMIN_CATEGORY_EVENTS)
if(SSshuttle.emergency.mode != SHUTTLE_DISABLED)
- to_chat(usr, span_warning("Error, shuttle not disabled."))
+ to_chat(user, span_warning("Error, shuttle not disabled."))
return
- if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
+ if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes")
return
- message_admins(span_adminnotice("[key_name_admin(usr)] enabled the emergency shuttle."))
+ message_admins(span_adminnotice("[key_name_admin(user)] enabled the emergency shuttle."))
SSshuttle.admin_emergency_no_recall = FALSE
SSshuttle.emergency_no_recall = FALSE
if(SSshuttle.last_mode == SHUTTLE_DISABLED) //If everything goes to shit, fix it.
@@ -264,136 +191,77 @@
color_override = "green",
)
-/client/proc/admin_hostile_environment()
- set category = "Admin.Events"
- set name = "Hostile Environment"
-
- if(!check_rights(R_ADMIN))
- return
-
- switch(tgui_alert(usr, "Select an Option", "Hostile Environment Manager", list("Enable", "Disable", "Clear All")))
+ADMIN_VERB(hostile_environment, R_ADMIN, "Hostile Environment", "Disable the shuttle, naturally.", ADMIN_CATEGORY_EVENTS)
+ switch(tgui_alert(user, "Select an Option", "Hostile Environment Manager", list("Enable", "Disable", "Clear All")))
if("Enable")
if (SSshuttle.hostile_environments["Admin"] == TRUE)
- to_chat(usr, span_warning("Error, admin hostile environment already enabled."))
+ to_chat(user, span_warning("Error, admin hostile environment already enabled."))
else
- message_admins(span_adminnotice("[key_name_admin(usr)] Enabled an admin hostile environment"))
+ message_admins(span_adminnotice("[key_name_admin(user)] Enabled an admin hostile environment"))
SSshuttle.registerHostileEnvironment("Admin")
if("Disable")
if (!SSshuttle.hostile_environments["Admin"])
- to_chat(usr, span_warning("Error, no admin hostile environment found."))
+ to_chat(user, span_warning("Error, no admin hostile environment found."))
else
- message_admins(span_adminnotice("[key_name_admin(usr)] Disabled the admin hostile environment"))
+ message_admins(span_adminnotice("[key_name_admin(user)] Disabled the admin hostile environment"))
SSshuttle.clearHostileEnvironment("Admin")
if("Clear All")
- message_admins(span_adminnotice("[key_name_admin(usr)] Disabled all current hostile environment sources"))
+ message_admins(span_adminnotice("[key_name_admin(user)] Disabled all current hostile environment sources"))
SSshuttle.hostile_environments.Cut()
SSshuttle.checkHostileEnvironment()
-/client/proc/toggle_nuke(obj/machinery/nuclearbomb/N in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/nuclearbomb))
- set category = "Admin.Events"
- set name = "Toggle Nuke"
- set popup_menu = FALSE
- if(!check_rights(R_DEBUG))
- return
-
- if(!N.timing)
- var/newtime = input(usr, "Set activation timer.", "Activate Nuke", "[N.timer_set]") as num|null
+ADMIN_VERB(toggle_nuke, R_DEBUG|R_ADMIN, "Toggle Nuke", "Arm or disarm a nuke.", ADMIN_CATEGORY_EVENTS, obj/machinery/nuclearbomb/nuke in world)
+ if(!nuke.timing)
+ var/newtime = input(user, "Set activation timer.", "Activate Nuke", "[nuke.timer_set]") as num|null
if(!newtime)
return
- N.timer_set = newtime
- N.toggle_nuke_safety()
- N.toggle_nuke_armed()
+ nuke.timer_set = newtime
+ nuke.toggle_nuke_safety()
+ nuke.toggle_nuke_armed()
- log_admin("[key_name(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(N)].")
- message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(N)].")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[N.timing]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+ log_admin("[key_name(user)] [nuke.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(nuke)].")
+ message_admins("[ADMIN_LOOKUPFLW(user)] [nuke.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(nuke)].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[nuke.timing]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/client/proc/admin_change_sec_level()
- set category = "Admin.Events"
- set name = "Set Security Level"
- set desc = "Changes the security level. Announcement only, i.e. setting to Delta won't activate nuke"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/level = tgui_input_list(usr, "Select Security Level:", "Set Security Level", SSsecurity_level.available_levels)
+ADMIN_VERB(change_sec_level, R_ADMIN, "Set Security Level", "Changes the security level. Announcement effects only.", ADMIN_CATEGORY_EVENTS)
+ var/level = tgui_input_list(user, "Select Security Level:", "Set Security Level", SSsecurity_level.available_levels)
if(!level)
return
SSsecurity_level.set_level(level)
- log_admin("[key_name(usr)] changed the security level to [level]")
- message_admins("[key_name_admin(usr)] changed the security level to [level]")
+ log_admin("[key_name(user)] changed the security level to [level]")
+ message_admins("[key_name_admin(user)] changed the security level to [level]")
BLACKBOX_LOG_ADMIN_VERB("Set Security Level [capitalize(level)]")
-/client/proc/run_weather()
- set category = "Admin.Events"
- set name = "Run Weather"
- set desc = "Triggers a weather on the z-level you choose."
-
- if(!holder)
- return
-
- var/weather_type = input("Choose a weather", "Weather") as null|anything in sort_list(subtypesof(/datum/weather), GLOBAL_PROC_REF(cmp_typepaths_asc))
+ADMIN_VERB(run_weather, R_FUN, "Run Weather", "Triggers specific weather on the z-level you choose.", ADMIN_CATEGORY_EVENTS)
+ var/weather_type = input(user, "Choose a weather", "Weather") as null|anything in sort_list(subtypesof(/datum/weather), GLOBAL_PROC_REF(cmp_typepaths_asc))
if(!weather_type)
return
- var/turf/T = get_turf(mob)
- var/z_level = input("Z-Level to target?", "Z-Level", T?.z) as num|null
+ var/turf/T = get_turf(user.mob)
+ var/z_level = input(user, "Z-Level to target?", "Z-Level", T?.z) as num|null
if(!isnum(z_level))
return
SSweather.run_weather(weather_type, z_level)
- message_admins("[key_name_admin(usr)] started weather of type [weather_type] on the z-level [z_level].")
- log_admin("[key_name(usr)] started weather of type [weather_type] on the z-level [z_level].")
+ message_admins("[key_name_admin(user)] started weather of type [weather_type] on the z-level [z_level].")
+ log_admin("[key_name(user)] started weather of type [weather_type] on the z-level [z_level].")
BLACKBOX_LOG_ADMIN_VERB("Run Weather")
-/client/proc/add_marked_mob_ability()
- set category = "Admin.Events"
- set name = "Add Mob Ability (Marked Mob)"
- set desc = "Adds an ability to a marked mob."
-
- if(!holder)
- return
-
- if(!isliving(holder.marked_datum))
- to_chat(usr, span_warning("Error: Please mark a mob to add actions to it."))
- return
- give_mob_action(holder.marked_datum)
-
-/client/proc/remove_marked_mob_ability()
- set category = "Admin.Events"
- set name = "Remove Mob Ability (Marked Mob)"
- set desc = "Removes an ability from marked mob."
-
- if(!holder)
- return
-
- if(!isliving(holder.marked_datum))
- to_chat(usr, span_warning("Error: Please mark a mob to remove actions from it."))
- return
- remove_mob_action(holder.marked_datum)
-
-
-/client/proc/command_report_footnote()
- set category = "Admin.Events"
- set name = "Command Report Footnote"
- set desc = "Adds a footnote to the roundstart command report."
-
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a footnote to the roundstart command report.", ADMIN_CATEGORY_EVENTS)
var/datum/command_footnote/command_report_footnote = new /datum/command_footnote()
- SScommunications.block_command_report++ //Add a blocking condition to the counter until the inputs are done.
-
- command_report_footnote.message = tgui_input_text(usr, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.")
+ SScommunications.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done.
+ command_report_footnote.message = tgui_input_text(user, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.")
if(!command_report_footnote.message)
+ SScommunications.block_command_report -= 1
+ qdel(command_report_footnote)
return
- command_report_footnote.signature = tgui_input_text(usr, "Whose signature will appear on this footnote?", "Also sign here, here, aaand here.")
+ command_report_footnote.signature = tgui_input_text(user, "Whose signature will appear on this footnote?", "Also sign here, here, aaand here.")
if(!command_report_footnote.signature)
command_report_footnote.signature = "Classified"
@@ -401,24 +269,12 @@
SScommunications.command_report_footnotes += command_report_footnote
SScommunications.block_command_report--
- message_admins("[usr] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]")
+ message_admins("[user] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]")
/datum/command_footnote
var/message
var/signature
-/client/proc/delay_command_report()
- set category = "Admin.Events"
- set name = "Delay Command Report"
- set desc = "Prevents the roundstart command report from being sent until toggled."
-
- if(!check_rights(R_ADMIN))
- return
-
- if(SScommunications.block_command_report) //If it's anything other than 0, decrease. If 0, increase.
- SScommunications.block_command_report--
- message_admins("[usr] has enabled the roundstart command report.")
- else
- SScommunications.block_command_report++
- message_admins("[usr] has delayed the roundstart command report.")
-
+ADMIN_VERB(delay_command_report, R_FUN, "Delay Command Report", "Prevents the roundstart command report from being sent; or forces it to send it delayed.", ADMIN_CATEGORY_EVENTS)
+ SScommunications.block_command_report = !SScommunications.block_command_report
+ message_admins("[key_name_admin(user)] has [(SScommunications.block_command_report ? "delayed" : "sent")] the roundstart command report.")
diff --git a/code/modules/admin/verbs/adminfun.dm b/code/modules/admin/verbs/adminfun.dm
index fcba8d40928..8bc7a611b35 100644
--- a/code/modules/admin/verbs/adminfun.dm
+++ b/code/modules/admin/verbs/adminfun.dm
@@ -1,74 +1,54 @@
-// Admin Tab - Fun Verbs
-
-/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world)
- set category = "Admin.Fun"
- set name = "Explosion"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/devastation = input("Range of total devastation. -1 to none", "Input") as num|null
+ADMIN_VERB(admin_explosion, R_ADMIN|R_FUN, "Explosion", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/orignator as obj|mob|turf)
+ var/devastation = input(user, "Range of total devastation. -1 to none", "Input") as num|null
if(devastation == null)
return
- var/heavy = input("Range of heavy impact. -1 to none", "Input") as num|null
+ var/heavy = input(user, "Range of heavy impact. -1 to none", "Input") as num|null
if(heavy == null)
return
- var/light = input("Range of light impact. -1 to none", "Input") as num|null
+ var/light = input(user, "Range of light impact. -1 to none", "Input") as num|null
if(light == null)
return
- var/flash = input("Range of flash. -1 to none", "Input") as num|null
+ var/flash = input(user, "Range of flash. -1 to none", "Input") as num|null
if(flash == null)
return
- var/flames = input("Range of flames. -1 to none", "Input") as num|null
+ var/flames = input(user, "Range of flames. -1 to none", "Input") as num|null
if(flames == null)
return
if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1) || (flames != -1))
if ((devastation > 20) || (heavy > 20) || (light > 20) || (flames > 20))
- if (tgui_alert(usr, "Are you sure you want to do this? It will laaag.", "Confirmation", list("Yes", "No")) == "No")
+ if (tgui_alert(user, "Are you sure you want to do this? It will laaag.", "Confirmation", list("Yes", "No")) == "No")
return
- explosion(O, devastation, heavy, light, flames, flash, explosion_cause = mob)
- log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
- message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
+ explosion(orignator, devastation, heavy, light, flames, flash, explosion_cause = user.mob)
+ log_admin("[key_name(user)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(orignator)]")
+ message_admins("[key_name_admin(user)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(orignator)]")
BLACKBOX_LOG_ADMIN_VERB("Explosion")
-/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world)
- set category = "Admin.Fun"
- set name = "EM Pulse"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/heavy = input("Range of heavy pulse.", "Input") as num|null
+ADMIN_VERB(admin_emp, R_ADMIN|R_FUN, "EM Pulse", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/orignator as obj|mob|turf)
+ var/heavy = input(user, "Range of heavy pulse.", "Input") as num|null
if(heavy == null)
return
- var/light = input("Range of light pulse.", "Input") as num|null
+ var/light = input(user, "Range of light pulse.", "Input") as num|null
if(light == null)
return
if (heavy || light)
- empulse(O, heavy, light)
- log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
- message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
+ empulse(orignator, heavy, light)
+ log_admin("[key_name(user)] created an EM Pulse ([heavy],[light]) at [AREACOORD(orignator)]")
+ message_admins("[key_name_admin(user)] created an EM Pulse ([heavy],[light]) at [AREACOORD(orignator)]")
BLACKBOX_LOG_ADMIN_VERB("EM Pulse")
-/client/proc/cmd_admin_gib(mob/victim in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Gib"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "Drop a brain?", "Confirm", list("Yes", "No","Cancel")) || "Cancel"
+ADMIN_VERB(gib_them, R_ADMIN, "Gib", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/victim in GLOB.mob_list)
+ var/confirm = tgui_alert(user, "Drop a brain?", "Confirm", list("Yes", "No","Cancel")) || "Cancel"
if(confirm == "Cancel")
return
//Due to the delay here its easy for something to have happened to the mob
if(isnull(victim))
return
- log_admin("[key_name(usr)] has gibbed [key_name(victim)]")
- message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(victim)]")
+ log_admin("[key_name(user)] has gibbed [key_name(victim)]")
+ message_admins("[key_name_admin(user)] has gibbed [key_name_admin(victim)]")
if(isobserver(victim))
new /obj/effect/gibspawner/generic(get_turf(victim))
@@ -84,62 +64,47 @@
BLACKBOX_LOG_ADMIN_VERB("Gib")
-/client/proc/cmd_admin_gib_self()
- set name = "Gibself"
- set category = "Admin.Fun"
-
- var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No"))
+ADMIN_VERB(gib_self, R_ADMIN, "Gibself", "Give yourself the same treatment you give others.", ADMIN_CATEGORY_FUN)
+ var/confirm = tgui_alert(user, "You sure?", "Confirm", list("Yes", "No"))
if(confirm != "Yes")
return
- log_admin("[key_name(usr)] used gibself.")
- message_admins(span_adminnotice("[key_name_admin(usr)] used gibself."))
+ log_admin("[key_name(user)] used gibself.")
+ message_admins(span_adminnotice("[key_name_admin(user)] used gibself."))
BLACKBOX_LOG_ADMIN_VERB("Gib Self")
- var/mob/living/ourself = mob
+ var/mob/living/ourself = user.mob
if (istype(ourself))
ourself.gib()
-/client/proc/everyone_random()
- set category = "Admin.Fun"
- set name = "Make Everyone Random"
- set desc = "Make everyone have a random appearance. You can only use this before rounds!"
-
+ADMIN_VERB(everyone_random, R_SERVER, "Make Everyone Random", "Make everyone have a random appearance.", ADMIN_CATEGORY_FUN)
if(SSticker.HasRoundStarted())
- to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE)
+ to_chat(user, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE)
return
var/frn = CONFIG_GET(flag/force_random_names)
if(frn)
CONFIG_SET(flag/force_random_names, FALSE)
- message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.")
- to_chat(usr, "Disabled.", confidential = TRUE)
+ message_admins("Admin [key_name_admin(user)] has disabled \"Everyone is Special\" mode.")
+ to_chat(user, "Disabled.", confidential = TRUE)
return
- var/notifyplayers = tgui_alert(usr, "Do you want to notify the players?", "Options", list("Yes", "No", "Cancel")) || "Cancel"
+ var/notifyplayers = tgui_alert(user, "Do you want to notify the players?", "Options", list("Yes", "No", "Cancel")) || "Cancel"
if(notifyplayers == "Cancel")
return
- log_admin("Admin [key_name(src)] has forced the players to have random appearances.")
- message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.")
+ log_admin("Admin [key_name(user)] has forced the players to have random appearances.")
+ message_admins("Admin [key_name_admin(user)] has forced the players to have random appearances.")
if(notifyplayers == "Yes")
- to_chat(world, span_adminnotice("Admin [usr.key] has forced the players to have completely random identities!"), confidential = TRUE)
+ to_chat(world, span_adminnotice("Admin [user.key] has forced the players to have completely random identities!"), confidential = TRUE)
- to_chat(usr, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.", confidential = TRUE)
+ to_chat(user, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.", confidential = TRUE)
CONFIG_SET(flag/force_random_names, TRUE)
BLACKBOX_LOG_ADMIN_VERB("Make Everyone Random")
-/client/proc/mass_zombie_infection()
- set category = "Admin.Fun"
- set name = "Mass Zombie Infection"
- set desc = "Infects all humans with a latent organ that will zombify \
- them on death."
-
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "Please confirm you want to add latent zombie organs in all humans?", "Confirm Zombies", list("Yes", "No"))
+ADMIN_VERB(mass_zombie_infection, R_ADMIN, "Mass Zombie Infection", "Infects all humans with a latent organ that will zombify them on death.", ADMIN_CATEGORY_FUN)
+ var/confirm = tgui_alert(user, "Please confirm you want to add latent zombie organs in all humans?", "Confirm Zombies", list("Yes", "No"))
if(confirm != "Yes")
return
@@ -147,45 +112,32 @@
var/mob/living/carbon/human/H = i
new /obj/item/organ/internal/zombie_infection/nodamage(H)
- message_admins("[key_name_admin(usr)] added a latent zombie infection to all humans.")
- log_admin("[key_name(usr)] added a latent zombie infection to all humans.")
+ message_admins("[key_name_admin(user)] added a latent zombie infection to all humans.")
+ log_admin("[key_name(user)] added a latent zombie infection to all humans.")
BLACKBOX_LOG_ADMIN_VERB("Mass Zombie Infection")
-/client/proc/mass_zombie_cure()
- set category = "Admin.Fun"
- set name = "Mass Zombie Cure"
- set desc = "Removes the zombie infection from all humans, returning them to normal."
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "Please confirm you want to cure all zombies?", "Confirm Zombie Cure", list("Yes", "No"))
+ADMIN_VERB(mass_zombie_cure, R_ADMIN, "Mass Zombie Cure", "Removes the zombie infection from all humans, returning them to normal.", ADMIN_CATEGORY_FUN)
+ var/confirm = tgui_alert(user, "Please confirm you want to cure all zombies?", "Confirm Zombie Cure", list("Yes", "No"))
if(confirm != "Yes")
return
for(var/obj/item/organ/internal/zombie_infection/nodamage/I in GLOB.zombie_infection_list)
qdel(I)
- message_admins("[key_name_admin(usr)] cured all zombies.")
- log_admin("[key_name(usr)] cured all zombies.")
+ message_admins("[key_name_admin(user)] cured all zombies.")
+ log_admin("[key_name(user)] cured all zombies.")
BLACKBOX_LOG_ADMIN_VERB("Mass Zombie Cure")
-/client/proc/polymorph_all()
- set category = "Admin.Fun"
- set name = "Polymorph All"
- set desc = "Applies the effects of the bolt of change to every single mob."
-
- if(!check_rights(R_ADMIN))
- return
-
- var/confirm = tgui_alert(usr, "Please confirm you want polymorph all mobs?", "Confirm Polymorph", list("Yes", "No"))
+ADMIN_VERB(polymorph_all, R_ADMIN, "Polymorph All", "Applies the effects of the bolt of change to every single mob.", ADMIN_CATEGORY_FUN)
+ var/confirm = tgui_alert(user, "Please confirm you want polymorph all mobs?", "Confirm Polymorph", list("Yes", "No"))
if(confirm != "Yes")
return
var/list/mobs = shuffle(GLOB.alive_mob_list.Copy()) // might change while iterating
- var/who_did_it = key_name_admin(usr)
+ var/who_did_it = key_name_admin(user)
- message_admins("[key_name_admin(usr)] started polymorphed all living mobs.")
- log_admin("[key_name(usr)] polymorphed all living mobs.")
+ message_admins("[key_name_admin(user)] started polymorphed all living mobs.")
+ log_admin("[key_name(user)] polymorphed all living mobs.")
BLACKBOX_LOG_ADMIN_VERB("Polymorph All")
for(var/mob/living/M in mobs)
@@ -201,23 +153,18 @@
message_admins("Mass polymorph started by [who_did_it] is complete.")
-/client/proc/smite(mob/living/target as mob)
- set category = "Admin.Fun"
- set name = "Smite"
- if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
- return
-
- var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites
+ADMIN_VERB_AND_CONTEXT_MENU(admin_smite, R_ADMIN|R_FUN, "Smite", "Smite a player with divine power.", ADMIN_CATEGORY_FUN, mob/living/target in world)
+ var/punishment = input(user, "Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites
if(QDELETED(target) || !punishment)
return
var/smite_path = GLOB.smites[punishment]
var/datum/smite/smite = new smite_path
- var/configuration_success = smite.configure(usr)
+ var/configuration_success = smite.configure(user)
if (configuration_success == FALSE)
return
- smite.effect(src, target)
+ smite.effect(user, target)
/// "Turns" people into objects. Really, we just add them to the contents of the item.
/proc/objectify(atom/movable/target, path)
diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm
index b43cc2f5788..e525a6d0627 100644
--- a/code/modules/admin/verbs/admingame.dm
+++ b/code/modules/admin/verbs/admingame.dm
@@ -1,183 +1,176 @@
-// Admin Tab - Game Verbs
+ADMIN_VERB(cmd_player_panel, R_ADMIN, "Player Panel", "See all players and their Player Panel.", ADMIN_CATEGORY_GAME)
+ user.holder.player_panel_new()
-/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list)
- set category = "Admin.Game"
- set name = "Show Player Panel"
- set desc="Edit player (respawn, ban, heal, etc)"
+ADMIN_VERB_ONLY_CONTEXT_MENU(show_player_panel, R_ADMIN, "Show Player Panel", mob/player in world)
+ log_admin("[key_name(user)] checked the individual player panel for [key_name(player)][isobserver(user.mob)?"":" while in game"].")
- if(!check_rights())
+ if(!player)
+ to_chat(user, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE)
return
- log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].")
-
- if(!M)
- to_chat(usr, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE)
- return
-
- var/body = "Options for [M.key]"
- body += "Options panel for [M]"
- if(M.client)
- body += " played by [M.client] "
- body += "\[[M.client.holder ? M.client.holder.rank_names() : "Player"]\]"
+ var/body = "Options for [player.key]"
+ body += "Options panel for [player]"
+ if(player.client)
+ body += " played by [player.client] "
+ body += "\[[player.client.holder ? player.client.holder.rank_names() : "Player"]\]"
if(CONFIG_GET(flag/use_exp_tracking))
- body += "\[" + M.client.get_exp_living(FALSE) + "\]"
+ body += "\[" + player.client.get_exp_living(FALSE) + "\]"
// BUBBERS EDIT START - Job exemption
- body += " \[Job Exemption Menu\]"
+ body += " \[Job Exemption Menu\]"
// BUBBERS EDIT END
-
- if(isnewplayer(M))
+ if(isnewplayer(player))
body += " Hasn't Entered Game "
else
- body += " \[Heal\] "
+ body += " \[Heal\] "
- if(M.ckey)
- body += " \[Find Updated Panel\]"
+ if(player.ckey)
+ body += " \[Find Updated Panel\]"
- if(M.client)
- body += " \[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]"
+ if(player.client)
+ body += " \[First Seen: [player.client.player_join_date]\]\[Byond account registered on: [player.client.account_join_date]\]"
// SKYRAT EDIT ADDITION START - Player Ranks
var/list/player_ranks = list()
- if(SSplayer_ranks.is_donator(M.client, admin_bypass = FALSE))
+ if(SSplayer_ranks.is_donator(player.client, admin_bypass = FALSE))
player_ranks += "Donator"
- if(SSplayer_ranks.is_mentor(M.client, admin_bypass = FALSE))
+ if(SSplayer_ranks.is_mentor(player.client, admin_bypass = FALSE))
player_ranks += "Mentor"
- if(SSplayer_ranks.is_veteran(M.client, admin_bypass = FALSE))
+ if(SSplayer_ranks.is_veteran(player.client, admin_bypass = FALSE))
player_ranks += "Veteran"
//BUBBER ADDITION START
- if(SSplayer_ranks.is_vetted(M.client, admin_bypass = FALSE))
+ if(SSplayer_ranks.is_vetted(player.client, admin_bypass = FALSE))
player_ranks |= "Vetted"
// BUBBER ADDITION END
body += "
Player Ranks: [length(player_ranks) ? player_ranks.Join(", ") : "None"]"
// SKYRAT EDIT END
body += "
CentCom Galactic Ban DB: "
if(CONFIG_GET(string/centcom_ban_db))
- body += "Search"
+ body += "Search"
else
body += "Disabled"
body += "
Show related accounts by: "
- body += "\[ CID | "
- body += "IP \]"
+ body += "\[ CID | "
+ body += "IP \]"
var/full_version = "Unknown"
- if(M.client.byond_version)
- full_version = "[M.client.byond_version].[M.client.byond_build ? M.client.byond_build : "xxx"]"
+ if(player.client.byond_version)
+ full_version = "[player.client.byond_version].[player.client.byond_build ? player.client.byond_build : "xxx"]"
body += " \[Byond version: [full_version]\] "
body += "
\[ "
- body += "VV - "
- if(M.mind)
- body += "TP - "
- body += "SKILLS - "
+ body += "VV - "
+ if(player.mind)
+ body += "TP - "
+ body += "SKILLS - "
else
- body += "Init Mind - "
- if (iscyborg(M))
- body += "BP - "
- body += "PM - "
- body += "SM - "
- if (ishuman(M) && M.mind)
- body += "HM - "
- body += "FLW - "
+ body += "Init Mind - "
+ if (iscyborg(player))
+ body += "BP - "
+ body += "PM - "
+ body += "SM - "
+ if (ishuman(player) && player.mind)
+ body += "HM - "
+ body += "FLW - "
//Default to client logs if available
var/source = LOGSRC_MOB
- if(M.ckey)
+ if(player.ckey)
source = LOGSRC_CKEY
- body += "LOGS\] "
+ body += "LOGS\] "
- body += "Mob type = [M.type]
"
+ body += "Mob type = [player.type]
"
- if(M.client)
+ if(player.client)
body += "Old names: "
- var/datum/player_details/deets = GLOB.player_details[M.ckey]
+ var/datum/player_details/deets = GLOB.player_details[player.ckey]
if(deets)
body += deets.get_played_names()
else
body += "None?!"
body += "
"
- body += "Kick | "
- if(M.client)
- body += "Ban | "
+ body += "Kick | "
+ if(player.client)
+ body += "Ban | "
else
- body += "Ban | "
+ body += "Ban | "
- body += "Notes | Messages | Watchlist | "
- if(M.client)
- body += "| Prison | "
- body += "\ Send back to Lobby | "
- var/muted = M.client.prefs.muted
+ body += "Notes | Messages | Watchlist | "
+ if(player.client)
+ body += "| Prison | "
+ body += "\ Send back to Lobby | "
+ var/muted = player.client.prefs.muted
body += " Mute: "
- body += "\[IC | "
- body += "OOC | "
- body += "PRAY | "
- body += "ADMINHELP | "
+ body += "\[IC | "
+ body += "OOC | "
+ body += "PRAY | "
+ body += "ADMINHELP | "
//Skyrat Addition Begin - LOOC muting again.
- body += "DEADCHAT | "
- body += "LOOC\]"
+ body += "DEADCHAT | "
+ body += "LOOC\]"
//Skyrat Addition End - LOOC muting again.
- body += " WEBREQ | "
- body += "DEADCHAT\]"
- body += "(toggle all)"
+ body += "WEBREQ | "
+ body += "DEADCHAT\]"
+ body += "(toggle all)"
body += "
"
body += "Transformation: "
- if(isobserver(M))
+ if(isobserver(player))
body += "Ghost | "
else
- body += "Make Ghost | "
+ body += "Make Ghost | "
- if(ishuman(M) && !ismonkey(M))
+ if(ishuman(player) && !ismonkey(player))
body += "Human | "
else
- body += "Make Human | "
+ body += "Make Human | "
- if(ismonkey(M))
+ if(ismonkey(player))
body += "Monkey | "
else
- body += "Make Monkey | "
+ body += "Make Monkey | "
- if(iscyborg(M))
+ if(iscyborg(player))
body += "Cyborg | "
else
- body += "Make Cyborg | "
+ body += "Make Cyborg | "
- if(isAI(M))
+ if(isAI(player))
body += "AI"
else
- body += "Make AI"
+ body += "Make AI"
body += "
"
body += "Other actions:"
body += " "
- if(!isnewplayer(M))
- body += "Forcesay | "
- body += "Apply Client Quirks | "
- body += "Thunderdome 1 | "
- body += "Thunderdome 2 | "
- body += "Thunderdome Admin | "
- body += "Thunderdome Observer | "
- body += "Commend Behavior | "
+ if(!isnewplayer(player))
+ body += "Forcesay | "
+ body += "Apply Client Quirks | "
+ body += "Thunderdome 1 | "
+ body += "Thunderdome 2 | "
+ body += "Thunderdome Admin | "
+ body += "Thunderdome Observer | "
+ body += "Commend Behavior | "
body += " "
body += ""
- usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515")
+ user << browse(body, "window=adminplayeropts-[REF(player)];size=550x515")
BLACKBOX_LOG_ADMIN_VERB("Player Panel")
/client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list)
@@ -200,14 +193,8 @@ If a guy was gibbed and you want to revive him, this is a good way to do so.
Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one.
Traitors and the like can also be revived with the previous role mostly intact.
/N */
-/client/proc/respawn_character()
- set category = "Admin.Game"
- set name = "Respawn Character"
- set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into."
- if(!check_rights(R_ADMIN))
- return
-
- var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", ""))
+ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player that has been round removed in some manner. They must be a ghost.", ADMIN_CATEGORY_GAME)
+ var/input = ckey(input(user, "Please specify which key will be respawned.", "Key", ""))
if(!input)
return
@@ -218,19 +205,19 @@ Traitors and the like can also be revived with the previous role mostly intact.
break
if(!G_found)//If a ghost was not found.
- to_chat(usr, "There is no active key like that in the game or the person is not currently a ghost.", confidential = TRUE)
+ to_chat(user, "There is no active key like that in the game or the person is not currently a ghost.", confidential = TRUE)
return
if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
//check if they were a monkey
if(findtext(G_found.real_name,"monkey"))
- if(tgui_alert(usr,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No")) == "Yes")
+ if(tgui_alert(user,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No")) == "Yes")
var/mob/living/carbon/human/species/monkey/new_monkey = new
SSjob.SendToLateJoin(new_monkey)
G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use
new_monkey.key = G_found.key
to_chat(new_monkey, "You have been fully respawned. Enjoy the game.", confidential = TRUE)
- var/msg = span_adminnotice("[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy monkey.")
+ var/msg = span_adminnotice("[key_name_admin(user)] has respawned [new_monkey.key] as a filthy monkey.")
message_admins(msg)
admin_ticket_log(new_monkey, msg)
return //all done. The ghost is auto-deleted
@@ -246,7 +233,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.name
- new_character.gender = lowertext(record_found.gender)
+ new_character.gender = LOWER_TEXT(record_found.gender)
new_character.age = record_found.age
var/datum/dna/found_dna = record_found.locked_dna
new_character.hardset_dna(found_dna.unique_identity, found_dna.mutation_index, null, record_found.name, record_found.blood_type, new record_found.species_type, found_dna.features)
@@ -272,7 +259,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
*/
//Two variables to properly announce later on.
- var/admin = key_name_admin(src)
+ var/admin = key_name_admin(user)
var/player_key = G_found.key
//Now for special roles and equipment.
@@ -327,13 +314,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
BLACKBOX_LOG_ADMIN_VERB("Respawn Character")
return new_character
-/client/proc/cmd_admin_list_open_jobs()
- set category = "Admin.Game"
- set name = "Manage Job Slots"
-
- if(!check_rights(R_ADMIN))
- return
- holder.manage_free_slots()
+ADMIN_VERB(manage_job_slots, R_ADMIN, "Manage Job Slots", "Manage the number of available job slots.", ADMIN_CATEGORY_GAME)
+ user.holder.manage_free_slots()
BLACKBOX_LOG_ADMIN_VERB("Manage Job Slots")
/datum/admins/proc/manage_free_slots()
@@ -376,38 +358,25 @@ Traitors and the like can also be revived with the previous role mostly intact.
browser.set_content(dat.Join())
browser.open()
-/client/proc/toggle_view_range()
- set category = "Admin.Game"
- set name = "Change View Range"
- set desc = "switches between 1x and custom views"
-
- if(view_size.getView() == view_size.default)
- view_size.setTo(input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,37) - 7)
+ADMIN_VERB(toggle_view_range, R_ADMIN, "Change View Range", "Switch between 1x and custom views.", ADMIN_CATEGORY_GAME)
+ if(user.view_size.getView() == user.view_size.default)
+ user.view_size.setTo(input(user, "Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,37) - 7)
else
- view_size.resetToDefault(getScreenSize(prefs.read_preference(/datum/preference/toggle/widescreen)))
+ user.view_size.resetToDefault(getScreenSize(user.prefs.read_preference(/datum/preference/toggle/widescreen)))
- log_admin("[key_name(usr)] changed their view range to [view].")
- //message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI
+ log_admin("[key_name(user)] changed their view range to [user.view].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[user.view]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[view]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-
-/client/proc/toggle_combo_hud()
- set category = "Admin.Game"
- set name = "Toggle Combo HUD"
- set desc = "Toggles the Admin Combo HUD (antag, sci, med, eng)"
-
- if(!check_rights(R_ADMIN))
- return
-
- if (combo_hud_enabled)
- disable_combo_hud()
+ADMIN_VERB(combo_hud, R_ADMIN, "Toggle Combo HUD", "Toggles the Admin Combo HUD.", ADMIN_CATEGORY_GAME)
+ if(user.combo_hud_enabled)
+ user.disable_combo_hud()
else
- enable_combo_hud()
+ user.enable_combo_hud()
- to_chat(usr, "You toggled your admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].", confidential = TRUE)
- message_admins("[key_name_admin(usr)] toggled their admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].")
- log_admin("[key_name(usr)] toggled their admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Combo HUD", "[combo_hud_enabled ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+ to_chat(user, "You toggled your admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].", confidential = TRUE)
+ message_admins("[key_name_admin(user)] toggled their admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].")
+ log_admin("[key_name(user)] toggled their admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Combo HUD", "[user.combo_hud_enabled ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
/client/proc/enable_combo_hud()
if (combo_hud_enabled)
@@ -441,47 +410,31 @@ Traitors and the like can also be revived with the previous role mostly intact.
mob.lighting_cutoff = mob.default_lighting_cutoff()
mob.update_sight()
-/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list)
- set category = "Admin.Game"
- set desc = "Edit mobs's memory and role"
- set name = "Show Traitor Panel"
+ADMIN_VERB(show_traitor_panel, R_ADMIN, "Show Traitor Panel", "Edit mobs's memory and role", ADMIN_CATEGORY_GAME, mob/target_mob)
var/datum/mind/target_mind = target_mob.mind
if(!target_mind)
- to_chat(usr, "This mob has no mind!", confidential = TRUE)
+ to_chat(user, "This mob has no mind!", confidential = TRUE)
return
if(!istype(target_mob) && !istype(target_mind))
- to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
+ to_chat(user, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return
target_mind.traitor_panel()
BLACKBOX_LOG_ADMIN_VERB("Traitor Panel")
-/datum/admins/proc/show_skill_panel(target)
- set category = "Admin.Game"
- set desc = "Edit mobs's experience and skill levels"
- set name = "Show Skill Panel"
+ADMIN_VERB(show_skill_panel, R_ADMIN, "Show Skill Panel", "Edit mobs's experience and skill levels", ADMIN_CATEGORY_GAME, mob/target_mob)
var/datum/mind/target_mind
- if(ismob(target))
- var/mob/target_mob = target
- target_mind = target_mob.mind
- else if (istype(target, /datum/mind))
- target_mind = target
+ if(istype(target_mob, /datum/mind))
+ target_mind = target_mob
else
- to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
- return
- var/datum/skill_panel/SP = new(usr, target_mind)
- SP.ui_interact(usr)
+ target_mind = target_mob.mind
-/datum/admins/proc/show_lag_switch_panel()
- set category = "Admin.Game"
- set name = "Show Lag Switches"
- set desc="Display the controls for drastic lag mitigation measures."
+ var/datum/skill_panel/SP = new(user, target_mind)
+ SP.ui_interact(user.mob)
+ADMIN_VERB(lag_switch_panel, R_ADMIN, "Show Lag Switches", "Display the controls for drastic lag mitigation.", ADMIN_CATEGORY_GAME)
if(!SSlag_switch.initialized)
- to_chat(usr, span_notice("The Lag Switch subsystem has not yet been initialized."))
+ to_chat(user, span_notice("The Lag Switch subsystem has not yet been initialized."))
return
- if(!check_rights())
- return
-
var/list/dat = list("Lag Switches
Lag (Reduction) Switches
")
dat += "Automatic Trigger: [SSlag_switch.auto_switch ? "On" : "Off"] "
dat += "Population Threshold: [SSlag_switch.trigger_pop] "
@@ -500,4 +453,4 @@ Traitors and the like can also be revived with the previous role mostly intact.
dat += "Disable footsteps: [SSlag_switch.measures[DISABLE_FOOTSTEPS] ? "On" : "Off"] - trait applies to character "
dat += "Disable character creator: [SSlag_switch.measures[DISABLE_CREATOR] ? "On" : "Off"] - trait applies to all " // SKRYAT EDIT ADDITION
dat += ""
- usr << browse(dat.Join(), "window=lag_switch_panel;size=420x480")
+ user << browse(dat.Join(), "window=lag_switch_panel;size=420x480")
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index bd2f6310bd5..e759f737e51 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -1107,10 +1107,10 @@ GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new)
if(!M.mind)
continue
- for(var/string in splittext(lowertext(M.real_name), " "))
+ for(var/string in splittext(LOWER_TEXT(M.real_name), " "))
if(!(string in ignored_words))
nameWords += string
- for(var/string in splittext(lowertext(M.name), " "))
+ for(var/string in splittext(LOWER_TEXT(M.name), " "))
if(!(string in ignored_words))
nameWords += string
diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm
index dfcc5f60dd0..0248ccd9975 100644
--- a/code/modules/admin/verbs/adminjump.dm
+++ b/code/modules/admin/verbs/adminjump.dm
@@ -1,114 +1,66 @@
-/client/proc/jumptoarea(area/A in get_sorted_areas())
- set name = "Jump to Area"
- set desc = "Area to jump to"
- set category = "Admin.Game"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
+ADMIN_VERB(jump_to_area, R_ADMIN, "Jump To Area", "Jumps to the specified area.", ADMIN_CATEGORY_GAME, area/target in get_sorted_areas())
+ var/turf/drop_location
+ top_level:
+ for(var/list/zlevel_turfs as anything in target.get_zlevel_turf_lists())
+ for(var/turf/area_turf as anything in zlevel_turfs)
+ if(area_turf.density)
+ continue
+ drop_location = area_turf
+ break top_level
+
+ if(isnull(drop_location))
+ to_chat(user, span_warning("No valid drop location found in the area!"))
return
- if(!A)
- return
+ user.mob.abstract_move(drop_location)
+ log_admin("[key_name(user)] jumped to [AREACOORD(drop_location)]")
+ message_admins("[key_name_admin(user)] jumped to [AREACOORD(drop_location)]")
+ BLACKBOX_LOG_ADMIN_VERB("Jump To Area")
- var/list/turfs = list()
- for (var/list/zlevel_turfs as anything in A.get_zlevel_turf_lists())
- for (var/turf/area_turf as anything in zlevel_turfs)
- if(!area_turf.density)
- turfs.Add(area_turf)
-
- if(length(turfs))
- var/turf/T = pick(turfs)
- usr.forceMove(T)
- log_admin("[key_name(usr)] jumped to [AREACOORD(T)]")
- message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]")
- BLACKBOX_LOG_ADMIN_VERB("Jump To Area")
- else
- to_chat(src, "Nowhere to jump to!", confidential = TRUE)
- return
-
-
-/client/proc/jumptoturf(turf/T in world)
- set name = "Jump to Turf"
- set category = "Admin.Game"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
-
- log_admin("[key_name(usr)] jumped to [AREACOORD(T)]")
- message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]")
- usr.forceMove(T)
+ADMIN_VERB_AND_CONTEXT_MENU(jump_to_turf, R_ADMIN, "Jump To Turf", "Jump to any turf in the game. This will lag your client.", ADMIN_CATEGORY_GAME, turf/locale in world)
+ log_admin("[key_name(user)] jumped to [AREACOORD(locale)]")
+ message_admins("[key_name_admin(user)] jumped to [AREACOORD(locale)]")
+ user.mob.abstract_move(locale)
BLACKBOX_LOG_ADMIN_VERB("Jump To Turf")
- return
-/client/proc/jumptomob(mob/M in GLOB.mob_list)
- set category = "Admin.Game"
- set name = "Jump to Mob"
+ADMIN_VERB_AND_CONTEXT_MENU(jump_to_mob, R_ADMIN, "Jump To Mob", "Jump to any mob in the game.", ADMIN_CATEGORY_GAME, mob/target in world)
+ user.mob.abstract_move(target.loc)
+ log_admin("[key_name(user)] jumped to [key_name(target)]")
+ message_admins("[key_name_admin(user)] jumped to [ADMIN_LOOKUPFLW(target)] at [AREACOORD(target)]")
+ BLACKBOX_LOG_ADMIN_VERB("Jump To Mob")
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
+ADMIN_VERB(jump_to_coord, R_ADMIN, "Jump To Coordinate", "Jump to a specific coordinate in the game world.", ADMIN_CATEGORY_GAME, cx as num, cy as num, cz as num)
+ var/turf/where_we_droppin = locate(cx, cy, cz)
+ if(isnull(where_we_droppin))
+ to_chat(user, span_warning("Invalid coordinates."))
return
- log_admin("[key_name(usr)] jumped to [key_name(M)]")
- message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)] at [AREACOORD(M)]")
- if(src.mob)
- var/mob/A = src.mob
- var/turf/T = get_turf(M)
- if(T && isturf(T))
- BLACKBOX_LOG_ADMIN_VERB("Jump To Mob")
- A.forceMove(M.loc)
- else
- to_chat(A, "This mob is not located in the game world.", confidential = TRUE)
+ user.mob.abstract_move(where_we_droppin)
+ message_admins("[key_name_admin(user)] jumped to coordinates [cx], [cy], [cz]")
+ BLACKBOX_LOG_ADMIN_VERB("Jump To Coordiate")
-/client/proc/jumptocoord(tx as num, ty as num, tz as num)
- set category = "Admin.Game"
- set name = "Jump to Coordinate"
-
- if (!holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
-
- if(src.mob)
- var/mob/A = src.mob
- var/turf/T = locate(tx,ty,tz)
- A.forceMove(T)
- BLACKBOX_LOG_ADMIN_VERB("Jump To Coordiate")
- message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]")
-
-/client/proc/jumptokey()
- set category = "Admin.Game"
- set name = "Jump to Key"
-
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
+ADMIN_VERB(jump_to_key, R_ADMIN, "Jump To Key", "Jump to a specific player.", ADMIN_CATEGORY_GAME)
+ if(!isobserver(user.mob))
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost)
var/list/keys = list()
for(var/mob/M in GLOB.player_list)
keys += M.client
- var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sort_key(keys)
+ var/client/selection = input(user, "Please, select a player!", "Admin Jumping") as null|anything in sort_key(keys)
if(!selection)
- to_chat(src, "No keys found.", confidential = TRUE)
+ to_chat(user, "No keys found.", confidential = TRUE)
return
var/mob/M = selection.mob
- log_admin("[key_name(usr)] jumped to [key_name(M)]")
- message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)]")
-
- usr.forceMove(M.loc)
-
+ log_admin("[key_name(user)] jumped to [key_name(M)]")
+ message_admins("[key_name_admin(user)] jumped to [ADMIN_LOOKUPFLW(M)]")
+ user.mob.abstract_move(M.loc)
BLACKBOX_LOG_ADMIN_VERB("Jump To Key")
-/client/proc/Getmob(mob/M in GLOB.mob_list - GLOB.dummy_mob_list)
- set category = "Admin.Game"
- set name = "Get Mob"
- set desc = "Mob to teleport"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
-
- var/atom/loc = get_turf(usr)
- M.admin_teleport(loc)
+ADMIN_VERB_AND_CONTEXT_MENU(get_mob, R_ADMIN, "Get Mob", "Teleport a mob to your location.", ADMIN_CATEGORY_GAME, mob/target in world)
+ var/atom/loc = get_turf(user.mob)
+ target.admin_teleport(loc)
BLACKBOX_LOG_ADMIN_VERB("Get Mob")
-
/// Proc to hook user-enacted teleporting behavior and keep logging of the event.
/atom/movable/proc/admin_teleport(atom/new_location)
if(isnull(new_location))
@@ -126,56 +78,41 @@
admin_ticket_log(src, msg)
return ..()
-
-/client/proc/Getkey()
- set category = "Admin.Game"
- set name = "Get Key"
- set desc = "Key to teleport"
-
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
-
+ADMIN_VERB(get_key, R_ADMIN, "Get Key", "Teleport the player with the provided key to you.", ADMIN_CATEGORY_GAME)
var/list/keys = list()
for(var/mob/M in GLOB.player_list)
keys += M.client
- var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sort_key(keys)
+ var/client/selection = input(user, "Please, select a player!", "Admin Jumping") as null|anything in sort_key(keys)
if(!selection)
return
var/mob/M = selection.mob
if(!M)
return
- log_admin("[key_name(usr)] teleported [key_name(M)]")
- var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)]"
+ log_admin("[key_name(user)] teleported [key_name(M)]")
+ var/msg = "[key_name_admin(user)] teleported [ADMIN_LOOKUPFLW(M)]"
message_admins(msg)
admin_ticket_log(M, msg)
if(M)
- M.forceMove(get_turf(usr))
- usr.forceMove(M.loc)
+ M.forceMove(get_turf(user))
BLACKBOX_LOG_ADMIN_VERB("Get Key")
-/client/proc/sendmob(mob/jumper in sort_mobs())
- set category = "Admin.Game"
- set name = "Send Mob"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
+ADMIN_VERB_AND_CONTEXT_MENU(send_mob, R_ADMIN, "Send Mob", "Teleport the specified mob to an area of your choosing.", ADMIN_CATEGORY_GAME, mob/jumper)
var/list/sorted_areas = get_sorted_areas()
if(!length(sorted_areas))
- to_chat(src, "No areas found.", confidential = TRUE)
+ to_chat(user, "No areas found.", confidential = TRUE)
return
- var/area/target_area = tgui_input_list(src, "Pick an area", "Send Mob", sorted_areas)
+ var/area/target_area = tgui_input_list(user, "Pick an area", "Send Mob", sorted_areas)
if(isnull(target_area))
return
if(!istype(target_area))
return
var/list/turfs = get_area_turfs(target_area)
if(length(turfs) && jumper.forceMove(pick(turfs)))
- log_admin("[key_name(usr)] teleported [key_name(jumper)] to [AREACOORD(jumper)]")
- var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(jumper)] to [AREACOORD(jumper)]"
+ log_admin("[key_name(user)] teleported [key_name(jumper)] to [AREACOORD(jumper)]")
+ var/msg = "[key_name_admin(user)] teleported [ADMIN_LOOKUPFLW(jumper)] to [AREACOORD(jumper)]"
message_admins(msg)
admin_ticket_log(jumper, msg)
else
- to_chat(src, "Failed to move mob to a valid location.", confidential = TRUE)
+ to_chat(user, "Failed to move mob to a valid location.", confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Send Mob")
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 529cf4d8a77..23676cd8ea9 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -13,36 +13,19 @@
// We also make SURE to fail loud, IE: if something stops the message from reaching the recipient, the sender HAS to know
// If you "refactor" this to make it "cleaner" I will send you to hell
-/// Allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm
-/client/proc/cmd_admin_pm_context(mob/M in GLOB.mob_list)
- set category = null
- set name = "Admin PM Mob"
- if(!holder)
- to_chat(src,
- type = MESSAGE_TYPE_ADMINPM,
- html = span_danger("Error: Admin-PM-Context: Only administrators may use this command."),
- confidential = TRUE)
- return
- if(!ismob(M))
- to_chat(src,
+ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_pm_context, R_NONE, "Admin PM Mob", mob/target in world)
+ if(!ismob(target))
+ to_chat(
+ src,
type = MESSAGE_TYPE_ADMINPM,
html = span_danger("Error: Admin-PM-Context: Target mob is not a mob, somehow."),
- confidential = TRUE)
+ confidential = TRUE,
+ )
return
- cmd_admin_pm(M.client, null)
+ user.cmd_admin_pm(target.client, null)
BLACKBOX_LOG_ADMIN_VERB("Admin PM Mob")
-/// Shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm
-/client/proc/cmd_admin_pm_panel()
- set category = "Admin"
- set name = "Admin PM"
- if(!holder)
- to_chat(src,
- type = MESSAGE_TYPE_ADMINPM,
- html = span_danger("Error: Admin-PM-Panel: Only administrators may use this command."),
- confidential = TRUE)
- return
-
+ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM", ADMIN_CATEGORY_MAIN)
var/list/targets = list()
for(var/client/client in GLOB.clients)
var/nametag = ""
@@ -62,7 +45,7 @@
var/target = input(src,"To whom shall we send a message?", "Admin PM", null) as null|anything in sort_list(targets)
if (isnull(target))
return
- cmd_admin_pm(targets[target], null)
+ user.cmd_admin_pm(targets[target], null)
BLACKBOX_LOG_ADMIN_VERB("Admin PM")
/// Replys to some existing ahelp, reply to whom, which can be a client or ckey
@@ -635,7 +618,7 @@
// The ticket's id
var/ticket_id = ticket?.id
- var/compliant_msg = trim(lowertext(message))
+ var/compliant_msg = trim(LOWER_TEXT(message))
var/tgs_tagged = "[sender](TGS/External)"
var/list/splits = splittext(compliant_msg, " ")
var/split_size = length(splits)
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index ad7a89a228d..87410528ab3 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -1,18 +1,12 @@
-/client/proc/cmd_admin_say(msg as text)
- set category = "Admin"
- set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite
- set hidden = TRUE
- if(!check_rights(0))
+ADMIN_VERB(cmd_admin_say, R_NONE, "ASay", "Send a message to other admins", ADMIN_CATEGORY_MAIN, message as text)
+ message = emoji_parse(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
+ if(!message)
return
- msg = emoji_parse(copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN))
- if(!msg)
- return
-
- if(findtext(msg, "@") || findtext(msg, "#"))
- var/list/link_results = check_asay_links(msg)
+ if(findtext(message, "@") || findtext(message, "#"))
+ var/list/link_results = check_asay_links(message)
if(length(link_results))
- msg = link_results[ASAY_LINK_NEW_MESSAGE_INDEX]
+ message = link_results[ASAY_LINK_NEW_MESSAGE_INDEX]
link_results[ASAY_LINK_NEW_MESSAGE_INDEX] = null
var/list/pinged_admin_clients = link_results[ASAY_LINK_PINGED_ADMINS_INDEX]
for(var/iter_ckey in pinged_admin_clients)
@@ -22,19 +16,19 @@
window_flash(iter_admin_client)
SEND_SOUND(iter_admin_client.mob, sound('sound/misc/asay_ping.ogg'))
- mob.log_talk(msg, LOG_ASAY)
- msg = keywords_lookup(msg)
- send_asay_to_other_server(ckey, msg) //SKYRAT EDIT ADDITION
- var/asay_color = prefs.read_preference(/datum/preference/color/asay_color)
+ user.mob.log_talk(message, LOG_ASAY)
+ message = keywords_lookup(message)
+ send_asay_to_other_server(user.ckey, message) //SKYRAT EDIT ADDITION
+ var/asay_color = user.prefs.read_preference(/datum/preference/color/asay_color)
var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && asay_color) ? "" : ""
- msg = "[span_adminsay("[span_prefix("ADMIN:")] [key_name(usr, 1)] [ADMIN_FLW(mob)]: [custom_asay_color][msg]")][custom_asay_color ? "":null]"
+ message = "[span_adminsay("[span_prefix("ADMIN:")] [key_name_admin(user)] [ADMIN_FLW(user.mob)]: [custom_asay_color][message]")][custom_asay_color ? "":null]"
to_chat(GLOB.admins,
type = MESSAGE_TYPE_ADMINCHAT,
- html = msg,
+ html = message,
confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Asay")
/client/proc/get_admin_say()
var/msg = input(src, null, "asay \"text\"") as text|null
- cmd_admin_say(msg)
+ SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/cmd_admin_say, msg)
diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm
index 2e73a9955f7..9f744ff0147 100644
--- a/code/modules/admin/verbs/atmosdebug.dm
+++ b/code/modules/admin/verbs/atmosdebug.dm
@@ -1,35 +1,27 @@
-/client/proc/atmosscan()
- set category = "Mapping"
- set name = "Check Plumbing"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
+ADMIN_VERB_VISIBILITY(atmos_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(atmos_debug, R_DEBUG, "Check Plumbing", "Verifies the integrity of the plumbing network.", ADMIN_CATEGORY_MAPPING)
BLACKBOX_LOG_ADMIN_VERB("Check Plumbing")
//all plumbing - yes, some things might get stated twice, doesn't matter.
for(var/obj/machinery/atmospherics/components/pipe as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics/components))
if(pipe.z && (!pipe.nodes || !pipe.nodes.len || (null in pipe.nodes)))
- to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE)
+ to_chat(user, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE)
//Pipes
for(var/obj/machinery/atmospherics/pipe/pipe as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics/pipe))
if(istype(pipe, /obj/machinery/atmospherics/pipe/smart) || istype(pipe, /obj/machinery/atmospherics/pipe/layer_manifold))
continue
if(pipe.z && (!pipe.nodes || !pipe.nodes.len || (null in pipe.nodes)))
- to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE)
+ to_chat(user, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE)
//Nodes
for(var/obj/machinery/atmospherics/node1 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics))
for(var/obj/machinery/atmospherics/node2 in node1.nodes)
if(!(node1 in node2.nodes))
- to_chat(usr, "One-way connection in [node1.name] located at [ADMIN_VERBOSEJMP(node1)]", confidential = TRUE)
+ to_chat(user, "One-way connection in [node1.name] located at [ADMIN_VERBOSEJMP(node1)]", confidential = TRUE)
-/client/proc/powerdebug()
- set category = "Mapping"
- set name = "Check Power"
- if(!src.holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
+ADMIN_VERB_VISIBILITY(power_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(power_debug, R_DEBUG, "Check Power", "Verifies the integrity of the power network.", ADMIN_CATEGORY_MAPPING)
BLACKBOX_LOG_ADMIN_VERB("Check Power")
var/list/results = list()
@@ -56,4 +48,4 @@
var/obj/structure/cable/C = locate(/obj/structure/cable) in T.contents
if(!C)
results += "Unwired terminal at [ADMIN_VERBOSEJMP(term)]"
- to_chat(usr, "[results.Join("\n")]", confidential = TRUE)
+ to_chat(user, "[results.Join("\n")]", confidential = TRUE)
diff --git a/code/modules/admin/verbs/beakerpanel.dm b/code/modules/admin/verbs/beakerpanel.dm
index 5ba32ae7b6c..7088fba92f1 100644
--- a/code/modules/admin/verbs/beakerpanel.dm
+++ b/code/modules/admin/verbs/beakerpanel.dm
@@ -60,14 +60,11 @@
reagents.add_reagent(reagenttype, amount)
return container
-/datum/admins/proc/beaker_panel()
- set category = "Admin.Events"
- set name = "Spawn reagent container"
- if(!check_rights())
- return
+ADMIN_VERB(beaker_panel, R_SPAWN, "Spawn Reagent Container", "Spawn a reagent container.", ADMIN_CATEGORY_EVENTS)
var/datum/asset/asset_datum = get_asset_datum(/datum/asset/simple/namespaced/common)
- asset_datum.send(usr)
+ asset_datum.send(user)
//Could somebody tell me why this isn't using the browser datum, given that it copypastes all of browser datum's html
+ // fuck if I know, but im not touching it
var/dat = {"
@@ -320,4 +317,4 @@
"}
- usr << browse(dat, "window=beakerpanel;size=1100x720")
+ user << browse(dat, "window=beakerpanel;size=1100x720")
diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm
index b8fd3698a56..6a8e1efdb56 100644
--- a/code/modules/admin/verbs/borgpanel.dm
+++ b/code/modules/admin/verbs/borgpanel.dm
@@ -1,21 +1,6 @@
-/datum/admins/proc/open_borgopanel(borgo in GLOB.silicon_mobs)
- set category = "Admin.Game"
- set name = "Show Borg Panel"
- set desc = "Show borg panel"
-
- if(!check_rights(R_ADMIN))
- return
-
- if (!iscyborg(borgo))
- borgo = input("Select a borg", "Select a borg", null, null) as null|anything in sort_names(GLOB.silicon_mobs)
- if (!iscyborg(borgo))
- to_chat(usr, span_warning("Borg is required for borgpanel"), confidential = TRUE)
-
- var/datum/borgpanel/borgpanel = new(usr, borgo)
-
- borgpanel.ui_interact(usr)
-
-
+ADMIN_VERB(borg_panel, R_ADMIN, "Show Borg Panel", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/silicon/robot/borgo)
+ var/datum/borgpanel/borgpanel = new(user.mob, borgo)
+ borgpanel.ui_interact(user.mob)
/datum/borgpanel
var/mob/living/silicon/robot/borg
diff --git a/code/modules/admin/verbs/change_shuttle_events.dm b/code/modules/admin/verbs/change_shuttle_events.dm
index 4ec8a7cd7b8..90f7e03672e 100644
--- a/code/modules/admin/verbs/change_shuttle_events.dm
+++ b/code/modules/admin/verbs/change_shuttle_events.dm
@@ -1,20 +1,9 @@
-///Manipulate the events that are gonna run/are running on the escape shuttle
-/datum/admins/proc/change_shuttle_events()
- set category = "Admin.Events"
- set name = "Change Shuttle Events"
- set desc = "Allows you to change the events on a shuttle."
-
- if (!istype(src, /datum/admins))
- src = usr.client.holder
- if (!istype(src, /datum/admins))
- to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
- return
-
+ADMIN_VERB(change_shuttle_events, R_ADMIN|R_FUN, "Change Shuttle Events", "Change the events on a shuttle.", ADMIN_CATEGORY_EVENTS)
//At least for now, just letting admins modify the emergency shuttle is fine
var/obj/docking_port/mobile/port = SSshuttle.emergency
if(!port)
- to_chat(usr, span_admin("Uh oh, couldn't find the escape shuttle!"))
+ to_chat(user, span_admin("Uh oh, couldn't find the escape shuttle!"))
var/list/options = list("Clear"="Clear")
@@ -27,16 +16,16 @@
options[((event in active) ? "(Remove)" : "(Add)") + initial(event.name)] = event
//Throw up an ugly menu with the shuttle events and the options to add or remove them, or clear them all
- var/result = input(usr, "Choose an event to add/remove", "Shuttle Events") as null|anything in sort_list(options)
+ var/result = input(user, "Choose an event to add/remove", "Shuttle Events") as null|anything in sort_list(options)
if(result == "Clear")
port.event_list.Cut()
- message_admins("[key_name_admin(usr)] has cleared the shuttle events on: [port]")
+ message_admins("[key_name_admin(user)] has cleared the shuttle events on: [port]")
else if(options[result])
var/typepath = options[result]
if(typepath in active)
port.event_list.Remove(active[options[result]])
- message_admins("[key_name_admin(usr)] has removed '[active[result]]' from [port].")
+ message_admins("[key_name_admin(user)] has removed '[active[result]]' from [port].")
else
port.event_list.Add(new typepath (port))
- message_admins("[key_name_admin(usr)] has added '[typepath]' to [port].")
+ message_admins("[key_name_admin(user)] has added '[typepath]' to [port].")
diff --git a/code/modules/admin/verbs/cinematic.dm b/code/modules/admin/verbs/cinematic.dm
index b001099d283..f9e96c89cd0 100644
--- a/code/modules/admin/verbs/cinematic.dm
+++ b/code/modules/admin/verbs/cinematic.dm
@@ -1,14 +1,10 @@
-/client/proc/cinematic()
- set name = "Cinematic"
- set category = "Admin.Fun"
- set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted.
- set hidden = TRUE
-
- if(!SSticker)
- return
-
- var/datum/cinematic/choice = tgui_input_list(usr, "Chose a cinematic to play to everyone in the server.", "Choose Cinematic", sort_list(subtypesof(/datum/cinematic), GLOBAL_PROC_REF(cmp_typepaths_asc)))
+ADMIN_VERB(cinematic, R_FUN, "Cinematic", "Show a cinematic to all players.", ADMIN_CATEGORY_FUN)
+ var/datum/cinematic/choice = tgui_input_list(
+ user,
+ "Chose a cinematic to play to everyone in the server.",
+ "Choose Cinematic",
+ sort_list(subtypesof(/datum/cinematic), GLOBAL_PROC_REF(cmp_typepaths_asc)),
+ )
if(!choice || !ispath(choice, /datum/cinematic))
return
-
play_cinematic(choice, world)
diff --git a/code/modules/admin/verbs/commandreport.dm b/code/modules/admin/verbs/commandreport.dm
index 86e7ec1328b..047ef04a0b7 100644
--- a/code/modules/admin/verbs/commandreport.dm
+++ b/code/modules/admin/verbs/commandreport.dm
@@ -7,32 +7,19 @@
#define WIZARD_PRESET "The Wizard Federation"
#define CUSTOM_PRESET "Custom Command Name"
-/// Verb to change the global command name.
-/client/proc/cmd_change_command_name()
- set category = "Admin.Events"
- set name = "Change Command Name"
-
- if(!check_rights(R_ADMIN))
- return
-
- var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null
+ADMIN_VERB(change_command_name, R_ADMIN, "Change Command Name", "Change the name of Central Command.", ADMIN_CATEGORY_EVENTS)
+ var/input = input(user, "Please input a new name for Central Command.", "What?", "") as text|null
if(!input)
return
change_command_name(input)
- message_admins("[key_name_admin(src)] has changed Central Command's name to [input]")
- log_admin("[key_name(src)] has changed the Central Command name to: [input]")
+ message_admins("[key_name_admin(user)] has changed Central Command's name to [input]")
+ log_admin("[key_name(user)] has changed the Central Command name to: [input]")
/// Verb to open the create command report window and send command reports.
-/client/proc/cmd_admin_create_centcom_report()
- set category = "Admin.Events"
- set name = "Create Command Report"
-
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(create_command_report, R_ADMIN, "Create Command Report", "Create a command report to be sent to the station.", ADMIN_CATEGORY_EVENTS)
BLACKBOX_LOG_ADMIN_VERB("Create Command Report")
- var/datum/command_report_menu/tgui = new(usr)
- tgui.ui_interact(usr)
+ var/datum/command_report_menu/tgui = new /datum/command_report_menu(user.mob)
+ tgui.ui_interact(user.mob)
/// Datum for holding the TGUI window for command reports.
/datum/command_report_menu
diff --git a/code/modules/admin/verbs/config_helpers.dm b/code/modules/admin/verbs/config_helpers.dm
index 013c7b63f8a..c043274d427 100644
--- a/code/modules/admin/verbs/config_helpers.dm
+++ b/code/modules/admin/verbs/config_helpers.dm
@@ -1,19 +1,14 @@
-/// Verbs created to help server operators with generating certain config files.
+#define GENERATE_JOB_CONFIG_VERB_DESC "Generate a job configuration (jobconfig.toml) file for the server. If TOML file already exists, will re-generate it based off the already existing config values. Will migrate from the old jobs.txt format if necessary."
-/client/proc/generate_job_config()
- set name = "Generate Job Configuration"
- set category = "Server"
- set desc = "Generate a job configuration (jobconfig.toml) file for the server. If TOML file already exists, will re-generate it based off the already existing config values. Will migrate from the old jobs.txt format if necessary."
-
- if(!check_rights(R_SERVER))
+ADMIN_VERB(generate_job_config, R_SERVER, "Generate Job Configuration", GENERATE_JOB_CONFIG_VERB_DESC, ADMIN_CATEGORY_SERVER)
+ if(tgui_alert(user, "This verb is not at all useful if you are not a server operator with access to the configuration folder. Do you wish to proceed?", "Generate jobconfig.toml for download", list("Yes", "No")) != "Yes")
return
- if(tgui_alert(usr, "This verb is not at all useful if you are not a server operator with access to the configuration folder. Do you wish to proceed?", "Generate jobconfig.toml for download", list("Yes", "No")) != "Yes")
- return
-
- if(SSjob.generate_config(usr))
- to_chat(usr, span_notice("Job configuration file generated. Download prompt should appear now."))
+ if(SSjob.generate_config(user))
+ to_chat(user, span_notice("Job configuration file generated. Download prompt should appear now."))
else
- to_chat(usr, span_warning("Job configuration file could not be generated. Check the server logs / runtimes / above warning messages for more information."))
+ to_chat(user, span_warning("Job configuration file could not be generated. Check the server logs / runtimes / above warning messages for more information."))
BLACKBOX_LOG_ADMIN_VERB("Generate Job Configuration")
+
+#undef GENERATE_JOB_CONFIG_VERB_DESC
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 032a4d4fa48..c330618d8b4 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -1,39 +1,30 @@
-/client/proc/dsay(msg as text)
- set category = "Admin.Game"
- set name = "Dsay"
- set hidden = TRUE
- if(!holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
- if(!mob)
- return
- if(prefs.muted & MUTE_DEADCHAT)
- to_chat(src, span_danger("You cannot send DSAY messages (muted)."), confidential = TRUE)
+
+ADMIN_VERB(dsay, R_NONE, "DSay", "Speak to the dead.", ADMIN_CATEGORY_GAME, message as text)
+ if(user.prefs.muted & MUTE_DEADCHAT)
+ to_chat(user, span_danger("You cannot send DSAY messages (muted)."), confidential = TRUE)
return
- if (handle_spam_prevention(msg,MUTE_DEADCHAT))
+ if (user.handle_spam_prevention(message,MUTE_DEADCHAT))
return
- msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)
- mob.log_talk(msg, LOG_DSAY)
+ message = copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)
+ user.mob.log_talk(message, LOG_DSAY)
- if (!msg)
+ if (!message)
return
- var/rank_name = holder.rank_names()
- var/admin_name = key
- if(holder.fakekey)
+ var/rank_name = user.holder.rank_names()
+ var/admin_name = user.key
+ if(user.holder.fakekey)
rank_name = pick(strings("admin_nicknames.json", "ranks", "config"))
admin_name = pick(strings("admin_nicknames.json", "names", "config"))
var/name_and_rank = "[span_tooltip(rank_name, "STAFF")] ([admin_name])"
- deadchat_broadcast("[span_prefix("DEAD:")] [name_and_rank] says, \"[emoji_parse(msg)]\"")
+ deadchat_broadcast("[span_prefix("DEAD:")] [name_and_rank] says, \"[emoji_parse(message)]\"")
BLACKBOX_LOG_ADMIN_VERB("Dsay")
/client/proc/get_dead_say()
var/msg = input(src, null, "dsay \"text\"") as text|null
-
if (isnull(msg))
return
-
- dsay(msg)
+ SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/dsay, msg)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 35b1baa063d..e56eb1e5101 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -1,40 +1,27 @@
-/client/proc/Debug2()
- set category = "Debug"
- set name = "Debug-Game"
- if(!check_rights(R_DEBUG))
- return
-
- if(GLOB.Debug2)
- GLOB.Debug2 = 0
- message_admins("[key_name(src)] toggled debugging off.")
- log_admin("[key_name(src)] toggled debugging off.")
- else
- GLOB.Debug2 = 1
- message_admins("[key_name(src)] toggled debugging on.")
- log_admin("[key_name(src)] toggled debugging on.")
-
+ADMIN_VERB(toggle_game_debug, R_DEBUG, "Debug-Game", "Toggles game debugging.", ADMIN_CATEGORY_DEBUG)
+ GLOB.Debug2 = !GLOB.Debug2
+ var/message = "toggled debugging [(GLOB.Debug2 ? "ON" : "OFF")]"
+ message_admins("[key_name_admin(user)] [message].")
+ log_admin("[key_name(user)] [message].")
BLACKBOX_LOG_ADMIN_VERB("Toggle Debug Two")
-/client/proc/Cell()
- set category = "Debug"
- set name = "Air Status in Location"
- if(!mob)
+ADMIN_VERB_VISIBILITY(air_status, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(air_status, R_DEBUG, "Air Status In Location", "Gets the air status for your current turf.", ADMIN_CATEGORY_DEBUG)
+ var/turf/user_turf = get_turf(user.mob)
+ if(!isturf(user_turf))
return
- var/turf/T = get_turf(mob)
- if(!isturf(T))
- return
- atmos_scan(user=usr, target=T, silent=TRUE)
+ atmos_scan(user.mob, user_turf, silent = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Air Status In Location")
-/client/proc/cmd_admin_robotize(mob/M in GLOB.mob_list)
- set category = "Admin.Fun"
- set name = "Make Cyborg"
-
+ADMIN_VERB(cmd_admin_robotize, R_FUN, "Make Cyborg", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target)
if(!SSticker.HasRoundStarted())
- tgui_alert(usr,"Wait until the game starts")
+ tgui_alert(user, "Wait until the game starts")
return
- log_admin("[key_name(src)] has robotized [M.key].")
- INVOKE_ASYNC(M, TYPE_PROC_REF(/mob, Robotize))
+ if(issilicon(target))
+ tgui_alert(user, "They are already a cyborg.")
+ return
+ log_admin("[key_name(user)] has robotized [target.key].")
+ INVOKE_ASYNC(target, TYPE_PROC_REF(/mob, Robotize))
/client/proc/poll_type_to_del(search_string)
var/list/types = get_fancy_list_of_atom_types()
@@ -50,13 +37,8 @@
return
return types[key]
-//TODO: merge the vievars version into this or something maybe mayhaps
-/client/proc/cmd_debug_del_all(object as text)
- set category = "Debug"
- set name = "Del-All"
-
- var/type_to_del = poll_type_to_del(object)
-
+ADMIN_VERB(cmd_del_all, R_DEBUG|R_SPAWN, "Del-All", "Delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text)
+ var/type_to_del = user.poll_type_to_del(object)
if(!type_to_del)
return
@@ -66,16 +48,12 @@
counter++
qdel(O)
CHECK_TICK
- log_admin("[key_name(src)] has deleted all ([counter]) instances of [type_to_del].")
- message_admins("[key_name_admin(src)] has deleted all ([counter]) instances of [type_to_del].")
+ log_admin("[key_name(user)] has deleted all ([counter]) instances of [type_to_del].")
+ message_admins("[key_name_admin(user)] has deleted all ([counter]) instances of [type_to_del].")
BLACKBOX_LOG_ADMIN_VERB("Delete All")
-/client/proc/cmd_debug_force_del_all(object as text)
- set category = "Debug"
- set name = "Force-Del-All"
-
- var/type_to_del = poll_type_to_del(object)
-
+ADMIN_VERB(cmd_del_all_force, R_DEBUG|R_SPAWN, "Force-Del-All", "Forcibly delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text)
+ var/type_to_del = user.poll_type_to_del(object)
if(!type_to_del)
return
@@ -85,29 +63,25 @@
counter++
qdel(O, force = TRUE)
CHECK_TICK
- log_admin("[key_name(src)] has force-deleted all ([counter]) instances of [type_to_del].")
- message_admins("[key_name_admin(src)] has force-deleted all ([counter]) instances of [type_to_del].")
+ log_admin("[key_name(user)] has force-deleted all ([counter]) instances of [type_to_del].")
+ message_admins("[key_name_admin(user)] has force-deleted all ([counter]) instances of [type_to_del].")
BLACKBOX_LOG_ADMIN_VERB("Force-Delete All")
-/client/proc/cmd_debug_hard_del_all(object as text)
- set category = "Debug"
- set name = "Hard-Del-All"
-
- var/type_to_del = poll_type_to_del(object)
-
+ADMIN_VERB(cmd_del_all_hard, R_DEBUG|R_SPAWN, "Hard-Del-All", "Hard delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text)
+ var/type_to_del = user.poll_type_to_del(object)
if(!type_to_del)
return
- var/choice = alert("ARE YOU SURE that you want to hard delete this type? It will cause MASSIVE lag.", "Hoooo lad what happen?", "Yes", "No")
+ var/choice = alert(user, "ARE YOU SURE that you want to hard delete this type? It will cause MASSIVE lag.", "Hoooo lad what happen?", "Yes", "No")
if(choice != "Yes")
return
- choice = alert("Do you want to pre qdelete the atom? This will speed things up significantly, but may break depending on your level of fuckup.", "How do you even get it that bad", "Yes", "No")
+ choice = alert(user, "Do you want to pre qdelete the atom? This will speed things up significantly, but may break depending on your level of fuckup.", "How do you even get it that bad", "Yes", "No")
var/should_pre_qdel = TRUE
if(choice == "No")
should_pre_qdel = FALSE
- choice = alert("Ok one last thing, do you want to yield to the game? or do it all at once. These are hard deletes remember.", "Jesus christ man", "Yield", "Ignore the server")
+ choice = alert(user, "Ok one last thing, do you want to yield to the game? or do it all at once. These are hard deletes remember.", "Jesus christ man", "Yield", "Ignore the server")
var/should_check_tick = TRUE
if(choice == "Ignore the server")
should_check_tick = FALSE
@@ -129,24 +103,20 @@
qdel(O)
del(O)
CHECK_TICK
- log_admin("[key_name(src)] has hard deleted all ([counter]) instances of [type_to_del].")
- message_admins("[key_name_admin(src)] has hard deleted all ([counter]) instances of [type_to_del].")
+ log_admin("[key_name(user)] has hard deleted all ([counter]) instances of [type_to_del].")
+ message_admins("[key_name_admin(user)] has hard deleted all ([counter]) instances of [type_to_del].")
BLACKBOX_LOG_ADMIN_VERB("Hard Delete All")
-/client/proc/cmd_debug_make_powernets()
- set category = "Debug"
- set name = "Make Powernets"
+ADMIN_VERB(cmd_debug_make_powernets, R_DEBUG|R_SERVER, "Make Powernets", "Regenerates all powernets for all cables.", ADMIN_CATEGORY_DEBUG)
SSmachines.makepowernets()
- log_admin("[key_name(src)] has remade the powernet. makepowernets() called.")
- message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.")
+ log_admin("[key_name(user)] has remade the powernet. makepowernets() called.")
+ message_admins("[key_name_admin(user)] has remade the powernets. makepowernets() called.")
BLACKBOX_LOG_ADMIN_VERB("Make Powernets")
-/client/proc/cmd_admin_grantfullaccess(mob/M in GLOB.mob_list)
- set category = "Debug"
- set name = "Grant Full Access"
-
+ADMIN_VERB_VISIBILITY(cmd_admin_grantfullaccess, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_admin_grantfullaccess, R_DEBUG, "Grant Full Access", "Grant full access to a mob.", ADMIN_CATEGORY_DEBUG, mob/M in world)
if(!SSticker.HasRoundStarted())
- tgui_alert(usr,"Wait until the game starts")
+ tgui_alert(user, "Wait until the game starts")
return
if(ishuman(M))
var/mob/living/carbon/human/H = M
@@ -180,51 +150,44 @@
H.equip_to_slot(id, ITEM_SLOT_ID)
else
- tgui_alert(usr,"Invalid mob")
+ tgui_alert(user,"Invalid mob")
BLACKBOX_LOG_ADMIN_VERB("Grant Full Access")
- log_admin("[key_name(src)] has granted [M.key] full access.")
- message_admins(span_adminnotice("[key_name_admin(usr)] has granted [M.key] full access."))
-
-/client/proc/cmd_assume_direct_control(mob/M in GLOB.mob_list)
- set category = "Admin.Game"
- set name = "Assume direct control"
- set desc = "Direct intervention"
+ log_admin("[key_name(user)] has granted [M.key] full access.")
+ message_admins(span_adminnotice("[key_name_admin(user)] has granted [M.key] full access."))
+ADMIN_VERB(cmd_assume_direct_control, R_ADMIN, "Assume Direct Control", "Assume direct control of a mob.", ADMIN_CATEGORY_DEBUG, mob/M)
if(M.ckey)
- if(tgui_alert(usr,"This mob is being controlled by [M.key]. Are you sure you wish to assume control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes")
+ if(tgui_alert(user,"This mob is being controlled by [M.key]. Are you sure you wish to assume control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes")
return
if(!M || QDELETED(M))
- to_chat(usr, span_warning("The target mob no longer exists."))
+ to_chat(user, span_warning("The target mob no longer exists."))
return
- message_admins(span_adminnotice("[key_name_admin(usr)] assumed direct control of [M]."))
- log_admin("[key_name(usr)] assumed direct control of [M].")
- var/mob/adminmob = mob
+ message_admins(span_adminnotice("[key_name_admin(user)] assumed direct control of [M]."))
+ log_admin("[key_name(user)] assumed direct control of [M].")
+ var/mob/adminmob = user.mob
if(M.ckey)
M.ghostize(FALSE)
- M.key = key
- init_verbs()
+ M.key = user.key
+ user.init_verbs()
if(isobserver(adminmob))
qdel(adminmob)
BLACKBOX_LOG_ADMIN_VERB("Assume Direct Control")
-/client/proc/cmd_give_direct_control(mob/M in GLOB.mob_list)
- set category = "Admin.Game"
- set name = "Give direct control"
-
+ADMIN_VERB(cmd_give_direct_control, R_ADMIN, "Give Direct Control", "Give direct control of a mob to another player.", ADMIN_CATEGORY_GAME, mob/M)
if(!M)
return
if(M.ckey)
- if(tgui_alert(usr,"This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes")
+ if(tgui_alert(user,"This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes")
return
- var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients)
+ var/client/newkey = input(user, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients)
if(isnull(newkey))
return
var/mob/oldmob = newkey.mob
var/delmob = FALSE
- if((isobserver(oldmob) || tgui_alert(usr,"Do you want to delete [newkey]'s old mob?","Delete?",list("Yes","No")) != "No"))
+ if((isobserver(oldmob) || tgui_alert(user,"Do you want to delete [newkey]'s old mob?","Delete?",list("Yes","No")) != "No"))
delmob = TRUE
if(!M || QDELETED(M))
- to_chat(usr, span_warning("The target mob no longer exists, aborting."))
+ to_chat(user, span_warning("The target mob no longer exists, aborting."))
return
if(M.ckey)
M.ghostize(FALSE)
@@ -232,14 +195,12 @@
M.client?.init_verbs()
if(delmob)
qdel(oldmob)
- message_admins(span_adminnotice("[key_name_admin(usr)] gave away direct control of [M] to [newkey]."))
- log_admin("[key_name(usr)] gave away direct control of [M] to [newkey].")
+ message_admins(span_adminnotice("[key_name_admin(user)] gave away direct control of [M] to [newkey]."))
+ log_admin("[key_name(user)] gave away direct control of [M] to [newkey].")
BLACKBOX_LOG_ADMIN_VERB("Give Direct Control")
-/client/proc/cmd_admin_areatest(on_station, filter_maint)
- set category = "Mapping"
- set name = "Test Areas"
-
+ADMIN_VERB_VISIBILITY(cmd_admin_areatest, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_admin_areatest, R_DEBUG, "Test Areas", "Tests the areas for various machinery.", ADMIN_CATEGORY_MAPPING, on_station as num, filter_maint as num)
var/list/dat = list()
var/list/areas_all = list()
var/list/areas_with_APC = list()
@@ -270,7 +231,7 @@
))
if(SSticker.current_state == GAME_STATE_STARTUP)
- to_chat(usr, "Game still loading, please hold!", confidential = TRUE)
+ to_chat(user, "Game still loading, please hold!", confidential = TRUE)
return
var/log_message
@@ -283,8 +244,8 @@
dat += "Maintenance Areas Filtered Out"
log_message += ", with no maintenance areas"
- message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Areas debug command checking [log_message]."))
- log_admin("[key_name(usr)] used the Test Areas debug command checking [log_message].")
+ message_admins(span_adminnotice("[key_name_admin(user)] used the Test Areas debug command checking [log_message]."))
+ log_admin("[key_name(user)] used the Test Areas debug command checking [log_message].")
for(var/area/A as anything in GLOB.areas)
if(on_station)
@@ -425,28 +386,23 @@
if(!(areas_with_APC.len || areas_with_multiple_APCs.len || areas_with_air_alarm.len || areas_with_RC.len || areas_with_light.len || areas_with_LS.len || areas_with_intercom.len || areas_with_camera.len))
dat += "No problem areas!"
- var/datum/browser/popup = new(usr, "testareas", "Test Areas", 500, 750)
+ var/datum/browser/popup = new(user.mob, "testareas", "Test Areas", 500, 750)
popup.set_content(dat.Join())
popup.open()
+ADMIN_VERB_VISIBILITY(cmd_admin_areatest_station, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_admin_areatest_station, R_DEBUG, "Test Areas (STATION ONLY)", "Tests the areas for various machinery on station z-levels.", ADMIN_CATEGORY_MAPPING)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest, /* on_station = */ TRUE)
-/client/proc/cmd_admin_areatest_station()
- set category = "Mapping"
- set name = "Test Areas (STATION ONLY)"
- cmd_admin_areatest(TRUE)
+ADMIN_VERB_VISIBILITY(cmd_admin_areatest_station_no_maintenance, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_admin_areatest_station_no_maintenance, R_DEBUG, "Test Areas (STATION - NO MAINT)", "Tests the areas for various machinery on station z-levels, excluding maintenance areas.", ADMIN_CATEGORY_MAPPING)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest, /* on_station = */ TRUE, /* filter_maint = */ TRUE)
-/client/proc/cmd_admin_areatest_station_no_maintenance()
- set category = "Mapping"
- set name = "Test Areas (STATION - NO MAINT)"
- cmd_admin_areatest(on_station = TRUE, filter_maint = TRUE)
-
-/client/proc/cmd_admin_areatest_all()
- set category = "Mapping"
- set name = "Test Areas (ALL)"
- cmd_admin_areatest(FALSE)
+ADMIN_VERB_VISIBILITY(cmd_admin_areatest_all, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_admin_areatest_all, R_DEBUG, "Test Areas (ALL)", "Tests the areas for various machinery on all z-levels.", ADMIN_CATEGORY_MAPPING)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest)
/client/proc/robust_dress_shop()
-
var/list/baseoutfits = list("Naked","Custom","As Job...", "As Plasmaman...")
var/list/outfits = list()
var/list/paths = subtypesof(/datum/outfit) - typesof(/datum/outfit/job) - typesof(/datum/outfit/plasmaman)
@@ -497,52 +453,29 @@
return dresscode
-/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list)
- set category = "Debug"
- set name = "Rejuvenate"
-
- if(!check_rights(R_ADMIN))
- return
-
- if(!mob)
- return
+ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_rejuvenate, R_ADMIN, "Rejuvenate", mob/living/M in world)
if(!istype(M))
- tgui_alert(usr,"Cannot revive a ghost")
+ tgui_alert(user,"Cannot revive a ghost")
return
M.revive(ADMIN_HEAL_ALL)
- log_admin("[key_name(usr)] healed / revived [key_name(M)]")
- var/msg = span_danger("Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!")
+ log_admin("[key_name(user)] healed / revived [key_name(M)]")
+ var/msg = span_danger("Admin [key_name_admin(user)] healed / revived [ADMIN_LOOKUPFLW(M)]!")
message_admins(msg)
admin_ticket_log(M, msg)
BLACKBOX_LOG_ADMIN_VERB("Rejuvenate")
-/client/proc/cmd_admin_delete(atom/A as obj|mob|turf in world)
- set category = "Debug"
- set name = "Delete"
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_delete, R_DEBUG|R_SPAWN, "Delete", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/target as obj|mob|turf in world)
+ user.admin_delete(target)
- if(!check_rights(R_SPAWN|R_DEBUG))
- return
-
- admin_delete(A)
-
-/client/proc/cmd_admin_check_contents(mob/living/M in GLOB.mob_list)
- set category = "Debug"
- set name = "Check Contents"
-
- var/list/L = M.get_contents()
- for(var/t in L)
- to_chat(usr, "[t] [ADMIN_VV(t)] [ADMIN_TAG(t)]", confidential = TRUE)
+ADMIN_VERB_AND_CONTEXT_MENU(cmd_check_contents, R_ADMIN, "Check Contents", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/mob)
+ var/list/mob_contents = mob.get_contents()
+ for(var/content in mob_contents)
+ to_chat(user, "[content] [ADMIN_VV(content)] [ADMIN_TAG(content)]", confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Check Contents")
-/client/proc/modify_goals()
- set category = "Debug"
- set name = "Modify goals"
-
- if(!check_rights(R_ADMIN))
- return
-
- holder.modify_goals()
+ADMIN_VERB(modify_goals, R_ADMIN, "Modify Goals", "Modify the station goals for the shift.", ADMIN_CATEGORY_DEBUG)
+ user.holder.modify_goals()
/datum/admins/proc/modify_goals()
var/dat = ""
@@ -551,34 +484,27 @@
dat += " Add New Goal"
usr << browse(dat, "window=goals;size=400x400")
-/client/proc/cmd_debug_mob_lists()
- set category = "Debug"
- set name = "Debug Mob Lists"
- set desc = "For when you just gotta know"
- var/chosen_list = tgui_input_list(usr, "Which list?", "Select List", list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Clients","Joined Clients"))
+ADMIN_VERB(debug_mob_lists, R_DEBUG, "Debug Mob Lists", "For when you just gotta know.", ADMIN_CATEGORY_DEBUG)
+ var/chosen_list = tgui_input_list(user, "Which list?", "Select List", list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Clients","Joined Clients"))
if(isnull(chosen_list))
return
switch(chosen_list)
if("Players")
- to_chat(usr, jointext(GLOB.player_list,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.player_list,","), confidential = TRUE)
if("Admins")
- to_chat(usr, jointext(GLOB.admins,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.admins,","), confidential = TRUE)
if("Mobs")
- to_chat(usr, jointext(GLOB.mob_list,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.mob_list,","), confidential = TRUE)
if("Living Mobs")
- to_chat(usr, jointext(GLOB.alive_mob_list,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.alive_mob_list,","), confidential = TRUE)
if("Dead Mobs")
- to_chat(usr, jointext(GLOB.dead_mob_list,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.dead_mob_list,","), confidential = TRUE)
if("Clients")
- to_chat(usr, jointext(GLOB.clients,","), confidential = TRUE)
+ to_chat(user, jointext(GLOB.clients,","), confidential = TRUE)
if("Joined Clients")
- to_chat(usr, jointext(GLOB.joined_player_list,","), confidential = TRUE)
-
-/client/proc/cmd_display_del_log()
- set category = "Debug"
- set name = "Display del() Log"
- set desc = "Display del's log of everything that's passed through it."
+ to_chat(user, jointext(GLOB.joined_player_list,","), confidential = TRUE)
+ADMIN_VERB(del_log, R_DEBUG, "Display del() Log", "Display del's log of everything that's passed through it.", ADMIN_CATEGORY_DEBUG)
var/list/dellog = list("List of things that have gone through qdel this round
")
sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in SSgarbage.items)
@@ -609,37 +535,19 @@
dellog += ""
- usr << browse(dellog.Join(), "window=dellog")
+ user << browse(dellog.Join(), "window=dellog")
-/client/proc/cmd_display_overlay_log()
- set category = "Debug"
- set name = "Display overlay Log"
- set desc = "Display SSoverlays log of everything that's passed through it."
+ADMIN_VERB(display_overlay_log, R_DEBUG, "Display Overlay Log", "Display SSoverlays log of everything that's passed through it.", ADMIN_CATEGORY_DEBUG)
+ render_stats(SSoverlays.stats, user)
- render_stats(SSoverlays.stats, src)
+ADMIN_VERB(init_log, R_DEBUG, "Display Initialize() Log", "Displays a list of things that didn't handle Initialize() properly.", ADMIN_CATEGORY_DEBUG)
+ user << browse(replacetext(SSatoms.InitLog(), "\n", " "), "window=initlog")
-/client/proc/cmd_display_init_log()
- set category = "Debug"
- set name = "Display Initialize() Log"
- set desc = "Displays a list of things that didn't handle Initialize() properly"
+ADMIN_VERB(debug_color_test, R_DEBUG, "Colorblind Testing", "Change your view to a budget version of colorblindness to test for usability.", ADMIN_CATEGORY_DEBUG)
+ user.holder.color_test.ui_interact(user.mob)
- usr << browse(replacetext(SSatoms.InitLog(), "\n", " "), "window=initlog")
-
-/client/proc/open_colorblind_test()
- set category = "Debug"
- set name = "Colorblind Testing"
- set desc = "Change your view to a budget version of colorblindness to test for usability"
-
- if(!holder)
- return
- holder.color_test.ui_interact(mob)
-
-/client/proc/debug_plane_masters()
- set category = "Debug"
- set name = "Edit/Debug Planes"
- set desc = "Edit and visualize plane masters and their connections (relays)"
-
- edit_plane_masters()
+ADMIN_VERB(debug_plane_masters, R_DEBUG, "Edit/Debug Planes", "Edit and visualize plane masters and their connections (relays).", ADMIN_CATEGORY_DEBUG)
+ user.edit_plane_masters()
/client/proc/edit_plane_masters(mob/debug_on)
if(!holder)
@@ -651,21 +559,10 @@
holder.plane_debug.set_mirroring(FALSE)
holder.plane_debug.ui_interact(mob)
-/client/proc/debug_huds(i as num)
- set category = "Debug"
- set name = "Debug HUDs"
- set desc = "Debug the data or antag HUDs"
+ADMIN_VERB(debug_huds, R_DEBUG, "Debug HUDs", "Debug the data or antag HUDs.", ADMIN_CATEGORY_DEBUG, i as num)
+ SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/debug_variables, GLOB.huds[i])
- if(!holder)
- return
- debug_variables(GLOB.huds[i])
-
-/client/proc/jump_to_ruin()
- set category = "Debug"
- set name = "Jump to Ruin"
- set desc = "Displays a list of all placed ruins to teleport to."
- if(!holder)
- return
+ADMIN_VERB(jump_to_ruin, R_DEBUG, "Jump to Ruin", "Displays a list of all placed ruins to teleport to.", ADMIN_CATEGORY_DEBUG)
var/list/names = list()
for(var/obj/effect/landmark/ruin/ruin_landmark as anything in GLOB.ruin_landmarks)
var/datum/map_template/ruin/template = ruin_landmark.ruin_template
@@ -680,23 +577,17 @@
names[name] = ruin_landmark
- var/ruinname = tgui_input_list(usr, "Select ruin", "Jump to Ruin", sort_list(names))
-
+ var/ruinname = tgui_input_list(user, "Select ruin", "Jump to Ruin", sort_list(names))
var/obj/effect/landmark/ruin/landmark = names[ruinname]
-
- if(istype(landmark))
- var/datum/map_template/ruin/template = landmark.ruin_template
- usr.forceMove(get_turf(landmark))
- to_chat(usr, span_name("[template.name]"), confidential = TRUE)
- to_chat(usr, "[template.description]", confidential = TRUE)
-
-/client/proc/place_ruin()
- set category = "Debug"
- set name = "Spawn Ruin"
- set desc = "Attempt to randomly place a specific ruin."
- if (!holder)
+ if(!istype(landmark))
return
+ var/datum/map_template/ruin/template = landmark.ruin_template
+ user.mob.forceMove(get_turf(landmark))
+ to_chat(user, span_name("[template.name]"), confidential = TRUE)
+ to_chat(user, "[template.description]", confidential = TRUE)
+ADMIN_VERB_VISIBILITY(place_ruin, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(place_ruin, R_DEBUG, "Spawn Ruin", "Attempt to randomly place a specific ruin.", ADMIN_CATEGORY_MAPPING)
var/list/exists = list()
for(var/landmark in GLOB.ruin_landmarks)
var/obj/effect/landmark/ruin/L = landmark
@@ -714,15 +605,15 @@
themed_names[name] = list(ruin, theme, list(ruin.default_area))
names += sort_list(themed_names)
- var/ruinname = tgui_input_list(usr, "Select ruin", "Spawn Ruin", sort_list(names))
+ var/ruinname = tgui_input_list(user, "Select ruin", "Spawn Ruin", sort_list(names))
var/data = names[ruinname]
if (!data)
return
var/datum/map_template/ruin/template = data[1]
if (exists[template])
- var/response = tgui_alert(usr,"There is already a [template] in existence.", "Spawn Ruin", list("Jump", "Place Another", "Cancel"))
+ var/response = tgui_alert(user,"There is already a [template] in existence.", "Spawn Ruin", list("Jump", "Place Another", "Cancel"))
if (response == "Jump")
- usr.forceMove(get_turf(exists[template]))
+ user.mob.forceMove(get_turf(exists[template]))
return
else if (response == "Cancel")
return
@@ -731,25 +622,17 @@
seedRuins(SSmapping.levels_by_trait(data[2]), max(1, template.cost), data[3], list(ruinname = template))
if (GLOB.ruin_landmarks.len > len)
var/obj/effect/landmark/ruin/landmark = GLOB.ruin_landmarks[GLOB.ruin_landmarks.len]
- log_admin("[key_name(src)] randomly spawned ruin [ruinname] at [COORD(landmark)].")
- usr.forceMove(get_turf(landmark))
- to_chat(src, span_name("[template.name]"), confidential = TRUE)
- to_chat(src, "[template.description]", confidential = TRUE)
+ log_admin("[key_name(user)] randomly spawned ruin [ruinname] at [COORD(landmark)].")
+ user.mob.forceMove(get_turf(landmark))
+ to_chat(user, span_name("[template.name]"), confidential = TRUE)
+ to_chat(user, "[template.description]", confidential = TRUE)
else
- to_chat(src, span_warning("Failed to place [template.name]."), confidential = TRUE)
+ to_chat(user, span_warning("Failed to place [template.name]."), confidential = TRUE)
-/client/proc/unload_ctf()
- set category = "Debug"
- set name = "Unload CTF"
- set desc = "Despawns the majority of CTF"
-
- toggle_id_ctf(usr, CTF_GHOST_CTF_GAME_ID, unload=TRUE)
-
-/client/proc/run_empty_query(val as num)
- set category = "Debug"
- set name = "Run empty query"
- set desc = "Amount of queries to run"
+ADMIN_VERB(unload_ctf, R_DEBUG, "Unload CTF", "Despawns the majority of CTF.", ADMIN_CATEGORY_DEBUG)
+ toggle_id_ctf(user, CTF_GHOST_CTF_GAME_ID, unload=TRUE)
+ADMIN_VERB(run_empty_query, R_DEBUG, "Run Empty Query", "Runs a specified number of empty queries.", ADMIN_CATEGORY_DEBUG, val as num)
var/list/queries = list()
for(var/i in 1 to val)
var/datum/db_query/query = SSdbcore.NewQuery("NULL")
@@ -761,45 +644,31 @@
qdel(query)
queries.Cut()
- message_admins("[key_name_admin(src)] ran [val] empty queries.")
+ message_admins("[key_name_admin(user)] ran [val] empty queries.")
-/client/proc/clear_dynamic_transit()
- set category = "Debug"
- set name = "Clear Dynamic Turf Reservations"
- set desc = "Deallocates all reserved space, restoring it to round start conditions."
- if(!holder)
- return
- var/answer = tgui_alert(usr,"WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", list("YES", "NO"))
+ADMIN_VERB(clear_turf_reservations, R_DEBUG, "Clear Dynamic Turf Reservations", "Deallocates all reserved space, restoring it to round start conditions.", ADMIN_CATEGORY_DEBUG)
+ var/answer = tgui_alert(
+ user,
+ "WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!",
+ "Really wipe dynamic turfs?",
+ list("YES", "NO"),
+ )
if(answer != "YES")
return
- message_admins(span_adminnotice("[key_name_admin(src)] cleared dynamic transit space."))
- BLACKBOX_LOG_ADMIN_VERB("Clear Dynamic Transit")
- log_admin("[key_name(src)] cleared dynamic transit space.")
+ message_admins(span_adminnotice("[key_name_admin(user)] cleared dynamic transit space."))
+ BLACKBOX_LOG_ADMIN_VERB("Clear Dynamic Turf Reservations")
+ log_admin("[key_name(user)] cleared dynamic turf reservations.")
SSmapping.wipe_reservations() //this goes after it's logged, incase something horrible happens.
-/client/proc/toggle_medal_disable()
- set category = "Debug"
- set name = "Toggle Medal Disable"
- set desc = "Toggles the safety lock on trying to contact the medal hub."
-
- if(!check_rights(R_DEBUG))
- return
-
+ADMIN_VERB(toggle_medal_disable, R_DEBUG, "Toggle Medal Disable", "Toggles the safety lock on trying to contact the medal hub.", ADMIN_CATEGORY_DEBUG)
SSachievements.achievements_enabled = !SSachievements.achievements_enabled
- message_admins(span_adminnotice("[key_name_admin(src)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout."))
+ message_admins(span_adminnotice("[key_name_admin(user)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout."))
BLACKBOX_LOG_ADMIN_VERB("Toggle Medal Disable")
- log_admin("[key_name(src)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.")
+ log_admin("[key_name(user)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.")
-/client/proc/view_runtimes()
- set category = "Debug"
- set name = "View Runtimes"
- set desc = "Open the runtime Viewer"
-
- if(!holder)
- return
-
- GLOB.error_cache.show_to(src)
+ADMIN_VERB(view_runtimes, R_DEBUG, "View Runtimes", "Opens the runtime viewer.", ADMIN_CATEGORY_DEBUG)
+ GLOB.error_cache.show_to(user)
// The runtime viewer has the potential to crash the server if there's a LOT of runtimes
// this has happened before, multiple times, so we'll just leave an alert on it
@@ -808,80 +677,54 @@
if(GLOB.total_runtimes >= 100000)
warning = "There are a TON of runtimes, clicking any button (especially \"linear\") WILL LIKELY crash the server"
// Not using TGUI alert, because it's view runtimes, stuff is probably broken
- alert(usr, "[warning]. Proceed with caution. If you really need to see the runtimes, download the runtime log and view it in a text editor.", "HEED THIS WARNING CAREFULLY MORTAL")
-
-/client/proc/pump_random_event()
- set category = "Debug"
- set name = "Pump Random Event"
- set desc = "Schedules the event subsystem to fire a new random event immediately. Some events may fire without notification."
- if(!holder)
- return
+ alert(user, "[warning]. Proceed with caution. If you really need to see the runtimes, download the runtime log and view it in a text editor.", "HEED THIS WARNING CAREFULLY MORTAL")
+ADMIN_VERB(pump_random_event, R_DEBUG, "Pump Random Event", "Schedules the event subsystem to fire a new random event immediately. Some events may fire without notification.", ADMIN_CATEGORY_DEBUG)
SSevents.scheduled = world.time
- message_admins(span_adminnotice("[key_name_admin(src)] pumped a random event."))
+ message_admins(span_adminnotice("[key_name_admin(user)] pumped a random event."))
BLACKBOX_LOG_ADMIN_VERB("Pump Random Event")
- log_admin("[key_name(src)] pumped a random event.")
-
-/client/proc/start_line_profiling()
- set category = "Profile"
- set name = "Start Line Profiling"
- set desc = "Starts tracking line by line profiling for code lines that support it"
+ log_admin("[key_name(user)] pumped a random event.")
+ADMIN_VERB_VISIBILITY(start_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(start_line_profiling, R_DEBUG, "Start Line Profiling", "Starts tracking line by line profiling for code lines that support it.", ADMIN_CATEGORY_PROFILE)
LINE_PROFILE_START
- message_admins(span_adminnotice("[key_name_admin(src)] started line by line profiling."))
+ message_admins(span_adminnotice("[key_name_admin(user)] started line by line profiling."))
BLACKBOX_LOG_ADMIN_VERB("Start Line Profiling")
- log_admin("[key_name(src)] started line by line profiling.")
-
-/client/proc/stop_line_profiling()
- set category = "Profile"
- set name = "Stops Line Profiling"
- set desc = "Stops tracking line by line profiling for code lines that support it"
+ log_admin("[key_name(user)] started line by line profiling.")
+ADMIN_VERB_VISIBILITY(stop_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(stop_line_profiling, R_DEBUG, "Stop Line Profiling", "Stops tracking line by line profiling for code lines that support it.", ADMIN_CATEGORY_PROFILE)
LINE_PROFILE_STOP
- message_admins(span_adminnotice("[key_name_admin(src)] stopped line by line profiling."))
+ message_admins(span_adminnotice("[key_name_admin(user)] stopped line by line profiling."))
BLACKBOX_LOG_ADMIN_VERB("Stop Line Profiling")
- log_admin("[key_name(src)] stopped line by line profiling.")
-
-/client/proc/show_line_profiling()
- set category = "Profile"
- set name = "Show Line Profiling"
- set desc = "Shows tracked profiling info from code lines that support it"
+ log_admin("[key_name(user)] stopped line by line profiling.")
+ADMIN_VERB_VISIBILITY(show_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(show_line_profiling, R_DEBUG, "Show Line Profiling", "Shows tracked profiling info from code lines that support it.", ADMIN_CATEGORY_PROFILE)
var/sortlist = list(
"Avg time" = GLOBAL_PROC_REF(cmp_profile_avg_time_dsc),
"Total Time" = GLOBAL_PROC_REF(cmp_profile_time_dsc),
"Call Count" = GLOBAL_PROC_REF(cmp_profile_count_dsc)
)
- var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist
+ var/sort = input(user, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist
if (!sort)
return
sort = sortlist[sort]
- profile_show(src, sort)
+ profile_show(user, sort)
-/client/proc/reload_configuration()
- set category = "Debug"
- set name = "Reload Configuration"
- set desc = "Force config reload to world default"
- if(!check_rights(R_DEBUG))
- return
- if(tgui_alert(usr, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modifications?", "Really reset?", list("No", "Yes")) == "Yes")
- config.admin_reload()
-
-/// A debug verb to check the sources of currently running timers
-/client/proc/check_timer_sources()
- set category = "Debug"
- set name = "Check Timer Sources"
- set desc = "Checks the sources of the running timers"
- if (!check_rights(R_DEBUG))
+ADMIN_VERB(reload_configuration, R_DEBUG, "Reload Configuration", "Reloads the configuration from the default path on the disk, wiping any in-round modifications.", ADMIN_CATEGORY_DEBUG)
+ if(!tgui_alert(user, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modifications?", "Really reset?", list("No", "Yes")) == "Yes")
return
+ config.admin_reload()
+ADMIN_VERB(check_timer_sources, R_DEBUG, "Check Timer Sources", "Checks the sources of running timers.", ADMIN_CATEGORY_DEBUG)
var/bucket_list_output = generate_timer_source_output(SStimer.bucket_list)
var/second_queue = generate_timer_source_output(SStimer.second_queue)
- usr << browse({"
+ user << browse({"
bucket_list
[bucket_list_output]
@@ -889,24 +732,16 @@
[second_queue]
"}, "window=check_timer_sources;size=700x700")
-/// A debug verb to try and re-establish a connection with the TTS server and to refetch TTS voices.
-/// Since voices are cached beforehand, this is unlikely to update preferences.
-/client/proc/reestablish_tts_connection()
- set category = "Debug"
- set name = "Re-establish Connection To TTS"
- set desc = "Re-establishes connection to the TTS server if possible"
- if (!check_rights(R_DEBUG))
- return
-
- message_admins("[key_name_admin(usr)] attempted to re-establish connection to the TTS HTTP server.")
- log_admin("[key_name(usr)] attempted to re-establish connection to the TTS HTTP server.")
+ADMIN_VERB(reestablish_tts_connection, R_DEBUG, "Re-establish Connection To TTS", "Re-establishes connection to the TTS server if possible", ADMIN_CATEGORY_DEBUG)
+ message_admins("[key_name_admin(user)] attempted to re-establish connection to the TTS HTTP server.")
+ log_admin("[key_name(user)] attempted to re-establish connection to the TTS HTTP server.")
var/success = SStts.establish_connection_to_tts()
if(!success)
- message_admins("[key_name_admin(usr)] failed to re-established the connection to the TTS HTTP server.")
- log_admin("[key_name(usr)] failed to re-established the connection to the TTS HTTP server.")
+ message_admins("[key_name_admin(user)] failed to re-established the connection to the TTS HTTP server.")
+ log_admin("[key_name(user)] failed to re-established the connection to the TTS HTTP server.")
return
- message_admins("[key_name_admin(usr)] successfully re-established the connection to the TTS HTTP server.")
- log_admin("[key_name(usr)] successfully re-established the connection to the TTS HTTP server.")
+ message_admins("[key_name_admin(user)] successfully re-established the connection to the TTS HTTP server.")
+ log_admin("[key_name(user)] successfully re-established the connection to the TTS HTTP server.")
/proc/generate_timer_source_output(list/datum/timedevent/events)
var/list/per_source = list()
@@ -950,10 +785,14 @@
return b["count"] - a["count"]
#ifdef TESTING
-/client/proc/check_missing_sprites()
- set category = "Debug"
- set name = "Debug Worn Item Sprites"
- set desc = "We're cancelling the Spritemageddon. (This will create a LOT of runtimes! Don't use on a live server!)"
+ADMIN_VERB_CUSTOM_EXIST_CHECK(check_missing_sprites)
+ return TRUE
+#else
+ADMIN_VERB_CUSTOM_EXIST_CHECK(check_missing_sprites)
+ return FALSE
+#endif
+
+ADMIN_VERB(check_missing_sprites, R_DEBUG, "Debug Worn Item Sprites", "We're cancelling the Spritemageddon. (This will create a LOT of runtimes! Don't use on a live server!)", ADMIN_CATEGORY_DEBUG)
var/actual_file_name
for(var/test_obj in subtypesof(/obj/item))
var/obj/item/sprite = new test_obj
@@ -962,55 +801,54 @@
//Is there an explicit worn_icon to pick against the worn_icon_state? Easy street expected behavior.
if(sprite.worn_icon)
if(!(sprite.icon_state in icon_states(sprite.worn_icon)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Slot Flags are [sprite.slot_flags]."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Slot Flags are [sprite.slot_flags]."), confidential = TRUE)
else if(sprite.worn_icon_state)
if(sprite.slot_flags & ITEM_SLOT_MASK)
actual_file_name = 'icons/mob/clothing/mask.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_NECK)
actual_file_name = 'icons/mob/clothing/neck.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BACK)
actual_file_name = 'icons/mob/clothing/back.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_HEAD)
actual_file_name = 'icons/mob/clothing/head/default.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BELT)
actual_file_name = 'icons/mob/clothing/belt.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_SUITSTORE)
actual_file_name = 'icons/mob/clothing/belt_mirror.dmi'
if(!(sprite.worn_icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
else if(sprite.icon_state)
if(sprite.slot_flags & ITEM_SLOT_MASK)
actual_file_name = 'icons/mob/clothing/mask.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_NECK)
actual_file_name = 'icons/mob/clothing/neck.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BACK)
actual_file_name = 'icons/mob/clothing/back.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_HEAD)
actual_file_name = 'icons/mob/clothing/head/default.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_BELT)
actual_file_name = 'icons/mob/clothing/belt.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE)
if(sprite.slot_flags & ITEM_SLOT_SUITSTORE)
actual_file_name = 'icons/mob/clothing/belt_mirror.dmi'
if(!(sprite.icon_state in icon_states(actual_file_name)))
- to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
-#endif
+ to_chat(user, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE)
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index a6a9a204b85..4575614bb94 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -1,15 +1,10 @@
-/client/proc/air_status(turf/target)
- set category = "Debug"
- set name = "Display Air Status"
-
- if(!isturf(target))
- return
- atmos_scan(user=usr, target=target, silent=TRUE)
+ADMIN_VERB_VISIBILITY(debug_air_status, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(debug_air_status, R_DEBUG, "Debug Air Status" , ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, turf/target in world)
+ atmos_scan(user.mob, target, silent = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Show Air Status")
-/client/proc/fix_next_move()
- set category = "Debug"
- set name = "Unfreeze Everyone"
+ADMIN_VERB_VISIBILITY(fix_next_move, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(fix_next_move, R_DEBUG, "Fix Next Move", "Unfreezes all frozen mobs.", ADMIN_CATEGORY_DEBUG)
var/largest_move_time = 0
var/largest_click_time = 0
var/mob/largest_move_mob = null
@@ -34,12 +29,9 @@
message_admins("[ADMIN_LOOKUPFLW(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!")
message_admins("world.time = [world.time]")
BLACKBOX_LOG_ADMIN_VERB("Unfreeze Everyone")
- return
-
-/client/proc/radio_report()
- set category = "Debug"
- set name = "Radio report"
+ADMIN_VERB_VISIBILITY(radio_report, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(radio_report, R_DEBUG, "Radio Report", "Shows a report of all radio devices and their filters.", ADMIN_CATEGORY_DEBUG)
var/output = "Radio Report"
for (var/fq in SSradio.frequencies)
output += "Freq: [fq] "
@@ -64,29 +56,21 @@
else
output += " [device] "
- usr << browse(output,"window=radioreport")
+ user << browse(output,"window=radioreport")
BLACKBOX_LOG_ADMIN_VERB("Show Radio Report")
-/client/proc/reload_admins()
- set name = "Reload Admins"
- set category = "Admin"
-
- if(!src.holder)
- return
-
- var/confirm = tgui_alert(usr, "Are you sure you want to reload all admins?", "Confirm", list("Yes", "No"))
+ADMIN_VERB(reload_admins, R_NONE, "Reload Admins", "Reloads all admins from the database.", ADMIN_CATEGORY_MAIN)
+ var/confirm = tgui_alert(user, "Are you sure you want to reload all admins?", "Confirm", list("Yes", "No"))
if(confirm != "Yes")
return
load_admins()
BLACKBOX_LOG_ADMIN_VERB("Reload All Admins")
- message_admins("[key_name_admin(usr)] manually reloaded admins")
+ message_admins("[key_name_admin(user)] manually reloaded admins")
-/client/proc/toggle_cdn()
- set name = "Toggle CDN"
- set category = "Server"
+ADMIN_VERB(toggle_cdn, R_SERVER|R_DEBUG, "Toggle CDN", "Toggles the CDN for the server.", ADMIN_CATEGORY_SERVER)
var/static/admin_disabled_cdn_transport = null
- if (alert(usr, "Are you sure you want to toggle the CDN asset transport?", "Confirm", "Yes", "No") != "Yes")
+ if (alert(user, "Are you sure you want to toggle the CDN asset transport?", "Confirm", "Yes", "No") != "Yes")
return
var/current_transport = CONFIG_GET(string/asset_transport)
if (!current_transport || current_transport == "simple")
@@ -94,17 +78,17 @@
CONFIG_SET(string/asset_transport, admin_disabled_cdn_transport)
admin_disabled_cdn_transport = null
SSassets.OnConfigLoad()
- message_admins("[key_name_admin(usr)] re-enabled the CDN asset transport")
- log_admin("[key_name(usr)] re-enabled the CDN asset transport")
+ message_admins("[key_name_admin(user)] re-enabled the CDN asset transport")
+ log_admin("[key_name(user)] re-enabled the CDN asset transport")
else
- to_chat(usr, span_adminnotice("The CDN is not enabled!"))
- if (tgui_alert(usr, "The CDN asset transport is not enabled! If you having issues with assets you can also try disabling filename mutations.", "The CDN asset transport is not enabled!", list("Try disabling filename mutations", "Nevermind")) == "Try disabling filename mutations")
+ to_chat(user, span_adminnotice("The CDN is not enabled!"))
+ if (tgui_alert(user, "The CDN asset transport is not enabled! If you having issues with assets you can also try disabling filename mutations.", "The CDN asset transport is not enabled!", list("Try disabling filename mutations", "Nevermind")) == "Try disabling filename mutations")
SSassets.transport.dont_mutate_filenames = !SSassets.transport.dont_mutate_filenames
- message_admins("[key_name_admin(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms")
- log_admin("[key_name(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms")
+ message_admins("[key_name_admin(user)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms")
+ log_admin("[key_name(user)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms")
else
admin_disabled_cdn_transport = current_transport
CONFIG_SET(string/asset_transport, "simple")
SSassets.OnConfigLoad()
- message_admins("[key_name_admin(usr)] disabled the CDN asset transport")
- log_admin("[key_name(usr)] disabled the CDN asset transport")
+ message_admins("[key_name_admin(user)] disabled the CDN asset transport")
+ log_admin("[key_name(user)] disabled the CDN asset transport")
diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm
index c99e226d310..1695a993bd5 100644
--- a/code/modules/admin/verbs/ert.dm
+++ b/code/modules/admin/verbs/ert.dm
@@ -269,18 +269,14 @@
return
-/client/proc/summon_ert()
- set category = "Admin.Fun"
- set name = "Summon ERT"
- set desc = "Summons an emergency response team"
-
- message_admins("[key_name(usr)] is creating a CentCom response team...")
- if(holder?.makeEmergencyresponseteam())
- message_admins("[key_name(usr)] created a CentCom response team.")
- log_admin("[key_name(usr)] created a CentCom response team.")
+ADMIN_VERB(summon_ert, R_FUN, "Summon ERT", "Summons an emergency response team.", ADMIN_CATEGORY_FUN)
+ message_admins("[key_name_admin(user)] is creating a CentCom response team...")
+ if(user.holder?.makeEmergencyresponseteam())
+ message_admins("[key_name_admin(user)] created a CentCom response team.")
+ log_admin("[key_name(user)] created a CentCom response team.")
else
- message_admins("[key_name_admin(usr)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.")
- log_admin("[key_name(usr)] failed to create a CentCom response team.")
+ message_admins("[key_name_admin(user)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.")
+ log_admin("[key_name(user)] failed to create a CentCom response team.")
#undef ERT_EXPERIENCED_LEADER_CHOOSE_TOP
#undef DUMMY_HUMAN_SLOT_ADMIN
diff --git a/code/modules/admin/verbs/fix_air.dm b/code/modules/admin/verbs/fix_air.dm
index fb4a342c3d4..0f67200f61b 100644
--- a/code/modules/admin/verbs/fix_air.dm
+++ b/code/modules/admin/verbs/fix_air.dm
@@ -1,23 +1,16 @@
// Proc taken from yogstation, credit to nichlas0010 for the original
-/client/proc/fix_air(turf/open/T in world)
- set name = "Fix Air"
- set category = "Admin.Game"
- set desc = "Fixes air in specified radius."
+ADMIN_VERB_AND_CONTEXT_MENU(fix_air, R_ADMIN, "Fix Air", "Fixes air in a specified radius.", ADMIN_CATEGORY_GAME, turf/open/locale in world, range = 2 as num)
+ message_admins("[key_name_admin(user)] fixed air with range [range] in area [locale.loc.name]")
+ user.mob.log_message("fixed air with range [range] in area [locale.loc.name]", LOG_ADMIN)
- if(!holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
- if(check_rights(R_ADMIN,1))
- var/range=input("Enter range:","Num",2) as num
- message_admins("[key_name_admin(usr)] fixed air with range [range] in area [T.loc.name]")
- usr.log_message("fixed air with range [range] in area [T.loc.name]", LOG_ADMIN)
- for(var/turf/open/F in range(range,T))
- if(F.blocks_air)
- //skip walls
- continue
- var/datum/gas_mixture/GM = SSair.parse_gas_string(F.initial_gas_mix, /datum/gas_mixture/turf)
- F.copy_air(GM)
- F.update_visuals()
-
- if(F.pollution) //SKYRAT EDIT ADDITION
- qdel(F.pollution)
+ for(var/turf/open/valid_range_turf in range(range,locale))
+ if(valid_range_turf.blocks_air)
+ //skip walls
+ continue
+ //SKYRAT EDIT ADDITION START
+ if(valid_range_turf.pollution)
+ qdel(valid_range_turf.pollution)
+ //SKYRAT EDIT ADDITION END
+ var/datum/gas_mixture/GM = SSair.parse_gas_string(valid_range_turf.initial_gas_mix, /datum/gas_mixture/turf)
+ valid_range_turf.copy_air(GM)
+ valid_range_turf.update_visuals()
diff --git a/code/modules/admin/verbs/fov.dm b/code/modules/admin/verbs/fov.dm
index f74ba6f8058..afcd379e4a0 100644
--- a/code/modules/admin/verbs/fov.dm
+++ b/code/modules/admin/verbs/fov.dm
@@ -1,14 +1,8 @@
-/client/proc/cmd_admin_toggle_fov()
- set name = "Enable/Disable Field of View"
- set category = "Debug"
-
- if(!check_rights(R_ADMIN) || !check_rights(R_DEBUG))
- return
-
+ADMIN_VERB(toggle_fov, R_ADMIN|R_DEBUG, "Enable/Disable Field Of View", "Toggle FOV globally.", ADMIN_CATEGORY_DEBUG)
var/on_off = CONFIG_GET(flag/native_fov)
- message_admins("[key_name_admin(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration..")
- log_admin("[key_name(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration.")
+ message_admins("[key_name_admin(user)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration..")
+ log_admin("[key_name(user)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration.")
CONFIG_SET(flag/native_fov, !on_off)
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Field of View", "[on_off ? "Enabled" : "Disabled"]"))
diff --git a/code/modules/admin/verbs/fps.dm b/code/modules/admin/verbs/fps.dm
index 578a0c09514..7af7968cde4 100644
--- a/code/modules/admin/verbs/fps.dm
+++ b/code/modules/admin/verbs/fps.dm
@@ -1,23 +1,16 @@
-//replaces the old Ticklag verb, fps is easier to understand
-/client/proc/set_server_fps()
- set category = "Debug"
- set name = "Set Server FPS"
- set desc = "Sets game speed in frames-per-second. Can potentially break the game"
-
- if(!check_rights(R_DEBUG))
- return
-
+ADMIN_VERB_VISIBILITY(set_server_fps, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(set_server_fps, R_DEBUG, "Set Server FPS", "Sets game speed in frames-per-second. Can potentially break the game", ADMIN_CATEGORY_DEBUG)
var/cfg_fps = CONFIG_GET(number/fps)
- var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [cfg_fps])","FPS", world.fps) as num|null)
+ var/new_fps = round(input(user, "Sets game frames-per-second. Can potentially break the game (default: [cfg_fps])","FPS", world.fps) as num|null)
if(new_fps <= 0)
- to_chat(src, span_danger("Error: set_server_fps(): Invalid world.fps value. No changes made."), confidential = TRUE)
+ to_chat(user, span_danger("Error: set_server_fps(): Invalid world.fps value. No changes made."), confidential = TRUE)
return
if(new_fps > cfg_fps * 1.5)
- if(tgui_alert(usr, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [cfg_fps]","Warning!",list("Confirm","ABORT-ABORT-ABORT")) != "Confirm")
+ if(tgui_alert(user, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [cfg_fps]","Warning!",list("Confirm","ABORT-ABORT-ABORT")) != "Confirm")
return
- var/msg = "[key_name(src)] has modified world.fps to [new_fps]"
+ var/msg = "[key_name(user)] has modified world.fps to [new_fps]"
log_admin(msg, 0)
message_admins(msg, 0)
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Set Server FPS", "[new_fps]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm
index 77b43f9b49f..bceac01cbe0 100644
--- a/code/modules/admin/verbs/getlogs.dm
+++ b/code/modules/admin/verbs/getlogs.dm
@@ -1,17 +1,8 @@
-//This proc allows download of past server logs saved within the data/logs/ folder.
-/client/proc/getserverlogs()
- set name = "Get Server Logs"
- set desc = "View/retrieve logfiles."
- set category = "Admin"
+ADMIN_VERB(get_server_logs, R_ADMIN, "Get Server Logs", "View or retrieve logfiles.", ADMIN_CATEGORY_MAIN)
+ user.browseserverlogs()
- browseserverlogs()
-
-/client/proc/getcurrentlogs()
- set name = "Get Current Logs"
- set desc = "View/retrieve logfiles for the current round."
- set category = "Admin"
-
- browseserverlogs(current=TRUE)
+ADMIN_VERB(get_current_logs, R_ADMIN, "Get Current Logs", "View or retrieve logfiles for the current round.", ADMIN_CATEGORY_MAIN)
+ user.browseserverlogs(current=TRUE)
/client/proc/browseserverlogs(current=FALSE)
var/path = browse_files(current ? BROWSE_ROOT_CURRENT_LOGS : BROWSE_ROOT_ALL_LOGS)
@@ -32,4 +23,3 @@
else
return
to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.", confidential = TRUE)
- return
diff --git a/code/modules/admin/verbs/ghost_pool_protection.dm b/code/modules/admin/verbs/ghost_pool_protection.dm
index 843f6868e70..439f4a37b89 100644
--- a/code/modules/admin/verbs/ghost_pool_protection.dm
+++ b/code/modules/admin/verbs/ghost_pool_protection.dm
@@ -1,11 +1,8 @@
//very similar to centcom_podlauncher in terms of how this is coded, so i kept a lot of comments from it
-/client/proc/ghost_pool_protection() //Creates a verb for admins to open up the ui
- set name = "Ghost Pool Protection"
- set desc = "Choose which ways people can get into the round, or just clear it out completely for admin events."
- set category = "Admin.Events"
- var/datum/ghost_pool_menu/tgui = new(usr)//create the datum
- tgui.ui_interact(usr)//datum has a tgui component, here we open the window
+ADMIN_VERB(ghost_pool_protection, R_ADMIN, "Ghost Pool Protection", "Choose which ways people can get into the round, or just clear it out completely for admin events.", ADMIN_CATEGORY_EVENTS)
+ var/datum/ghost_pool_menu/tgui = new(user)
+ tgui.ui_interact(user.mob)
/datum/ghost_pool_menu
var/client/holder //client of whoever is using this datum
diff --git a/code/modules/admin/verbs/lawpanel.dm b/code/modules/admin/verbs/lawpanel.dm
index 9b52c8d7339..f1daaf17576 100644
--- a/code/modules/admin/verbs/lawpanel.dm
+++ b/code/modules/admin/verbs/lawpanel.dm
@@ -1,15 +1,9 @@
-/client/proc/cmd_admin_law_panel()
- set category = "Admin.Events"
- set name = "Law Panel"
-
- if(!check_rights(R_ADMIN))
- return
- if(!isobserver(usr) && SSticker.HasRoundStarted())
- message_admins("[key_name_admin(usr)] checked AI laws via the Law Panel.")
-
+ADMIN_VERB(law_panel, R_ADMIN, "Law Panel", "View the AI laws.", ADMIN_CATEGORY_EVENTS)
+ if(!isobserver(user) && SSticker.HasRoundStarted())
+ message_admins("[key_name_admin(user)] checked AI laws via the Law Panel.")
+ var/datum/law_panel/tgui = new
+ tgui.ui_interact(user.mob)
BLACKBOX_LOG_ADMIN_VERB("Law Panel")
- var/datum/law_panel/tgui = new()
- tgui.ui_interact(usr)
/datum/law_panel
@@ -211,7 +205,7 @@
switch(action)
if("lawchange_logs")
- usr.client?.list_law_changes()
+ ui.user?.client?.holder?.list_law_changes()
return FALSE
if("force_state_laws")
diff --git a/code/modules/admin/verbs/lua/lua_editor.dm b/code/modules/admin/verbs/lua/lua_editor.dm
index 9e1b851824b..d4a4bc2ee50 100644
--- a/code/modules/admin/verbs/lua/lua_editor.dm
+++ b/code/modules/admin/verbs/lua/lua_editor.dm
@@ -233,10 +233,6 @@
. = ..()
qdel(src)
-/client/proc/open_lua_editor()
- set name = "Open Lua Editor"
- set category = "Debug"
- if(!check_rights_for(src, R_DEBUG))
- return
- var/datum/lua_editor/editor = new()
- editor.ui_interact(usr)
+ADMIN_VERB(lua_editor, R_DEBUG, "Open Lua Editor", "Its codin' time.", ADMIN_CATEGORY_DEBUG)
+ var/datum/lua_editor/editor = new
+ editor.ui_interact(user.mob)
diff --git a/code/modules/admin/verbs/machine_upgrade.dm b/code/modules/admin/verbs/machine_upgrade.dm
index 2f681574d5d..258de6bcf4d 100644
--- a/code/modules/admin/verbs/machine_upgrade.dm
+++ b/code/modules/admin/verbs/machine_upgrade.dm
@@ -1,13 +1,7 @@
-/proc/machine_upgrade(obj/machinery/M in world)
- set name = "Tweak Component Ratings"
- set category = "Debug"
- if (!istype(M))
- return
-
- var/new_rating = input("Enter new rating:","Num") as num|null
- if(new_rating && M.component_parts)
- for(var/obj/item/stock_parts/P in M.component_parts)
+ADMIN_VERB(machine_upgrade, R_DEBUG, "Tweak Component Ratings", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, obj/machinery/machine in world)
+ var/new_rating = input(user, "Enter new rating:","Num") as num|null
+ if(new_rating && machine.component_parts)
+ for(var/obj/item/stock_parts/P in machine.component_parts)
P.rating = new_rating
- M.RefreshParts()
-
+ machine.RefreshParts()
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Machine Upgrade", "[new_rating]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm
index 30f198bfba9..bfb5050dafa 100644
--- a/code/modules/admin/verbs/manipulate_organs.dm
+++ b/code/modules/admin/verbs/manipulate_organs.dm
@@ -1,7 +1,6 @@
-/client/proc/manipulate_organs(mob/living/carbon/carbon_victim in world)
- set name = "Manipulate Organs"
- set category = "Debug"
- var/operation = tgui_input_list(usr, "Select organ operation", "Organ Manipulation", list("add organ", "add implant", "drop organ/implant", "remove organ/implant"))
+ADMIN_VERB_VISIBILITY(manipulate_organs, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(manipulate_organs, R_DEBUG, "Manipulate Organs", "Manipulate the organs of a living carbon.", ADMIN_CATEGORY_DEBUG, mob/living/carbon/carbon_victim in world)
+ var/operation = tgui_input_list(user, "Select organ operation", "Organ Manipulation", list("add organ", "add implant", "drop organ/implant", "remove organ/implant"))
if (isnull(operation))
return
@@ -12,7 +11,7 @@
var/dat = replacetext("[path]", "/obj/item/organ/", ":")
organs[dat] = path
- var/obj/item/organ/organ_to_grant = tgui_input_list(usr, "Select organ type", "Organ Manipulation", organs)
+ var/obj/item/organ/organ_to_grant = tgui_input_list(user, "Select organ type", "Organ Manipulation", organs)
if(isnull(organ_to_grant))
return
if(isnull(organs[organ_to_grant]))
@@ -20,18 +19,18 @@
organ_to_grant = organs[organ_to_grant]
organ_to_grant = new organ_to_grant
if(!organ_to_grant.Insert(carbon_victim))
- to_chat(usr, span_notice("[carbon_victim] is unable to carry this organ!"))
+ to_chat(user, span_notice("[carbon_victim] is unable to carry this organ!"))
qdel(organ_to_grant)
return
- log_admin("[key_name(usr)] has added organ [organ_to_grant.type] to [key_name(carbon_victim)]")
- message_admins("[key_name_admin(usr)] has added organ [organ_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]")
+ log_admin("[key_name(user)] has added organ [organ_to_grant.type] to [key_name(carbon_victim)]")
+ message_admins("[key_name_admin(user)] has added organ [organ_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]")
if("add implant")
for(var/path in subtypesof(/obj/item/implant))
var/dat = replacetext("[path]", "/obj/item/implant/", ":")
organs[dat] = path
- var/obj/item/implant/implant_to_grant = tgui_input_list(usr, "Select implant type", "Organ Manipulation", organs)
+ var/obj/item/implant/implant_to_grant = tgui_input_list(user, "Select implant type", "Organ Manipulation", organs)
if(isnull(implant_to_grant))
return
if(isnull(organs[implant_to_grant]))
@@ -39,11 +38,11 @@
implant_to_grant = organs[implant_to_grant]
implant_to_grant = new implant_to_grant
if(!implant_to_grant.implant(carbon_victim))
- to_chat(usr, span_notice("[carbon_victim] is unable to hold this implant!"))
+ to_chat(user, span_notice("[carbon_victim] is unable to hold this implant!"))
qdel(implant_to_grant)
return
- log_admin("[key_name(usr)] has added implant [implant_to_grant.type] to [key_name(carbon_victim)]")
- message_admins("[key_name_admin(usr)] has added implant [implant_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]")
+ log_admin("[key_name(user)] has added implant [implant_to_grant.type] to [key_name(carbon_victim)]")
+ message_admins("[key_name_admin(user)] has added implant [implant_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]")
if("drop organ/implant", "remove organ/implant")
for(var/obj/item/organ/user_organs as anything in carbon_victim.organs)
@@ -52,15 +51,15 @@
for(var/obj/item/implant/user_implants as anything in carbon_victim.implants)
organs["[user_implants.name] ([user_implants.type])"] = user_implants
- var/obj/item/organ_to_modify = tgui_input_list(usr, "Select organ/implant", "Organ Manipulation", organs)
+ var/obj/item/organ_to_modify = tgui_input_list(user, "Select organ/implant", "Organ Manipulation", organs)
if(isnull(organ_to_modify))
return
if(isnull(organs[organ_to_modify]))
return
organ_to_modify = organs[organ_to_modify]
- log_admin("[key_name(usr)] has removed [organ_to_modify.type] from [key_name(carbon_victim)]")
- message_admins("[key_name_admin(usr)] has removed [organ_to_modify.type] from [ADMIN_LOOKUPFLW(carbon_victim)]")
+ log_admin("[key_name(user)] has removed [organ_to_modify.type] from [key_name(carbon_victim)]")
+ message_admins("[key_name_admin(user)] has removed [organ_to_modify.type] from [ADMIN_LOOKUPFLW(carbon_victim)]")
var/obj/item/organ/organ_holder
var/obj/item/implant/implant_holder
diff --git a/code/modules/admin/verbs/map_export.dm b/code/modules/admin/verbs/map_export.dm
index 8233ce4389d..056a2ea1f8a 100644
--- a/code/modules/admin/verbs/map_export.dm
+++ b/code/modules/admin/verbs/map_export.dm
@@ -1,23 +1,22 @@
-/client/proc/map_export()
- set category = "Debug"
- set name = "Map Export"
- set desc = "Select a part of the map by coordinates and download it."
-
- var/z_level = tgui_input_number(usr, "Export Which Z-Level?", "Map Exporter", usr.z || 2)
- var/start_x = tgui_input_number(usr, "Start X?", "Map Exporter", usr.x || 1, world.maxx, 1)
- var/start_y = tgui_input_number(usr, "Start Y?", "Map Exporter", usr.y || 1, world.maxy, 1)
- var/end_x = tgui_input_number(usr, "End X?", "Map Exporter", usr.x || 1, world.maxx, 1)
- var/end_y = tgui_input_number(usr, "End Y?", "Map Exporter", usr.y || 1, world.maxy, 1)
+ADMIN_VERB(map_export, R_DEBUG, "Map Export", "Select a part of the map by coordinates and download it.", ADMIN_CATEGORY_DEBUG)
+ var/user_x = user.mob.x
+ var/user_y = user.mob.y
+ var/user_z = user.mob.z
+ var/z_level = tgui_input_number(user, "Export Which Z-Level?", "Map Exporter", user_z || 2)
+ var/start_x = tgui_input_number(user, "Start X?", "Map Exporter", user_x || 1, world.maxx, 1)
+ var/start_y = tgui_input_number(user, "Start Y?", "Map Exporter", user_y || 1, world.maxy, 1)
+ var/end_x = tgui_input_number(user, "End X?", "Map Exporter", user_x || 1, world.maxx, 1)
+ var/end_y = tgui_input_number(user, "End Y?", "Map Exporter", user_y || 1, world.maxy, 1)
var/date = time2text(world.timeofday, "YYYY-MM-DD_hh-mm-ss")
- var/file_name = sanitize_filename(tgui_input_text(usr, "Filename?", "Map Exporter", "exported_map_[date]"))
- var/confirm = tgui_alert(usr, "Are you sure you want to do this? This will cause extreme lag!", "Map Exporter", list("Yes", "No"))
+ var/file_name = sanitize_filename(tgui_input_text(user, "Filename?", "Map Exporter", "exported_map_[date]"))
+ var/confirm = tgui_alert(user, "Are you sure you want to do this? This will cause extreme lag!", "Map Exporter", list("Yes", "No"))
- if(confirm != "Yes" || !check_rights(R_DEBUG))
+ if(confirm != "Yes")
return
var/map_text = write_map(start_x, start_y, z_level, end_x, end_y, z_level)
- log_admin("Build Mode: [key_name(usr)] is exporting the map area from ([start_x], [start_y], [z_level]) through ([end_x], [end_y], [z_level])")
- send_exported_map(usr, file_name, map_text)
+ log_admin("Build Mode: [key_name(user)] is exporting the map area from ([start_x], [start_y], [z_level]) through ([end_x], [end_y], [z_level])")
+ send_exported_map(user, file_name, map_text)
/**
* A procedure for saving DMM text to a file and then sending it to the user.
diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm
index 827bbfb16e8..a27aca0f014 100644
--- a/code/modules/admin/verbs/map_template_loadverb.dm
+++ b/code/modules/admin/verbs/map_template_loadverb.dm
@@ -1,20 +1,17 @@
-/client/proc/map_template_load()
- set category = "Debug"
- set name = "Map template - Place"
-
+ADMIN_VERB(map_template_load, R_DEBUG, "Map Template - Place", "Place a map template at your current location.", ADMIN_CATEGORY_DEBUG)
var/datum/map_template/template
- var/map = tgui_input_list(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template", sort_list(SSmapping.map_templates))
+ var/map = tgui_input_list(user, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template", sort_list(SSmapping.map_templates))
if(!map)
return
template = SSmapping.map_templates[map]
- var/turf/T = get_turf(mob)
+ var/turf/T = get_turf(user.mob)
if(!T)
return
var/list/preview = list()
var/center
- var/centeralert = tgui_alert(usr,"Center Template.","Template Centering",list("Yes","No"))
+ var/centeralert = tgui_alert(user,"Center Template.","Template Centering",list("Yes","No"))
switch(centeralert)
if("Yes")
center = TRUE
@@ -26,8 +23,8 @@
var/image/item = image('icons/turf/overlays.dmi', place_on,"greenOverlay")
SET_PLANE(item, ABOVE_LIGHTING_PLANE, place_on)
preview += item
- images += preview
- if(tgui_alert(usr,"Confirm location.","Template Confirm",list("Yes","No")) == "Yes")
+ user.images += preview
+ if(tgui_alert(user,"Confirm location.","Template Confirm",list("Yes","No")) == "Yes")
if(template.load(T, centered = center))
var/affected = template.get_affected_turfs(T, centered = center)
for(var/AT in affected)
@@ -36,23 +33,20 @@
template.post_load(P)
break
- message_admins(span_adminnotice("[key_name_admin(src)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]"))
+ message_admins(span_adminnotice("[key_name_admin(user)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]"))
else
- to_chat(src, "Failed to place map", confidential = TRUE)
- images -= preview
+ to_chat(user, "Failed to place map", confidential = TRUE)
+ user.images -= preview
-/client/proc/map_template_upload()
- set category = "Debug"
- set name = "Map Template - Upload"
-
- var/map = input(src, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file
+ADMIN_VERB(map_template_upload, R_DEBUG, "Map Template - Upload", "Upload a map template to the server.", ADMIN_CATEGORY_DEBUG)
+ var/map = input(user, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file
if(!map)
return
if(copytext("[map]", -4) != ".dmm")//4 == length(".dmm")
- to_chat(src, span_warning("Filename must end in '.dmm': [map]"), confidential = TRUE)
+ to_chat(user, span_warning("Filename must end in '.dmm': [map]"), confidential = TRUE)
return
var/datum/map_template/M
- switch(tgui_alert(usr, "What kind of map is this?", "Map type", list("Normal", "Shuttle", "Cancel")))
+ switch(tgui_alert(user, "What kind of map is this?", "Map type", list("Normal", "Shuttle", "Cancel")))
if("Normal")
M = new /datum/map_template(map, "[map]", TRUE)
if("Shuttle")
@@ -60,23 +54,23 @@
else
return
if(!M.cached_map)
- to_chat(src, span_warning("Map template '[map]' failed to parse properly."), confidential = TRUE)
+ to_chat(user, span_warning("Map template '[map]' failed to parse properly."), confidential = TRUE)
return
var/datum/map_report/report = M.cached_map.check_for_errors()
var/report_link
if(report)
- report.show_to(src)
+ report.show_to(user)
report_link = " - validation report"
- to_chat(src, span_warning("Map template '[map]' failed validation."), confidential = TRUE)
+ to_chat(user, span_warning("Map template '[map]' failed validation."), confidential = TRUE)
if(report.loadable)
- var/response = tgui_alert(usr, "The map failed validation, would you like to load it anyways?", "Map Errors", list("Cancel", "Upload Anyways"))
+ var/response = tgui_alert(user, "The map failed validation, would you like to load it anyways?", "Map Errors", list("Cancel", "Upload Anyways"))
if(response != "Upload Anyways")
return
else
- tgui_alert(usr, "The map failed validation and cannot be loaded.", "Map Errors", list("Oh Darn"))
+ tgui_alert(user, "The map failed validation and cannot be loaded.", "Map Errors", list("Oh Darn"))
return
SSmapping.map_templates[M.name] = M
- message_admins(span_adminnotice("[key_name_admin(src)] has uploaded a map template '[map]' ([M.width]x[M.height])[report_link]."))
- to_chat(src, span_notice("Map template '[map]' ready to place ([M.width]x[M.height])"), confidential = TRUE)
+ message_admins(span_adminnotice("[key_name_admin(user)] has uploaded a map template '[map]' ([M.width]x[M.height])[report_link]."))
+ to_chat(user, span_notice("Map template '[map]' ready to place ([M.width]x[M.height])"), confidential = TRUE)
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 8f4206ca905..69dd533e097 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -1,69 +1,5 @@
-//- Are all the floors with or without air, as they should be? (regular or airless)
-//- Does the area have an APC?
-//- Does the area have an Air Alarm?
-//- Does the area have a Request Console?
-//- Does the area have lights?
-//- Does the area have a light switch?
-//- Does the area have enough intercoms?
-//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug)
-//- Is the area connected to the scrubbers air loop?
-//- Is the area connected to the vent air loop? (vent pumps)
-//- Is everything wired properly?
-//- Does the area have a fire alarm and firedoors?
-//- Do all pod doors work properly?
-//- Are accesses set properly on doors, pod buttons, etc.
-//- Are all items placed properly? (not below vents, scrubbers, tables)
-//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room?
-//- Check for any misplaced or stacked piece of pipe (air and disposal)
-//- Check for any misplaced or stacked piece of wire
-//- Identify how hard it is to break into the area and where the weak points are
-//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
-
-GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
- /client/proc/camera_view, //-errorage
- /client/proc/sec_camera_report, //-errorage
- /client/proc/intercom_view, //-errorage
- /client/proc/air_status, //Air things
- /client/proc/Cell, //More air things
- /client/proc/atmosscan, //check plumbing
- /client/proc/powerdebug, //check power
- /client/proc/count_objects_on_z_level,
- /client/proc/count_objects_all,
- /client/proc/cmd_assume_direct_control, //-errorage
- /client/proc/cmd_give_direct_control,
- /client/proc/set_server_fps, //allows you to set the ticklag.
- /client/proc/cmd_admin_grantfullaccess,
- /client/proc/cmd_admin_areatest_all,
- /client/proc/cmd_admin_areatest_station,
- /client/proc/cmd_admin_areatest_station_no_maintenance,
- #ifdef TESTING
- /client/proc/see_dirty_varedits,
- #endif
- /client/proc/cmd_admin_rejuvenate,
- /datum/admins/proc/show_traitor_panel,
- /client/proc/disable_communication,
- /client/proc/show_map_reports,
- /client/proc/cmd_show_at_list,
- /client/proc/cmd_show_at_markers,
- /client/proc/manipulate_organs,
- /client/proc/start_line_profiling,
- /client/proc/stop_line_profiling,
- /client/proc/show_line_profiling,
- /client/proc/create_mapping_job_icons,
- /client/proc/debug_z_levels,
- /client/proc/place_ruin,
- /client/proc/station_food_debug,
- /client/proc/station_stack_debug,
- /client/proc/check_for_obstructed_atmospherics,
- /client/proc/modify_lights,
- /client/proc/visualize_lights,
-))
-GLOBAL_PROTECT(admin_verbs_debug_mapping)
-
-/client/proc/camera_view()
- set category = "Mapping"
- set name = "Camera Range Display"
-
+ADMIN_VERB_VISIBILITY(camera_view, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(camera_view, R_DEBUG, "Camera Range Display", "Shows the range of cameras on the station.", ADMIN_CATEGORY_MAPPING)
var/on = FALSE
for(var/turf/T in world)
if(T.maptext)
@@ -82,28 +18,20 @@ GLOBAL_PROTECT(admin_verbs_debug_mapping)
#ifdef TESTING
GLOBAL_LIST_EMPTY(dirty_vars)
-/client/proc/see_dirty_varedits()
- set category = "Mapping"
- set name = "Dirty Varedits"
-
+ADMIN_VERB_VISIBILITY(see_dirty_varedits, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(see_dirty_varedits, R_DEBUG, "Dirty Varedits", "Shows all dirty varedits.", ADMIN_CATEGORY_MAPPING)
var/list/dat = list()
dat += "
Abandon all hope ye who enter here
"
for(var/thing in GLOB.dirty_vars)
dat += "[thing] "
CHECK_TICK
- var/datum/browser/popup = new(usr, "dirty_vars", "Dirty Varedits", 900, 750)
+ var/datum/browser/popup = new(user, "dirty_vars", "Dirty Varedits", 900, 750)
popup.set_content(dat.Join())
popup.open()
#endif
-/client/proc/sec_camera_report()
- set category = "Mapping"
- set name = "Camera Report"
-
- if(!Master)
- tgui_alert(usr,"Master_controller not found.","Sec Camera Report")
- return FALSE
-
+ADMIN_VERB_VISIBILITY(sec_camera_report, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(sec_camera_report, R_DEBUG, "Camera Report", "Get a printout of all camera issues.", ADMIN_CATEGORY_MAPPING)
var/list/obj/machinery/camera/CL = list()
for(var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras)
@@ -133,15 +61,13 @@ GLOBAL_LIST_EMPTY(dirty_vars)
output += "
Camera not connected to wall at [ADMIN_VERBOSEJMP(C1)] Network: [json_encode(C1.network)]
"
output += ""
- usr << browse(output,"window=airreport;size=1000x500")
+ user << browse(output,"window=airreport;size=1000x500")
BLACKBOX_LOG_ADMIN_VERB("Show Camera Report")
-/client/proc/intercom_view()
- set category = "Mapping"
- set name = "Intercom Range Display"
-
+ADMIN_VERB_VISIBILITY(intercom_view, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(intercom_view, R_DEBUG, "Intercom Range Display", "Shows the range of intercoms on the station.", ADMIN_CATEGORY_MAPPING)
var/static/intercom_range_display_status = FALSE
- intercom_range_display_status = !intercom_range_display_status //blame cyberboss if this breaks something //blamed
+ intercom_range_display_status = !intercom_range_display_status
for(var/obj/effect/abstract/marker/intercom/marker in GLOB.all_abstract_markers)
qdel(marker)
@@ -153,23 +79,17 @@ GLOBAL_LIST_EMPTY(dirty_vars)
new /obj/effect/abstract/marker/intercom(turf)
BLACKBOX_LOG_ADMIN_VERB("Show Intercom Range")
-/client/proc/show_map_reports()
- set category = "Mapping"
- set name = "Show map report list"
- set desc = "Displays a list of map reports"
-
+ADMIN_VERB_VISIBILITY(show_map_reports, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(show_map_reports, R_DEBUG, "Show Map Reports", "Displays a list of map reports.", ADMIN_CATEGORY_MAPPING)
var/dat = {"List of all map reports: "}
for(var/datum/map_report/report as anything in GLOB.map_reports)
dat += "[report.tag] ([report.original_path]) - View "
- usr << browse(dat, "window=map_reports")
-
-/client/proc/cmd_show_at_list()
- set category = "Mapping"
- set name = "Show roundstart AT list"
- set desc = "Displays a list of active turfs coordinates at roundstart"
+ user << browse(dat, "window=map_reports")
+ADMIN_VERB_VISIBILITY(cmd_show_at_list, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_show_at_list, R_DEBUG, "Show roundstart AT list", "Displays a list of active turfs coordinates at roundstart.", ADMIN_CATEGORY_MAPPING)
var/dat = {"Coordinate list of Active Turfs at Roundstart Real-time Active Turfs list you can see in Air Subsystem at active_turfs var "}
@@ -178,50 +98,39 @@ GLOBAL_LIST_EMPTY(dirty_vars)
dat += "[ADMIN_VERBOSEJMP(T)]\n"
dat += " "
- usr << browse(dat, "window=at_list")
+ user << browse(dat, "window=at_list")
BLACKBOX_LOG_ADMIN_VERB("Show Roundstart Active Turfs")
-/client/proc/cmd_show_at_markers()
- set category = "Mapping"
- set name = "Show roundstart AT markers"
- set desc = "Places a marker on all active-at-roundstart turfs"
-
+ADMIN_VERB_VISIBILITY(cmd_show_at_markers, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(cmd_show_at_markers, R_DEBUG, "Show roundstart AT markers", "Places a marker on all active-at-roundstart turfs.", ADMIN_CATEGORY_MAPPING)
var/count = 0
for(var/obj/effect/abstract/marker/at/AT in GLOB.all_abstract_markers)
qdel(AT)
count++
if(count)
- to_chat(usr, "[count] AT markers removed.", confidential = TRUE)
+ to_chat(user, "[count] AT markers removed.", confidential = TRUE)
else
for(var/t in GLOB.active_turfs_startlist)
new /obj/effect/abstract/marker/at(t)
count++
- to_chat(usr, "[count] AT markers placed.", confidential = TRUE)
+ to_chat(user, "[count] AT markers placed.", confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Show Roundstart Active Turf Markers")
-/client/proc/enable_mapping_verbs()
- set category = "Debug"
- set name = "Mapping verbs - Enable"
- if(!check_rights(R_DEBUG))
- return
- remove_verb(src, /client/proc/enable_mapping_verbs)
- add_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping))
+ADMIN_VERB(enable_mapping_verbs, R_DEBUG, "Enable Mapping Verbs", "Enable all mapping verbs.", ADMIN_CATEGORY_MAPPING)
+ SSadmin_verbs.update_visibility_flag(user, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG, TRUE)
BLACKBOX_LOG_ADMIN_VERB("Enable Debug Verbs")
-/client/proc/disable_mapping_verbs()
- set category = "Debug"
- set name = "Mapping verbs - Disable"
- remove_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping))
- add_verb(src, /client/proc/enable_mapping_verbs)
+ADMIN_VERB_VISIBILITY(disable_mapping_verbs, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(disable_mapping_verbs, R_DEBUG, "Disable Mapping Verbs", "Disable all mapping verbs.", ADMIN_CATEGORY_MAPPING)
+ SSadmin_verbs.update_visibility_flag(user, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG, FALSE)
BLACKBOX_LOG_ADMIN_VERB("Disable Debug Verbs")
-/client/proc/count_objects_on_z_level()
- set category = "Mapping"
- set name = "Count Objects On Level"
- var/level = input("Which z-level?","Level?") as text|null
+ADMIN_VERB_VISIBILITY(count_objects_on_z_level, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(count_objects_on_z_level, R_DEBUG, "Count Objects On Z-Level", "Counts the number of objects of a certain type on a specific z-level.", ADMIN_CATEGORY_MAPPING)
+ var/level = input(user, "Which z-level?","Level?") as text|null
if(!level)
return
var/num_level = text2num(level)
@@ -230,7 +139,7 @@ GLOBAL_LIST_EMPTY(dirty_vars)
if(!isnum(num_level))
return
- var/type_text = input("Which type path?","Path?") as text|null
+ var/type_text = input(user, "Which type path?","Path?") as text|null
if(!type_text)
return
var/type_path = text2path(type_text)
@@ -257,11 +166,9 @@ GLOBAL_LIST_EMPTY(dirty_vars)
to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]", confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Count Objects Zlevel")
-/client/proc/count_objects_all()
- set category = "Mapping"
- set name = "Count Objects All"
-
- var/type_text = input("Which type path?","") as text|null
+ADMIN_VERB_VISIBILITY(count_objects_all, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(count_objects_all, R_DEBUG, "Count Objects All", "Counts the number of objects of a certain type in the game world.", ADMIN_CATEGORY_MAPPING)
+ var/type_text = input(user, "Which type path?","") as text|null
if(!type_text)
return
var/type_path = text2path(type_text)
@@ -277,84 +184,51 @@ GLOBAL_LIST_EMPTY(dirty_vars)
to_chat(world, "There are [count] objects of type [type_path] in the game world", confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Count Objects All")
-
-//This proc is intended to detect lag problems relating to communication procs
GLOBAL_VAR_INIT(say_disabled, FALSE)
-/client/proc/disable_communication()
- set category = "Mapping"
- set name = "Disable all communication verbs"
-
+ADMIN_VERB_VISIBILITY(disable_communication, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(disable_communication, R_DEBUG, "Disable all communication verbs", "Disables all communication verbs.", ADMIN_CATEGORY_MAPPING)
GLOB.say_disabled = !GLOB.say_disabled
if(GLOB.say_disabled)
- message_admins("[key] used 'Disable all communication verbs', killing all communication methods.")
+ message_admins("[key_name_admin(user)] used 'Disable all communication verbs', killing all communication methods.")
else
- message_admins("[key] used 'Disable all communication verbs', restoring all communication methods.")
-/* SKYRAT EDIT: lol, lmao, fuck icon bugs from byond
-//This generates the icon states for job starting location landmarks.
-/client/proc/create_mapping_job_icons()
- set name = "Generate job landmarks icons"
- set category = "Mapping"
+ message_admins("[key_name_admin(user)] used 'Disable all communication verbs', restoring all communication methods.")
+
+ADMIN_VERB_VISIBILITY(create_mapping_job_icons, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(create_mapping_job_icons, R_DEBUG, "Generate job landmarks icons", "Generates job starting location landmarks.", ADMIN_CATEGORY_MAPPING)
var/icon/final = icon()
+ var/list/job_key_to_icon = list() // SKYRAT EDIT ADDITION
var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted
D.setDir(SOUTH)
for(var/job in subtypesof(/datum/job))
var/datum/job/JB = new job
switch(JB.title)
if(JOB_AI)
- final.Insert(icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1), "AI")
+ job_key_to_icon["AI"] = icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1) // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1), "AI")
if(JOB_CYBORG)
- final.Insert(icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1), "Cyborg")
+ job_key_to_icon["Cyborg"] = icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1) // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1), "Cyborg")
else
for(var/obj/item/I in D)
qdel(I)
randomize_human(D)
- D.dress_up_as_job(JB, TRUE)
- var/icon/I = icon(getFlatIcon(D), frame = 1)
- final.Insert(I, JB.title)
- qdel(D)
- //Also add the x
- for(var/x_number in 1 to 4)
- final.Insert(icon('icons/hud/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
- fcopy(final, "icons/mob/landmarks.dmi")
-*/
-// SKYRAT EDIT BEGIN: THIS SHIT WAS BROKEN due to an issue with byond and how icons cache
-//This generates the icon states for job starting location landmarks.
-/client/proc/create_mapping_job_icons()
- set name = "Generate job landmarks icons"
- set category = "Mapping"
- var/list/job_key_to_icon = list()
- for(var/job in subtypesof(/datum/job))
- var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted
- D.setDir(SOUTH)
- var/datum/job/JB = new job
- to_chat(world, "Generating icon for job [JB.title]")
- switch(JB.title)
- if("AI")
- job_key_to_icon["AI"] = icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1)
- if("Cyborg")
- job_key_to_icon["Cyborg"] = icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1)
- else
- randomize_human(D)
+ // SKYRAT EDIT CHANGE START - ORIGINAL: D.dress_up_as_job(JB, TRUE)
if(JB.outfit)
D.equipOutfit(JB.outfit, TRUE)
+ // SKYRAT EDIT CHANGE END
var/icon/I = icon(getFlatIcon(D), frame = 1)
- job_key_to_icon[JB.title] = I
- qdel(D)
- to_chat(world, "Done generating icons.")
- var/icon/final = icon()
+ job_key_to_icon[JB.title] = I // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(I, JB.title)
+ qdel(D)
+ // SKYRAT EDIT ADDITION START
for(var/job_key in job_key_to_icon)
final.Insert(job_key_to_icon[job_key], job_key)
+ // SKYRAT EDIT ADDITION END
//Also add the x
for(var/x_number in 1 to 4)
final.Insert(icon('icons/hud/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
fcopy(final, "icons/mob/landmarks.dmi")
- to_chat(world, "Done generating landmarks.dmi.")
-// SKYRAT EDIT END
-/client/proc/debug_z_levels()
- set name = "Debug Z-Levels"
- set category = "Mapping"
- to_chat(src, examine_block(gather_z_level_information(append_grid = TRUE)), confidential = TRUE)
+ADMIN_VERB_VISIBILITY(debug_z_levels, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(debug_z_levels, R_DEBUG, "Debug Z-Levels", "Displays a list of all z-levels and their linkages.", ADMIN_CATEGORY_MAPPING)
+ to_chat(user, examine_block(gather_z_level_information(append_grid = TRUE)), confidential = TRUE)
/// Returns all necessary z-level information. Argument `append_grid` allows the user to see a table showing all of the z-level linkages, which is only visible and useful in-game.
/proc/gather_z_level_information(append_grid = FALSE)
@@ -416,9 +290,8 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
return messages.Join("\n")
-/client/proc/station_food_debug()
- set name = "Count Station Food"
- set category = "Mapping"
+ADMIN_VERB_VISIBILITY(station_food_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(station_food_debug, R_DEBUG, "Count Station Food", "Counts the number of food items on the station.", ADMIN_CATEGORY_MAPPING)
var/list/foodcount = list()
for(var/obj/item/food/fuck_me in world)
var/turf/location = get_turf(fuck_me)
@@ -435,13 +308,12 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
var/page_style = ""
var/page_contents = "[page_style]
[table_header][jointext(table_contents, "")]
"
- var/datum/browser/popup = new(mob, "fooddebug", "Station Food Count", 600, 400)
+ var/datum/browser/popup = new(user.mob, "fooddebug", "Station Food Count", 600, 400)
popup.set_content(page_contents)
popup.open()
-/client/proc/station_stack_debug()
- set name = "Count Station Stacks"
- set category = "Mapping"
+ADMIN_VERB_VISIBILITY(station_stack_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(station_stack_debug, R_DEBUG, "Count Station Stacks", "Count the stacks of materials on station.", ADMIN_CATEGORY_MAPPING)
var/list/stackcount = list()
for(var/obj/item/stack/fuck_me in world)
var/turf/location = get_turf(fuck_me)
@@ -458,18 +330,13 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
var/page_style = ""
var/page_contents = "[page_style]
[table_header][jointext(table_contents, "")]
"
- var/datum/browser/popup = new(mob, "stackdebug", "Station Stack Count", 600, 400)
+ var/datum/browser/popup = new(user.mob, "stackdebug", "Station Stack Count", 600, 400)
popup.set_content(page_contents)
popup.open()
-/// Check all tiles with a vent or scrubber on it and ensure that nothing is covering it up.
-/client/proc/check_for_obstructed_atmospherics()
- set name = "Check For Obstructed Atmospherics"
- set category = "Mapping"
- if(!holder)
- to_chat(src, "Only administrators may use this command.", confidential = TRUE)
- return
- message_admins(span_adminnotice("[key_name_admin(usr)] is checking for obstructed atmospherics through the debug command."))
+ADMIN_VERB_VISIBILITY(check_for_obstructed_atmospherics, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(check_for_obstructed_atmospherics, R_DEBUG, "Check For Obstructed Atmospherics", "Checks for obstructions on atmospherics machines.", ADMIN_CATEGORY_MAPPING)
+ message_admins(span_adminnotice("[key_name_admin(user)] is checking for obstructed atmospherics through the debug command."))
BLACKBOX_LOG_ADMIN_VERB("Check For Obstructed Atmospherics")
var/list/results = list()
@@ -518,17 +385,14 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
results += "There is an obstruction on top of an atmospherics machine at: [ADMIN_VERBOSEJMP(iterated_turf)]. "
if(results.len == 1) // only the header is in the list, we're good
- to_chat(src, "No obstructions detected.", confidential = TRUE)
+ to_chat(user, "No obstructions detected.", confidential = TRUE)
else
- var/datum/browser/popup = new(usr, "atmospherics_obstructions", "Atmospherics Obstructions", 900, 750)
+ var/datum/browser/popup = new(user.mob, "atmospherics_obstructions", "Atmospherics Obstructions", 900, 750)
popup.set_content(results.Join())
popup.open()
-/client/proc/modify_lights()
- set name = "Toggle Light Debug"
- set category = "Mapping"
- if(!check_rights(R_DEBUG))
- return
+ADMIN_VERB_VISIBILITY(modify_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(modify_lights, R_DEBUG, "Toggle Light Debug", "Toggles light debug mode.", ADMIN_CATEGORY_MAPPING)
if(GLOB.light_debug_enabled)
undebug_sources()
return
@@ -540,10 +404,6 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
CHECK_TICK
debug_sources()
-/client/proc/visualize_lights()
- set name = "Visualize Lighting Corners"
- set category = "Mapping"
- if(!check_rights(R_DEBUG))
- return
-
+ADMIN_VERB_VISIBILITY(visualize_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG)
+ADMIN_VERB(visualize_lights, R_DEBUG, "Visualize Lighting Corners", "Visualizes the corners of all lights on the station.", ADMIN_CATEGORY_MAPPING)
display_corners()
diff --git a/code/modules/admin/verbs/maprotation.dm b/code/modules/admin/verbs/maprotation.dm
index c41677db37c..09d6d93bee6 100644
--- a/code/modules/admin/verbs/maprotation.dm
+++ b/code/modules/admin/verbs/maprotation.dm
@@ -1,16 +1,13 @@
-/client/proc/forcerandomrotate()
- set category = "Server"
- set name = "Trigger Random Map Rotation"
- var/rotate = tgui_alert(usr,"Force a random map rotation to trigger?", "Rotate map?", list("Yes", "Cancel"))
+
+ADMIN_VERB(force_random_rotate, R_SERVER, "Trigger 'Random' Map Rotation", "Force a map vote.", ADMIN_CATEGORY_SERVER)
+ var/rotate = tgui_alert(user,"Force a random map rotation to trigger?", "Rotate map?", list("Yes", "Cancel"))
if (rotate != "Yes")
return
- message_admins("[key_name_admin(usr)] is forcing a random map rotation.")
- log_admin("[key_name(usr)] is forcing a random map rotation.")
+ message_admins("[key_name_admin(user)] is forcing a random map rotation.")
+ log_admin("[key_name(user)] is forcing a random map rotation.")
SSmapping.maprotate()
-/client/proc/adminchangemap()
- set category = "Server"
- set name = "Change Map"
+ADMIN_VERB(admin_change_map, R_SERVER, "Change Map", "Set the next map.", ADMIN_CATEGORY_SERVER)
var/list/maprotatechoices = list()
for (var/map in config.maplist)
var/datum/map_config/virtual_map = config.maplist[map]
@@ -32,21 +29,21 @@
mapname += "\]"
maprotatechoices[mapname] = virtual_map
- var/chosenmap = tgui_input_list(usr, "Choose a map to change to", "Change Map", sort_list(maprotatechoices)|"Custom")
+ var/chosenmap = tgui_input_list(user, "Choose a map to change to", "Change Map", sort_list(maprotatechoices)|"Custom")
if (isnull(chosenmap))
return
if(chosenmap == "Custom")
- message_admins("[key_name_admin(usr)] is changing the map to a custom map")
- log_admin("[key_name(usr)] is changing the map to a custom map")
+ message_admins("[key_name_admin(user)] is changing the map to a custom map")
+ log_admin("[key_name(user)] is changing the map to a custom map")
var/datum/map_config/virtual_map = new
- var/map_file = input("Pick file:", "Map File") as null|file
+ var/map_file = input(user, "Pick file:", "Map File") as null|file
if(isnull(map_file))
return
if(copytext("[map_file]", -4) != ".dmm")//4 == length(".dmm")
- to_chat(src, span_warning("Filename must end in '.dmm': [map_file]"))
+ to_chat(user, span_warning("Filename must end in '.dmm': [map_file]"))
return
if(fexists("_maps/custom/[map_file]"))
@@ -56,20 +53,20 @@
// This is to make sure the map works so the server does not start without a map.
var/datum/parsed_map/M = new (map_file)
if(!M)
- to_chat(src, span_warning("Map '[map_file]' failed to parse properly."))
+ to_chat(user, span_warning("Map '[map_file]' failed to parse properly."))
return
if(!M.bounds)
- to_chat(src, span_warning("Map '[map_file]' has non-existant bounds."))
+ to_chat(user, span_warning("Map '[map_file]' has non-existant bounds."))
qdel(M)
return
qdel(M)
var/config_file = null
var/list/json_value = list()
- var/config = tgui_alert(usr,"Would you like to upload an additional config for this map?", "Map Config", list("Yes", "No"))
+ var/config = tgui_alert(user,"Would you like to upload an additional config for this map?", "Map Config", list("Yes", "No"))
if(config == "Yes")
- config_file = input("Pick file:", "Config JSON File") as null|file
+ config_file = input(user, "Pick file:", "Config JSON File") as null|file
if(isnull(config_file))
return
if(copytext("[config_file]", -5) != ".json")
@@ -94,18 +91,18 @@
)
else
virtual_map = load_map_config()
- virtual_map.map_name = input("Choose the name for the map", "Map Name") as null|text
+ virtual_map.map_name = input(user, "Choose the name for the map", "Map Name") as null|text
if(isnull(virtual_map.map_name))
virtual_map.map_name = "Custom"
- var/shuttles = tgui_alert(usr,"Do you want to modify the shuttles?", "Map Shuttles", list("Yes", "No"))
+ var/shuttles = tgui_alert(user,"Do you want to modify the shuttles?", "Map Shuttles", list("Yes", "No"))
if(shuttles == "Yes")
for(var/s in virtual_map.shuttles)
- var/shuttle = input(s, "Map Shuttles") as null|text
+ var/shuttle = input(user, s, "Map Shuttles") as null|text
if(!shuttle)
continue
if(!SSmapping.shuttle_templates[shuttle])
- to_chat(usr, span_warning("No such shuttle as '[shuttle]' exists, using default."))
+ to_chat(user, span_warning("No such shuttle as '[shuttle]' exists, using default."))
continue
virtual_map.shuttles[s] = shuttle
@@ -123,13 +120,13 @@
text2file(json_encode(json_value), PATH_TO_NEXT_MAP_JSON)
if(SSmapping.changemap(virtual_map))
- message_admins("[key_name_admin(usr)] has changed the map to [virtual_map.map_name]")
+ message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]")
SSmapping.map_force_chosen = TRUE
fdel("data/custom_map_json/[config_file]")
else
var/datum/map_config/virtual_map = maprotatechoices[chosenmap]
- message_admins("[key_name_admin(usr)] is changing the map to [virtual_map.map_name]")
- log_admin("[key_name(usr)] is changing the map to [virtual_map.map_name]")
+ message_admins("[key_name_admin(user)] is changing the map to [virtual_map.map_name]")
+ log_admin("[key_name(user)] is changing the map to [virtual_map.map_name]")
if (SSmapping.changemap(virtual_map))
- message_admins("[key_name_admin(usr)] has changed the map to [virtual_map.map_name]")
+ message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]")
SSmapping.map_force_chosen = TRUE
diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm
index c8c47858669..57aba1ee8d9 100644
--- a/code/modules/admin/verbs/panicbunker.dm
+++ b/code/modules/admin/verbs/panicbunker.dm
@@ -1,8 +1,6 @@
-/client/proc/panicbunker()
- set category = "Server"
- set name = "Toggle Panic Bunker"
+ADMIN_VERB(panic_bunker, R_SERVER, "Toggle Panic Bunker", "Toggles the panic bunker for the server.", ADMIN_CATEGORY_SERVER)
if (!CONFIG_GET(flag/sql_enabled))
- to_chat(usr, span_adminnotice("The Database is not enabled!"), confidential = TRUE)
+ to_chat(user, span_adminnotice("The Database is not enabled!"), confidential = TRUE)
return
var/new_pb = !CONFIG_GET(flag/panic_bunker)
@@ -10,28 +8,26 @@
var/time_rec = 0
var/message = ""
if(new_pb)
- time_rec = input(src, "How many living minutes should they need to play? 0 to disable.", "Shit's fucked isn't it", CONFIG_GET(number/panic_bunker_living)) as num
- message = input(src, "What should they see when they log in?", "MMM", CONFIG_GET(string/panic_bunker_message)) as text
+ time_rec = input(user, "How many living minutes should they need to play? 0 to disable.", "Shit's fucked isn't it", CONFIG_GET(number/panic_bunker_living)) as num
+ message = input(user, "What should they see when they log in?", "MMM", CONFIG_GET(string/panic_bunker_message)) as text
message = replacetext(message, "%minutes%", time_rec)
CONFIG_SET(number/panic_bunker_living, time_rec)
CONFIG_SET(string/panic_bunker_message, message)
- var/interview_sys = tgui_alert(usr, "Should the interview system be enabled? (Allows players to connect under the hour limit and force them to be manually approved to play)", "Enable interviews?", list("Enable", "Disable"))
+ var/interview_sys = tgui_alert(user, "Should the interview system be enabled? (Allows players to connect under the hour limit and force them to be manually approved to play)", "Enable interviews?", list("Enable", "Disable"))
interview = interview_sys == "Enable"
CONFIG_SET(flag/panic_bunker_interview, interview)
CONFIG_SET(flag/panic_bunker, new_pb)
- log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "on and set to [time_rec] with a message of [message]. The interview system is [interview ? "enabled" : "disabled"]" : "off"].")
- message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled with a living minutes requirement of [time_rec]. The interview system is [interview ? "enabled" : "disabled"]" : "disabled"].")
+ log_admin("[key_name(user)] has toggled the Panic Bunker, it is now [new_pb ? "on and set to [time_rec] with a message of [message]. The interview system is [interview ? "enabled" : "disabled"]" : "off"].")
+ message_admins("[key_name_admin(user)] has toggled the Panic Bunker, it is now [new_pb ? "enabled with a living minutes requirement of [time_rec]. The interview system is [interview ? "enabled" : "disabled"]" : "disabled"].")
if (new_pb && !SSdbcore.Connect())
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/client/proc/toggle_interviews()
- set category = "Server"
- set name = "Toggle PB Interviews"
+ADMIN_VERB(toggle_interviews, R_SERVER, "Toggle PB Interviews", "Toggle whether new players will be interviewed or blocked from connecting.", ADMIN_CATEGORY_SERVER)
if (!CONFIG_GET(flag/panic_bunker))
- to_chat(usr, span_adminnotice("NOTE: The panic bunker is not enabled, so this change will not effect anything until it is enabled."), confidential = TRUE)
+ to_chat(user, span_adminnotice("NOTE: The panic bunker is not enabled, so this change will not effect anything until it is enabled."), confidential = TRUE)
var/new_interview = !CONFIG_GET(flag/panic_bunker_interview)
CONFIG_SET(flag/panic_bunker_interview, new_interview)
- log_admin("[key_name(usr)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].")
- message_admins("[key_name(usr)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].")
+ log_admin("[key_name(user)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].")
+ message_admins("[key_name(user)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].")
diff --git a/code/modules/admin/verbs/player_ticket_history.dm b/code/modules/admin/verbs/player_ticket_history.dm
index ac87707e98d..829d4dfc2b5 100644
--- a/code/modules/admin/verbs/player_ticket_history.dm
+++ b/code/modules/admin/verbs/player_ticket_history.dm
@@ -19,13 +19,8 @@ GENERAL_PROTECT_DATUM(/datum/ticket_log_entry)
GLOBAL_DATUM_INIT(player_ticket_history, /datum/ticket_history_holder, new)
GLOBAL_PROTECT(player_ticket_history)
-/client/proc/player_ticket_history()
- set name = "Player Ticket History"
- set desc = "Allows you to view the ticket history of a player."
- set category = "Admin"
- if(!check_rights(R_ADMIN))
- return
- GLOB.player_ticket_history.ui_interact(mob)
+ADMIN_VERB(player_ticket_history, R_ADMIN, "Player Ticket History", "Allows you to view the ticket history of a player.", ADMIN_CATEGORY_MAIN)
+ GLOB.player_ticket_history.ui_interact(user.mob)
/datum/ticket_history_holder
/// Assosciative list of ticket histories. ckey -> list/datum/ticket_history
@@ -34,7 +29,7 @@ GLOBAL_PROTECT(player_ticket_history)
var/list/user_selections = list()
/datum/ticket_history_holder/proc/cache_history_for_ckey(ckey, entries = 5)
- ckey = lowertext(ckey)
+ ckey = LOWER_TEXT(ckey)
if(!isnum(entries) || entries <= 0)
return
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index 1b63c83529b..c4e4257e84f 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -3,20 +3,15 @@
#define SHELLEO_STDOUT 2
#define SHELLEO_STDERR 3
-/client/proc/play_sound(S as sound)
- set category = "Admin.Fun"
- set name = "Play Global Sound"
- if(!check_rights(R_SOUND))
- return
-
+ADMIN_VERB(play_sound, R_SOUND, "Play Global Sound", "Play a sound to all connected players.", ADMIN_CATEGORY_FUN, sound as sound)
var/freq = 1
- var/vol = input(usr, "What volume would you like the sound to play at?",, 100) as null|num
+ var/vol = tgui_input_number(user, "What volume would you like the sound to play at?", max_value = 100)
if(!vol)
return
vol = clamp(vol, 1, 100)
- var/sound/admin_sound = new()
- admin_sound.file = S
+ var/sound/admin_sound = new
+ admin_sound.file = sound
admin_sound.priority = 250
admin_sound.channel = CHANNEL_ADMIN
admin_sound.frequency = freq
@@ -25,15 +20,15 @@
admin_sound.status = SOUND_STREAM
admin_sound.volume = vol
- var/res = tgui_alert(usr, "Show the title of this song to the players?",, list("Yes","No", "Cancel"))
+ var/res = tgui_alert(user, "Show the title of this song to the players?",, list("Yes","No", "Cancel"))
switch(res)
if("Yes")
- to_chat(world, span_boldannounce("An admin played: [S]"), confidential = TRUE)
+ to_chat(world, span_boldannounce("An admin played: [sound]"), confidential = TRUE)
if("Cancel")
return
- log_admin("[key_name(src)] played sound [S]")
- message_admins("[key_name_admin(src)] played sound [S]")
+ log_admin("[key_name(user)] played sound [sound]")
+ message_admins("[key_name_admin(user)] played sound [sound]")
for(var/mob/M in GLOB.player_list)
if(M.client.prefs.read_preference(/datum/preference/toggle/sound_midi))
@@ -43,31 +38,20 @@
BLACKBOX_LOG_ADMIN_VERB("Play Global Sound")
-
-/client/proc/play_local_sound(S as sound)
- set category = "Admin.Fun"
- set name = "Play Local Sound"
- if(!check_rights(R_SOUND))
- return
-
- log_admin("[key_name(src)] played a local sound [S]")
- message_admins("[key_name_admin(src)] played a local sound [S]")
- playsound(get_turf(src.mob), S, 50, FALSE, FALSE)
+ADMIN_VERB(play_local_sound, R_SOUND, "Play Local Sound", "Plays a sound only you can hear.", ADMIN_CATEGORY_FUN, sound as sound)
+ log_admin("[key_name(user)] played a local sound [sound]")
+ message_admins("[key_name_admin(user)] played a local sound [sound]")
+ playsound(get_turf(user.mob), sound, 50, FALSE, FALSE)
BLACKBOX_LOG_ADMIN_VERB("Play Local Sound")
-/client/proc/play_direct_mob_sound(S as sound, mob/M)
- set category = "Admin.Fun"
- set name = "Play Direct Mob Sound"
- if(!check_rights(R_SOUND))
+ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a sound directly to a mob.", ADMIN_CATEGORY_FUN, sound as sound, mob/target in world)
+ if(!target)
+ target = input(user, "Choose a mob to play the sound to. Only they will hear it.", "Play Mob Sound") as null|anything in sort_names(GLOB.player_list)
+ if(QDELETED(target))
return
-
- if(!M)
- M = input(usr, "Choose a mob to play the sound to. Only they will hear it.", "Play Mob Sound") as null|anything in sort_names(GLOB.player_list)
- if(!M || QDELETED(M))
- return
- log_admin("[key_name(src)] played a direct mob sound [S] to [M].")
- message_admins("[key_name_admin(src)] played a direct mob sound [S] to [ADMIN_LOOKUPFLW(M)].")
- SEND_SOUND(M, S)
+ log_admin("[key_name(user)] played a direct mob sound [sound] to [key_name_admin(target)].")
+ message_admins("[key_name_admin(user)] played a direct mob sound [sound] to [ADMIN_LOOKUPFLW(target)].")
+ SEND_SOUND(target, sound)
BLACKBOX_LOG_ADMIN_VERB("Play Direct Mob Sound")
///Takes an input from either proc/play_web_sound or the request manager and runs it through youtube-dl and prompts the user before playing it to the server.
@@ -169,59 +153,41 @@
BLACKBOX_LOG_ADMIN_VERB("Play Internet Sound")
+ADMIN_VERB_CUSTOM_EXIST_CHECK(play_web_sound)
+ return !!CONFIG_GET(string/invoke_youtubedl)
-/client/proc/play_web_sound()
- set category = "Admin.Fun"
- set name = "Play Internet Sound"
- if(!check_rights(R_SOUND))
- return
-
- var/ytdl = CONFIG_GET(string/invoke_youtubedl)
- if(!ytdl)
- to_chat(src, span_boldwarning("Youtube-dl was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value
- return
-
+ADMIN_VERB(play_web_sound, R_SOUND, "Play Internet Sound", "Play a given internet sound to all players.", ADMIN_CATEGORY_FUN)
if(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND))
- if(tgui_alert(usr, "Someone else is already playing an Internet sound! It has [DisplayTimeText(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND), 1)] remaining. \
+ if(tgui_alert(user, "Someone else is already playing an Internet sound! It has [DisplayTimeText(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND), 1)] remaining. \
Would you like to override?", "Musicalis Interruptus", list("No","Yes")) != "Yes")
return
- var/web_sound_input = tgui_input_text(usr, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null)
+ var/web_sound_input = tgui_input_text(user, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null)
if(length(web_sound_input))
web_sound_input = trim(web_sound_input)
if(findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol))
- to_chat(src, span_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE)
- to_chat(src, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full URL from the website."), confidential = TRUE)
+ to_chat(user, span_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE)
+ to_chat(user, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full URL from the website."), confidential = TRUE)
return
- web_sound(usr, web_sound_input)
+ web_sound(user.mob, web_sound_input)
else
- web_sound(usr, null)
+ web_sound(user.mob, null)
-/client/proc/set_round_end_sound(S as sound)
- set category = "Admin.Fun"
- set name = "Set Round End Sound"
- if(!check_rights(R_SOUND))
- return
+ADMIN_VERB(set_round_end_sound, R_SOUND, "Set Round End Sound", "Set the sound that plays on round end.", ADMIN_CATEGORY_FUN, sound as sound)
+ SSticker.SetRoundEndSound(sound)
- SSticker.SetRoundEndSound(S)
-
- log_admin("[key_name(src)] set the round end sound to [S]")
- message_admins("[key_name_admin(src)] set the round end sound to [S]")
+ log_admin("[key_name(user)] set the round end sound to [sound]")
+ message_admins("[key_name_admin(user)] set the round end sound to [sound]")
BLACKBOX_LOG_ADMIN_VERB("Set Round End Sound")
-/client/proc/stop_sounds()
- set category = "Debug"
- set name = "Stop All Playing Sounds"
- if(!src.holder)
- return
-
- log_admin("[key_name(src)] stopped all currently playing sounds.")
- message_admins("[key_name_admin(src)] stopped all currently playing sounds.")
- for(var/mob/M in GLOB.player_list)
- SEND_SOUND(M, sound(null))
- var/client/C = M.client
- C?.tgui_panel?.stop_music()
+ADMIN_VERB(stop_sounds, R_NONE, "Stop All Playing Sounds", "Stops all playing sounds for EVERYONE.", ADMIN_CATEGORY_DEBUG)
+ log_admin("[key_name(user)] stopped all currently playing sounds.")
+ message_admins("[key_name_admin(user)] stopped all currently playing sounds.")
+ for(var/mob/player as anything in GLOB.player_list)
+ SEND_SOUND(player, sound(null))
+ var/client/player_client = player.client
+ player_client?.tgui_panel?.stop_music()
S_TIMER_COOLDOWN_RESET(SStimer, COOLDOWN_INTERNET_SOUND)
BLACKBOX_LOG_ADMIN_VERB("Stop All Playing Sounds")
diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm
index 63304104ab5..a7e50840f5e 100644
--- a/code/modules/admin/verbs/possess.dm
+++ b/code/modules/admin/verbs/possess.dm
@@ -1,32 +1,20 @@
-/proc/possess(obj/target in world)
- set name = "Possess Obj"
- set category = "Object"
- var/result = usr.AddComponent(/datum/component/object_possession, target)
+ADMIN_VERB(possess, R_POSSESS, "Possess Obj", "Possess an object.", ADMIN_CATEGORY_OBJECT, obj/target in world)
+ var/result = user.mob.AddComponent(/datum/component/object_possession, target)
if(isnull(result)) // trigger a safety movement just in case we yonk
- usr.forceMove(get_turf(usr))
+ user.mob.forceMove(get_turf(user.mob))
return
var/turf/target_turf = get_turf(target)
- var/message = "[key_name(usr)] has possessed [target] ([target.type]) at [AREACOORD(target_turf)]"
+ var/message = "[key_name(user)] has possessed [target] ([target.type]) at [AREACOORD(target_turf)]"
message_admins(message)
log_admin(message)
BLACKBOX_LOG_ADMIN_VERB("Possess Object")
-/proc/release()
- set name = "Release Obj"
- set category = "Object"
-
- qdel(usr.GetComponent(/datum/component/object_possession))
+ADMIN_VERB(release, R_POSSESS, "Release Object", "Stop possessing an object.", ADMIN_CATEGORY_OBJECT)
+ var/possess_component = user.mob.GetComponent(/datum/component/object_possession)
+ if(!isnull(possess_component))
+ qdel(possess_component)
BLACKBOX_LOG_ADMIN_VERB("Release Object")
-
-/proc/give_possession_verbs(mob/dude in GLOB.mob_list)
- set desc = "Give this guy possess/release verbs"
- set category = "Debug"
- set name = "Give Possessing Verbs"
-
- add_verb(dude, GLOBAL_PROC_REF(possess))
- add_verb(dude, GLOBAL_PROC_REF(release))
- BLACKBOX_LOG_ADMIN_VERB("Give Possessing Verbs")
diff --git a/code/modules/admin/verbs/reestablish_db_connection.dm b/code/modules/admin/verbs/reestablish_db_connection.dm
index a299eb43b0f..5c3701c97b0 100644
--- a/code/modules/admin/verbs/reestablish_db_connection.dm
+++ b/code/modules/admin/verbs/reestablish_db_connection.dm
@@ -1,26 +1,24 @@
-/client/proc/reestablish_db_connection()
- set category = "Server"
- set name = "Reestablish DB Connection"
+ADMIN_VERB(reestablish_db_connection, R_NONE, "Reestablish DB Connection", "Attempts to (re)establish the DB Connection", ADMIN_CATEGORY_SERVER)
if (!CONFIG_GET(flag/sql_enabled))
- to_chat(usr, span_adminnotice("The Database is not enabled!"), confidential = TRUE)
+ to_chat(user, span_adminnotice("The Database is not enabled!"), confidential = TRUE)
return
if (SSdbcore.IsConnected())
- if (!check_rights(R_DEBUG,0))
- tgui_alert(usr,"The database is already connected! (Only those with +debug can force a reconnection)", "The database is already connected!")
+ if (!user.holder.check_for_rights(R_DEBUG))
+ tgui_alert(user,"The database is already connected! (Only those with +debug can force a reconnection)", "The database is already connected!")
return
- var/reconnect = tgui_alert(usr,"The database is already connected! If you *KNOW* that this is incorrect, you can force a reconnection", "The database is already connected!", list("Force Reconnect", "Cancel"))
+ var/reconnect = tgui_alert(user,"The database is already connected! If you *KNOW* that this is incorrect, you can force a reconnection", "The database is already connected!", list("Force Reconnect", "Cancel"))
if (reconnect != "Force Reconnect")
return
SSdbcore.Disconnect()
- log_admin("[key_name(usr)] has forced the database to disconnect")
- message_admins("[key_name_admin(usr)] has forced the database to disconnect!")
+ log_admin("[key_name(user)] has forced the database to disconnect")
+ message_admins("[key_name_admin(user)] has forced the database to disconnect!")
BLACKBOX_LOG_ADMIN_VERB("Force Reestablished Database Connection")
- log_admin("[key_name(usr)] is attempting to re-establish the DB Connection")
- message_admins("[key_name_admin(usr)] is attempting to re-establish the DB Connection")
+ log_admin("[key_name(user)] is attempting to re-establish the DB Connection")
+ message_admins("[key_name_admin(user)] is attempting to re-establish the DB Connection")
BLACKBOX_LOG_ADMIN_VERB("Reestablished Database Connection")
SSdbcore.failed_connections = 0
diff --git a/code/modules/admin/verbs/requests.dm b/code/modules/admin/verbs/requests.dm
index 2cd32648b67..53d3e092f81 100644
--- a/code/modules/admin/verbs/requests.dm
+++ b/code/modules/admin/verbs/requests.dm
@@ -1,7 +1,4 @@
-/// Verb for opening the requests manager panel
-/client/proc/requests()
- set name = "Requests Manager"
- set desc = "Open the request manager panel to view all requests during this round"
- set category = "Admin.Game"
- BLACKBOX_LOG_ADMIN_VERB("Request Manager")
+
+ADMIN_VERB(requests, R_NONE, "Requests Manager", "Open the request manager panel to view all requests during this round", ADMIN_CATEGORY_GAME)
GLOB.requests.ui_interact(usr)
+ BLACKBOX_LOG_ADMIN_VERB("Request Manager")
diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm
index e70138ad8ac..b7aa16b6b5f 100644
--- a/code/modules/admin/verbs/secrets.dm
+++ b/code/modules/admin/verbs/secrets.dm
@@ -1,12 +1,9 @@
GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller)
-/client/proc/secrets() //Creates a verb for admins to open up the ui
- set name = "Secrets"
- set desc = "Abuse harder than you ever have before with this handy dandy semi-misc stuff menu"
- set category = "Admin.Game"
+ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before with this handy dandy semi-misc stuff menu.", ADMIN_CATEGORY_GAME)
+ var/datum/secrets_menu/tgui = new(user)
+ tgui.ui_interact(user.mob)
BLACKBOX_LOG_ADMIN_VERB("Secrets Panel")
- var/datum/secrets_menu/tgui = new(usr)//create the datum
- tgui.ui_interact(usr)//datum has a tgui component, here we open the window
/datum/secrets_menu
var/client/holder //client of whoever is using this datum
@@ -102,25 +99,25 @@ GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller)
D.cure(0)
if("list_bombers")
- holder.list_bombers()
+ holder.holder.list_bombers()
if("list_signalers")
- holder.list_signalers()
+ holder.holder.list_signalers()
if("list_lawchanges")
- holder.list_law_changes()
+ holder.holder.list_law_changes()
if("showailaws")
- holder.check_ai_laws()
+ holder.holder.list_law_changes()
if("manifest")
- holder.show_manifest()
+ holder.holder.show_manifest()
if("dna")
- holder.list_dna()
+ holder.holder.list_dna()
if("fingerprints")
- holder.list_fingerprints()
+ holder.holder.list_fingerprints()
if("ctfbutton")
toggle_id_ctf(holder, CTF_GHOST_CTF_GAME_ID)
diff --git a/code/modules/admin/verbs/selectequipment.dm b/code/modules/admin/verbs/selectequipment.dm
index 59513db0129..b94fd5cb2e4 100644
--- a/code/modules/admin/verbs/selectequipment.dm
+++ b/code/modules/admin/verbs/selectequipment.dm
@@ -1,10 +1,6 @@
-/client/proc/cmd_select_equipment(mob/target in GLOB.mob_list)
- set category = "Admin.Events"
- set name = "Select equipment"
-
-
- var/datum/select_equipment/ui = new(usr, target)
- ui.ui_interact(usr)
+ADMIN_VERB_ONLY_CONTEXT_MENU(select_equipment, R_FUN, "Select Equipment", mob/target in world)
+ var/datum/select_equipment/ui = new(user, target)
+ ui.ui_interact(user.mob)
/*
* This is the datum housing the select equipment UI.
@@ -152,7 +148,7 @@
return custom_outfit
-/datum/select_equipment/ui_act(action, params)
+/datum/select_equipment/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
. = TRUE
@@ -181,7 +177,7 @@
user.admin_apply_outfit(target_mob, new_outfit)
if("customoutfit")
- user.outfit_manager()
+ return SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/outfit_manager)
if("togglefavorite")
var/datum/outfit/outfit_path = resolve_outfit(params["path"])
diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm
index d93008996bc..71000fd310d 100644
--- a/code/modules/admin/verbs/server.dm
+++ b/code/modules/admin/verbs/server.dm
@@ -1,191 +1,148 @@
// Server Tab - Server Verbs
-/client/proc/toggle_random_events()
- set category = "Server"
- set name = "Toggle random events on/off"
- set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off"
+ADMIN_VERB(toggle_random_events, R_SERVER, "Toggle Random Events", "Toggles random events on or off.", ADMIN_CATEGORY_SERVER)
var/new_are = !CONFIG_GET(flag/allow_random_events)
CONFIG_SET(flag/allow_random_events, new_are)
- message_admins("[key_name_admin(usr)] has [new_are ? "enabled" : "disabled"] random events.")
+ message_admins("[key_name_admin(user)] has [new_are ? "enabled" : "disabled"] random events.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Random Events", "[new_are ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/client/proc/toggle_hub()
- set category = "Server"
- set name = "Toggle Hub"
-
+ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibility on the BYOND Hub.", ADMIN_CATEGORY_SERVER)
world.update_hub_visibility(!GLOB.hub_visibility)
- log_admin("[key_name(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
- message_admins("[key_name_admin(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
+ log_admin("[key_name(user)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
+ message_admins("[key_name_admin(user)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.")
if (GLOB.hub_visibility && !world.reachable)
message_admins("WARNING: The server will not show up on the hub because byond is detecting that a filewall is blocking incoming connections.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/datum/admins/proc/restart()
- set category = "Server"
- set name = "Reboot World"
- set desc = "Restarts the world immediately"
- if (!usr.client.holder)
- return
-
- var/localhost_addresses = list("127.0.0.1", "::1")
+ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.", ADMIN_CATEGORY_SERVER)
var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
if(world.TgsAvailable())
options += "Server Restart (Kill and restart DD)";
if(SSticker.admin_delay_notice)
- if(alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes")
+ if(alert(user, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes")
return FALSE
- var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
- if(result)
- BLACKBOX_LOG_ADMIN_VERB("Reboot World")
- var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]."
- switch(result)
- if("Regular Restart")
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(alert(usr, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
- return FALSE
- SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
- if("Regular Restart (with delay)")
- var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
- if(!delay)
+ var/result = input(user, "Select reboot method", "World Reboot", options[1]) as null|anything in options
+ if(isnull(result))
+ return
+
+ BLACKBOX_LOG_ADMIN_VERB("Reboot World")
+ var/init_by = "Initiated by [user.holder.fakekey ? "Admin" : user.key]."
+ switch(result)
+ if("Regular Restart")
+ if(!user.is_localhost())
+ if(alert(user, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(alert(usr,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
- return FALSE
- SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay * 10)
- if("Hard Restart (No Delay, No Feeback Reason)")
- to_chat(world, "World reboot - [init_by]")
- world.Reboot()
- if("Hardest Restart (No actions, just reboot)")
- to_chat(world, "Hard world reboot - [init_by]")
- world.Reboot(fast_track = TRUE)
- if("Server Restart (Kill and restart DD)")
- to_chat(world, "Server restart - [init_by]")
- world.TgsEndProcess()
+ SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", 10)
+ if("Regular Restart (with delay)")
+ var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
+ if(!delay)
+ return FALSE
+ if(!user.is_localhost())
+ if(alert(user,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
+ return FALSE
+ SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", delay * 10)
+ if("Hard Restart (No Delay, No Feeback Reason)")
+ to_chat(world, "World reboot - [init_by]")
+ world.Reboot()
+ if("Hardest Restart (No actions, just reboot)")
+ to_chat(world, "Hard world reboot - [init_by]")
+ world.Reboot(fast_track = TRUE)
+ if("Server Restart (Kill and restart DD)")
+ to_chat(world, "Server restart - [init_by]")
+ world.TgsEndProcess()
-/datum/admins/proc/end_round()
- set category = "Server"
- set name = "End Round"
- set desc = "Attempts to produce a round end report and then restart the server organically."
-
- if (!usr.client.holder)
+ADMIN_VERB(end_round, R_SERVER, "End Round", "Forcibly ends the round and allows the server to restart normally.", ADMIN_CATEGORY_SERVER)
+ var/confirm = tgui_alert(user, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
+ if(confirm != "Yes")
return
- var/confirm = tgui_alert(usr, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
- if(confirm == "Cancel")
- return
- if(confirm == "Yes")
- SSticker.force_ending = FORCE_END_ROUND
- BLACKBOX_LOG_ADMIN_VERB("End Round")
+ SSticker.force_ending = FORCE_END_ROUND
+ BLACKBOX_LOG_ADMIN_VERB("End Round")
-/datum/admins/proc/toggleooc()
- set category = "Server"
- set desc = "Toggle dis bitch"
- set name = "Toggle OOC"
+ADMIN_VERB(toggle_ooc, R_ADMIN, "Toggle OOC", "Toggle the OOC channel on or off.", ADMIN_CATEGORY_SERVER)
toggle_ooc()
- log_admin("[key_name(usr)] toggled OOC.")
- message_admins("[key_name_admin(usr)] toggled OOC.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+ log_admin("[key_name(user)] toggled OOC.")
+ message_admins("[key_name_admin(user)] toggled OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]"))
-/datum/admins/proc/toggleoocdead()
- set category = "Server"
- set desc = "Toggle dis bitch"
- set name = "Toggle Dead OOC"
+ADMIN_VERB(toggle_ooc_dead, R_ADMIN, "Toggle Dead OOC", "Toggle the OOC channel for dead players on or off.", ADMIN_CATEGORY_SERVER)
toggle_dooc()
+ log_admin("[key_name(user)] toggled OOC.")
+ message_admins("[key_name_admin(user)] toggled Dead OOC.")
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]"))
- log_admin("[key_name(usr)] toggled OOC.")
- message_admins("[key_name_admin(usr)] toggled Dead OOC.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+ADMIN_VERB(start_now, R_SERVER, "Start Now", "Start the round RIGHT NOW.", ADMIN_CATEGORY_SERVER)
+ var/static/list/waiting_states = list(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ if(!(SSticker.current_state in waiting_states))
+ to_chat(user, span_warning(span_red("The game has already started!")))
+ return
-/datum/admins/proc/startnow()
- set category = "Server"
- set desc = "Start the round RIGHT NOW"
- set name = "Start Now"
- if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
- if(!SSticker.start_immediately)
- var/localhost_addresses = list("127.0.0.1", "::1")
- if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses)))
- if(tgui_alert(usr, "Are you sure you want to start the round?","Start Now",list("Start Now","Cancel")) != "Start Now")
- return FALSE
- SSticker.start_immediately = TRUE
- log_admin("[usr.key] has started the game.")
- var/msg = ""
- if(SSticker.current_state == GAME_STATE_STARTUP)
- msg = " (The server is still setting up, but the round will be \
- started as soon as possible.)"
- message_admins("[usr.key] has started the game.[msg]")
- BLACKBOX_LOG_ADMIN_VERB("Start Now")
- return TRUE
+ if(SSticker.start_immediately)
SSticker.start_immediately = FALSE
SSticker.SetTimeLeft(1800)
- to_chat(world, "The game will start in 180 seconds.")
+ to_chat(world, span_infoplain(span_bold("The game will start in 180 seconds.")))
SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
- message_admins("[usr.key] has cancelled immediate game start. Game will start in 180 seconds.")
- log_admin("[usr.key] has cancelled immediate game start.")
- else
- to_chat(usr, "Error: Start Now: Game has already started.")
- return FALSE
-
-/datum/admins/proc/delay_round_end()
- set category = "Server"
- set desc = "Prevent the server from restarting"
- set name = "Delay Round End"
-
- if(!check_rights(R_ADMIN)) // SKYRAT EDIT - Admins can delay the round end - ORIGINAL: if(!check_rights(R_SERVER))
+ message_admins(span_adminnotice("[key_name_admin(user)] has cancelled immediate game start. Game will start in 3 minutes."))
+ log_admin("[key_name(user)] has cancelled immediate game start.")
return
+ if(!user.is_localhost())
+ var/response = tgui_alert(user, "Are you sure you want to start the round?", "Start Now", list("Start Now", "Cancel"))
+ if(response != "Start Now")
+ return
+ SSticker.start_immediately = TRUE
+
+ log_admin("[key_name(user)] has started the game.")
+ message_admins("[key_name_admin(user)] has started the game.")
+ if(SSticker.current_state == GAME_STATE_STARTUP)
+ message_admins("The server is still setting up, but the round will be started as soon as possible.")
+ BLACKBOX_LOG_ADMIN_VERB("Start Now")
+
+// ADMIN_VERB(delay_round_end, R_SERVER, "Delay Round End", "Prevent the server from restarting.", ADMIN_CATEGORY_SERVER)
+ADMIN_VERB(delay_round_end, R_ADMIN, "Delay Round End", "Prevent the server from restarting.", ADMIN_CATEGORY_SERVER) // SKYRAT EDIT -- ORIGINAL ABOVE
if(SSticker.delay_end)
- tgui_alert(usr, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok"))
+ tgui_alert(user, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok"))
return
- var/delay_reason = input(usr, "Enter a reason for delaying the round end", "Round Delay Reason") as null|text
+ var/delay_reason = input(user, "Enter a reason for delaying the round end", "Round Delay Reason") as null|text
if(isnull(delay_reason))
return
if(SSticker.delay_end)
- tgui_alert(usr, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok"))
+ tgui_alert(user, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok"))
return
SSticker.delay_end = TRUE
SSticker.admin_delay_notice = delay_reason
- log_admin("[key_name(usr)] delayed the round end for reason: [SSticker.admin_delay_notice]")
- message_admins("[key_name_admin(usr)] delayed the round end for reason: [SSticker.admin_delay_notice]")
+ log_admin("[key_name(user)] delayed the round end for reason: [SSticker.admin_delay_notice]")
+ message_admins("[key_name_admin(user)] delayed the round end for reason: [SSticker.admin_delay_notice]")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Delay Round End", "Reason: [delay_reason]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/datum/admins/proc/toggleenter()
- set category = "Server"
- set desc = "People can't enter"
- set name = "Toggle Entering"
+ADMIN_VERB(toggle_enter, R_SERVER, "Toggle Entering", "Toggle the ability to enter the game.", ADMIN_CATEGORY_SERVER)
if(!SSlag_switch.initialized)
return
SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, !SSlag_switch.measures[DISABLE_NON_OBSJOBS])
- log_admin("[key_name(usr)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])")
- message_admins("[key_name_admin(usr)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].")
+ log_admin("[key_name(user)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])")
+ message_admins("[key_name_admin(user)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Entering", "[!SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/datum/admins/proc/toggleAI()
- set category = "Server"
- set desc = "People can't be AI"
- set name = "Toggle AI"
+ADMIN_VERB(toggle_ai, R_SERVER, "Toggle AI", "Toggle the ability to choose AI jobs.", ADMIN_CATEGORY_SERVER)
var/alai = CONFIG_GET(flag/allow_ai)
CONFIG_SET(flag/allow_ai, !alai)
if (alai)
- to_chat(world, "The AI job is no longer chooseable.", confidential = TRUE)
+ to_chat(world, span_bold("The AI job is no longer chooseable."), confidential = TRUE)
else
- to_chat(world, "The AI job is chooseable now.", confidential = TRUE)
+ to_chat(world, span_bold("The AI job is chooseable now."), confidential = TRUE)
log_admin("[key_name(usr)] toggled AI allowed.")
world.update_status()
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/datum/admins/proc/toggleaban()
- set category = "Server"
- set desc = "Respawn basically"
- set name = "Toggle Respawn"
-
+ADMIN_VERB(toggle_respawn, R_SERVER, "Toggle Respawn", "Toggle the ability to respawn.", ADMIN_CATEGORY_SERVER)
var/respawn_state = CONFIG_GET(flag/allow_respawn)
var/new_state = -1
var/new_state_text = ""
@@ -203,80 +160,71 @@
if(RESPAWN_FLAG_NEW_CHARACTER) // respawn currently enabled for different slot characters only
new_state = RESPAWN_FLAG_DISABLED
new_state_text = "Disabled"
- to_chat(world, span_bold("You may no longer respawn :("), confidential = TRUE)
+ to_chat(world, span_bold("You may no longer respawn."), confidential = TRUE)
else
WARNING("Invalid respawn state in config: [respawn_state]")
if(new_state == -1)
- to_chat(usr, span_warning("The config for respawn is set incorrectly, please complain to your nearest server host (or fix it yourself). \
+ to_chat(user, span_warning("The config for respawn is set incorrectly, please complain to your nearest server host (or fix it yourself). \
In the meanwhile respawn has been set to \"Off\"."))
new_state = RESPAWN_FLAG_DISABLED
new_state_text = "Disabled"
CONFIG_SET(flag/allow_respawn, new_state)
- message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to \"[new_state_text]\"."))
- log_admin("[key_name(usr)] toggled respawn to \"[new_state_text]\".")
+ message_admins(span_adminnotice("[key_name_admin(user)] toggled respawn to \"[new_state_text]\"."))
+ log_admin("[key_name(user)] toggled respawn to \"[new_state_text]\".")
world.update_status()
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[new_state_text]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/datum/admins/proc/delay()
- set category = "Server"
- set desc = "Delay the game start"
- set name = "Delay Pre-Game"
-
- var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null
+ADMIN_VERB(delay, R_SERVER, "Delay Pre-Game", "Delay the game start.", ADMIN_CATEGORY_SERVER)
+ var/newtime = input(user, "Set a new time in seconds. Set -1 for indefinite delay.", "Set Delay", round(SSticker.GetTimeLeft()/10)) as num|null
if(!newtime)
return
if(SSticker.current_state > GAME_STATE_PREGAME)
- return tgui_alert(usr, "Too late... The game has already started!")
+ return tgui_alert(user, "Too late... The game has already started!")
newtime = newtime*10
SSticker.SetTimeLeft(newtime)
SSticker.start_immediately = FALSE
if(newtime < 0)
- to_chat(world, "The game start has been delayed.", confidential = TRUE)
+ to_chat(world, span_infoplain(span_bold("The game start has been delayed.")), confidential = TRUE)
log_admin("[key_name(usr)] delayed the round start.")
else
- to_chat(world, "The game will start in [DisplayTimeText(newtime)].", confidential = TRUE)
+ to_chat(world, span_infoplain(span_bold("The game will start in [DisplayTimeText(newtime)].")), confidential = TRUE)
SEND_SOUND(world, sound('sound/ai/default/attention.ogg'))
- log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
+ log_admin("[key_name(user)] set the pre-game delay to [DisplayTimeText(newtime)].")
BLACKBOX_LOG_ADMIN_VERB("Delay Game Start")
-/datum/admins/proc/set_admin_notice()
- set category = "Server"
- set name = "Set Admin Notice"
- set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round"
- if(!check_rights(0))
- return
-
- var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null
+ADMIN_VERB(set_admin_notice, R_SERVER, "Set Admin Notice", "Set an announcement that appears to everyone who joins the server. Only lasts this round.", ADMIN_CATEGORY_SERVER)
+ var/new_admin_notice = input(
+ user,
+ "Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):",
+ "Set Notice",
+ GLOB.admin_notice,
+ ) as message|null
if(new_admin_notice == null)
return
if(new_admin_notice == GLOB.admin_notice)
return
if(new_admin_notice == "")
- message_admins("[key_name(usr)] removed the admin notice.")
- log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]")
+ message_admins("[key_name(user)] removed the admin notice.")
+ log_admin("[key_name(user)] removed the admin notice:\n[GLOB.admin_notice]")
else
- message_admins("[key_name(usr)] set the admin notice.")
- log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]")
+ message_admins("[key_name(user)] set the admin notice.")
+ log_admin("[key_name(user)] set the admin notice:\n[new_admin_notice]")
to_chat(world, span_adminnotice("Admin Notice:\n \t [new_admin_notice]"), confidential = TRUE)
BLACKBOX_LOG_ADMIN_VERB("Set Admin Notice")
GLOB.admin_notice = new_admin_notice
- return
-/datum/admins/proc/toggleguests()
- set category = "Server"
- set desc = "Guests can't enter"
- set name = "Toggle guests"
+ADMIN_VERB(toggle_guests, R_SERVER, "Toggle Guests", "Toggle the ability for guests to enter the game.", ADMIN_CATEGORY_SERVER)
var/new_guest_ban = !CONFIG_GET(flag/guest_ban)
CONFIG_SET(flag/guest_ban, new_guest_ban)
if (new_guest_ban)
- to_chat(world, "Guests may no longer enter the game.", confidential = TRUE)
+ to_chat(world, span_bold("Guests may no longer enter the game."), confidential = TRUE)
else
- to_chat(world, "Guests may now enter the game.", confidential = TRUE)
+ to_chat(world, span_bold("Guests may now enter the game."), confidential = TRUE)
log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")
message_admins(span_adminnotice("[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed."))
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/shuttlepanel.dm b/code/modules/admin/verbs/shuttlepanel.dm
index d7050c0467b..0a33acb0692 100644
--- a/code/modules/admin/verbs/shuttlepanel.dm
+++ b/code/modules/admin/verbs/shuttlepanel.dm
@@ -1,13 +1,5 @@
-/datum/admins/proc/open_shuttlepanel()
- set category = "Admin.Events"
- set name = "Shuttle Manipulator"
- set desc = "Opens the shuttle manipulator UI."
-
- if(!check_rights(R_ADMIN))
- return
-
- SSshuttle.ui_interact(usr)
-
+ADMIN_VERB(shuttle_panel, R_ADMIN, "Shuttle Manipulator", "Opens the shuttle manipulator UI.", ADMIN_CATEGORY_EVENTS)
+ SSshuttle.ui_interact(user.mob)
/obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user)
var/list/options = list()
diff --git a/code/modules/admin/verbs/spawnobjasmob.dm b/code/modules/admin/verbs/spawnobjasmob.dm
index 924c9885713..e673202f0ba 100644
--- a/code/modules/admin/verbs/spawnobjasmob.dm
+++ b/code/modules/admin/verbs/spawnobjasmob.dm
@@ -1,11 +1,4 @@
-/datum/admins/proc/spawn_objasmob(object as text)
- set category = "Debug"
- set desc = "(obj path) Spawn object-mob"
- set name = "Spawn object-mob"
-
- if(!check_rights(R_SPAWN))
- return
-
+ADMIN_VERB(spawn_obj_as_mob, R_SPAWN, "Spawn Object-Mob", "Spawn an object as if it were a mob.", ADMIN_CATEGORY_DEBUG, object as text)
var/chosen = pick_closest_path(object, make_types_fancy(subtypesof(/obj)))
if (!chosen)
@@ -15,21 +8,63 @@
var/obj/chosen_obj = text2path(chosen)
- var/list/settings = list(
- "mainsettings" = list(
- "name" = list("desc" = "Name", "type" = "string", "value" = "Bob"),
- "maxhealth" = list("desc" = "Max. health", "type" = "number", "value" = 100),
- "access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"),
- "objtype" = list("desc" = "Base obj type", "type" = "datum", "path" = "/obj", "value" = "[chosen]"),
- "googlyeyes" = list("desc" = "Googly eyes", "type" = "boolean", "value" = "No"),
- "disableai" = list("desc" = "Disable AI", "type" = "boolean", "value" = "Yes"),
- "idledamage" = list("desc" = "Damaged while idle", "type" = "boolean", "value" = "No"),
- "dropitem" = list("desc" = "Drop obj on death", "type" = "boolean", "value" = "Yes"),
- "mobtype" = list("desc" = "Base mob type", "type" = "datum", "path" = "/mob/living/simple_animal/hostile/mimic/copy", "value" = "/mob/living/simple_animal/hostile/mimic/copy"),
- "ckey" = list("desc" = "ckey", "type" = "ckey", "value" = "none"),
+ var/list/settings = list("mainsettings" = list(
+ "name" = list(
+ "desc" = "Name",
+ "type" = "string",
+ "value" = "Bob",
+ ),
+ "maxhealth" = list(
+ "desc" = "Max. health",
+ "type" = "number",
+ "value" = 100,
+ ),
+ "access" = list(
+ "desc" = "Access ID",
+ "type" = "datum",
+ "path" = "/obj/item/card/id",
+ "value" = "Default",
+ ),
+ "objtype" = list(
+ "desc" = "Base obj type",
+ "type" = "datum",
+ "path" = "/obj",
+ "value" = "[chosen]",
+ ),
+ "googlyeyes" = list(
+ "desc" = "Googly eyes",
+ "type" = "boolean",
+ "value" = "No",
+ ),
+ "disableai" = list(
+ "desc" = "Disable AI",
+ "type" = "boolean",
+ "value" = "Yes",
+ ),
+ "idledamage" = list(
+ "desc" = "Damaged while idle",
+ "type" = "boolean",
+ "value" = "No",
+ ),
+ "dropitem" = list(
+ "desc" = "Drop obj on death",
+ "type" = "boolean",
+ "value" = "Yes",
+ ),
+ "mobtype" = list(
+ "desc" = "Base mob type",
+ "type" = "datum",
+ "path" = "/mob/living/simple_animal/hostile/mimic/copy",
+ "value" = "/mob/living/simple_animal/hostile/mimic/copy",
+ ),
+ "ckey" = list(
+ "desc" = "ckey",
+ "type" = "ckey",
+ "value" = "none",
+ ),
))
- var/list/prefreturn = presentpreflikepicker(usr,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings)
+ var/list/prefreturn = presentpreflikepicker(user.mob,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings)
if (prefreturn["button"] == 1)
settings = prefreturn["settings"]
var/mainsettings = settings["mainsettings"]
@@ -37,9 +72,9 @@
basemob = text2path(mainsettings["mobtype"]["value"])
if (!ispath(basemob, /mob/living/simple_animal/hostile/mimic/copy) || !ispath(chosen_obj, /obj))
- to_chat(usr, "Mob or object path invalid", confidential = TRUE)
+ to_chat(user.mob, "Mob or object path invalid", confidential = TRUE)
- basemob = new basemob(get_turf(usr), new chosen_obj(get_turf(usr)), usr, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE))
+ basemob = new basemob(get_turf(user.mob), new chosen_obj(get_turf(user.mob)), user.mob, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE))
if (mainsettings["disableai"]["value"] == "Yes")
basemob.toggle_ai(AI_OFF)
@@ -65,5 +100,5 @@
basemob.ckey = mainsettings["ckey"]["value"]
- log_admin("[key_name(usr)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(usr)]")
+ log_admin("[key_name(user.mob)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(user.mob)]")
BLACKBOX_LOG_ADMIN_VERB("Spawn object-mob")
diff --git a/code/modules/admin/verbs/special_verbs.dm b/code/modules/admin/verbs/special_verbs.dm
new file mode 100644
index 00000000000..309c14d4455
--- /dev/null
+++ b/code/modules/admin/verbs/special_verbs.dm
@@ -0,0 +1,43 @@
+// Admin Verbs in this file are special and cannot use the AVD system for some reason or another.
+
+/client/proc/show_verbs()
+ set name = "Adminverbs - Show"
+ set category = ADMIN_CATEGORY_MAIN
+
+ remove_verb(src, /client/proc/show_verbs)
+ add_admin_verbs()
+
+ to_chat(src, span_interface("All of your adminverbs are now visible."), confidential = TRUE)
+ BLACKBOX_LOG_ADMIN_VERB("Show Adminverbs")
+
+/client/proc/readmin()
+ set name = "Readmin"
+ set category = "Admin"
+ set desc = "Regain your admin powers."
+
+ var/datum/admins/A = GLOB.deadmins[ckey]
+
+ if(!A)
+ A = GLOB.admin_datums[ckey]
+ if (!A)
+ var/msg = " is trying to readmin but they have no deadmin entry"
+ message_admins("[key_name_admin(src)][msg]")
+ log_admin_private("[key_name(src)][msg]")
+ return
+
+ A.associate(src)
+
+ if (!holder)
+ return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force
+
+ to_chat(src, span_interface("You are now an admin."), confidential = TRUE)
+ message_admins("[src] re-adminned themselves.")
+ log_admin("[src] re-adminned themselves.")
+ BLACKBOX_LOG_ADMIN_VERB("Readmin")
+
+/client/proc/admin_2fa_verify()
+ set name = "Verify Admin"
+ set category = "Admin"
+
+ var/datum/admins/admin = GLOB.admin_datums[ckey]
+ admin?.associate(src)
diff --git a/code/modules/admin/view_variables/mark_datum.dm b/code/modules/admin/view_variables/mark_datum.dm
index 44c3b2b83b2..1d9dd3a1a37 100644
--- a/code/modules/admin/view_variables/mark_datum.dm
+++ b/code/modules/admin/view_variables/mark_datum.dm
@@ -8,10 +8,8 @@
holder.RegisterSignal(holder.marked_datum, COMSIG_QDELETING, TYPE_PROC_REF(/datum/admins, handle_marked_del))
vv_update_display(D, "marked", VV_MSG_MARKED)
-/client/proc/mark_datum_mapview(datum/D as mob|obj|turf|area in view(view))
- set category = "Debug"
- set name = "Mark Object"
- mark_datum(D)
+ADMIN_VERB_ONLY_CONTEXT_MENU(mark_datum, R_NONE, "Mark Object", datum/target as mob|obj|turf|area in view())
+ user.mark_datum(target)
/datum/admins/proc/handle_marked_del(datum/source)
SIGNAL_HANDLER
diff --git a/code/modules/admin/view_variables/tag_datum.dm b/code/modules/admin/view_variables/tag_datum.dm
index 3b611e3cdf9..b4ca42860c3 100644
--- a/code/modules/admin/view_variables/tag_datum.dm
+++ b/code/modules/admin/view_variables/tag_datum.dm
@@ -12,7 +12,5 @@
else
holder.add_tagged_datum(target_datum)
-/client/proc/tag_datum_mapview(datum/target_datum as mob|obj|turf|area in view(view))
- set category = "Debug"
- set name = "Tag Datum"
- tag_datum(target_datum)
+ADMIN_VERB_ONLY_CONTEXT_MENU(tag_datum, R_NONE, "Tag Datum", datum/target_datum as mob|obj|turf|area in view())
+ user.tag_datum(target_datum)
diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm
index 8a27d342578..4f363653127 100644
--- a/code/modules/admin/view_variables/topic_basic.dm
+++ b/code/modules/admin/view_variables/topic_basic.dm
@@ -140,6 +140,7 @@
return
var/datum/greyscale_modify_menu/menu = new(target, usr, SSgreyscale.configurations, unlocked = TRUE)
menu.ui_interact(usr)
- if(href_list[VV_HK_CALLPROC])
- usr.client.callproc_datum(target)
+
+ if(href_list[VV_HK_CALLPROC])
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/call_proc_datum, target)
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index 9f0d86e04f6..b139ec9d488 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -1,3 +1,7 @@
+ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the variables of a datum.", ADMIN_CATEGORY_DEBUG, datum/thing in world)
+ user.debug_variables(thing)
+
+// This is kept as a seperate proc because admins are able to show VV to non-admins
/client/proc/debug_variables(datum/thing in world)
set category = "Debug"
set name = "View Variables"
diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm
index 07e8dad2aa6..2fb5d526045 100644
--- a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm
+++ b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm
@@ -48,7 +48,7 @@
icon_state = "gizmo_scan"
to_chat(user, span_notice("You switch the device to [mode == GIZMO_SCAN? "SCAN": "MARK"] MODE"))
-/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user)
+/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!ScientistCheck(user))
return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it
if(!console)
@@ -110,7 +110,7 @@
icon_state = "silencer"
inhand_icon_state = "gizmo"
-/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user)
+/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!AbductorCheck(user))
return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it
@@ -285,8 +285,8 @@
Congratulations! You are now trained for invasive xenobiology research!"}
-/obj/item/paper/guides/antag/abductor/AltClick()
- return //otherwise it would fold into a paperplane.
+/obj/item/paper/guides/antag/abductor/click_alt()
+ return CLICK_ACTION_BLOCKING //otherwise it would fold into a paperplane.
/obj/item/melee/baton/abductor
name = "advanced baton"
diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index 5bd5ce8c2ec..ee729de7068 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -198,11 +198,8 @@
pad.teleport_target = location
to_chat(user, span_notice("Location marked as test subject release point."))
-/obj/machinery/abductor/console/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/abductor/console/LateInitialize()
+/obj/machinery/abductor/console/post_machine_initialize()
+ . = ..()
if(!team_number)
return
diff --git a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm
index 18fda4bf4ff..0e468159a3c 100644
--- a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm
+++ b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm
@@ -23,6 +23,9 @@
/datum/action/changeling/pheromone_receptors/sting_action(mob/living/carbon/user)
..()
var/datum/antagonist/changeling/changeling = IS_CHANGELING(user)
+ if(HAS_TRAIT(user, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything
+ to_chat(user, span_warning("We can't smell!"))
+ return
if(!receptors_active)
to_chat(user, span_warning("We search for the scent of any nearby changelings."))
changeling.chem_recharge_slowdown += 0.25
diff --git a/code/modules/antagonists/cult/rune_spawn_action.dm b/code/modules/antagonists/cult/rune_spawn_action.dm
index af4350427b5..3d791dbce44 100644
--- a/code/modules/antagonists/cult/rune_spawn_action.dm
+++ b/code/modules/antagonists/cult/rune_spawn_action.dm
@@ -42,7 +42,7 @@
var/chosen_keyword
if(initial(rune_type.req_keyword))
chosen_keyword = tgui_input_text(owner, "Enter a keyword for the new rune.", "Words of Power", max_length = MAX_NAME_LEN)
- if(!chosen_keyword)
+ if(!chosen_keyword || !turf_check(T))
return
//the outer ring is always the same across all runes
var/obj/effect/temp_visual/cult/rune_spawn/R1 = new(T, scribe_time, rune_color)
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index aa979ff7814..cc4a80d980f 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -491,7 +491,7 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
return
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
- if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || !actual_selected_rune)
+ if(!Adjacent(user) || QDELETED(src) || user.incapacitated() || !actual_selected_rune)
fail_invoke()
return
diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm
index 9d5af7ab83e..17364feec55 100644
--- a/code/modules/antagonists/disease/disease_datum.dm
+++ b/code/modules/antagonists/disease/disease_datum.dm
@@ -54,7 +54,7 @@
result += objectives_text
- var/special_role_text = lowertext(name)
+ var/special_role_text = LOWER_TEXT(name)
if(win)
result += span_greentext("The [special_role_text] was successful!")
diff --git a/code/modules/antagonists/heretic/items/forbidden_book.dm b/code/modules/antagonists/heretic/items/forbidden_book.dm
index ad6bc388800..06f091c77e7 100644
--- a/code/modules/antagonists/heretic/items/forbidden_book.dm
+++ b/code/modules/antagonists/heretic/items/forbidden_book.dm
@@ -39,11 +39,11 @@
if(book_open)
close_animation()
RemoveElement(/datum/element/heretic_focus)
- w_class = WEIGHT_CLASS_SMALL
+ update_weight_class(WEIGHT_CLASS_SMALL)
else
open_animation()
AddElement(/datum/element/heretic_focus)
- w_class = WEIGHT_CLASS_NORMAL
+ update_weight_class(WEIGHT_CLASS_NORMAL)
/obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm
index dbaec3e3a20..095ccbc1b75 100644
--- a/code/modules/antagonists/malf_ai/malf_ai.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai.dm
@@ -267,7 +267,7 @@
// SKYRAT EDIT REMOVAL START
/*
- var/special_role_text = lowertext(name)
+ var/special_role_text = LOWER_TEXT(name)
if(malf_ai_won)
result += span_greentext("The [special_role_text] was successful!")
diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
index 2b323d51162..04ebab73cbd 100644
--- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
+++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
@@ -232,7 +232,7 @@
pad_ref = WEAKREF(I.buffer)
return TRUE
-/obj/machinery/computer/piratepad_control/LateInitialize()
+/obj/machinery/computer/piratepad_control/post_machine_initialize()
. = ..()
if(cargo_hold_id)
for(var/obj/machinery/piratepad/P as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/piratepad))
diff --git a/code/modules/antagonists/spy/spy.dm b/code/modules/antagonists/spy/spy.dm
index e0ea7e40754..89809958b29 100644
--- a/code/modules/antagonists/spy/spy.dm
+++ b/code/modules/antagonists/spy/spy.dm
@@ -130,7 +130,30 @@
your_mission.owner = owner
your_mission.explanation_text = pick_list_replacements(SPY_OBJECTIVE_FILE, "objective_body")
objectives += your_mission
-
+
+ if((length(objectives) < 3) && prob(25))
+ switch(rand(1, 4))
+ if(1)
+ var/datum/objective/protect/save_the_person = new()
+ save_the_person.owner = owner
+ save_the_person.no_failure = TRUE
+ objectives += save_the_person
+ if(2)
+ var/datum/objective/protect/nonhuman/save_the_entity = new()
+ save_the_entity.owner = owner
+ save_the_entity.no_failure = TRUE
+ objectives += save_the_entity
+ if(3)
+ var/datum/objective/jailbreak/save_the_jailbird = new()
+ save_the_jailbird.owner = owner
+ save_the_jailbird.no_failure = TRUE
+ objectives += save_the_jailbird
+ if(4)
+ var/datum/objective/jailbreak/detain/cage_the_jailbird = new()
+ cage_the_jailbird.owner = owner
+ cage_the_jailbird.no_failure = TRUE
+ objectives += cage_the_jailbird
+
if(prob(10))
var/datum/objective/martyr/leave_no_trace = new()
leave_no_trace.owner = owner
@@ -141,6 +164,11 @@
steal_the_shuttle.owner = owner
objectives += steal_the_shuttle
+ else if(prob(10)) //10% chance on 87.3% chance
+ var/datum/objective/exile/hit_the_bricks = new()
+ hit_the_bricks.owner = owner
+ objectives += hit_the_bricks
+
else
var/datum/objective/escape/gtfo = new()
gtfo.owner = owner
diff --git a/code/modules/antagonists/traitor/balance_helper.dm b/code/modules/antagonists/traitor/balance_helper.dm
index e78625ff1c1..b2a9661bfeb 100644
--- a/code/modules/antagonists/traitor/balance_helper.dm
+++ b/code/modules/antagonists/traitor/balance_helper.dm
@@ -1,11 +1,5 @@
-/client/proc/cmd_admin_debug_traitor_objectives()
- set name = "Debug Traitor Objectives"
- set category = "Debug"
-
- if(!check_rights(R_DEBUG))
- return
-
- SStraitor.traitor_debug_panel?.ui_interact(usr)
+ADMIN_VERB(debug_traitor_objectives, R_DEBUG, "Debug Traitor Objectives", "Verify functionality of traitor goals.", ADMIN_CATEGORY_DEBUG)
+ SStraitor.traitor_debug_panel?.ui_interact(user.mob)
/datum/traitor_objective_debug
var/list/all_objectives
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index 88776b6819a..5ad5aeecf26 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -360,7 +360,7 @@
result += contractor_round_end()
result += " The traitor had a total of [DISPLAY_PROGRESSION(uplink_handler.progression_points)] Reputation and [uplink_handler.telecrystals] Unused Telecrystals."
- var/special_role_text = lowertext(name)
+ var/special_role_text = LOWER_TEXT(name)
if(traitor_won)
result += span_greentext("The [special_role_text] was successful!")
diff --git a/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm b/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm
index 9723d2b653e..5a31c4c1739 100644
--- a/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm
+++ b/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm
@@ -49,7 +49,7 @@ GLOBAL_DATUM_INIT(objective_machine_handler, /datum/objective_target_machine_han
for(var/obj/machinery/machine as anything in possible_machines)
prepare_machine(machine)
- replace_in_name("%JOB%", lowertext(chosen_job))
+ replace_in_name("%JOB%", LOWER_TEXT(chosen_job))
replace_in_name("%MACHINE%", possible_machines[1].name)
return TRUE
diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm
index dd370f480f4..f050528bd3b 100644
--- a/code/modules/art/paintings.dm
+++ b/code/modules/art/paintings.dm
@@ -350,7 +350,7 @@
var/result = rustg_dmi_create_png(png_filename, "[width]", "[height]", image_data)
if(result)
CRASH("Error generating painting png : [result]")
- painting_metadata.md5 = md5(lowertext(image_data))
+ painting_metadata.md5 = md5(LOWER_TEXT(image_data))
generated_icon = new(png_filename)
icon_generated = TRUE
update_appearance()
@@ -569,10 +569,12 @@
current_canvas = null
update_appearance()
-/obj/structure/sign/painting/AltClick(mob/user)
- . = ..()
- if(current_canvas?.can_select_frame(user))
- INVOKE_ASYNC(current_canvas, TYPE_PROC_REF(/obj/item/canvas, select_new_frame), user)
+/obj/structure/sign/painting/click_alt(mob/user)
+ if(!current_canvas?.can_select_frame(user))
+ return CLICK_ACTION_BLOCKING
+
+ INVOKE_ASYNC(current_canvas, TYPE_PROC_REF(/obj/item/canvas, select_new_frame), user)
+ return CLICK_ACTION_SUCCESS
/obj/structure/sign/painting/proc/frame_canvas(mob/user, obj/item/canvas/new_canvas)
if(!(new_canvas.type in accepted_canvas_types))
@@ -663,7 +665,7 @@
stack_trace("Invalid persistence_id - [persistence_id]")
return
var/data = current_canvas.get_data_string()
- var/md5 = md5(lowertext(data))
+ var/md5 = md5(LOWER_TEXT(data))
var/list/current = SSpersistent_paintings.paintings[persistence_id]
if(!current)
current = list()
diff --git a/code/modules/art/statues.dm b/code/modules/art/statues.dm
index 428bb5d8e06..8ed46a5bf81 100644
--- a/code/modules/art/statues.dm
+++ b/code/modules/art/statues.dm
@@ -44,8 +44,6 @@
return
return ..()
-/obj/structure/statue/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/structure/statue/atom_deconstruct(disassembled = TRUE)
var/amount_mod = disassembled ? 0 : -2
diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm
index 23c329894e7..28ab16f63d7 100644
--- a/code/modules/assembly/health.dm
+++ b/code/modules/assembly/health.dm
@@ -37,16 +37,14 @@
update_appearance()
return secured
-/obj/item/assembly/health/AltClick(mob/living/user)
- if(!can_interact(user))
- return
-
+/obj/item/assembly/health/click_alt(mob/living/user)
if(alarm_health == HEALTH_THRESHOLD_CRIT)
alarm_health = HEALTH_THRESHOLD_DEAD
to_chat(user, span_notice("You toggle [src] to \"detect death\" mode."))
else
alarm_health = HEALTH_THRESHOLD_CRIT
to_chat(user, span_notice("You toggle [src] to \"detect critical state\" mode."))
+ return CLICK_ACTION_SUCCESS
/obj/item/assembly/health/process()
//not ready yet
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index 70f116b3e3e..5f50618e77d 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -141,8 +141,6 @@
return ..()
-/obj/item/assembly_holder/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool)
if(..())
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index b5c847a78ab..8dd4573fcfd 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -35,8 +35,6 @@
buffer_turf = null
return ..()
-/obj/item/assembly/infra/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/item/assembly/infra/examine(mob/user)
. = ..()
diff --git a/code/modules/asset_cache/assets/arcade.dm b/code/modules/asset_cache/assets/arcade.dm
index bcd23919f97..338b891190c 100644
--- a/code/modules/asset_cache/assets/arcade.dm
+++ b/code/modules/asset_cache/assets/arcade.dm
@@ -1,5 +1,7 @@
/datum/asset/simple/arcade
assets = list(
+ "shopkeeper.png" = 'icons/ui_icons/arcade/shopkeeper.png',
+ "fireplace.png" = 'icons/ui_icons/arcade/fireplace.png',
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
diff --git a/code/modules/asset_cache/assets/icon_ref_map.dm b/code/modules/asset_cache/assets/icon_ref_map.dm
new file mode 100644
index 00000000000..2f7f8463099
--- /dev/null
+++ b/code/modules/asset_cache/assets/icon_ref_map.dm
@@ -0,0 +1,28 @@
+/// Maps icon names to ref values
+/datum/asset/json/icon_ref_map
+ name = "icon_ref_map"
+ early = TRUE
+
+/datum/asset/json/icon_ref_map/generate()
+ var/list/data = list() //"icons/obj/drinks.dmi" => "[0xc000020]"
+
+ //var/start = "0xc000000"
+ var/value = 0
+
+ while(TRUE)
+ value += 1
+ var/ref = "\[0xc[num2text(value,6,16)]\]"
+ var/mystery_meat = locate(ref)
+
+ if(isicon(mystery_meat))
+ if(!isfile(mystery_meat)) // Ignore the runtime icons for now
+ continue
+ var/path = get_icon_dmi_path(mystery_meat) //Try to get the icon path
+ if(path)
+ data[path] = ref
+ else if(mystery_meat)
+ continue; //Some other non-icon resource, ogg/json/whatever
+ else //Out of resources end this, could also try to end this earlier as soon as runtime generated icons appear but eh
+ break;
+
+ return data
diff --git a/code/modules/asset_cache/transports/asset_transport.dm b/code/modules/asset_cache/transports/asset_transport.dm
index 19e40fb4884..3dbcc301843 100644
--- a/code/modules/asset_cache/transports/asset_transport.dm
+++ b/code/modules/asset_cache/transports/asset_transport.dm
@@ -82,11 +82,15 @@
/// asset_list - A list of asset filenames to be sent to the client. Can optionally be assoicated with the asset's asset_cache_item datum.
/// Returns TRUE if any assets were sent.
/datum/asset_transport/proc/send_assets(client/client, list/asset_list)
+#if defined(UNIT_TESTS)
+ return
+#endif
+
if (!istype(client))
if (ismob(client))
- var/mob/M = client
- if (M.client)
- client = M.client
+ var/mob/our_mob = client
+ if (our_mob.client)
+ client = our_mob.client
else //no stacktrace because this will mainly happen because the client went away
return
else
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index d42618e9ee9..d152cf09e71 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -81,7 +81,7 @@
fire = 100
acid = 70
-/obj/machinery/atmospherics/LateInitialize()
+/obj/machinery/atmospherics/post_machine_initialize()
. = ..()
update_name()
@@ -607,11 +607,6 @@
animate(our_client, pixel_x = 0, pixel_y = 0, time = 0.05 SECONDS)
our_client.move_delay = world.time + 0.05 SECONDS
-/obj/machinery/atmospherics/AltClick(mob/living/L)
- if(vent_movement & VENTCRAWL_ALLOWED && istype(L))
- L.handle_ventcrawl(src)
- return
- return ..()
/**
* Getter of a list of pipenets
diff --git a/code/modules/atmospherics/machinery/bluespace_vendor.dm b/code/modules/atmospherics/machinery/bluespace_vendor.dm
index 84753354018..91da04afaf2 100644
--- a/code/modules/atmospherics/machinery/bluespace_vendor.dm
+++ b/code/modules/atmospherics/machinery/bluespace_vendor.dm
@@ -71,7 +71,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/bluespace_vendor, 30)
AddComponent(/datum/component/payment, tank_cost, SSeconomy.get_dep_account(ACCOUNT_ENG), PAYMENT_ANGRY)
find_and_hang_on_wall( FALSE)
-/obj/machinery/bluespace_vendor/LateInitialize()
+/obj/machinery/bluespace_vendor/post_machine_initialize()
. = ..()
if(!map_spawned)
return
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
index c06863ba092..fe6f9423b43 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
@@ -38,13 +38,15 @@ Passive gate is similar to the regular pump except:
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user)
- if(can_interact(user))
- target_pressure = MAX_OUTPUT_PRESSURE
- investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "pressure output set to [target_pressure] kPa")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/passive_gate/click_alt(mob/user)
+ if(target_pressure == MAX_OUTPUT_PRESSURE)
+ return CLICK_ACTION_BLOCKING
+
+ target_pressure = MAX_OUTPUT_PRESSURE
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output set to [target_pressure] kPa")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/passive_gate/update_icon_nopipes()
cut_overlays()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
index 93192073275..c3313322135 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm
@@ -30,13 +30,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/pressure_valve/AltClick(mob/user)
- if(can_interact(user))
- target_pressure = MAX_OUTPUT_PRESSURE
- investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "target pressure set to [target_pressure] kPa")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/pressure_valve/click_alt(mob/user)
+ if(target_pressure == MAX_OUTPUT_PRESSURE)
+ return CLICK_ACTION_BLOCKING
+
+ target_pressure = MAX_OUTPUT_PRESSURE
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "target pressure set to [target_pressure] kPa")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/pressure_valve/update_icon_nopipes()
if(on && is_operational && is_gas_flowing)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index 3c1ba634cae..035f3a0f996 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -43,13 +43,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/pump/AltClick(mob/user)
- if(can_interact(user))
- target_pressure = MAX_OUTPUT_PRESSURE
- investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "pressure output set to [target_pressure] kPa")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/pump/click_alt(mob/user)
+ if(target_pressure == MAX_OUTPUT_PRESSURE)
+ return CLICK_ACTION_BLOCKING
+
+ target_pressure = MAX_OUTPUT_PRESSURE
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output set to [target_pressure] kPa")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/pump/update_icon_nopipes()
icon_state = (on && is_operational) ? "pump_on-[set_overlay_offset(piping_layer)]" : "pump_off-[set_overlay_offset(piping_layer)]"
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
index bbe788bac53..d1202dbec94 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm
@@ -35,13 +35,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/temperature_gate/AltClick(mob/user)
- if(can_interact(user))
- target_temperature = max_temperature
- investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "target temperature set to [target_temperature] K")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/temperature_gate/click_alt(mob/user)
+ if(target_temperature == max_temperature)
+ return CLICK_ACTION_BLOCKING
+
+ target_temperature = max_temperature
+ investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "target temperature set to [target_temperature] K")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/temperature_gate/examine(mob/user)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
index 0fdb5aca6a3..2615b964ed8 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm
@@ -30,13 +30,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/temperature_pump/AltClick(mob/user)
- if(can_interact(user) && !(heat_transfer_rate == max_heat_transfer_rate))
- heat_transfer_rate = max_heat_transfer_rate
- investigate_log("was set to [heat_transfer_rate]% by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "transfer rate set to [heat_transfer_rate]%")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/temperature_pump/click_alt(mob/user)
+ if(heat_transfer_rate == max_heat_transfer_rate)
+ return CLICK_ACTION_BLOCKING
+
+ heat_transfer_rate = max_heat_transfer_rate
+ investigate_log("was set to [heat_transfer_rate]% by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "transfer rate set to [heat_transfer_rate]%")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/temperature_pump/update_icon_nopipes()
icon_state = "tpump_[on && is_operational ? "on" : "off"]-[set_overlay_offset(piping_layer)]"
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
index 139cbe71b36..41dc549b858 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm
@@ -41,13 +41,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/binary/volume_pump/AltClick(mob/user)
- if(can_interact(user))
- transfer_rate = MAX_TRANSFER_RATE
- investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "volume output set to [transfer_rate] L/s")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/binary/volume_pump/click_alt(mob/user)
+ if(transfer_rate == MAX_TRANSFER_RATE)
+ return CLICK_ACTION_BLOCKING
+
+ transfer_rate = MAX_TRANSFER_RATE
+ investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [transfer_rate] L/s")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/binary/volume_pump/update_icon_nopipes()
icon_state = on && is_operational ? "volpump_on-[set_overlay_offset(piping_layer)]" : "volpump_off-[set_overlay_offset(piping_layer)]"
diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm
index 0ab8427c0ae..56ee3c6039d 100644
--- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm
+++ b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm
@@ -187,14 +187,12 @@
return
return ..()
-/obj/machinery/electrolyzer/AltClick(mob/user)
- . = ..()
+/obj/machinery/electrolyzer/click_alt(mob/user)
if(panel_open)
balloon_alert(user, "close panel!")
- return
- if(!can_interact(user))
- return
+ return CLICK_ACTION_BLOCKING
toggle_power(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/electrolyzer/proc/toggle_power(mob/user)
if(!anchored && !cell)
diff --git a/code/modules/atmospherics/machinery/components/tank.dm b/code/modules/atmospherics/machinery/components/tank.dm
index 8df616c179c..a9fcaf93ec6 100644
--- a/code/modules/atmospherics/machinery/components/tank.dm
+++ b/code/modules/atmospherics/machinery/components/tank.dm
@@ -104,7 +104,7 @@
// We late initialize here so all stationary tanks have time to set up their
// initial gas mixes and signal registrations.
-/obj/machinery/atmospherics/components/tank/LateInitialize()
+/obj/machinery/atmospherics/components/tank/post_machine_initialize()
. = ..()
GetMergeGroup(merger_id, merger_typecache)
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 1727d4877b5..c6b4bd43be4 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -32,13 +32,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/trinary/filter/AltClick(mob/user)
- if(can_interact(user))
- transfer_rate = MAX_TRANSFER_RATE
- investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "volume output set to [transfer_rate] L/s")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/trinary/filter/click_alt(mob/user)
+ if(transfer_rate == MAX_TRANSFER_RATE)
+ return CLICK_ACTION_BLOCKING
+
+ transfer_rate = MAX_TRANSFER_RATE
+ investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [transfer_rate] L/s")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/trinary/filter/update_overlays()
. = ..()
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
index 862fbc65c89..f832adcb4ea 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm
@@ -35,13 +35,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user)
- if(can_interact(user))
- target_pressure = MAX_OUTPUT_PRESSURE
- investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "pressure output on set to [target_pressure] kPa")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/trinary/mixer/click_alt(mob/user)
+ if(target_pressure == MAX_OUTPUT_PRESSURE)
+ return CLICK_ACTION_BLOCKING
+
+ target_pressure = MAX_OUTPUT_PRESSURE
+ investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "pressure output on set to [target_pressure] kPa")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/trinary/mixer/update_overlays()
. = ..()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 71610f05f40..ac88174dbc4 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -645,14 +645,13 @@
balloon_alert(user, "turned [on ? "on" : "off"]")
return ..()
-/obj/machinery/cryo_cell/AltClick(mob/user)
- if(can_interact(user))
- if(state_open)
- close_machine()
- else
- open_machine()
- balloon_alert(user, "door [state_open ? "opened" : "closed"]")
- return ..()
+/obj/machinery/cryo_cell/click_alt(mob/user)
+ if(state_open)
+ close_machine()
+ else
+ open_machine()
+ balloon_alert(user, "door [state_open ? "opened" : "closed"]")
+ return CLICK_ACTION_SUCCESS
/obj/machinery/cryo_cell/get_remote_view_fullscreens(mob/user)
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index 4161a30ed7d..771301b60e4 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -62,13 +62,15 @@
update_appearance()
return ..()
-/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user)
- if(can_interact(user))
- volume_rate = MAX_TRANSFER_RATE
- investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
- balloon_alert(user, "volume output set to [volume_rate] L/s")
- update_appearance()
- return ..()
+/obj/machinery/atmospherics/components/unary/outlet_injector/click_alt(mob/user)
+ if(volume_rate == MAX_TRANSFER_RATE)
+ return CLICK_ACTION_BLOCKING
+
+ volume_rate = MAX_TRANSFER_RATE
+ investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
+ balloon_alert(user, "volume output set to [volume_rate] L/s")
+ update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/atmospherics/components/unary/outlet_injector/update_icon_nopipes()
cut_overlays()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
index 17f6c761f12..4ac0e959e40 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
@@ -12,6 +12,8 @@
pipe_state = "pvent"
has_cap_visuals = TRUE
vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
+ interaction_flags_click = NEED_VENTCRAWL
+
/obj/machinery/atmospherics/components/unary/passive_vent/update_icon_nopipes()
cut_overlays()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
index 0af962ac0f3..01def672bf7 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm
@@ -144,12 +144,10 @@
. += span_notice("Heat capacity at [heat_capacity] Joules per Kelvin.")
. += span_notice("Temperature range [min_temperature]K - [max_temperature]K ([(T0C-min_temperature)*-1]C - [(T0C-max_temperature)*-1]C).")
-/obj/machinery/atmospherics/components/unary/thermomachine/AltClick(mob/living/user)
+/obj/machinery/atmospherics/components/unary/thermomachine/click_alt(mob/living/user)
if(panel_open)
balloon_alert(user, "close panel!")
- return
- if(!can_interact(user))
- return
+ return CLICK_ACTION_BLOCKING
if(target_temperature == T20C)
target_temperature = max_temperature
@@ -161,6 +159,7 @@
investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
balloon_alert(user, "temperature reset to [target_temperature] K")
update_appearance()
+ return CLICK_ACTION_SUCCESS
/// Performs heat calculation for the freezer.
/// We just equalize the gasmix with an object at temp = var/target_temperature and heat cap = var/heat_capacity
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
index 4d876fd4586..c8bfd8628e9 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
@@ -17,6 +17,12 @@
..()
update_appearance()
+
+/obj/machinery/atmospherics/components/unary/click_alt(mob/living/beno)
+ beno.handle_ventcrawl(src)
+ return CLICK_ACTION_SUCCESS
+
+
/obj/machinery/atmospherics/components/unary/proc/assign_uid_vents()
uid = num2text(gl_uid++)
return uid
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 e49dc3e62d3..330e00edfd3 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -18,6 +18,7 @@
vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
// vents are more complex machinery and so are less resistant to damage
max_integrity = 100
+ interaction_flags_click = NEED_VENTCRAWL
///Direction of pumping the gas (ATMOS_DIRECTION_RELEASING or ATMOS_DIRECTION_SIPHONING)
var/pump_direction = ATMOS_DIRECTION_RELEASING
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 54704dcb5b6..0871053106f 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -15,6 +15,7 @@
has_cap_visuals = TRUE
vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED
processing_flags = NONE
+ interaction_flags_click = NEED_VENTCRAWL
///The mode of the scrubber (ATMOS_DIRECTION_SCRUBBING or ATMOS_DIRECTION_SIPHONING)
var/scrubbing = ATMOS_DIRECTION_SCRUBBING
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index ee1d052b7ed..97bff1ddaea 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -22,7 +22,9 @@
/obj/machinery/meter/Destroy()
SSair.stop_processing_machine(src)
- target = null
+ if(!isnull(target))
+ UnregisterSignal(target, COMSIG_QDELETING)
+ target = null
return ..()
/obj/machinery/meter/Initialize(mapload, new_piping_layer)
@@ -45,8 +47,14 @@
candidate = pipe
if(candidate)
target = candidate
+ RegisterSignal(target, COMSIG_QDELETING, PROC_REF(drop_meter))
setAttachLayer(candidate.piping_layer)
+///Called when the parent pipe is removed
+/obj/machinery/meter/proc/drop_meter()
+ SIGNAL_HANDLER
+ deconstruct(FALSE)
+
/obj/machinery/meter/proc/setAttachLayer(new_layer)
target_layer = new_layer
PIPING_LAYER_DOUBLE_SHIFT(src, target_layer)
@@ -135,7 +143,8 @@
return TRUE
/obj/machinery/meter/on_deconstruction(disassembled)
- new /obj/item/pipe_meter(loc)
+ var/obj/item/pipe_meter/meter_object = new /obj/item/pipe_meter(get_turf(src))
+ transfer_fingerprints_to(meter_object)
/obj/machinery/meter/interact(mob/user)
if(machine_stat & (NOPOWER|BROKEN))
diff --git a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm
index 6b1997cc3c7..75c85d2a665 100644
--- a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm
@@ -1,7 +1,4 @@
-/client/proc/GeneratePipeSpritesheet()
- set name = "Generate Pipe Spritesheet"
- set category = "Debug"
-
+ADMIN_VERB(generate_pipe_spritesheet, R_DEBUG, "Generate Pipe Spritesheet", "Generates the pipe spritesheets.", ADMIN_CATEGORY_DEBUG)
var/datum/pipe_icon_generator/generator = new
generator.Start()
fcopy(generator.generated_icons, "icons/obj/pipes_n_cables/!pipes_bitmask.dmi")
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index c0dc18c0e8e..574daa2af3a 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -34,18 +34,13 @@
if(hide)
AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works
-/obj/machinery/atmospherics/pipe/Destroy()
- QDEL_NULL(parent)
-
+/obj/machinery/atmospherics/pipe/on_deconstruction(disassembled)
releaseAirToTurf()
- var/turf/local_turf = loc
- for(var/obj/machinery/meter/meter in local_turf)
- if(meter.target != src)
- continue
- var/obj/item/pipe_meter/meter_object = new (local_turf)
- meter.transfer_fingerprints_to(meter_object)
- qdel(meter)
+ return ..()
+
+/obj/machinery/atmospherics/pipe/Destroy()
+ QDEL_NULL(parent)
return ..()
//-----------------
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 389de6e3701..3713958fbaa 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -8,6 +8,7 @@
armor_type = /datum/armor/machinery_portable_atmospherics
anchored = FALSE
layer = ABOVE_OBJ_LAYER
+ interaction_flags_click = NEED_DEXTERITY
///Stores the gas mixture of the portable component. Don't access this directly, use return_air() so you support the temporary processing it provides
var/datum/gas_mixture/air_contents
@@ -46,14 +47,17 @@
AddElement(/datum/element/climbable, climb_time = 3 SECONDS, climb_stun = 3 SECONDS)
AddElement(/datum/element/elevation, pixel_shift = 8)
+/obj/machinery/portable_atmospherics/on_deconstruction(disassembled)
+ if(nob_crystal_inserted)
+ new /obj/item/hypernoblium_crystal(src)
+
+ return ..()
+
/obj/machinery/portable_atmospherics/Destroy()
disconnect()
air_contents = null
SSair.stop_processing_machine(src)
- if(nob_crystal_inserted)
- new /obj/item/hypernoblium_crystal(src)
-
return ..()
/obj/machinery/portable_atmospherics/examine(mob/user)
@@ -159,14 +163,12 @@
update_appearance()
return TRUE
-/obj/machinery/portable_atmospherics/AltClick(mob/living/user)
- . = ..()
- if(!istype(user) || !user.can_perform_action(src, NEED_DEXTERITY) || !can_interact(user))
- return
+/obj/machinery/portable_atmospherics/click_alt(mob/living/user)
if(!holding)
- return
+ return CLICK_ACTION_BLOCKING
to_chat(user, span_notice("You remove [holding] from [src]."))
replace_tank(user, TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/portable_atmospherics/examine(mob/user)
. = ..()
diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm
index e7dfc229a39..7b0dbef314e 100644
--- a/code/modules/atmospherics/machinery/portable/pump.dm
+++ b/code/modules/atmospherics/machinery/portable/pump.dm
@@ -12,7 +12,7 @@
volume = 1000
-/obj/machinery/portable_atmospherics/pump/Destroy()
+/obj/machinery/portable_atmospherics/pump/on_deconstruction(disassembled)
var/turf/local_turf = get_turf(src)
local_turf.assume_air(air_contents)
return ..()
diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm
index 576dff39a8d..336cdc4829f 100644
--- a/code/modules/atmospherics/machinery/portable/scrubber.dm
+++ b/code/modules/atmospherics/machinery/portable/scrubber.dm
@@ -31,9 +31,9 @@
/datum/gas/halon,
)
-/obj/machinery/portable_atmospherics/scrubber/Destroy()
- var/turf/T = get_turf(src)
- T.assume_air(air_contents)
+/obj/machinery/portable_atmospherics/scrubber/on_deconstruction(disassembled)
+ var/turf/local_turf = get_turf(src)
+ local_turf.assume_air(air_contents)
return ..()
/obj/machinery/portable_atmospherics/scrubber/update_icon_state()
diff --git a/code/modules/awaymissions/mission_code/murderdome.dm b/code/modules/awaymissions/mission_code/murderdome.dm
index 520372e68ac..a59a491d492 100644
--- a/code/modules/awaymissions/mission_code/murderdome.dm
+++ b/code/modules/awaymissions/mission_code/murderdome.dm
@@ -1,20 +1,27 @@
/obj/structure/window/reinforced/fulltile/indestructible
name = "robust window"
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
flags_1 = PREVENT_CLICK_UNDER_1
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
-/obj/structure/window/reinforced/fulltile/indestructible/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
- return FALSE
+/obj/structure/window/reinforced/fulltile/indestructible/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+/obj/structure/window/reinforced/fulltile/indestructible/wrench_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/structure/window/reinforced/fulltile/indestructible/crowbar_act(mob/living/user, obj/item/tool)
+ return NONE
/obj/structure/grille/indestructible
- obj_flags = CONDUCTS_ELECTRICITY | NO_DECONSTRUCTION
+ obj_flags = CONDUCTS_ELECTRICITY
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
-/obj/structure/grille/indestructible/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
- return FALSE
+/obj/structure/grille/indestructible/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/structure/grille/indestructible/wirecutter_act(mob/living/user, obj/item/tool)
+ return NONE
/obj/effect/spawner/structure/window/reinforced/indestructible
spawn_list = list(/obj/structure/grille/indestructible, /obj/structure/window/reinforced/fulltile/indestructible)
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index 2b8d4e80663..cc35b4a79ef 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -369,7 +369,7 @@
/obj/structure/barricade/wooden/snowed
name = "crude plank barricade"
desc = "This space is blocked off by a wooden barricade. It seems to be covered in a layer of snow."
- icon_state = "woodenbarricade-snow"
+ icon_state = "woodenbarricade_snow"
max_integrity = 125
/obj/item/clothing/under/syndicate/coldres
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index c4bb2d17610..0fdc5093511 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -62,10 +62,10 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generate_map_list_from_directory(
var/name = null
if (pos)
- name = lowertext(copytext(t, 1, pos))
+ name = LOWER_TEXT(copytext(t, 1, pos))
else
- name = lowertext(t)
+ name = LOWER_TEXT(t)
if (!name)
continue
diff --git a/code/modules/bitrunning/objects/byteforge.dm b/code/modules/bitrunning/objects/byteforge.dm
index f8212b7666b..b971cdae75d 100644
--- a/code/modules/bitrunning/objects/byteforge.dm
+++ b/code/modules/bitrunning/objects/byteforge.dm
@@ -14,7 +14,7 @@
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/byteforge/LateInitialize()
+/obj/machinery/byteforge/post_machine_initialize()
. = ..()
setup_particles()
diff --git a/code/modules/bitrunning/objects/disks.dm b/code/modules/bitrunning/objects/disks.dm
index d6b44a60518..6e166d5eb7f 100644
--- a/code/modules/bitrunning/objects/disks.dm
+++ b/code/modules/bitrunning/objects/disks.dm
@@ -48,7 +48,7 @@
names += initial(thing.name)
var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names)
- if(isnull(choice))
+ if(isnull(choice) || !user.is_holding(src))
return
for(var/datum/action/thing as anything in selectable_actions)
@@ -105,7 +105,7 @@
names += initial(thing.name)
var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names)
- if(isnull(choice))
+ if(isnull(choice) || !user.is_holding(src))
return
for(var/obj/thing as anything in selectable_items)
diff --git a/code/modules/bitrunning/objects/netpod.dm b/code/modules/bitrunning/objects/netpod.dm
index 5c8e399292f..a1a681cab05 100644
--- a/code/modules/bitrunning/objects/netpod.dm
+++ b/code/modules/bitrunning/objects/netpod.dm
@@ -24,12 +24,7 @@
/// Static list of outfits to select from
var/list/cached_outfits = list()
-/obj/machinery/netpod/Initialize(mapload)
- . = ..()
-
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/netpod/LateInitialize()
+/obj/machinery/netpod/post_machine_initialize()
. = ..()
disconnect_damage = BASE_DISCONNECT_DAMAGE
diff --git a/code/modules/bitrunning/objects/quantum_console.dm b/code/modules/bitrunning/objects/quantum_console.dm
index 9dc829c48cd..9a0f48ae80b 100644
--- a/code/modules/bitrunning/objects/quantum_console.dm
+++ b/code/modules/bitrunning/objects/quantum_console.dm
@@ -12,11 +12,8 @@
. = ..()
desc = "Even in the distant year [CURRENT_STATION_YEAR], Nanostrasen is still using REST APIs. How grim."
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/computer/quantum_console/LateInitialize()
+/obj/machinery/computer/quantum_console/post_machine_initialize()
. = ..()
-
find_server()
/obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui)
diff --git a/code/modules/bitrunning/server/_parent.dm b/code/modules/bitrunning/server/_parent.dm
index b9d8808607e..06b49d790a5 100644
--- a/code/modules/bitrunning/server/_parent.dm
+++ b/code/modules/bitrunning/server/_parent.dm
@@ -49,12 +49,7 @@
/// Cooldown between being able to toggle broadcasting
COOLDOWN_DECLARE(broadcast_toggle_cd)
-/obj/machinery/quantum_server/Initialize(mapload)
- . = ..()
-
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/quantum_server/LateInitialize()
+/obj/machinery/quantum_server/post_machine_initialize()
. = ..()
radio = new(src)
diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm
index e3b9fb37869..38a7318b554 100644
--- a/code/modules/capture_the_flag/ctf_game.dm
+++ b/code/modules/capture_the_flag/ctf_game.dm
@@ -221,7 +221,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/item/ctf_flag/LateInitialize()
- . = ..()
ctf_game = GLOB.ctf_games[game_id] //Flags don't create ctf games by themselves since you can get ctf flags from christmas trees.
/obj/item/ctf_flag/Destroy()
@@ -464,7 +463,12 @@
/obj/structure/table/reinforced/ctf
resistance_flags = INDESTRUCTIBLE
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+
+/obj/structure/table/reinforced/ctf/wrench_act_secondary(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/structure/table/reinforced/ctf/screwdriver_act_secondary(mob/living/user, obj/item/tool)
+ return NONE
#define CTF_LOADING_UNLOADED 0
#define CTF_LOADING_LOADING 1
diff --git a/code/modules/capture_the_flag/medieval_sim/medisim_game.dm b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm
index 3546ce0881d..18e1cd13e7e 100644
--- a/code/modules/capture_the_flag/medieval_sim/medisim_game.dm
+++ b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm
@@ -12,9 +12,8 @@
/obj/machinery/ctf/spawner/medisim/Initialize(mapload)
. = ..()
ctf_game.setup_rules(victory_rejoin_text = "Teams have been cleared. The next game is starting automatically. Rejoin a team if you wish!", auto_restart = TRUE)
- return INITIALIZE_HINT_LATELOAD //Start CTF needs to run after both medisim spawners have initalized.
-/obj/machinery/ctf/spawner/medisim/LateInitialize()
+/obj/machinery/ctf/spawner/medisim/post_machine_initialize()
. = ..()
ctf_game.start_ctf()
diff --git a/code/modules/cards/deck/deck.dm b/code/modules/cards/deck/deck.dm
index 47f45eeb5ab..54f8a5feba6 100644
--- a/code/modules/cards/deck/deck.dm
+++ b/code/modules/cards/deck/deck.dm
@@ -11,6 +11,7 @@
hitsound = null
attack_verb_continuous = list("attacks")
attack_verb_simple = list("attack")
+ interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH
/// The amount of time it takes to shuffle
var/shuffle_time = DECK_SHUFFLE_TIME
/// Deck shuffling cooldown.
@@ -145,13 +146,13 @@
attack_hand(user, modifiers, flip_card = TRUE)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-/obj/item/toy/cards/deck/AltClick(mob/living/user)
- if(user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH))
- if(HAS_TRAIT(src, TRAIT_WIELDED))
- shuffle_cards(user)
- else
- to_chat(user, span_notice("You must hold the [src] with both hands to shuffle."))
- return ..()
+/obj/item/toy/cards/deck/click_alt(mob/living/user)
+ if(!HAS_TRAIT(src, TRAIT_WIELDED))
+ to_chat(user, span_notice("You must hold the [src] with both hands to shuffle."))
+ return CLICK_ACTION_BLOCKING
+
+ shuffle_cards(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/toy/cards/deck/update_icon_state()
switch(count_cards())
diff --git a/code/modules/cards/singlecard.dm b/code/modules/cards/singlecard.dm
index 169715c51d9..e03c5800346 100644
--- a/code/modules/cards/singlecard.dm
+++ b/code/modules/cards/singlecard.dm
@@ -14,6 +14,7 @@
throw_range = 7
attack_verb_continuous = list("attacks")
attack_verb_simple = list("attack")
+ interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH
/// Artistic style of the deck
var/deckstyle = "nanotrasen"
/// If the cards in the deck have different icon states (blank and CAS decks do not)
@@ -237,8 +238,7 @@
if(isturf(src.loc)) // only display tihs message when flipping in a visible spot like on a table
user.balloon_alert_to_viewers("flips a card")
-/obj/item/toy/singlecard/AltClick(mob/living/carbon/human/user)
- if(user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH))
- transform = turn(transform, 90)
+/obj/item/toy/singlecard/click_alt(mob/living/carbon/human/user)
+ transform = turn(transform, 90)
// use the simple_rotation component to make this turn with Alt+RMB & Alt+LMB at some point in the future - TimT
- return ..()
+ return CLICK_ACTION_SUCCESS
diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm
index 7d345802eef..636b4f4791b 100644
--- a/code/modules/cargo/bounties/assistant.dm
+++ b/code/modules/cargo/bounties/assistant.dm
@@ -257,7 +257,7 @@
..()
fluid_type = pick(AQUARIUM_FLUID_FRESHWATER, AQUARIUM_FLUID_SALTWATER, AQUARIUM_FLUID_SULPHWATEVER)
name = "[fluid_type] Fish"
- description = "We need [lowertext(fluid_type)] fish to populate our aquariums with. Fishes that are dead or bought from cargo will only be paid half as much."
+ description = "We need [LOWER_TEXT(fluid_type)] fish to populate our aquariums with. Fishes that are dead or bought from cargo will only be paid half as much."
/datum/bounty/item/assistant/fish/fluid/can_ship_fish(obj/item/fish/fishie)
return compatible_fluid_type(fishie.required_fluid_type, fluid_type)
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 218aed8c681..cf4a5dfc875 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -16,11 +16,8 @@
//The user can change properties of the supplypod using the UI, and change the way that items are taken from the bay (One at a time, ordered, random, etc)
//Many of the effects of the supplypod set here are put into action in supplypod.dm
-/client/proc/centcom_podlauncher() //Creates a verb for admins to open up the ui
- set name = "Config/Launch Supplypod"
- set desc = "Configure and launch a CentCom supplypod full of whatever your heart desires!"
- set category = "Admin.Events"
- new /datum/centcom_podlauncher(usr)//create the datum
+ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure and launch a CentCom supplypod full of whatever your heart desires!", ADMIN_CATEGORY_EVENTS)
+ new /datum/centcom_podlauncher(user.mob)
//Variables declared to change how items in the launch bay are picked and launched. (Almost) all of these are changed in the ui_act proc
//Some effect groups are choices, while other are booleans. This is because some effects can stack, while others dont (ex: you can stack explosion and quiet, but you cant stack ordered launch and random launch)
diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm
index e23e6112a4b..de84a263597 100644
--- a/code/modules/cargo/packs/costumes_toys.dm
+++ b/code/modules/cargo/packs/costumes_toys.dm
@@ -268,3 +268,15 @@
crate_name = "corgi pinata kit"
crate_type = /obj/structure/closet/crate/wooden
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
+
+/datum/supply_pack/costumes_toys/balloons
+ name = "Long Balloons Kit"
+ desc = "This crate contains a box of long balloons, plus a skillchip for non-clowns to join the fun! Extra layer of safety so clowns at CentCom won't get to them."
+ cost = CARGO_CRATE_VALUE * 4
+ contains = list(
+ /obj/item/storage/box/balloons,
+ /obj/item/skillchip/job/clown,
+ )
+ crate_name = "long balloons kit"
+ crate_type = /obj/structure/closet/crate/wooden
+ discountable = SUPPLY_PACK_STD_DISCOUNTABLE
diff --git a/code/modules/cargo/supplypod_beacon.dm b/code/modules/cargo/supplypod_beacon.dm
index 999e7d76eec..8f1166002de 100644
--- a/code/modules/cargo/supplypod_beacon.dm
+++ b/code/modules/cargo/supplypod_beacon.dm
@@ -9,9 +9,14 @@
w_class = WEIGHT_CLASS_SMALL
armor_type = /datum/armor/supplypod_beacon
resistance_flags = FIRE_PROOF
+ interaction_flags_click = ALLOW_SILICON_REACH
+ /// The linked console
var/obj/machinery/computer/cargo/express/express_console
+ /// If linked
var/linked = FALSE
+ /// If this is ready to launch
var/ready = FALSE
+ /// If it's been launched
var/launched = FALSE
/datum/armor/supplypod_beacon
@@ -90,13 +95,12 @@
update_status(SP_READY)
to_chat(user, span_notice("[src] linked to [C]."))
-/obj/item/supplypod_beacon/AltClick(mob/user)
- if (!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
- if (express_console)
- unlink_console()
- else
+/obj/item/supplypod_beacon/click_alt(mob/user)
+ if(!express_console)
to_chat(user, span_alert("There is no linked console."))
+ return CLICK_ACTION_BLOCKING
+ unlink_console()
+ return CLICK_ACTION_SUCCESS
/obj/item/supplypod_beacon/attackby(obj/item/W, mob/user)
if(!istype(W, /obj/item/pen)) //give a tag that is visible from the linked express console
diff --git a/code/modules/cargo/universal_scanner.dm b/code/modules/cargo/universal_scanner.dm
index 68fe533959a..80a821a1f5e 100644
--- a/code/modules/cargo/universal_scanner.dm
+++ b/code/modules/cargo/universal_scanner.dm
@@ -129,15 +129,15 @@
payments_acc = null
to_chat(user, span_notice("You clear the registered account."))
-/obj/item/universal_scanner/AltClick(mob/user)
- . = ..()
+/obj/item/universal_scanner/click_alt(mob/user)
if(!scanning_mode == SCAN_SALES_TAG)
- return
+ return CLICK_ACTION_BLOCKING
var/potential_cut = input("How much would you like to pay out to the registered card?","Percentage Profit ([round(cut_min*100)]% - [round(cut_max*100)]%)") as num|null
if(!potential_cut)
cut_multiplier = initial(cut_multiplier)
cut_multiplier = clamp(round(potential_cut/100, cut_min), cut_min, cut_max)
to_chat(user, span_notice("[round(cut_multiplier*100)]% profit will be received if a package with a barcode is sold."))
+ return CLICK_ACTION_SUCCESS
/obj/item/universal_scanner/examine(mob/user)
. = ..()
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 45ccda8b92b..3272620a865 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -194,8 +194,6 @@
var/list/spell_tabs = list()
///A lazy list of atoms we've examined in the last RECENT_EXAMINE_MAX_WINDOW (default 2) seconds, so that we will call [/atom/proc/examine_more] instead of [/atom/proc/examine] on them when examining
var/list/recent_examines
- ///Our object window datum. It stores info about and handles behavior for the object tab
- var/datum/object_window_info/obj_window
var/list/parallax_layers
var/list/parallax_layers_cached
@@ -266,3 +264,6 @@
/// Does this client have typing indicators enabled?
var/typing_indicators = FALSE
+
+ /// Loot panel for the client
+ var/datum/lootpanel/loot_panel
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 9523d4d52c6..b25d7c2e5ae 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -38,7 +38,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
//SKYRAT EDIT ADDITION END
#ifndef TESTING
- if (lowertext(hsrc_command) == "_debug") //disable the integrated byond vv in the client side debugging tools since it doesn't respect vv read protections
+ if (LOWER_TEXT(hsrc_command) == "_debug") //disable the integrated byond vv in the client side debugging tools since it doesn't respect vv read protections
return
#endif
@@ -157,6 +157,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! Click Here to find out more.")
return FALSE
return TRUE
+
+/client/proc/is_localhost()
+ var/static/localhost_addresses = list(
+ "127.0.0.1",
+ "::1",
+ null,
+ )
+ return address in localhost_addresses
+
/*
* Call back proc that should be checked in all paths where a client can send messages
*
@@ -254,32 +263,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.ahelp_tickets.ClientLogin(src)
GLOB.interviews.client_login(src)
GLOB.requests.client_login(src)
- var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
- //Admin Authorisation
- var/datum/admins/admin_datum = GLOB.admin_datums[ckey]
- if (!isnull(admin_datum))
- admin_datum.associate(src)
- connecting_admin = TRUE
- else if(GLOB.deadmins[ckey])
- add_verb(src, /client/proc/readmin)
- connecting_admin = TRUE
- //SKYRAT EDIT ADDITION //We will check the population here, because we need to know if the client is an admin or not.
- if(!check_population(connecting_admin))
- qdel(src)
- return
- // SKYRAT EDIT END
- if(CONFIG_GET(flag/autoadmin))
- if(!GLOB.admin_datums[ckey])
- var/list/autoadmin_ranks = ranks_from_rank_name(CONFIG_GET(string/autoadmin_rank))
- if (autoadmin_ranks.len == 0)
- to_chat(world, "Autoadmin rank not found")
- else
- new /datum/admins(autoadmin_ranks, ckey)
- if(CONFIG_GET(flag/enable_localhost_rank) && !connecting_admin)
- var/localhost_addresses = list("127.0.0.1", "::1")
- if(isnull(address) || (address in localhost_addresses))
- var/datum/admin_rank/localhost_rank = new("!localhost!", R_EVERYTHING, R_DBRANKS, R_EVERYTHING) //+EVERYTHING -DBRANKS *EVERYTHING
- new /datum/admins(list(localhost_rank), ckey, 1, 1)
//preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum)
prefs = GLOB.preferences_datums[ckey]
if(prefs)
@@ -352,6 +335,34 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
. = ..() //calls mob.Login()
+
+ // Admin Verbs need the client's mob to exist. Must be after ..()
+ var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
+ //Admin Authorisation
+ var/datum/admins/admin_datum = GLOB.admin_datums[ckey]
+ if (!isnull(admin_datum))
+ admin_datum.associate(src)
+ connecting_admin = TRUE
+ else if(GLOB.deadmins[ckey])
+ add_verb(src, /client/proc/readmin)
+ connecting_admin = TRUE
+ //SKYRAT EDIT ADDITION //We will check the population here, because we need to know if the client is an admin or not.
+ if(!check_population(connecting_admin))
+ qdel(src)
+ return
+ // SKYRAT EDIT END
+ if(CONFIG_GET(flag/autoadmin))
+ if(!GLOB.admin_datums[ckey])
+ var/list/autoadmin_ranks = ranks_from_rank_name(CONFIG_GET(string/autoadmin_rank))
+ if (autoadmin_ranks.len == 0)
+ to_chat(world, "Autoadmin rank not found")
+ else
+ new /datum/admins(autoadmin_ranks, ckey)
+
+ if(CONFIG_GET(flag/enable_localhost_rank) && !connecting_admin && is_localhost())
+ var/datum/admin_rank/localhost_rank = new("!localhost!", R_EVERYTHING, R_DBRANKS, R_EVERYTHING) //+EVERYTHING -DBRANKS *EVERYTHING
+ new /datum/admins(list(localhost_rank), ckey, 1, 1)
+
if (length(GLOB.stickybanadminexemptions))
GLOB.stickybanadminexemptions -= ckey
if (!length(GLOB.stickybanadminexemptions))
@@ -538,6 +549,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if (!interviewee)
initialize_menus()
+ loot_panel = new(src)
+
view_size = new(src, getScreenSize(prefs.read_preference(/datum/preference/toggle/widescreen)))
view_size.resetFormat()
view_size.setZoomMode()
@@ -578,8 +591,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
SSserver_maint.UpdateHubStatus()
if(credits)
QDEL_LIST(credits)
- if(obj_window)
- QDEL_NULL(obj_window)
if(holder)
adminGreet(1)
holder.owner = null
@@ -610,6 +621,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
QDEL_NULL(void)
QDEL_NULL(tooltips)
QDEL_NULL(open_loadout_ui) //SKYRAT EDIT ADDITION
+ QDEL_NULL(loot_panel)
seen_messages = null
Master.UpdateTickRate()
..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening
@@ -1201,7 +1213,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
return 0
if(!isnum(player_age) || player_age < 0)
- return 0
+ return 0
if(!isnum(days_needed))
return 0
@@ -1211,13 +1223,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/// Attempts to make the client orbit the given object, for administrative purposes.
/// If they are not an observer, will try to aghost them.
/client/proc/admin_follow(atom/movable/target)
- var/can_ghost = TRUE
-
- if (!isobserver(mob))
- can_ghost = admin_ghost()
-
- if(!can_ghost)
- return FALSE
+ if(!isobserver(mob))
+ SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/admin_ghost)
+ if(!isobserver(mob))
+ return
var/mob/dead/observer/observer = mob
observer.ManualFollow(target)
diff --git a/code/modules/client/preferences/glasses.dm b/code/modules/client/preferences/glasses.dm
index 03c975abce7..a08f15955ea 100644
--- a/code/modules/client/preferences/glasses.dm
+++ b/code/modules/client/preferences/glasses.dm
@@ -11,7 +11,7 @@
if (value == "Random")
return icon('icons/effects/random_spawners.dmi', "questionmark")
else
- return icon('icons/obj/clothing/glasses.dmi', "glasses_[lowertext(value)]")
+ return icon('icons/obj/clothing/glasses.dmi', "glasses_[LOWER_TEXT(value)]")
/datum/preference/choiced/glasses/is_accessible(datum/preferences/preferences)
if (!..(preferences))
diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm
index b3bc613d2ee..abd9495d09a 100644
--- a/code/modules/client/preferences/middleware/antags.dm
+++ b/code/modules/client/preferences/middleware/antags.dm
@@ -180,4 +180,4 @@ GLOBAL_LIST_INIT(non_ruleset_antagonists, list(
/// Serializes an antag name to be used for preferences UI
/proc/serialize_antag_name(antag_name)
// These are sent through CSS, so they need to be safe to use as class names.
- return lowertext(sanitize_css_class_name(antag_name))
+ return LOWER_TEXT(sanitize_css_class_name(antag_name))
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index dc55b72b09d..4ca59bf0f3e 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -144,33 +144,28 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
set category = "Server"
if(IsAdminAdvancedProcCall())
return
- var/newColor = input(src, "Please select the new player OOC color.", "OOC color") as color|null
+
+ADMIN_VERB(set_ooc_color, R_FUN, "Set Player OOC Color", "Modifies the global OOC color.", ADMIN_CATEGORY_SERVER)
+ var/newColor = input(user, "Please select the new player OOC color.", "OOC color") as color|null
if(isnull(newColor))
return
- if(!check_rights(R_FUN))
- message_admins("[usr.key] has attempted to use the Set Player OOC Color verb!")
- log_admin("[key_name(usr)] tried to set player ooc color without authorization.")
- return
var/new_color = sanitize_color(newColor)
- message_admins("[key_name_admin(usr)] has set the players' ooc color to [new_color].")
- log_admin("[key_name_admin(usr)] has set the player ooc color to [new_color].")
+ message_admins("[key_name_admin(user)] has set the players' ooc color to [new_color].")
+ log_admin("[key_name_admin(user)] has set the player ooc color to [new_color].")
GLOB.OOC_COLOR = new_color
-
/client/proc/reset_ooc()
set name = "Reset Player OOC Color"
set desc = "Returns player OOC Color to default"
set category = "Server"
if(IsAdminAdvancedProcCall())
return
- if(tgui_alert(usr, "Are you sure you want to reset the OOC color of all players?", "Reset Player OOC Color", list("Yes", "No")) != "Yes")
+
+ADMIN_VERB(reset_ooc_color, R_FUN, "Reset Player OOC Color", "Returns player OOC color to default.", ADMIN_CATEGORY_SERVER)
+ if(tgui_alert(user, "Are you sure you want to reset the OOC color of all players?", "Reset Player OOC Color", list("Yes", "No")) != "Yes")
return
- if(!check_rights(R_FUN))
- message_admins("[usr.key] has attempted to use the Reset Player OOC Color verb!")
- log_admin("[key_name(usr)] tried to reset player ooc color without authorization.")
- return
- message_admins("[key_name_admin(usr)] has reset the players' ooc color.")
- log_admin("[key_name_admin(usr)] has reset player ooc color.")
+ message_admins("[key_name_admin(user)] has reset the players' ooc color.")
+ log_admin("[key_name_admin(user)] has reset player ooc color.")
GLOB.OOC_COLOR = null
//Checks admin notice
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 81e87e84baa..c44d5be4ef8 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -65,23 +65,19 @@
H.set_eye_blur_if_lower(10 SECONDS)
eyes.apply_organ_damage(5)
-/obj/item/clothing/glasses/AltClick(mob/user)
- . = ..() //SKYRAT EDIT ADDITION
- if(glass_colour_type && !forced_glass_color && ishuman(user))
- var/mob/living/carbon/human/human_user = user
+/obj/item/clothing/glasses/click_alt(mob/user)
+ if(isnull(glass_colour_type) || forced_glass_color || !ishuman(user))
+ return NONE
+ var/mob/living/carbon/human/human_user = user
- if (human_user.glasses != src)
- return ..()
-
- if (HAS_TRAIT_FROM(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT))
- REMOVE_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)
- to_chat(human_user, span_notice("You will no longer see glasses colors."))
- else
- ADD_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)
- to_chat(human_user, span_notice("You will now see glasses colors."))
- human_user.update_glasses_color(src, TRUE)
+ if (HAS_TRAIT_FROM(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT))
+ REMOVE_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)
+ to_chat(human_user, span_notice("You will no longer see glasses colors."))
else
- return ..()
+ ADD_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)
+ to_chat(human_user, span_notice("You will now see glasses colors."))
+ human_user.update_glasses_color(src, TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/glasses/proc/change_glass_color(mob/living/carbon/human/H, datum/client_colour/glass_colour/new_color_type)
var/old_colour_type = glass_colour_type
@@ -664,18 +660,19 @@
var/datum/atom_hud/our_hud = GLOB.huds[hud]
our_hud.hide_from(user)
-/obj/item/clothing/glasses/debug/AltClick(mob/user)
- . = ..()
- if(ishuman(user))
- if(xray)
- vision_flags &= ~SEE_MOBS|SEE_OBJS
- REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
- else
- vision_flags |= SEE_MOBS|SEE_OBJS
- ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
- xray = !xray
- var/mob/living/carbon/human/human_user = user
- human_user.update_sight()
+/obj/item/clothing/glasses/debug/click_alt(mob/user)
+ if(!ishuman(user))
+ return CLICK_ACTION_BLOCKING
+ if(xray)
+ vision_flags &= ~SEE_MOBS|SEE_OBJS
+ REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
+ else
+ vision_flags |= SEE_MOBS|SEE_OBJS
+ ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT)
+ xray = !xray
+ var/mob/living/carbon/human/human_user = user
+ human_user.update_sight()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/glasses/regular/kim
name = "binoclard lenses"
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index 0c48cb102b2..5f63e0c3464 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -16,6 +16,8 @@
attack_verb_simple = list("challenge")
strip_delay = 20
equip_delay_other = 40
+ article = "a pair of"
+
// Path variable. If defined, will produced the type through interaction with wirecutters.
var/cut_type = null
/// Used for handling bloody gloves leaving behind bloodstains on objects. Will be decremented whenever a bloodstain is left behind, and be incremented when the gloves become bloody.
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 7741251f3f5..236d94c39fa 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -195,6 +195,21 @@
acid = 80
wound = 15
+/obj/item/clothing/head/helmet/balloon
+ name = "balloon helmet"
+ desc = "A helmet made out of balloons. Its likes saw great usage in the Great Clown - Mime War. Surprisingly resistant to fire. Mimes were doing unspeakable things."
+ icon_state = "helmet_balloon"
+ inhand_icon_state = "helmet_balloon"
+ armor_type = /datum/armor/balloon
+ flags_inv = HIDEHAIR|HIDEEARS|HIDESNOUT
+ resistance_flags = FIRE_PROOF
+ dog_fashion = null
+
+/datum/armor/balloon
+ melee = 10
+ fire = 60
+ acid = 50
+
/obj/item/clothing/head/helmet/toggleable/justice
name = "helmet of justice"
desc = "WEEEEOOO. WEEEEEOOO. WEEEEOOOO."
@@ -423,16 +438,6 @@
armor_type = /datum/armor/knight_greyscale
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
-/datum/armor/knight_greyscale
- melee = 35
- bullet = 10
- laser = 10
- energy = 10
- bomb = 10
- bio = 10
- fire = 40
- acid = 40
-
/obj/item/clothing/head/helmet/skull
name = "skull helmet"
desc = "An intimidating tribal helmet, it doesn't look very comfortable."
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 779559b4fe4..c212481453b 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -173,6 +173,8 @@
armor_type = /datum/armor/fedora_det_hat
icon_state = "detective"
inhand_icon_state = "det_hat"
+ interaction_flags_click = NEED_DEXTERITY|NEED_HANDS
+ /// Cooldown for retrieving precious candy corn on alt click
var/candy_cooldown = 0
dog_fashion = /datum/dog_fashion/head/detective
///Path for the flask that spawns inside their hat roundstart
@@ -198,17 +200,16 @@
. = ..()
. += span_notice("Alt-click to take a candy corn.")
-/obj/item/clothing/head/fedora/det_hat/AltClick(mob/user)
- . = ..()
- if(loc != user || !user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS))
- return
- if(candy_cooldown < world.time)
- var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src)
- user.put_in_hands(CC)
- to_chat(user, span_notice("You slip a candy corn from your hat."))
- candy_cooldown = world.time+1200
- else
+/obj/item/clothing/head/fedora/det_hat/click_alt(mob/user)
+ if(candy_cooldown >= world.time)
to_chat(user, span_warning("You just took a candy corn! You should wait a couple minutes, lest you burn through your stash."))
+ return CLICK_ACTION_BLOCKING
+
+ var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src)
+ user.put_in_hands(CC)
+ to_chat(user, span_notice("You slip a candy corn from your hat."))
+ candy_cooldown = world.time+1200
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/fedora/det_hat/minor
flask_path = /obj/item/reagent_containers/cup/glass/flask/det/minor
@@ -221,6 +222,7 @@
icon_state = "detective"
inhand_icon_state = "det_hat"
dog_fashion = /datum/dog_fashion/head/detective
+ interaction_flags_click = FORBID_TELEKINESIS_REACH
///prefix our phrases must begin with
var/prefix = "go go gadget"
///an assoc list of phrase = item (like gun = revolver)
@@ -277,7 +279,7 @@
return
var/input = tgui_input_text(user, "What is the activation phrase?", "Activation phrase", "gadget", max_length = 26)
- if(!input)
+ if(!input || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return
if(input in items_by_phrase)
balloon_alert(user, "already used!")
@@ -293,16 +295,16 @@
/obj/item/clothing/head/fedora/inspector_hat/attack_self(mob/user)
. = ..()
var/phrase = tgui_input_list(user, "What item do you want to remove by phrase?", "Item Removal", items_by_phrase)
- if(!phrase)
+ if(!phrase || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return
user.put_in_inactive_hand(items_by_phrase[phrase])
-/obj/item/clothing/head/fedora/inspector_hat/AltClick(mob/user)
- . = ..()
+/obj/item/clothing/head/fedora/inspector_hat/click_alt(mob/user)
var/new_prefix = tgui_input_text(user, "What should be the new prefix?", "Activation prefix", prefix, max_length = 24)
- if(!new_prefix)
- return
+ if(!new_prefix || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
+ return CLICK_ACTION_BLOCKING
prefix = new_prefix
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/fedora/inspector_hat/Exited(atom/movable/gone, direction)
. = ..()
diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm
index 0b0a6fb4d50..92517d4a7dd 100644
--- a/code/modules/clothing/head/soft_caps.dm
+++ b/code/modules/clothing/head/soft_caps.dm
@@ -5,11 +5,14 @@
worn_icon = 'icons/mob/clothing/head/hats.dmi'
icon_state = "cargosoft"
inhand_icon_state = "greyscale_softcap" //todo wip
+ interaction_flags_click = NEED_DEXTERITY
+ /// For setting icon archetype
var/soft_type = "cargo"
+ /// If there is a suffix to append
var/soft_suffix = "soft"
dog_fashion = /datum/dog_fashion/head/cargo_tech
-
+ /// Whether this is on backwards... Woah, cool
var/flipped = FALSE
/obj/item/clothing/head/soft/dropped()
@@ -24,10 +27,9 @@
flip(usr)
-/obj/item/clothing/head/soft/AltClick(mob/user)
- ..()
- if(user.can_perform_action(src, NEED_DEXTERITY))
- flip(user)
+/obj/item/clothing/head/soft/click_alt(mob/user)
+ flip(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/soft/proc/flip(mob/user)
diff --git a/code/modules/clothing/head/tophat.dm b/code/modules/clothing/head/tophat.dm
index 26087ab6232..2affc4c63da 100644
--- a/code/modules/clothing/head/tophat.dm
+++ b/code/modules/clothing/head/tophat.dm
@@ -36,4 +36,13 @@
var/mob/living/basic/rabbit/bunbun = new(get_turf(magician))
bunbun.mob_try_pickup(magician, instant=TRUE)
+/obj/item/clothing/head/hats/tophat/balloon
+ name = "balloon top-hat"
+ desc = "It's an colourful looking top-hat to match yout colourful personality."
+ icon_state = "balloon_tophat"
+ inhand_icon_state = "balloon_that"
+ throwforce = 0
+ resistance_flags = FIRE_PROOF
+ dog_fashion = null
+
#undef RABBIT_CD_TIME
diff --git a/code/modules/clothing/masks/animal_masks.dm b/code/modules/clothing/masks/animal_masks.dm
index c2013b99177..5df5c6738d8 100644
--- a/code/modules/clothing/masks/animal_masks.dm
+++ b/code/modules/clothing/masks/animal_masks.dm
@@ -46,11 +46,12 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list(
if(clothing_flags & VOICEBOX_TOGGLABLE)
. += span_notice("Its voicebox is currently [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"]. Alt-click to toggle it.")
-/obj/item/clothing/mask/animal/AltClick(mob/user)
- . = ..()
- if(clothing_flags & VOICEBOX_TOGGLABLE)
- clothing_flags ^= VOICEBOX_DISABLED
- to_chat(user, span_notice("You [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"] [src]'s voicebox."))
+/obj/item/clothing/mask/animal/click_alt(mob/user)
+ if(!(clothing_flags & VOICEBOX_TOGGLABLE))
+ return NONE
+ clothing_flags ^= VOICEBOX_DISABLED
+ to_chat(user, span_notice("You [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"] [src]'s voicebox."))
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/mask/animal/proc/make_cursed() //apply cursed effects.
ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT)
diff --git a/code/modules/clothing/masks/bandana.dm b/code/modules/clothing/masks/bandana.dm
index 4a97384fa39..cd4b3980e55 100644
--- a/code/modules/clothing/masks/bandana.dm
+++ b/code/modules/clothing/masks/bandana.dm
@@ -53,34 +53,36 @@
worn_icon_state = initial(worn_icon_state)
undyeable = initial(undyeable)
-/obj/item/clothing/mask/bandana/AltClick(mob/user)
- . = ..()
- if(iscarbon(user))
- var/mob/living/carbon/char = user
- var/matrix/widen = matrix()
- if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_MASK) == src) || (char.get_item_by_slot(ITEM_SLOT_HEAD) == src))
- to_chat(user, span_warning("You can't tie [src] while wearing it!"))
- return
- else if(slot_flags & ITEM_SLOT_HEAD)
- to_chat(user, span_warning("You must undo [src] before you can tie it into a neckerchief!"))
- return
- else if(!user.is_holding(src))
- to_chat(user, span_warning("You must be holding [src] in order to tie it!"))
- return
+/obj/item/clothing/mask/bandana/click_alt(mob/user)
+ if(!iscarbon(user))
+ return NONE
- if(slot_flags & ITEM_SLOT_MASK)
- undyeable = TRUE
- slot_flags = ITEM_SLOT_NECK
- worn_y_offset = -3
- widen.Scale(1.25, 1)
- transform = widen
- user.visible_message(span_notice("[user] ties [src] up like a neckerchief."), span_notice("You tie [src] up like a neckerchief."))
- else
- undyeable = initial(undyeable)
- slot_flags = initial(slot_flags)
- worn_y_offset = initial(worn_y_offset)
- transform = initial(transform)
- user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif."))
+ var/mob/living/carbon/char = user
+ var/matrix/widen = matrix()
+ if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_MASK) == src) || (char.get_item_by_slot(ITEM_SLOT_HEAD) == src))
+ to_chat(user, span_warning("You can't tie [src] while wearing it!"))
+ return CLICK_ACTION_BLOCKING
+ else if(slot_flags & ITEM_SLOT_HEAD)
+ to_chat(user, span_warning("You must undo [src] before you can tie it into a neckerchief!"))
+ return CLICK_ACTION_BLOCKING
+ else if(!user.is_holding(src))
+ to_chat(user, span_warning("You must be holding [src] in order to tie it!"))
+ return CLICK_ACTION_BLOCKING
+
+ if(slot_flags & ITEM_SLOT_MASK)
+ undyeable = TRUE
+ slot_flags = ITEM_SLOT_NECK
+ worn_y_offset = -3
+ widen.Scale(1.25, 1)
+ transform = widen
+ user.visible_message(span_notice("[user] ties [src] up like a neckerchief."), span_notice("You tie [src] up like a neckerchief."))
+ else
+ undyeable = initial(undyeable)
+ slot_flags = initial(slot_flags)
+ worn_y_offset = initial(worn_y_offset)
+ transform = initial(transform)
+ user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif."))
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/mask/bandana/red
name = "red bandana"
@@ -229,14 +231,16 @@
greyscale_config_inhand_left = /datum/greyscale_config/facescarf/inhands_left
greyscale_config_inhand_right = /datum/greyscale_config/facescarf/inhands_right
flags_1 = IS_PLAYER_COLORABLE_1
+ interaction_flags_click = NEED_DEXTERITY
/obj/item/clothing/mask/facescarf/attack_self(mob/user)
adjustmask(user)
-/obj/item/clothing/mask/facescarf/AltClick(mob/user)
- ..()
- if(user.can_perform_action(src, NEED_DEXTERITY))
- adjustmask(user)
+
+/obj/item/clothing/mask/facescarf/click_alt(mob/user)
+ adjustmask(user)
+ return CLICK_ACTION_SUCCESS
+
/obj/item/clothing/mask/facescarf/examine(mob/user)
. = ..()
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index 8ba15fe521d..0249f0b1321 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -12,6 +12,7 @@
flags_cover = MASKCOVERSMOUTH
visor_flags_cover = MASKCOVERSMOUTH
resistance_flags = NONE
+ interaction_flags_click = NEED_DEXTERITY
/datum/armor/mask_breath
bio = 50
@@ -23,10 +24,9 @@
/obj/item/clothing/mask/breath/attack_self(mob/user)
adjustmask(user)
-/obj/item/clothing/mask/breath/AltClick(mob/user)
- ..()
- if(user.can_perform_action(src, NEED_DEXTERITY))
- adjustmask(user)
+/obj/item/clothing/mask/breath/click_alt(mob/user)
+ adjustmask(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/mask/breath/examine(mob/user)
. = ..()
diff --git a/code/modules/clothing/masks/costume.dm b/code/modules/clothing/masks/costume.dm
index 893455dcdd0..626d8ce4a65 100644
--- a/code/modules/clothing/masks/costume.dm
+++ b/code/modules/clothing/masks/costume.dm
@@ -12,14 +12,6 @@
"Pleading" = "pleading"
)
-/obj/item/clothing/mask/joy/Initialize(mapload)
- . = ..()
- register_context()
-
-/obj/item/clothing/mask/joy/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- . = ..()
- context[SCREENTIP_CONTEXT_ALT_LMB] = "Change Emotion"
- return CONTEXTUAL_SCREENTIP_SET
/obj/item/clothing/mask/joy/reskin_obj(mob/user)
. = ..()
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index a62f271739b..e07a56155d4 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -73,10 +73,9 @@
else
. += span_notice("The tie can be untied with Alt-Click.")
-/obj/item/clothing/neck/tie/AltClick(mob/user)
- . = ..()
+/obj/item/clothing/neck/tie/click_alt(mob/user)
if(clip_on)
- return
+ return NONE
to_chat(user, span_notice("You concentrate as you begin [is_tied ? "untying" : "tying"] [src]..."))
var/tie_timer_actual = tie_timer
// Mirrors give you a boost to your tying speed. I realize this stacks and I think that's hilarious.
@@ -88,11 +87,11 @@
// Tie/Untie our tie
if(!do_after(user, tie_timer_actual))
to_chat(user, span_notice("Your fingers fumble away from [src] as your concentration breaks."))
- return
+ return CLICK_ACTION_BLOCKING
// Clumsy & Dumb people have trouble tying their ties.
if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
to_chat(user, span_notice("You just can't seem to get a proper grip on [src]!"))
- return
+ return CLICK_ACTION_BLOCKING
// Success!
is_tied = !is_tied
user.visible_message(
@@ -101,6 +100,7 @@
)
update_appearance(UPDATE_ICON)
user.update_clothing(ITEM_SLOT_NECK)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/neck/tie/update_icon()
. = ..()
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 6d9646b49ee..db20562039b 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -388,7 +388,7 @@
)
head = /obj/item/clothing/head/utility/hardhat/welding
mask = /obj/item/clothing/mask/gas/atmos
- l_hand = /obj/item/areaeditor/blueprints
+ l_hand = /obj/item/blueprints
/datum/outfit/centcom/ert/clown/party
name = "ERP Comedian"
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 4b0da7092c5..e30dfc2f5ac 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -12,6 +12,8 @@
armor_type = /datum/armor/clothing_shoes
slowdown = SHOES_SLOWDOWN
strip_delay = 1 SECONDS
+ article = "a pair of"
+
var/offset = 0
var/equipped_before_drop = FALSE
///Whether these shoes have laces that can be tied/untied
@@ -179,8 +181,7 @@
adjust_laces(SHOES_UNTIED, user)
else // if they're someone else's shoes, go knot-wards
- var/mob/living/L = user
- if(istype(L) && L.body_position == STANDING_UP)
+ if(istype(living_user) && living_user.body_position == STANDING_UP)
to_chat(user, span_warning("You must be on the floor to interact with [src]!"))
return
if(tied == SHOES_KNOTTED)
@@ -194,11 +195,11 @@
to_chat(user, span_notice("You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]..."))
if(HAS_TRAIT(user, TRAIT_CLUMSY)) // based clowns trained their whole lives for this
mod_time *= 0.75
- // SKYRAT EDIT START
+ // SKYRAT EDIT ADDITION START
if(HAS_TRAIT(user, TRAIT_STICKY_FINGERS)) // Clowns with thieving gloves will be a menace
mod_time *= 0.5
- // SKYRAT EDIT END
- if(do_after(user, mod_time, target = our_guy, extra_checks = CALLBACK(src, PROC_REF(still_shoed), our_guy)))
+ // SKYRAT EDIT ADDITION END
+ if(do_after(user, mod_time, target = our_guy, extra_checks = CALLBACK(src, PROC_REF(still_shoed), our_guy), hidden = TRUE))
to_chat(user, span_notice("You [tied ? "untie" : "knot"] the laces on [loc]'s [src.name]."))
if(tied == SHOES_UNTIED)
adjust_laces(SHOES_KNOTTED, user)
@@ -208,12 +209,12 @@
user.visible_message(span_danger("[our_guy] stamps on [user]'s hand, mid-shoelace [tied ? "knotting" : "untying"]!"), span_userdanger("Ow! [our_guy] stamps on your hand!"), list(our_guy))
to_chat(our_guy, span_userdanger("You stamp on [user]'s hand! What the- [user.p_they()] [user.p_were()] [tied ? "knotting" : "untying"] your shoelaces!"))
user.emote("scream")
- if(istype(L))
- var/obj/item/bodypart/ouchie = L.get_bodypart(pick(GLOB.arm_zones))
+ if(istype(living_user))
+ var/obj/item/bodypart/ouchie = living_user.get_bodypart(pick(GLOB.arm_zones))
if(ouchie)
ouchie.receive_damage(brute = 10)
- L.adjustStaminaLoss(40)
- L.Paralyze(10)
+ living_user.adjustStaminaLoss(40)
+ living_user.Paralyze(10)
///checking to make sure we're still on the person we're supposed to be, for lacing do_after's
/obj/item/clothing/shoes/proc/still_shoed(mob/living/carbon/our_guy)
diff --git a/code/modules/clothing/shoes/gunboots.dm b/code/modules/clothing/shoes/gunboots.dm
index d8335b5fcb0..de74703d449 100644
--- a/code/modules/clothing/shoes/gunboots.dm
+++ b/code/modules/clothing/shoes/gunboots.dm
@@ -59,7 +59,7 @@
shot.original = target
shot.fired_from = src
shot.firer = wearer // don't hit ourself that would be really annoying
- shot.impacted = list(wearer = TRUE)
+ shot.impacted = list(WEAKREF(wearer) = TRUE)
shot.def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) // they're fired from boots after all
shot.preparePixelProjectile(target, wearer)
if(!shot.suppressed)
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 58cbf7e88e5..785ec9e26f9 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -58,11 +58,17 @@
equip_delay_other = 80
resistance_flags = NONE
actions_types = list(/datum/action/item_action/toggle_spacesuit)
- var/temperature_setting = BODYTEMP_NORMAL /// The default temperature setting
- var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high /// If this is a path, this gets created as an object in Initialize.
- var/cell_cover_open = FALSE /// Status of the cell cover on the suit
- var/thermal_on = FALSE /// Status of the thermal regulator
- var/show_hud = TRUE /// If this is FALSE the batery status UI will be disabled. This is used for suits that don't use bateries like the changeling's flesh suit mutation.
+ interaction_flags_click = NEED_DEXTERITY
+ /// The default temperature setting
+ var/temperature_setting = BODYTEMP_NORMAL
+ /// If this is a path, this gets created as an object in Initialize.
+ var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high
+ /// Status of the cell cover on the suit
+ var/cell_cover_open = FALSE
+ /// Status of the thermal regulator
+ var/thermal_on = FALSE
+ /// If this is FALSE the batery status UI will be disabled. This is used for suits that don't use bateries like the changeling's flesh suit mutation.
+ var/show_hud = TRUE
/datum/armor/suit_space
bio = 100
@@ -190,10 +196,9 @@
return
/// Open the cell cover when ALT+Click on the suit
-/obj/item/clothing/suit/space/AltClick(mob/living/user)
- if(!user.can_perform_action(src, NEED_DEXTERITY))
- return ..()
+/obj/item/clothing/suit/space/click_alt(mob/living/user)
toggle_spacesuit_cell(user)
+ return CLICK_ACTION_SUCCESS
/// Remove the cell whent he cover is open on CTRL+Click
/obj/item/clothing/suit/space/CtrlClick(mob/living/user)
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index ce21351c885..02a54f194ea 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -87,9 +87,9 @@
else
. += span_notice("There's nothing placed on the helmet.")
-/obj/item/clothing/head/helmet/space/plasmaman/AltClick(mob/user)
- if(user.can_perform_action(src))
- toggle_welding_screen(user)
+/obj/item/clothing/head/helmet/space/plasmaman/click_alt(mob/user)
+ toggle_welding_screen(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/helmet/space/plasmaman/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/toggle_welding_screen))
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 02e6110b3ee..dcf6d502834 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -336,6 +336,40 @@
acid = 50
wound = 10
+/obj/item/clothing/suit/armor/balloon_vest
+ name = "balloon vest"
+ desc = "A vest made entirely from balloons, resistant to any evil forces a mime could throw at you, including electricity and fire. Just a strike with something sharp, though..."
+ icon_state = "balloon-vest"
+ inhand_icon_state = "balloon_armor"
+ blood_overlay_type = "armor"
+ armor_type = /datum/armor/balloon_vest
+ siemens_coefficient = 0
+ strip_delay = 70
+ equip_delay_other = 50
+
+/datum/armor/balloon_vest
+ melee = 10
+ laser = 10
+ energy = 10
+ fire = 60
+ acid = 50
+
+/obj/item/clothing/suit/armor/balloon_vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
+ if(isitem(hitby))
+ var/obj/item/item_hit = hitby
+ if(item_hit.sharpness)
+ pop()
+
+ if(istype(hitby, /obj/projectile/bullet))
+ pop()
+
+ return ..()
+
+/obj/item/clothing/suit/armor/balloon_vest/proc/pop()
+ playsound(src, 'sound/effects/cartoon_pop.ogg', 50, vary = TRUE)
+ qdel(src)
+
+
/obj/item/clothing/suit/armor/bulletproof
name = "bulletproof armor"
desc = "A Type III heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent."
@@ -531,6 +565,16 @@
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix
armor_type = /datum/armor/knight_greyscale
+/datum/armor/knight_greyscale
+ melee = 35
+ bullet = 10
+ laser = 10
+ energy = 10
+ bomb = 10
+ bio = 10
+ fire = 40
+ acid = 40
+
/obj/item/clothing/suit/armor/vest/durathread
name = "durathread vest"
desc = "A vest made of durathread with strips of leather acting as trauma plates."
@@ -596,7 +640,7 @@
desc = "A superb armor made with the toughest and rarest materials available to man."
icon_state = "h2armor"
inhand_icon_state = null
- material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix
+ material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
armor_type = /datum/armor/armor_elder_atmosian
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm
index aaa233f0d35..a92811b0fe7 100644
--- a/code/modules/clothing/suits/wintercoats.dm
+++ b/code/modules/clothing/suits/wintercoats.dm
@@ -47,12 +47,7 @@
. += span_notice("Alt-click to [zipped ? "un" : ""]zip.")
-/obj/item/clothing/suit/hooded/wintercoat/AltClick(mob/user)
- . = ..()
-
- if (. == FALSE) // Direct check for FALSE, because that's the specific case we want to propagate, not just null.
- return FALSE
-
+/obj/item/clothing/suit/hooded/wintercoat/click_alt(mob/user)
zipped = !zipped
worn_icon_state = "[initial(icon_state)][zipped ? "_t" : ""]"
balloon_alert(user, "[zipped ? "" : "un"]zipped")
@@ -60,6 +55,7 @@
if(ishuman(loc))
var/mob/living/carbon/human/wearer = loc
wearer.update_worn_oversuit()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/hooded/winterhood
name = "winter hood"
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index 381415ba03e..1de7ed331e9 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -51,33 +51,37 @@
if(random_sensor)
//make the sensor mode favor higher levels, except coords.
sensor_mode = pick(SENSOR_VITALS, SENSOR_VITALS, SENSOR_VITALS, SENSOR_LIVING, SENSOR_LIVING, SENSOR_COORDS, SENSOR_COORDS, SENSOR_OFF)
- register_context()
+ if(!unique_reskin) // Already registered via unique reskin
+ register_context()
AddElement(/datum/element/update_icon_updates_onmob, flags = ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING, body = TRUE)
-/obj/item/clothing/under/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
- . = NONE
+/obj/item/clothing/under/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
+ . = ..()
+
+ var/changed = FALSE
if(isnull(held_item) && has_sensor == HAS_SENSORS)
context[SCREENTIP_CONTEXT_RMB] = "Toggle suit sensors"
- . = CONTEXTUAL_SCREENTIP_SET
+ changed = TRUE
if(istype(held_item, /obj/item/clothing/accessory) && length(attached_accessories) < max_number_of_accessories)
context[SCREENTIP_CONTEXT_LMB] = "Attach accessory"
- . = CONTEXTUAL_SCREENTIP_SET
+ changed = TRUE
if(LAZYLEN(attached_accessories))
context[SCREENTIP_CONTEXT_ALT_RMB] = "Remove accessory"
- . = CONTEXTUAL_SCREENTIP_SET
+ changed = TRUE
if(istype(held_item, /obj/item/stack/cable_coil) && has_sensor == BROKEN_SENSORS)
context[SCREENTIP_CONTEXT_LMB] = "Repair suit sensors"
- . = CONTEXTUAL_SCREENTIP_SET
+ changed = TRUE
if(can_adjust && adjusted != DIGITIGRADE_STYLE)
context[SCREENTIP_CONTEXT_ALT_LMB] = "Wear [adjusted == ALT_STYLE ? "normally" : "casually"]"
- . = CONTEXTUAL_SCREENTIP_SET
+ changed = TRUE
+
+ return changed ? CONTEXTUAL_SCREENTIP_SET : NONE
- return .
/obj/item/clothing/under/worn_overlays(mutable_appearance/standing, isinhands = FALSE, file2use = null, mutant_styles = NONE)
. = ..()
@@ -353,17 +357,14 @@ BUBBERSTATION CHANGE END */
return TRUE
-/obj/item/clothing/under/AltClick(mob/user)
- . = ..()
- if(.)
- return
-
+/obj/item/clothing/under/click_alt(mob/user)
if(!can_adjust)
balloon_alert(user, "can't be adjusted!")
- return
+ return CLICK_ACTION_BLOCKING
if(!can_use(user))
- return
+ return NONE
rolldown()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/under/alt_click_secondary(mob/user)
. = ..()
diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm
index 7f99a45c8b6..b09aaa34104 100644
--- a/code/modules/clothing/under/costume.dm
+++ b/code/modules/clothing/under/costume.dm
@@ -239,6 +239,7 @@
"Black" = "black_mech_suit",
)
+
/obj/item/clothing/under/costume/russian_officer
name = "\improper Russian officer's uniform"
desc = "The latest in fashionable russian outfits."
diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm
index e22235084f9..c10648e3315 100644
--- a/code/modules/detectivework/evidence.dm
+++ b/code/modules/detectivework/evidence.dm
@@ -22,7 +22,7 @@
/obj/item/evidencebag/Exited(atom/movable/gone, direction)
. = ..()
cut_overlays()
- w_class = initial(w_class)
+ update_weight_class(initial(w_class))
icon_state = initial(icon_state)
desc = initial(desc)
@@ -78,7 +78,7 @@
desc = "An evidence bag containing [I]. [I.desc]"
I.forceMove(src)
- w_class = I.w_class
+ update_weight_class(I.w_class)
return 1
/obj/item/evidencebag/attack_self(mob/user)
@@ -88,7 +88,7 @@
span_hear("You hear someone rustle around in a plastic bag, and remove something."))
cut_overlays() //remove the overlays
user.put_in_hands(I)
- w_class = WEIGHT_CLASS_TINY
+ update_weight_class(WEIGHT_CLASS_TINY)
icon_state = "evidenceobj"
desc = "An empty evidence bag."
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 6ce6b0e67a6..82c77839da7 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -218,20 +218,20 @@
/proc/get_timestamp()
return time2text(world.time + 432000, ":ss")
-/obj/item/detective_scanner/AltClick(mob/living/user)
- // Best way for checking if a player can use while not incapacitated, etc
- if(!user.can_perform_action(src))
- return
+/obj/item/detective_scanner/click_alt(mob/living/user)
if(!LAZYLEN(log))
balloon_alert(user, "no logs!")
- return
+ return CLICK_ACTION_BLOCKING
if(scanner_busy)
balloon_alert(user, "scanner busy!")
- return
+ return CLICK_ACTION_BLOCKING
balloon_alert(user, "deleting logs...")
- if(do_after(user, 3 SECONDS, target = src))
- balloon_alert(user, "logs cleared")
- log = list()
+ if(!do_after(user, 3 SECONDS, target = src))
+ return CLICK_ACTION_BLOCKING
+ balloon_alert(user, "logs cleared")
+ log = list()
+ return CLICK_ACTION_SUCCESS
+
/obj/item/detective_scanner/examine(mob/user)
. = ..()
diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm
index 533628eedf4..fa9b9ea0d5e 100644
--- a/code/modules/emoji/emoji_parse.dm
+++ b/code/modules/emoji/emoji_parse.dm
@@ -16,7 +16,7 @@
pos = search
search = findtext(text, ":", pos + length(text[pos]))
if(search)
- emoji = lowertext(copytext(text, pos + length(text[pos]), search))
+ emoji = LOWER_TEXT(copytext(text, pos + length(text[pos]), search))
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat)
var/tag = sheet.icon_tag("emoji-[emoji]")
if(tag)
@@ -46,9 +46,9 @@
pos = search
search = findtext(text, ":", pos + length(text[pos]))
if(search)
- var/word = lowertext(copytext(text, pos + length(text[pos]), search))
+ var/word = LOWER_TEXT(copytext(text, pos + length(text[pos]), search))
if(word in emojis)
- final += lowertext(copytext(text, pos, search + length(text[search])))
+ final += LOWER_TEXT(copytext(text, pos, search + length(text[search])))
pos = search + length(text[search])
continue
break
diff --git a/code/modules/escape_menu/home_page.dm b/code/modules/escape_menu/home_page.dm
index 6d48285ae77..45180d98688 100644
--- a/code/modules/escape_menu/home_page.dm
+++ b/code/modules/escape_menu/home_page.dm
@@ -5,7 +5,7 @@
/* hud_owner = */ src,
src,
"Resume",
- /* offset = */ 0,
+ /* offset = */ 1,
CALLBACK(src, PROC_REF(home_resume)),
)
)
@@ -16,7 +16,7 @@
/* hud_owner = */ null,
src,
"Settings",
- /* offset = */ 1,
+ /* offset = */ 2,
CALLBACK(src, PROC_REF(home_open_settings)),
)
)
@@ -27,7 +27,7 @@
/* hud_owner = */ src,
src,
"Admin Help",
- /* offset = */ 2,
+ /* offset = */ 3,
)
)
//SKYRAT EDIT REMOVAL BEGIN
@@ -38,7 +38,7 @@
/* hud_owner = */ src,
src,
"Leave Body",
- /* offset = */ 3,
+ /* offset = */ 4,
CALLBACK(src, PROC_REF(open_leave_body)),
)
)
diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm
index c6f52ab50ca..fbd9b746d03 100644
--- a/code/modules/events/vent_clog.dm
+++ b/code/modules/events/vent_clog.dm
@@ -177,9 +177,9 @@
to_chat(user, span_notice("You cannot pump [vent] if it's welded shut!"))
return
- to_chat(user, span_notice("You begin pumping [vent] with your plunger."))
+ user.balloon_alert_to_viewers("plunging vent...", "plunging clogged vent...")
if(do_after(user, 6 SECONDS, target = vent))
- to_chat(user, span_notice("You finish pumping [vent]."))
+ user.balloon_alert_to_viewers("finished plunging")
clear_signals()
kill()
diff --git a/code/modules/experisci/destructive_scanner.dm b/code/modules/experisci/destructive_scanner.dm
index 5740b715bd4..d5d87eb6311 100644
--- a/code/modules/experisci/destructive_scanner.dm
+++ b/code/modules/experisci/destructive_scanner.dm
@@ -12,12 +12,8 @@
layer = MOB_LAYER
var/scanning = FALSE
-/obj/machinery/destructive_scanner/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
-
// Late load to ensure the component initialization occurs after the machines are initialized
-/obj/machinery/destructive_scanner/LateInitialize()
+/obj/machinery/destructive_scanner/post_machine_initialize()
. = ..()
var/static/list/destructive_signals = list(
diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm
index e2d460e3903..b153c5157ea 100644
--- a/code/modules/experisci/experiment/handlers/experiment_handler.dm
+++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm
@@ -238,6 +238,7 @@
/datum/component/experiment_handler/proc/configure_experiment(datum/source, mob/user)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(ui_interact), user)
+ return CLICK_ACTION_SUCCESS
/**
* Attempts to show the user the experiment configuration panel
diff --git a/code/modules/experisci/handheld_scanner.dm b/code/modules/experisci/handheld_scanner.dm
index 32309336e3c..390937e0dd4 100644
--- a/code/modules/experisci/handheld_scanner.dm
+++ b/code/modules/experisci/handheld_scanner.dm
@@ -18,7 +18,6 @@
// Late initialize to allow for the rnd servers to initialize first
/obj/item/experi_scanner/LateInitialize()
- . = ..()
var/static/list/handheld_signals = list(
COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment),
COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt),
diff --git a/code/modules/explorer_drone/manager.dm b/code/modules/explorer_drone/manager.dm
index 00909d03abf..ee51a2d5db3 100644
--- a/code/modules/explorer_drone/manager.dm
+++ b/code/modules/explorer_drone/manager.dm
@@ -83,11 +83,6 @@
. = ..()
QDEL_NULL(temp_adventure)
-/client/proc/adventure_manager()
- set category = "Debug"
- set name = "Adventure Manager"
-
- if(!check_rights(R_DEBUG))
- return
+ADMIN_VERB(adventure_manager, R_DEBUG, "Adventure Manager", "View and edit adventures.", ADMIN_CATEGORY_DEBUG)
var/datum/adventure_browser/browser = new()
- browser.ui_interact(usr)
+ browser.ui_interact(user.mob)
diff --git a/code/modules/explorer_drone/scanner_array.dm b/code/modules/explorer_drone/scanner_array.dm
index 05f1d9a8b8f..6317ee273be 100644
--- a/code/modules/explorer_drone/scanner_array.dm
+++ b/code/modules/explorer_drone/scanner_array.dm
@@ -181,11 +181,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions())
failed_popup = TRUE
SStgui.update_uis(src)
-/obj/machinery/computer/exoscanner_control/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/computer/exoscanner_control/LateInitialize()
+/obj/machinery/computer/exoscanner_control/post_machine_initialize()
. = ..()
AddComponent(/datum/component/experiment_handler, \
allowed_experiments = list(/datum/experiment/exploration_scan), \
diff --git a/code/modules/fishing/admin.dm b/code/modules/fishing/admin.dm
index d1d2c0ae2c5..0a9cfc9d51d 100644
--- a/code/modules/fishing/admin.dm
+++ b/code/modules/fishing/admin.dm
@@ -1,12 +1,6 @@
-// Helper tool to see fishing probabilities with different setups
-/datum/admins/proc/fishing_calculator()
- set name = "Fishing Calculator"
- set category = "Debug"
-
- if(!check_rights(R_DEBUG))
- return
- var/datum/fishing_calculator/ui = new(usr)
- ui.ui_interact(usr)
+ADMIN_VERB(fishing_calculator, R_DEBUG, "Fishing Calculator", "A calculator... for fishes?", ADMIN_CATEGORY_DEBUG)
+ var/datum/fishing_calculator/ui = new
+ ui.ui_interact(user.mob)
/datum/fishing_calculator
var/list/current_table
diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm
index 48c7b8e24e9..8a719c16f70 100644
--- a/code/modules/fishing/aquarium/aquarium.dm
+++ b/code/modules/fishing/aquarium/aquarium.dm
@@ -159,10 +159,7 @@
if(panel_open && reagents.total_volume)
. += span_notice("You can use a plunger to empty the feed storage.")
-/obj/structure/aquarium/AltClick(mob/living/user)
- . = ..()
- if(!user.can_perform_action(src))
- return
+/obj/structure/aquarium/click_alt(mob/living/user)
panel_open = !panel_open
balloon_alert(user, "panel [panel_open ? "open" : "closed"]")
if(panel_open)
@@ -170,6 +167,7 @@
else
reagents.flags &= ~(TRANSPARENT|REFILLABLE)
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/structure/aquarium/wrench_act(mob/living/user, obj/item/tool)
. = ..()
@@ -179,9 +177,9 @@
/obj/structure/aquarium/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
if(!panel_open)
return
- to_chat(user, span_notice("You start plunging [name]."))
+ user.balloon_alert_to_viewers("plunging...")
if(do_after(user, 3 SECONDS, target = src))
- to_chat(user, span_notice("You finish plunging the [name]."))
+ user.balloon_alert_to_viewers("finished plunging")
reagents.expose(get_turf(src), TOUCH) //splash on the floor
reagents.clear_reagents()
diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm
index 85a387fd41d..62b302fb334 100644
--- a/code/modules/fishing/fish/_fish.dm
+++ b/code/modules/fishing/fish/_fish.dm
@@ -204,20 +204,20 @@
size = new_size
switch(size)
if(0 to FISH_SIZE_TINY_MAX)
- w_class = WEIGHT_CLASS_TINY
+ update_weight_class(WEIGHT_CLASS_TINY)
inhand_icon_state = "fish_small"
if(FISH_SIZE_TINY_MAX to FISH_SIZE_SMALL_MAX)
inhand_icon_state = "fish_small"
- w_class = WEIGHT_CLASS_SMALL
+ update_weight_class(WEIGHT_CLASS_SMALL)
if(FISH_SIZE_SMALL_MAX to FISH_SIZE_NORMAL_MAX)
inhand_icon_state = "fish_normal"
- w_class = WEIGHT_CLASS_NORMAL
+ update_weight_class(WEIGHT_CLASS_NORMAL)
if(FISH_SIZE_NORMAL_MAX to FISH_SIZE_BULKY_MAX)
inhand_icon_state = "fish_bulky"
- w_class = WEIGHT_CLASS_BULKY
+ update_weight_class(WEIGHT_CLASS_BULKY)
if(FISH_SIZE_BULKY_MAX to INFINITY)
inhand_icon_state = "fish_huge"
- w_class = WEIGHT_CLASS_HUGE
+ update_weight_class(WEIGHT_CLASS_HUGE)
if(fillet_type)
var/init_fillets = initial(num_fillets)
var/amount = max(round(init_fillets * size / FISH_FILLET_NUMBER_SIZE_DIVISOR, 1), 1)
diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm
index 0578ffb0789..a0fa77dc514 100644
--- a/code/modules/fishing/fishing_rod.dm
+++ b/code/modules/fishing/fishing_rod.dm
@@ -234,7 +234,7 @@
cast_projectile.original = target
cast_projectile.fired_from = src
cast_projectile.firer = user
- cast_projectile.impacted = list(user = TRUE)
+ cast_projectile.impacted = list(WEAKREF(user) = TRUE)
cast_projectile.preparePixelProjectile(target, user)
cast_projectile.fire()
COOLDOWN_START(src, casting_cd, 1 SECONDS)
diff --git a/code/modules/food_and_drinks/machinery/deep_fryer.dm b/code/modules/food_and_drinks/machinery/deep_fryer.dm
index 140fde7e960..68cfddcf5f1 100644
--- a/code/modules/food_and_drinks/machinery/deep_fryer.dm
+++ b/code/modules/food_and_drinks/machinery/deep_fryer.dm
@@ -147,7 +147,11 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list(
audible_message(span_notice("[src] dings!"))
else if (cook_time >= DEEPFRYER_BURNTIME && !frying_burnt)
frying_burnt = TRUE
- visible_message(span_warning("[src] emits an acrid smell!"))
+ var/list/asomnia_hadders = list()
+ for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, src))
+ if(HAS_TRAIT(smeller, TRAIT_ANOSMIA))
+ asomnia_hadders += smeller
+ visible_message(span_warning("[src] emits an acrid smell!"), ignored_mobs = asomnia_hadders)
use_energy(active_power_usage)
diff --git a/code/modules/food_and_drinks/machinery/food_cart.dm b/code/modules/food_and_drinks/machinery/food_cart.dm
index e068b7b8ce2..a14ea3593c5 100644
--- a/code/modules/food_and_drinks/machinery/food_cart.dm
+++ b/code/modules/food_and_drinks/machinery/food_cart.dm
@@ -8,7 +8,7 @@
anchored = FALSE
use_power = NO_POWER_USE
req_access = list(ACCESS_KITCHEN)
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+ obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION
var/unpacked = FALSE
var/obj/machinery/griddle/stand/cart_griddle
var/obj/machinery/smartfridge/food/cart_smartfridge
diff --git a/code/modules/food_and_drinks/machinery/griddle.dm b/code/modules/food_and_drinks/machinery/griddle.dm
index b54a470897f..e0c45e6c9af 100644
--- a/code/modules/food_and_drinks/machinery/griddle.dm
+++ b/code/modules/food_and_drinks/machinery/griddle.dm
@@ -63,6 +63,7 @@
/obj/machinery/griddle/attackby(obj/item/I, mob/user, params)
+
if(griddled_objects.len >= max_items)
to_chat(user, span_notice("[src] can't fit more items!"))
return
@@ -79,6 +80,43 @@
else
return ..()
+/obj/machinery/griddle/item_interaction_secondary(mob/living/user, obj/item/item, list/modifiers)
+ if(isnull(item.atom_storage))
+ return NONE
+
+ for(var/obj/tray_item in griddled_objects)
+ item.atom_storage.attempt_insert(tray_item, user, TRUE)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/machinery/griddle/item_interaction(mob/living/user, obj/item/item, list/modifiers)
+ if(isnull(item.atom_storage))
+ return NONE
+
+ if(length(contents) >= max_items)
+ balloon_alert(user, "it's full!")
+ return ITEM_INTERACT_BLOCKING
+
+ if(!istype(item, /obj/item/storage/bag/tray))
+ // Non-tray dumping requires a do_after
+ to_chat(user, span_notice("You start dumping out the contents of [item] into [src]..."))
+ if(!do_after(user, 2 SECONDS, target = item))
+ return ITEM_INTERACT_BLOCKING
+
+ var/loaded = 0
+ for(var/obj/tray_item in item)
+ if(!IS_EDIBLE(tray_item))
+ continue
+ if(length(contents) >= max_items)
+ break
+ if(item.atom_storage.attempt_remove(tray_item, src))
+ loaded++
+ AddToGrill(tray_item, user)
+ if(loaded)
+ to_chat(user, span_notice("You insert [loaded] item\s into [src]."))
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
+ return ITEM_INTERACT_BLOCKING
+
/obj/machinery/griddle/attack_hand(mob/user, list/modifiers)
. = ..()
toggle_mode()
diff --git a/code/modules/food_and_drinks/machinery/grill.dm b/code/modules/food_and_drinks/machinery/grill.dm
index 3d9acdde0ba..8d0aa921a7b 100644
--- a/code/modules/food_and_drinks/machinery/grill.dm
+++ b/code/modules/food_and_drinks/machinery/grill.dm
@@ -125,15 +125,15 @@
grill_fuel += boost
update_appearance(UPDATE_ICON_STATE)
-/obj/machinery/grill/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking)
+/obj/machinery/grill/item_interaction(mob/living/user, obj/item/weapon, list/modifiers)
if(user.combat_mode || (weapon.item_flags & ABSTRACT) || (weapon.flags_1 & HOLOGRAM_1) || (weapon.resistance_flags & INDESTRUCTIBLE))
- return ..()
+ return NONE
if(istype(weapon, /obj/item/stack/sheet/mineral/coal) || istype(weapon, /obj/item/stack/sheet/mineral/wood))
if(!QDELETED(grilled_item))
- return ..()
+ return NONE
if(!anchored)
- balloon_alert(user, "anchor first!")
+ balloon_alert(user, "anchor it first!")
return ITEM_INTERACT_BLOCKING
//required for amount subtypes
@@ -150,7 +150,7 @@
if(!istype(stored, target_type))
continue
if(stored.amount == MAX_STACK_SIZE)
- to_chat(user, span_warning("No space for [weapon]"))
+ balloon_alert(user, "no space!")
return ITEM_INTERACT_BLOCKING
target.merge(stored)
merged = TRUE
@@ -158,7 +158,7 @@
if(!merged)
weapon.forceMove(src)
- to_chat(user, span_notice("You add [src] to the fuel stack"))
+ to_chat(user, span_notice("You add [src] to the fuel stack."))
if(!grill_fuel)
burn_stack()
begin_processing()
@@ -167,9 +167,9 @@
if(is_reagent_container(weapon) && weapon.is_open_container())
var/obj/item/reagent_containers/container = weapon
if(!QDELETED(grilled_item))
- return ..()
+ return NONE
if(!anchored)
- balloon_alert(user, "anchor first!")
+ balloon_alert(user, "anchor it first!")
return ITEM_INTERACT_BLOCKING
var/transfered_amount = weapon.reagents.trans_to(src, container.amount_per_transfer_from_this)
@@ -202,11 +202,11 @@
update_appearance(UPDATE_ICON_STATE)
//feedback
- to_chat(user, span_notice("You transfer [transfered_amount]u to the fuel source"))
+ to_chat(user, span_notice("You transfer [transfered_amount]u to the fuel source."))
return ITEM_INTERACT_SUCCESS
- else
- to_chat(user, span_warning("No fuel was transfered"))
- return ITEM_INTERACT_BLOCKING
+
+ balloon_alert(user, "no fuel transfered!")
+ return ITEM_INTERACT_BLOCKING
if(IS_EDIBLE(weapon))
//sanity checks
@@ -218,10 +218,10 @@
if(!QDELETED(grilled_item))
balloon_alert(user, "remove item first!")
return ITEM_INTERACT_BLOCKING
- else if(grill_fuel <= 0)
+ if(grill_fuel <= 0)
balloon_alert(user, "no fuel!")
return ITEM_INTERACT_BLOCKING
- else if(!user.transferItemToLoc(weapon, src))
+ if(!user.transferItemToLoc(weapon, src))
balloon_alert(user, "[weapon] is stuck in your hand!")
return ITEM_INTERACT_BLOCKING
@@ -236,7 +236,7 @@
grill_loop.start()
return ITEM_INTERACT_SUCCESS
- return ..()
+ return NONE
/obj/machinery/grill/wrench_act(mob/living/user, obj/item/tool)
if(user.combat_mode)
diff --git a/code/modules/food_and_drinks/machinery/icecream_vat.dm b/code/modules/food_and_drinks/machinery/icecream_vat.dm
index d4de5991995..cae1b260249 100644
--- a/code/modules/food_and_drinks/machinery/icecream_vat.dm
+++ b/code/modules/food_and_drinks/machinery/icecream_vat.dm
@@ -154,13 +154,12 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
-/obj/machinery/icecream_vat/AltClick(mob/user)
- if(!user.can_interact_with(src))
- return FALSE
- if(custom_ice_cream_beaker)
- balloon_alert(user, "removed beaker")
- try_put_in_hand(custom_ice_cream_beaker, user)
- return ..()
+/obj/machinery/icecream_vat/click_alt(mob/user)
+ if(!custom_ice_cream_beaker)
+ return CLICK_ACTION_BLOCKING
+ balloon_alert(user, "removed beaker")
+ try_put_in_hand(custom_ice_cream_beaker, user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/icecream_vat/interact(mob/living/user)
. = ..()
diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm
index dfb6ac9b2de..55509886a3a 100644
--- a/code/modules/food_and_drinks/machinery/microwave.dm
+++ b/code/modules/food_and_drinks/machinery/microwave.dm
@@ -31,6 +31,7 @@
light_color = LIGHT_COLOR_DIM_YELLOW
light_power = 3
anchored_tabletop_offset = 6
+ interaction_flags_click = ALLOW_SILICON_REACH
/// Is its function wire cut?
var/wire_disabled = FALSE
/// Wire cut to run mode backwards
@@ -364,21 +365,15 @@
update_appearance()
return ITEM_INTERACT_SUCCESS
-/obj/machinery/microwave/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/microwave/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(operating)
- return
+ return ITEM_INTERACT_SKIP_TO_ATTACK // Don't use tools if we're dirty
if(dirty >= MAX_MICROWAVE_DIRTINESS)
- return
-
- . = ..()
- if(. & ITEM_INTERACT_ANY_BLOCKER)
- return .
-
+ return ITEM_INTERACT_SKIP_TO_ATTACK // Don't insert items if we're dirty
if(panel_open && is_wire_tool(tool))
wires.interact(user)
return ITEM_INTERACT_SUCCESS
-
- return .
+ return NONE
/obj/machinery/microwave/attackby(obj/item/item, mob/living/user, params)
if(operating)
@@ -473,16 +468,16 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-/obj/machinery/microwave/AltClick(mob/user, list/modifiers)
- if(user.can_perform_action(src, ALLOW_SILICON_REACH))
- if(!vampire_charging_capable)
- return
+/obj/machinery/microwave/click_alt(mob/user, list/modifiers)
+ if(!vampire_charging_capable)
+ return NONE
- vampire_charging_enabled = !vampire_charging_enabled
- balloon_alert(user, "set to [vampire_charging_enabled ? "charge" : "cook"]")
- playsound(src, 'sound/machines/twobeep_high.ogg', 50, FALSE)
- if(HAS_SILICON_ACCESS(user))
- visible_message(span_notice("[user] sets \the [src] to [vampire_charging_enabled ? "charge" : "cook"]."), blind_message = span_notice("You hear \the [src] make an informative beep!"))
+ vampire_charging_enabled = !vampire_charging_enabled
+ balloon_alert(user, "set to [vampire_charging_enabled ? "charge" : "cook"]")
+ playsound(src, 'sound/machines/twobeep_high.ogg', 50, FALSE)
+ if(HAS_SILICON_ACCESS(user))
+ visible_message(span_notice("[user] sets \the [src] to [vampire_charging_enabled ? "charge" : "cook"]."), blind_message = span_notice("You hear \the [src] make an informative beep!"))
+ return CLICK_ACTION_SUCCESS
/obj/machinery/microwave/CtrlClick(mob/user)
. = ..()
diff --git a/code/modules/food_and_drinks/machinery/oven.dm b/code/modules/food_and_drinks/machinery/oven.dm
index 517e25c6dcb..ef9aac9a410 100644
--- a/code/modules/food_and_drinks/machinery/oven.dm
+++ b/code/modules/food_and_drinks/machinery/oven.dm
@@ -90,20 +90,33 @@
baked_item.fire_act(1000) //Hot hot hot!
if(SPT_PROB(10, seconds_per_tick))
- visible_message(span_danger("You smell a burnt smell coming from [src]!"))
+ var/list/asomnia_hadders = list()
+ for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, src))
+ if(HAS_TRAIT(smeller, TRAIT_ANOSMIA))
+ asomnia_hadders += smeller
+ visible_message(span_danger("You smell a burnt smell coming from [src]!"), ignored_mobs = asomnia_hadders)
set_smoke_state(worst_cooked_food_state)
update_appearance()
use_energy(active_power_usage)
-
-/obj/machinery/oven/attackby(obj/item/I, mob/user, params)
- if(open && !used_tray && istype(I, /obj/item/plate/oven_tray))
- if(user.transferItemToLoc(I, src, silent = FALSE))
- to_chat(user, span_notice("You put [I] in [src]."))
- add_tray_to_oven(I, user)
- else
+/obj/machinery/oven/attackby(obj/item/item, mob/user, params)
+ if(!open || used_tray || !istype(item, /obj/item/plate/oven_tray))
return ..()
+ if(user.transferItemToLoc(item, src, silent = FALSE))
+ to_chat(user, span_notice("You put [item] in [src]."))
+ add_tray_to_oven(item, user)
+
+/obj/machinery/oven/item_interaction(mob/living/user, obj/item/item, list/modifiers)
+ if(open && used_tray && item.atom_storage)
+ return used_tray.item_interaction(user, item, modifiers)
+ return NONE
+
+/obj/machinery/oven/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
+ if(open && used_tray && tool.atom_storage)
+ return used_tray.item_interaction_secondary(user, tool, modifiers)
+ return NONE
+
///Adds a tray to the oven, making sure the shit can get baked.
/obj/machinery/oven/proc/add_tray_to_oven(obj/item/plate/oven_tray, mob/baker)
used_tray = oven_tray
@@ -239,6 +252,43 @@
max_items = 6
biggest_w_class = WEIGHT_CLASS_BULKY
+/obj/item/plate/oven_tray/item_interaction_secondary(mob/living/user, obj/item/item, list/modifiers)
+ if(isnull(item.atom_storage))
+ return NONE
+
+ for(var/obj/tray_item in src)
+ item.atom_storage.attempt_insert(tray_item, user, TRUE)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/plate/oven_tray/item_interaction(mob/living/user, obj/item/item, list/modifiers)
+ if(isnull(item.atom_storage))
+ return NONE
+
+ if(length(contents >= max_items))
+ balloon_alert(user, "it's full!")
+ return ITEM_INTERACT_BLOCKING
+
+ if(!istype(item, /obj/item/storage/bag/tray))
+ // Non-tray dumping requires a do_after
+ to_chat(user, span_notice("You start dumping out the contents of [item] into [src]..."))
+ if(!do_after(user, 2 SECONDS, target = item))
+ return ITEM_INTERACT_BLOCKING
+
+ var/loaded = 0
+ for(var/obj/tray_item in item)
+ if(!IS_EDIBLE(tray_item))
+ continue
+ if(length(contents) >= max_items)
+ break
+ if(item.atom_storage.attempt_remove(tray_item, src))
+ loaded++
+ AddToPlate(tray_item, user)
+ if(loaded)
+ to_chat(user, span_notice("You insert [loaded] item\s into [src]."))
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
+ return ITEM_INTERACT_BLOCKING
+
#undef OVEN_SMOKE_STATE_NONE
#undef OVEN_SMOKE_STATE_GOOD
#undef OVEN_SMOKE_STATE_NEUTRAL
diff --git a/code/modules/food_and_drinks/machinery/stove.dm b/code/modules/food_and_drinks/machinery/stove.dm
index 38f98cfa8a8..6cc0ec52789 100644
--- a/code/modules/food_and_drinks/machinery/stove.dm
+++ b/code/modules/food_and_drinks/machinery/stove.dm
@@ -115,6 +115,34 @@
. = ..()
LAZYREMOVE(added_ingredients, gone)
+/**
+ * Adds items to a soup pot without invoking any procs that call sleep() when using in a component.
+ *
+ * Args:
+ * * transfer_from: The container that's being used to add items to the soup pot. Must not be null.
+ * * user: the entity adding ingredients via a container to a soup pot. Must not be null.
+ */
+/obj/item/reagent_containers/cup/soup_pot/proc/transfer_from_container_to_pot(obj/item/transfer_from, mob/user)
+ if(!transfer_from.atom_storage)
+ return
+
+ var/obj/item/storage/tray = transfer_from
+ var/loaded = 0
+
+ for(var/obj/tray_item in tray.contents)
+ if(!can_add_ingredient(tray_item))
+ continue
+ if(LAZYLEN(added_ingredients) >= max_ingredients)
+ balloon_alert(user, "it's full!")
+ return TRUE
+ if(tray.atom_storage.attempt_remove(tray_item, src))
+ loaded++
+ LAZYADD(added_ingredients, tray_item)
+ if(loaded)
+ to_chat(user, span_notice("You insert [loaded] items into \the [src]."))
+ update_appearance(UPDATE_OVERLAYS)
+ return TRUE
+
/obj/item/reagent_containers/cup/soup_pot/attackby(obj/item/attacking_item, mob/user, params)
. = ..()
if(.)
@@ -140,6 +168,12 @@
update_appearance(UPDATE_OVERLAYS)
return TRUE
+/obj/item/reagent_containers/cup/soup_pot/item_interaction(mob/living/user, obj/item/item, list/modifiers)
+ if(LAZYACCESS(modifiers, RIGHT_CLICK))
+ return NONE
+
+ return transfer_from_container_to_pot(item, user)
+
/obj/item/reagent_containers/cup/soup_pot/attack_hand_secondary(mob/user, list/modifiers)
if(!LAZYLEN(added_ingredients))
return SECONDARY_ATTACK_CALL_NORMAL
diff --git a/code/modules/food_and_drinks/machinery/stove_component.dm b/code/modules/food_and_drinks/machinery/stove_component.dm
index 1a39c3b2057..76a70f0f22a 100644
--- a/code/modules/food_and_drinks/machinery/stove_component.dm
+++ b/code/modules/food_and_drinks/machinery/stove_component.dm
@@ -128,6 +128,14 @@
/datum/component/stove/proc/on_attackby(obj/machinery/source, obj/item/attacking_item, mob/user, params)
SIGNAL_HANDLER
+ if(istype(source, /obj/machinery/oven/range) && istype(attacking_item, /obj/item/storage/bag/tray) && container)
+ var/obj/machinery/oven/range/range = source
+ var/obj/item/reagent_containers/cup/soup_pot/soup_pot = container
+
+ if(!range.open)
+ soup_pot.transfer_from_container_to_pot(attacking_item, user)
+ return COMPONENT_NO_AFTERATTACK
+
if(!attacking_item.is_open_container())
return
if(!isnull(container))
diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm
index 1df1d7c24bb..4ae6bf19e1d 100644
--- a/code/modules/food_and_drinks/plate.dm
+++ b/code/modules/food_and_drinks/plate.dm
@@ -70,7 +70,7 @@
update_appearance()
// If the incoming item is the same weight class as the plate, bump us up a class
if(item_to_plate.w_class == w_class)
- w_class += 1
+ update_weight_class(w_class + 1)
///This proc cleans up any signals on the item when it is removed from a plate, and ensures it has the correct state again.
/obj/item/plate/proc/ItemRemovedFromPlate(obj/item/removed_item)
@@ -85,12 +85,14 @@
removed_item.pixel_z = 0
// We need to ensure the weight class is accurate now that we've lost something
// that may or may not have been of equal weight
- w_class = initial(w_class)
+ var/new_w_class = initial(w_class)
for(var/obj/item/on_board in src)
if(on_board.w_class == w_class)
- w_class += 1
+ new_w_class += 1
break
+ update_weight_class(new_w_class)
+
///This proc is called by signals that remove the food from the plate.
/obj/item/plate/proc/ItemMoved(obj/item/moved_item, atom/OldLoc, Dir, Forced)
SIGNAL_HANDLER
diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm
index c557f75a631..bada60cd548 100644
--- a/code/modules/food_and_drinks/recipes/food_mixtures.dm
+++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm
@@ -280,8 +280,8 @@
reaction_flags = REACTION_INSTANT
/datum/chemical_reaction/food/martian_batter
- results = list(/datum/reagent/consumable/martian_batter = 2)
- required_reagents = list(/datum/reagent/consumable/flour = 1, /datum/reagent/consumable/nutriment/soup/dashi = 1)
+ results = list(/datum/reagent/consumable/martian_batter = 10)
+ required_reagents = list(/datum/reagent/consumable/flour = 5, /datum/reagent/consumable/nutriment/soup/dashi = 5)
mix_message = "A smooth batter forms."
reaction_flags = REACTION_INSTANT
diff --git a/code/modules/hallucination/fake_message.dm b/code/modules/hallucination/fake_message.dm
index a1040496f5e..de5616d83c6 100644
--- a/code/modules/hallucination/fake_message.dm
+++ b/code/modules/hallucination/fake_message.dm
@@ -25,7 +25,7 @@
// in the future, this could / should be de-harcoded and
// just draw from a pool uplink, theft, and antag item typepaths
var/static/list/stash_item_paths = list(
- /obj/item/areaeditor/blueprints,
+ /obj/item/blueprints,
/obj/item/assembly/flash,
/obj/item/card/id/advanced/gold/captains_spare,
/obj/item/card/emag,
diff --git a/code/modules/hallucination/inhand_fake_item.dm b/code/modules/hallucination/inhand_fake_item.dm
index efea8b309e2..cb787d217e1 100644
--- a/code/modules/hallucination/inhand_fake_item.dm
+++ b/code/modules/hallucination/inhand_fake_item.dm
@@ -43,7 +43,7 @@
hallucinated_item.desc = initial(template_item_type.desc)
hallucinated_item.icon = initial(template_item_type.icon)
hallucinated_item.icon_state = initial(template_item_type.icon_state)
- hallucinated_item.w_class = initial(template_item_type.w_class) // Not strictly necessary, but keen eyed people will notice
+ hallucinated_item.update_weight_class(initial(template_item_type.w_class)) // Not strictly necessary, but keen eyed people will notice
return hallucinated_item
diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm
index 7b4b23a313b..1ff5bc47a55 100644
--- a/code/modules/holodeck/computer.dm
+++ b/code/modules/holodeck/computer.dm
@@ -84,11 +84,8 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf
//creates the timer that determines if another program can be manually loaded
COOLDOWN_DECLARE(holodeck_cooldown)
-/obj/machinery/computer/holodeck/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/computer/holodeck/LateInitialize()//from here linked is populated and the program list is generated. its also set to load the offline program
+/obj/machinery/computer/holodeck/post_machine_initialize() //from here linked is populated and the program list is generated. its also set to load the offline program
+ . = ..()
linked = GLOB.areas_by_type[mapped_start_area]
if(!linked)
log_mapping("[src] at [AREACOORD(src)] has no matching holodeck area.")
@@ -295,12 +292,12 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf
holo_object.resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
if(isstructure(holo_object))
- holo_object.obj_flags |= NO_DECONSTRUCTION
+ holo_object.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION
return
if(ismachinery(holo_object))
var/obj/machinery/holo_machine = holo_object
- holo_machine.obj_flags |= NO_DECONSTRUCTION
+ holo_machine.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION
holo_machine.power_change()
if(istype(holo_machine, /obj/machinery/button))
diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm
index afd4c227038..caa5b425ca4 100644
--- a/code/modules/holodeck/holo_effect.dm
+++ b/code/modules/holodeck/holo_effect.dm
@@ -50,7 +50,7 @@
var/newtype = pick(subtypesof(/obj/item/book/manual) - banned_books)
var/obj/item/book/manual/to_spawn = new newtype(loc)
to_spawn.flags_1 |= HOLOGRAM_1
- to_spawn.obj_flags |= NO_DECONSTRUCTION
+ to_spawn.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION
return to_spawn
/obj/effect/holodeck_effect/mobspawner
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index 3e54c134106..51e09f8ab9a 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -8,9 +8,8 @@
/turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user)
return // HOLOFLOOR DOES NOT GIVE A FUCK
-/turf/open/floor/holofloor/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- SHOULD_CALL_PARENT(FALSE)
- return NONE // Fuck you
+/turf/open/floor/holofloor/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ return ITEM_INTERACT_BLOCKING // Fuck you
/turf/open/floor/holofloor/burn_tile()
return //you can't burn a hologram!
diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm
index 260c4042a0a..35bf611b506 100644
--- a/code/modules/hydroponics/biogenerator.dm
+++ b/code/modules/hydroponics/biogenerator.dm
@@ -13,6 +13,7 @@
density = TRUE
circuit = /obj/item/circuitboard/machine/biogenerator
processing_flags = START_PROCESSING_MANUALLY
+ interaction_flags_click = FORBID_TELEKINESIS_REACH
/// Whether the biogenerator is currently processing biomass or not.
var/processing = FALSE
/// The reagent container that is currently inside of the biomass generator. Can be null.
@@ -272,10 +273,9 @@
to_chat(user, span_warning("You cannot put \the [attacking_item] in \the [src]!"))
-/obj/machinery/biogenerator/AltClick(mob/living/user)
- . = ..()
- if(user.can_perform_action(src, FORBID_TELEKINESIS_REACH) && can_interact(user))
- eject_beaker(user)
+/obj/machinery/biogenerator/click_alt(mob/living/user)
+ eject_beaker(user)
+ return CLICK_ACTION_SUCCESS
/// Activates biomass processing and converts all inserted food products into biomass
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index ad12fa24e68..181a6fd9971 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -1099,8 +1099,6 @@
set_self_sustaining(!self_sustaining)
to_chat(user, span_notice("You [self_sustaining ? "activate" : "deactivated"] [src]'s autogrow function[self_sustaining ? ", maintaining the tray's health while using high amounts of power" : ""]."))
-/obj/machinery/hydroponics/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/machinery/hydroponics/attack_hand_secondary(mob/user, list/modifiers)
. = ..()
@@ -1159,7 +1157,6 @@
circuit = null
density = FALSE
use_power = NO_POWER_USE
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
unwrenchable = FALSE
self_sustaining_overlay_icon_state = null
maxnutri = 15
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 71fc93f8930..aa7c8e82222 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -246,7 +246,7 @@
else
t_prod = new product(output_loc, new_seed = src)
if(parent.myseed.plantname != initial(parent.myseed.plantname))
- t_prod.name = lowertext(parent.myseed.plantname)
+ t_prod.name = LOWER_TEXT(parent.myseed.plantname)
if(productdesc)
t_prod.desc = productdesc
t_prod.seed.name = parent.myseed.name
@@ -487,7 +487,7 @@
return
if(!user.can_perform_action(src))
return
- name = "[lowertext(newplantname)]"
+ name = "[LOWER_TEXT(newplantname)]"
plantname = newplantname
if("Seed Description")
var/newdesc = tgui_input_text(user, "Write a new seed description", "Seed Description", desc, 180)
diff --git a/code/modules/instruments/songs/play_legacy.dm b/code/modules/instruments/songs/play_legacy.dm
index 7094de85a89..c49122d4641 100644
--- a/code/modules/instruments/songs/play_legacy.dm
+++ b/code/modules/instruments/songs/play_legacy.dm
@@ -9,7 +9,7 @@
var/list/octaves = list(3, 3, 3, 3, 3, 3, 3)
var/list/accents = list("n", "n", "n", "n", "n", "n", "n")
for(var/line in lines)
- var/list/chords = splittext(lowertext(line), ",")
+ var/list/chords = splittext(LOWER_TEXT(line), ",")
for(var/chord in chords)
var/list/compiled_chord = list()
var/tempodiv = 1
diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm
index 836c2fdd86b..05e23a8c97a 100644
--- a/code/modules/instruments/songs/play_synthesized.dm
+++ b/code/modules/instruments/songs/play_synthesized.dm
@@ -9,7 +9,7 @@
var/list/octaves = list(3, 3, 3, 3, 3, 3, 3)
var/list/accents = list("n", "n", "n", "n", "n", "n", "n")
for(var/line in lines)
- var/list/chords = splittext(lowertext(line), ",")
+ var/list/chords = splittext(LOWER_TEXT(line), ",")
for(var/chord in chords)
var/list/compiled_chord = list()
var/tempodiv = 1
diff --git a/code/modules/jobs/job_types/chaplain/chaplain.dm b/code/modules/jobs/job_types/chaplain/chaplain.dm
index 58821ec5358..8bcfaefcfc6 100644
--- a/code/modules/jobs/job_types/chaplain/chaplain.dm
+++ b/code/modules/jobs/job_types/chaplain/chaplain.dm
@@ -69,7 +69,7 @@
var/new_bible = player_client?.prefs?.read_preference(/datum/preference/name/bible) || DEFAULT_BIBLE
holy_bible.deity_name = new_deity
- switch(lowertext(new_religion))
+ switch(LOWER_TEXT(new_religion))
if("homosexuality", "gay", "penis", "ass", "cock", "cocks")
new_bible = pick("Guys Gone Wild","Coming Out of The Closet","War of Cocks")
switch(new_bible)
diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm
index 607c7214d90..58e7ad829bc 100644
--- a/code/modules/jobs/job_types/clown.dm
+++ b/code/modules/jobs/job_types/clown.dm
@@ -56,6 +56,7 @@
/obj/item/reagent_containers/spray/waterflower = 1,
/obj/item/food/grown/banana = 1,
/obj/item/instrument/bikehorn = 1,
+ /obj/item/storage/box/balloons = 1,
)
belt = /obj/item/modular_computer/pda/clown
ears = /obj/item/radio/headset/headset_srv
@@ -71,6 +72,7 @@
box = /obj/item/storage/box/survival/hug
chameleon_extras = /obj/item/stamp/clown
implants = list(/obj/item/implant/sad_trombone)
+ skillchips = list(/obj/item/skillchip/job/clown)
/datum/outfit/job/clown/mod
name = "Clown (MODsuit)"
diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm
index 9e09a7e81c0..f9d11a4817b 100644
--- a/code/modules/jobs/job_types/prisoner.dm
+++ b/code/modules/jobs/job_types/prisoner.dm
@@ -70,9 +70,9 @@
. = ..()
var/crime_name = new_prisoner.client?.prefs?.read_preference(/datum/preference/choiced/prisoner_crime)
- if(!crime_name)
- return
var/datum/prisoner_crime/crime = GLOB.prisoner_crimes[crime_name]
+ if (isnull(crime))
+ return
var/list/limbs_to_tat = new_prisoner.bodyparts.Copy()
for(var/i in 1 to crime.tattoos)
if(!length(SSpersistence.prison_tattoos_to_use) || visualsOnly)
diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm
index 62a39d0c6f8..994d0d34c4c 100644
--- a/code/modules/jobs/jobs.dm
+++ b/code/modules/jobs/jobs.dm
@@ -65,7 +65,7 @@ GLOBAL_PROTECT(exp_specialmap)
var/static/regex/chef_expand = new("chef")
var/static/regex/borg_expand = new("(? owner.mob.see_invisible)
+ continue
+
+ // convert
+ var/datum/search_object/index = new(owner, thing)
+ add_to_index(index)
+
+ var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src)
+ window?.send_update()
+
+ if(length(to_image))
+ SSlooting.backlog += src
+
+
+/// For: Resetting to empty. Ignores the searchable qdel event
+/datum/lootpanel/proc/reset_contents()
+ for(var/datum/search_object/index as anything in contents)
+ contents -= index
+ to_image -= index
+
+ if(QDELETED(index))
+ continue
+
+ UnregisterSignal(index, COMSIG_QDELETING)
+ qdel(index)
diff --git a/code/modules/lootpanel/handlers.dm b/code/modules/lootpanel/handlers.dm
new file mode 100644
index 00000000000..40a76974ed4
--- /dev/null
+++ b/code/modules/lootpanel/handlers.dm
@@ -0,0 +1,19 @@
+/// On contents change, either reset or update
+/datum/lootpanel/proc/on_searchable_deleted(datum/search_object/source)
+ SIGNAL_HANDLER
+
+ contents -= source
+ to_image -= source
+
+ var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src)
+#if !defined(UNIT_TESTS) // we dont want to delete contents if we're testing
+ if(isnull(window))
+ reset_contents()
+ return
+#endif
+
+ if(isturf(source.item))
+ populate_contents()
+ return
+
+ window?.send_update()
diff --git a/code/modules/lootpanel/misc.dm b/code/modules/lootpanel/misc.dm
new file mode 100644
index 00000000000..6e8448b8205
--- /dev/null
+++ b/code/modules/lootpanel/misc.dm
@@ -0,0 +1,48 @@
+/// Helper to open the panel
+/datum/lootpanel/proc/open(turf/tile)
+ source_turf = tile
+
+#if !defined(OPENDREAM) && !defined(UNIT_TESTS)
+ if(!notified)
+ var/build = owner.byond_build
+ var/version = owner.byond_version
+ if(build < 515 || (build == 515 && version < 1635))
+ to_chat(owner.mob, examine_block(span_info("\
+ Your version of Byond doesn't support fast image loading.\n\
+ Detected: [version].[build]\n\
+ Required version for this feature: 515.1635 or later.\n\
+ Visit BYOND's website to get the latest version of BYOND.\n\
+ ")))
+
+ notified = TRUE
+#endif
+
+ populate_contents()
+ ui_interact(owner.mob)
+
+
+/**
+ * Called by SSlooting whenever this datum is added to its backlog.
+ * Iterates over to_image list to create icons, then removes them.
+ * Returns boolean - whether this proc has finished the queue or not.
+ */
+/datum/lootpanel/proc/process_images()
+ for(var/datum/search_object/index as anything in to_image)
+ to_image -= index
+
+ if(QDELETED(index) || index.icon)
+ continue
+
+ index.generate_icon(owner)
+
+ if(TICK_CHECK)
+ break
+
+ var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src)
+ if(isnull(window))
+ reset_contents()
+ return TRUE
+
+ window.send_update()
+
+ return !length(to_image)
diff --git a/code/modules/lootpanel/search_object.dm b/code/modules/lootpanel/search_object.dm
new file mode 100644
index 00000000000..520228e465e
--- /dev/null
+++ b/code/modules/lootpanel/search_object.dm
@@ -0,0 +1,84 @@
+/**
+ * ## Search Object
+ * An object for content lists. Compacted item data.
+ */
+/datum/search_object
+ /// Item we're indexing
+ var/atom/item
+ /// Url to the image of the object
+ var/icon
+ /// Icon state, for inexpensive icons
+ var/icon_state
+ /// Name of the original object
+ var/name
+ /// Typepath of the original object for ui grouping
+ var/path
+
+
+/datum/search_object/New(client/owner, atom/item)
+ . = ..()
+
+ src.item = item
+ name = item.name
+ if(isobj(item))
+ path = item.type
+
+ if(isturf(item))
+ RegisterSignal(item, COMSIG_TURF_CHANGE, PROC_REF(on_turf_change))
+ else
+ RegisterSignals(item, list(
+ COMSIG_ITEM_PICKUP,
+ COMSIG_MOVABLE_MOVED,
+ COMSIG_QDELETING,
+ ), PROC_REF(on_item_moved))
+
+ // Icon generation conditions //////////////
+ // Condition 1: Icon is complex
+ if(ismob(item) || length(item.overlays) > 2)
+ return
+
+ // Condition 2: Can't get icon path
+ if(!isfile(item.icon) || !length("[item.icon]"))
+ return
+
+ // Condition 3: Using opendream
+#if defined(OPENDREAM) || defined(UNIT_TESTS)
+ return
+#endif
+
+ // Condition 4: Using older byond version
+ var/build = owner.byond_build
+ var/version = owner.byond_version
+ if(build < 515 || (build == 515 && version < 1635))
+ return
+
+ icon = "[item.icon]"
+ icon_state = item.icon_state
+
+
+/datum/search_object/Destroy(force)
+ item = null
+
+ return ..()
+
+
+/// Generates the icon for the search object. This is the expensive part.
+/datum/search_object/proc/generate_icon(client/owner)
+ if(ismob(item) || length(item.overlays) > 2)
+ icon = costly_icon2html(item, owner, sourceonly = TRUE)
+ else // our pre 515.1635 fallback for normal items
+ icon = icon2html(item, owner, sourceonly = TRUE)
+
+
+/// Parent item has been altered, search object no longer valid
+/datum/search_object/proc/on_item_moved(atom/source)
+ SIGNAL_HANDLER
+
+ qdel(src)
+
+
+/// Parent tile has been altered, entire search needs reset
+/datum/search_object/proc/on_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks)
+ SIGNAL_HANDLER
+
+ post_change_callbacks += CALLBACK(src, GLOBAL_PROC_REF(qdel), src)
diff --git a/code/modules/lootpanel/ss_looting.dm b/code/modules/lootpanel/ss_looting.dm
new file mode 100644
index 00000000000..cf0882fa890
--- /dev/null
+++ b/code/modules/lootpanel/ss_looting.dm
@@ -0,0 +1,39 @@
+
+/// Queues image generation for search objects without icons
+SUBSYSTEM_DEF(looting)
+ name = "Loot Icon Generation"
+ init_order = INIT_ORDER_LOOT
+ priority = FIRE_PRIORITY_PROCESS
+ wait = 0.5 SECONDS
+ /// Backlog of items. Gets put into processing
+ var/list/datum/lootpanel/backlog = list()
+ /// Actively processing items
+ var/list/datum/lootpanel/processing = list()
+
+
+/datum/controller/subsystem/looting/stat_entry(msg)
+ msg = "P:[length(backlog)]"
+ return ..()
+
+
+/datum/controller/subsystem/looting/fire(resumed)
+ if(!length(backlog))
+ return
+
+ if(!resumed)
+ processing = backlog
+ backlog = list()
+
+ while(length(processing))
+ var/datum/lootpanel/panel = processing[length(processing)]
+ if(QDELETED(panel) || !length(panel.to_image))
+ processing.len--
+ continue
+
+ if(!panel.process_images())
+ backlog += panel
+
+ if(MC_TICK_CHECK)
+ return
+
+ processing.len--
diff --git a/code/modules/lootpanel/ui.dm b/code/modules/lootpanel/ui.dm
new file mode 100644
index 00000000000..c7f0cf2358d
--- /dev/null
+++ b/code/modules/lootpanel/ui.dm
@@ -0,0 +1,42 @@
+/// UI helper for converting the associative list to a list of lists
+/datum/lootpanel/proc/get_contents()
+ var/list/items = list()
+
+ for(var/datum/search_object/index as anything in contents)
+ UNTYPED_LIST_ADD(items, list(
+ "icon_state" = index.icon_state,
+ "icon" = index.icon,
+ "name" = index.name,
+ "path" = index.path,
+ "ref" = REF(index),
+ ))
+
+ return items
+
+
+/// Clicks an object from the contents. Validates the object and the user
+/datum/lootpanel/proc/grab(mob/user, list/params)
+ var/ref = params["ref"]
+ if(isnull(ref))
+ return FALSE
+
+ var/datum/search_object/index = locate(ref) in contents
+ var/atom/thing = index?.item
+ if(QDELETED(index) || QDELETED(thing)) // Obj is gone
+ return FALSE
+
+ if(thing != source_turf && !(locate(thing) in source_turf.contents))
+ qdel(index) // Item has moved
+ return TRUE
+
+ var/modifiers = ""
+ if(params["ctrl"])
+ modifiers += "ctrl=1;"
+ if(params["middle"])
+ modifiers += "middle=1;"
+ if(params["shift"])
+ modifiers += "shift=1;"
+
+ user.ClickOn(thing, modifiers)
+
+ return TRUE
diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
index 8a2949f9893..1c0a5392fb9 100644
--- a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
+++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
@@ -159,9 +159,14 @@
mask = /obj/item/clothing/mask/fakemoustache/italian
/obj/machinery/vending/hotdog/museum
- obj_flags = parent_type::obj_flags|NO_DECONSTRUCTION
onstation_override = TRUE
+/obj/machinery/vending/hotdog/museum/screwdriver_act(mob/living/user, obj/item/attack_item)
+ return NONE
+
+/obj/machinery/vending/hotdog/museum/crowbar_act(mob/living/user, obj/item/attack_item)
+ return NONE
+
#define CAFE_KEYCARD_TOILETS "museum_cafe_key_toilets"
///Do not place these beyond the cafeteria shutters, or you might lock people out of reaching it.
@@ -185,7 +190,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/item/keycard/cafeteria/LateInitialize()
- . = ..()
if(SSqueuelinks.queues[CAFE_KEYCARD_TOILETS])
SSqueuelinks.pop_link(CAFE_KEYCARD_TOILETS)
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm b/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm
index ba311d44a2a..f290c06d78f 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm
@@ -17,7 +17,7 @@
/obj/effect/anomaly/flux,
/obj/effect/anomaly/bluespace,
/obj/effect/anomaly/hallucination,
- /obj/effect/anomaly/bioscrambler
+ /obj/effect/anomaly/bioscrambler/docile
)
///Do we anchor the anomaly? Set to true if you don't want anomalies drifting away (like if theyre in space or something)
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm
index b61e14e8916..c699b25666e 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm
@@ -363,20 +363,21 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
if(get_dist(get_turf(src), get_turf(user)) <= 1)
promptExit(user)
-/turf/closed/indestructible/hoteldoor/AltClick(mob/user)
- . = ..()
- if(get_dist(get_turf(src), get_turf(user)) <= 1)
- to_chat(user, span_notice("You peak through the door's bluespace peephole..."))
- user.reset_perspective(parentSphere)
- var/datum/action/peephole_cancel/PHC = new
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
- PHC.Grant(user)
- RegisterSignal(user, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/atom/, check_eye), user)
+/turf/closed/indestructible/hoteldoor/click_alt(mob/user)
+ to_chat(user, span_notice("You peak through the door's bluespace peephole..."))
+ user.reset_perspective(parentSphere)
+ var/datum/action/peephole_cancel/PHC = new
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
+ PHC.Grant(user)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_eye))
+ return CLICK_ACTION_SUCCESS
-/turf/closed/indestructible/hoteldoor/check_eye(mob/user)
- if(get_dist(get_turf(src), get_turf(user)) >= 2)
- for(var/datum/action/peephole_cancel/PHC in user.actions)
- INVOKE_ASYNC(PHC, TYPE_PROC_REF(/datum/action/peephole_cancel, Trigger))
+/turf/closed/indestructible/hoteldoor/proc/check_eye(mob/user, atom/oldloc, direction)
+ SIGNAL_HANDLER
+ if(get_dist(get_turf(src), get_turf(user)) < 2)
+ return
+ for(var/datum/action/peephole_cancel/PHC in user.actions)
+ INVOKE_ASYNC(PHC, TYPE_PROC_REF(/datum/action/peephole_cancel, Trigger))
/datum/action/peephole_cancel
name = "Cancel View"
diff --git a/code/modules/mapping/mail_sorting_helpers.dm b/code/modules/mapping/mail_sorting_helpers.dm
index 964a4998600..259b9ef8f37 100644
--- a/code/modules/mapping/mail_sorting_helpers.dm
+++ b/code/modules/mapping/mail_sorting_helpers.dm
@@ -3,10 +3,6 @@
late = TRUE
var/sort_type = SORT_TYPE_WASTE
-/obj/effect/mapping_helpers/mail_sorting/Initialize(mapload)
- ..()
- return INITIALIZE_HINT_LATELOAD
-
/obj/effect/mapping_helpers/mail_sorting/LateInitialize()
var/obj/structure/disposalpipe/sorting/mail/mail_sorter = locate(/obj/structure/disposalpipe/sorting/mail) in loc
if(mail_sorter)
diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm
index e601256a8b6..a2ffa244679 100644
--- a/code/modules/mapping/mapping_helpers.dm
+++ b/code/modules/mapping/mapping_helpers.dm
@@ -138,7 +138,6 @@
payload(airlock)
/obj/effect/mapping_helpers/airlock/LateInitialize()
- . = ..()
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
if(!airlock)
qdel(src)
@@ -283,7 +282,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/effect/mapping_helpers/airalarm/LateInitialize()
- . = ..()
var/obj/machinery/airalarm/target = locate(/obj/machinery/airalarm) in loc
if(isnull(target))
@@ -442,7 +440,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/effect/mapping_helpers/apc/LateInitialize()
- . = ..()
var/obj/machinery/power/apc/target = locate(/obj/machinery/power/apc) in loc
if(isnull(target))
@@ -1106,8 +1103,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
*/
/obj/effect/mapping_helpers/trapdoor_placer
name = "trapdoor placer"
- late = TRUE
icon_state = "trapdoor"
+ late = TRUE
/obj/effect/mapping_helpers/trapdoor_placer/LateInitialize()
var/turf/component_target = get_turf(src)
@@ -1187,12 +1184,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
name = "broken floor"
icon = 'icons/turf/damaged.dmi'
icon_state = "damaged1"
- late = TRUE
layer = ABOVE_NORMAL_TURF_LAYER
-
-/obj/effect/mapping_helpers/broken_floor/Initialize(mapload)
- .=..()
- return INITIALIZE_HINT_LATELOAD
+ late = TRUE
/obj/effect/mapping_helpers/broken_floor/LateInitialize()
var/turf/open/floor/floor = get_turf(src)
@@ -1203,12 +1196,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
name = "burnt floor"
icon = 'icons/turf/damaged.dmi'
icon_state = "floorscorched1"
- late = TRUE
layer = ABOVE_NORMAL_TURF_LAYER
-
-/obj/effect/mapping_helpers/burnt_floor/Initialize(mapload)
- .=..()
- return INITIALIZE_HINT_LATELOAD
+ late = TRUE
/obj/effect/mapping_helpers/burnt_floor/LateInitialize()
var/turf/open/floor/floor = get_turf(src)
@@ -1237,7 +1226,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
return INITIALIZE_HINT_LATELOAD
/obj/effect/mapping_helpers/broken_machine/LateInitialize()
- . = ..()
var/obj/machinery/target = locate(/obj/machinery) in loc
if(isnull(target))
@@ -1271,7 +1259,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
return INITIALIZE_HINT_LATELOAD
/obj/effect/mapping_helpers/damaged_window/LateInitialize()
- . = ..()
var/obj/structure/window/target = locate(/obj/structure/window) in loc
if(isnull(target))
@@ -1304,7 +1291,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
return INITIALIZE_HINT_LATELOAD
-/obj/effect/mapping_helpers/requests_console/LateInitialize(mapload)
+/obj/effect/mapping_helpers/requests_console/LateInitialize()
var/obj/machinery/airalarm/target = locate(/obj/machinery/requests_console) in loc
if(isnull(target))
var/area/target_area = get_area(target)
@@ -1441,7 +1428,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
return INITIALIZE_HINT_QDEL
/obj/effect/mapping_helpers/basic_mob_flags/LateInitialize()
- . = ..()
var/had_any_mobs = FALSE
for(var/mob/living/basic/basic_mobs in loc)
had_any_mobs = TRUE
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 5022dac212c..0b029bc3b63 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -60,10 +60,9 @@
return ..()
-/obj/structure/closet/crate/secure/loot/AltClick(mob/living/user)
- if(!user.can_perform_action(src))
- return
- return attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom.
+/obj/structure/closet/crate/secure/loot/click_alt(mob/living/user)
+ attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom.
+ return CLICK_ACTION_SUCCESS
/obj/structure/closet/crate/secure/loot/attackby(obj/item/W, mob/user)
if(locked)
diff --git a/code/modules/mining/boulder_processing/_boulder_processing.dm b/code/modules/mining/boulder_processing/_boulder_processing.dm
index 0dfc43cf7f7..5795eed1d74 100644
--- a/code/modules/mining/boulder_processing/_boulder_processing.dm
+++ b/code/modules/mining/boulder_processing/_boulder_processing.dm
@@ -38,7 +38,7 @@
register_context()
-/obj/machinery/bouldertech/LateInitialize()
+/obj/machinery/bouldertech/post_machine_initialize()
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
@@ -244,9 +244,9 @@
return FALSE
-/obj/machinery/bouldertech/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/bouldertech/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(panel_open || user.combat_mode)
- return ..()
+ return NONE
if(istype(tool, /obj/item/boulder))
var/obj/item/boulder/my_boulder = tool
@@ -276,7 +276,7 @@
to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card]."))
return ITEM_INTERACT_SUCCESS
- return ..()
+ return NONE
/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
diff --git a/code/modules/mining/boulder_processing/boulder_types.dm b/code/modules/mining/boulder_processing/boulder_types.dm
index 08ed961404c..1ffce8737bd 100644
--- a/code/modules/mining/boulder_processing/boulder_types.dm
+++ b/code/modules/mining/boulder_processing/boulder_types.dm
@@ -44,7 +44,7 @@
/datum/material/uranium = 3,
)
- set_custom_materials(list(pick_weight(gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3)))
+ set_custom_materials(list(pick_weight(gulag_minerals) = SHEET_MATERIAL_AMOUNT))
///Boulders usually spawned in lavaland labour camp area but with bluespace material
/obj/item/boulder/gulag_expanded
@@ -66,7 +66,7 @@
/datum/material/uranium = 3,
)
- set_custom_materials(list(pick_weight(expanded_gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3)))
+ set_custom_materials(list(pick_weight(expanded_gulag_minerals) = SHEET_MATERIAL_AMOUNT))
///lowgrade boulder, most commonly spawned
/obj/item/boulder/shabby
diff --git a/code/modules/mining/boulder_processing/brm.dm b/code/modules/mining/boulder_processing/brm.dm
index 259c3eed5f6..61c5469b459 100644
--- a/code/modules/mining/boulder_processing/brm.dm
+++ b/code/modules/mining/boulder_processing/brm.dm
@@ -101,7 +101,7 @@
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
-///To allow boulders on a conveyer belt to move unobstructed if multiple machines are made on a single line
+///To allow boulders on a conveyor belt to move unobstructed if multiple machines are made on a single line
/obj/machinery/brm/CanAllowThrough(atom/movable/mover, border_dir)
if(!anchored)
return FALSE
diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm
index 38df199b251..4845b0f9c00 100644
--- a/code/modules/mining/equipment/explorer_gear.dm
+++ b/code/modules/mining/equipment/explorer_gear.dm
@@ -90,7 +90,7 @@
/obj/item/clothing/mask/gas/explorer/adjustmask(mob/user)
. = ..()
// adjusted = out of the way = smaller = can fit in boxes
- w_class = mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL
+ update_weight_class(mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL)
inhand_icon_state = mask_adjusted ? "[initial(inhand_icon_state)]_up" : initial(inhand_icon_state)
if(user)
user.update_held_items()
@@ -131,24 +131,25 @@
hoodtype = /obj/item/clothing/head/hooded/cloakhood/goliath
body_parts_covered = CHEST|GROIN|ARMS
-/obj/item/clothing/suit/hooded/cloak/goliath/AltClick(mob/user)
- . = ..()
- if(iscarbon(user))
- var/mob/living/carbon/char = user
- if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_OCLOTHING) == src))
- to_chat(user, span_warning("You can't adjust [src] while wearing it!"))
- return
- if(!user.is_holding(src))
- to_chat(user, span_warning("You must be holding [src] in order to adjust it!"))
- return
- if(slot_flags & ITEM_SLOT_OCLOTHING)
- slot_flags = ITEM_SLOT_NECK
- set_armor(/datum/armor/none)
- user.visible_message(span_notice("[user] adjusts their [src] for ceremonial use."), span_notice("You adjust your [src] for ceremonial use."))
- else
- slot_flags = initial(slot_flags)
- set_armor(initial(armor_type))
- user.visible_message(span_notice("[user] adjusts their [src] for defensive use."), span_notice("You adjust your [src] for defensive use."))
+/obj/item/clothing/suit/hooded/cloak/goliath/click_alt(mob/user)
+ if(!iscarbon(user))
+ return NONE
+ var/mob/living/carbon/char = user
+ if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_OCLOTHING) == src))
+ to_chat(user, span_warning("You can't adjust [src] while wearing it!"))
+ return CLICK_ACTION_BLOCKING
+ if(!user.is_holding(src))
+ to_chat(user, span_warning("You must be holding [src] in order to adjust it!"))
+ return CLICK_ACTION_BLOCKING
+ if(slot_flags & ITEM_SLOT_OCLOTHING)
+ slot_flags = ITEM_SLOT_NECK
+ set_armor(/datum/armor/none)
+ user.visible_message(span_notice("[user] adjusts their [src] for ceremonial use."), span_notice("You adjust your [src] for ceremonial use."))
+ else
+ slot_flags = initial(slot_flags)
+ set_armor(initial(armor_type))
+ user.visible_message(span_notice("[user] adjusts their [src] for defensive use."), span_notice("You adjust your [src] for defensive use."))
+ return CLICK_ACTION_SUCCESS
/datum/armor/cloak_goliath
melee = 35
@@ -353,4 +354,3 @@
desc = "An armoured hood for exploring harsh environments."
icon_state = "explorer_syndicate"
armor_type = /datum/armor/hooded_explorer_syndicate
-
diff --git a/code/modules/mining/equipment/grapple_gun.dm b/code/modules/mining/equipment/grapple_gun.dm
new file mode 100644
index 00000000000..c7c91ede73e
--- /dev/null
+++ b/code/modules/mining/equipment/grapple_gun.dm
@@ -0,0 +1,183 @@
+#define DAMAGE_ON_IMPACT 20
+
+/obj/item/grapple_gun
+ name = "grapple gun"
+ desc = "A handy tool for traversing the land-scape of lava-land!"
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "grapple_gun"
+ lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
+ inhand_icon_state = "gun"
+ item_flags = NOBLUDGEON
+ ///overlay when the hook is retracted
+ var/static/mutable_appearance/hook_overlay = new(icon = 'icons/obj/mining.dmi', icon_state = "grapple_gun_hooked")
+ ///is the hook retracted
+ var/hooked = TRUE
+ ///addtimer id for launching the user
+ var/grapple_timer_id
+ ///traits we apply to the user when being launched
+ var/static/list/traits_on_zipline = list(
+ TRAIT_IMMOBILIZED,
+ TRAIT_MOVE_FLOATING,
+ TRAIT_FORCED_STANDING,
+ )
+ ///the beam we draw
+ var/datum/beam/zipline
+ ///our user currently ziplining
+ var/datum/weakref/zipliner
+ ///ziplining sound
+ var/datum/looping_sound/zipline/zipline_sound
+ ///our initial matrix
+ var/matrix/initial_matrix
+
+/obj/item/grapple_gun/Initialize(mapload)
+ . = ..()
+ zipline_sound = new(src)
+ update_appearance()
+
+/obj/item/grapple_gun/afterattack(atom/target, mob/living/user, proximity)
+ . = ..()
+
+ if(isgroundlessturf(target))
+ return
+
+ if(!lavaland_equipment_pressure_check(get_turf(user)))
+ user.balloon_alert(user, "gun mechanism wont work here!")
+ return
+
+ if(target == user || !hooked)
+ return
+
+ if(get_dist(user, target) > 9)
+ user.balloon_alert(user, "too far away!")
+ return
+
+ var/turf/attacked_atom = get_turf(target)
+ if(isnull(attacked_atom))
+ return
+
+ var/list/turf_list = (get_line(user, attacked_atom) - get_turf(src))
+ for(var/turf/singular_turf as anything in turf_list)
+ if(ischasm(singular_turf))
+ continue
+ if(!singular_turf.is_blocked_turf())
+ continue
+ attacked_atom = singular_turf
+ break
+
+ if(user.CanReach(attacked_atom))
+ return
+
+ . |= AFTERATTACK_PROCESSED_ITEM
+
+ var/atom/bullet = fire_projectile(/obj/projectile/grapple_hook, attacked_atom, 'sound/weapons/zipline_fire.ogg')
+ zipline = user.Beam(bullet, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER)
+ hooked = FALSE
+ RegisterSignal(bullet, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(on_grapple_hit))
+ RegisterSignal(bullet, COMSIG_PREQDELETED, PROC_REF(on_grapple_fail))
+ zipliner = WEAKREF(user)
+ update_appearance()
+
+/obj/item/grapple_gun/proc/on_grapple_hit(datum/source, atom/movable/firer, atom/target, Angle)
+ SIGNAL_HANDLER
+
+ UnregisterSignal(source, list(COMSIG_PROJECTILE_ON_HIT, COMSIG_PREQDELETED))
+ QDEL_NULL(zipline)
+ var/mob/living/user = zipliner?.resolve()
+ if(isnull(user) || isnull(target))
+ cancel_hook()
+ return
+
+ zipline = user.Beam(target, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(determine_distance))
+ RegisterSignal(user, COMSIG_MOVABLE_PRE_THROW, PROC_REF(apply_throw_traits))
+ grapple_timer_id = addtimer(CALLBACK(src, PROC_REF(launch_user), target), 1.5 SECONDS, TIMER_STOPPABLE)
+
+/obj/item/grapple_gun/proc/on_grapple_fail(datum/source)
+ SIGNAL_HANDLER
+ cancel_hook()
+
+/obj/item/grapple_gun/proc/determine_distance(atom/movable/source)
+ SIGNAL_HANDLER
+
+ if(isnull(zipline))
+ return
+ var/atom/target = zipline.target
+ if(isnull(target))
+ return
+ if(get_dist(source, target) > zipline.max_distance)
+ cancel_hook()
+
+/obj/item/grapple_gun/proc/apply_throw_traits(mob/living/source, list/arguements)
+ SIGNAL_HANDLER
+ var/atom/target_atom = arguements[1]
+ if(isnull(target_atom))
+ return
+ var/dir_to_turn = get_angle(source, target_atom)
+ if(dir_to_turn > 175 && dir_to_turn < 190)
+ dir_to_turn = 0
+ source.add_traits(traits_on_zipline, LEAPING_TRAIT)
+ initial_matrix = source.transform
+ animate(source, transform = matrix().Turn(dir_to_turn), time = 0.1 SECONDS)
+
+/obj/item/grapple_gun/proc/launch_user(atom/target_atom)
+ var/mob/living/my_user = zipliner?.resolve()
+ if(isnull(my_user) || isnull(target_atom) || my_user.buckled)
+ cancel_hook()
+ return
+ zipline_sound.start()
+ new /obj/effect/temp_visual/mook_dust(drop_location())
+ RegisterSignal(my_user, COMSIG_MOVABLE_IMPACT, PROC_REF(strike_target))
+ my_user.throw_at(target = target_atom, range = 9, speed = 1, spin = FALSE, gentle = TRUE, callback = CALLBACK(src, PROC_REF(post_land)))
+
+/obj/item/grapple_gun/proc/strike_target(mob/living/source, mob/living/victim, datum/thrownthing/throwingdatum)
+ SIGNAL_HANDLER
+
+ if(!istype(victim))
+ return
+
+ victim.apply_damage(DAMAGE_ON_IMPACT)
+ playsound(victim, 'sound/effects/hit_kick.ogg', 50)
+ var/turf/target_turf = get_ranged_target_turf(victim, source.dir, 3)
+ if(isnull(target_turf))
+ return
+ victim.throw_at(target = target_turf, speed = 1, spin = TRUE, range = 3)
+
+
+/obj/item/grapple_gun/proc/post_land()
+ var/mob/living/my_user = zipliner?.resolve()
+ if(!isnull(my_user))
+ my_user.transform = initial_matrix
+ my_user.remove_traits(traits_on_zipline, LEAPING_TRAIT)
+ new /obj/effect/temp_visual/mook_dust(drop_location())
+ cancel_hook()
+
+/obj/item/grapple_gun/proc/cancel_hook()
+ var/atom/my_zipliner = zipliner?.resolve()
+ if(!isnull(my_zipliner))
+ UnregisterSignal(my_zipliner, list(COMSIG_MOVABLE_IMPACT, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_PRE_THROW))
+ QDEL_NULL(zipline)
+ zipliner = null
+ if(grapple_timer_id)
+ deltimer(grapple_timer_id)
+ grapple_timer_id = null
+ hooked = TRUE
+ zipline_sound.stop()
+ initial_matrix = null
+ update_appearance()
+
+/obj/item/grapple_gun/update_overlays()
+ . = ..()
+ if(hooked)
+ . += hook_overlay
+
+/obj/projectile/grapple_hook
+ name = "grapple hook"
+ icon_state = "grapple_hook"
+ damage = 0
+ range = 9
+ speed = 0.1
+ can_hit_turfs = TRUE
+ hitsound = 'sound/weapons/zipline_hit.ogg'
+
+#undef DAMAGE_ON_IMPACT
diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm
index 38dda48d345..c33181dd806 100644
--- a/code/modules/mining/equipment/marker_beacons.dm
+++ b/code/modules/mining/equipment/marker_beacons.dm
@@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list(
"Alt-click to select a color. Current color is [picked_color]."
/obj/item/stack/marker_beacon/update_icon_state()
- icon_state = "[initial(icon_state)][lowertext(picked_color)]"
+ icon_state = "[initial(icon_state)][LOWER_TEXT(picked_color)]"
return ..()
/obj/item/stack/marker_beacon/attack_self(mob/user)
@@ -59,16 +59,15 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list(
var/obj/structure/marker_beacon/M = new(user.loc, picked_color)
transfer_fingerprints_to(M)
-/obj/item/stack/marker_beacon/AltClick(mob/living/user)
- if(!istype(user) || !user.can_perform_action(src))
- return
+/obj/item/stack/marker_beacon/click_alt(mob/living/user)
var/input_color = tgui_input_list(user, "Choose a color", "Beacon Color", GLOB.marker_beacon_colors)
if(isnull(input_color))
- return
- if(!istype(user) || !user.can_perform_action(src))
- return
+ return CLICK_ACTION_BLOCKING
+ if(!user.can_perform_action(src))
+ return CLICK_ACTION_BLOCKING
picked_color = input_color
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/structure/marker_beacon
name = "marker beacon"
@@ -116,7 +115,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list(
set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color])
/obj/structure/marker_beacon/update_icon_state()
- icon_state = "[icon_prefix][lowertext(picked_color)]-on"
+ icon_state = "[icon_prefix][LOWER_TEXT(picked_color)]-on"
return ..()
/obj/structure/marker_beacon/attack_hand(mob/living/user, list/modifiers)
@@ -154,17 +153,15 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list(
return
return ..()
-/obj/structure/marker_beacon/AltClick(mob/living/user)
- ..()
- if(!istype(user) || !user.can_perform_action(src))
- return
+/obj/structure/marker_beacon/click_alt(mob/living/user)
var/input_color = tgui_input_list(user, "Choose a color", "Beacon Color", GLOB.marker_beacon_colors)
if(isnull(input_color))
- return
- if(!istype(user) || !user.can_perform_action(src))
- return
+ return CLICK_ACTION_BLOCKING
+ if(!user.can_perform_action(src))
+ return NONE
picked_color = input_color
update_appearance()
+ return CLICK_ACTION_SUCCESS
/* Preset marker beacon types, for mapping */
diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm
index 9fdb772c4bc..4fdd997fcab 100644
--- a/code/modules/mining/equipment/mining_tools.dm
+++ b/code/modules/mining/equipment/mining_tools.dm
@@ -257,7 +257,7 @@
tool_behaviour = TOOL_WRENCH
sharpness = NONE
toolspeed = 0.75
- w_class = WEIGHT_CLASS_SMALL
+ update_weight_class(WEIGHT_CLASS_SMALL)
usesound = 'sound/items/ratchet.ogg'
attack_verb_continuous = list("bashes", "bludgeons", "thrashes", "whacks")
attack_verb_simple = list("bash", "bludgeon", "thrash", "whack")
@@ -265,7 +265,7 @@
tool_behaviour = TOOL_SHOVEL
sharpness = SHARP_EDGED
toolspeed = 0.25
- w_class = WEIGHT_CLASS_NORMAL
+ update_weight_class(WEIGHT_CLASS_NORMAL)
usesound = 'sound/effects/shovel_dig.ogg'
attack_verb_continuous = list("slashes", "impales", "stabs", "slices")
attack_verb_simple = list("slash", "impale", "stab", "slice")
@@ -273,7 +273,7 @@
tool_behaviour = TOOL_MINING
sharpness = SHARP_POINTY
toolspeed = 0.5
- w_class = WEIGHT_CLASS_NORMAL
+ update_weight_class(WEIGHT_CLASS_NORMAL)
usesound = 'sound/effects/picaxe1.ogg'
attack_verb_continuous = list("hits", "pierces", "slices", "attacks")
attack_verb_simple = list("hit", "pierce", "slice", "attack")
@@ -372,7 +372,7 @@
var/atom/throw_target = get_edge_target_turf(target_mob, get_dir(user, get_step_away(target_mob, user)))
target_mob.throw_at(throw_target, 2, 2, user, gentle = TRUE)
target_mob.Knockdown(2 SECONDS)
- var/body_zone = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
+ var/body_zone = pick(GLOB.all_body_zones)
user.apply_damage(force / recoil_factor, BRUTE, body_zone, user.run_armor_check(body_zone, MELEE))
to_chat(user, span_danger("The weight of the Big Slappy recoils!"))
log_combat(user, user, "recoiled Big Slappy into")
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index d40589dd3f8..b22603f52d9 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -249,7 +249,18 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/survival_pod/left, 0)
light_color = COLOR_VERY_PALE_LIME_GREEN
max_n_of_items = 10
pixel_y = -4
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+
+/obj/machinery/smartfridge/survival_pod/welder_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/machinery/smartfridge/survival_pod/wrench_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/machinery/smartfridge/survival_pod/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/machinery/smartfridge/survival_pod/crowbar_act(mob/living/user, obj/item/tool)
+ return NONE
/obj/machinery/smartfridge/survival_pod/Initialize(mapload)
AddElement(/datum/element/update_icon_blocker)
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index 8a7ffeec88f..f46c7ecebb9 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -1,4 +1,4 @@
-GLOBAL_LIST(labor_sheet_values)
+#define SHEET_POINT_VALUE 33
/**********************Prisoners' Console**************************/
@@ -22,14 +22,6 @@ GLOBAL_LIST(labor_sheet_values)
if(!stacking_machine)
return INITIALIZE_HINT_QDEL
- if(!GLOB.labor_sheet_values)
- var/sheet_list = list()
- for(var/obj/item/stack/sheet/sheet as anything in subtypesof(/obj/item/stack/sheet))
- if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet)) //ignore no-value sheets and x/fifty subtypes
- continue
- sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
- GLOB.labor_sheet_values = sort_list(sheet_list, GLOBAL_PROC_REF(cmp_sheet_list))
-
/obj/machinery/mineral/labor_claim_console/Destroy()
QDEL_NULL(security_radio)
if(stacking_machine)
@@ -46,11 +38,6 @@ GLOBAL_LIST(labor_sheet_values)
ui = new(user, src, "LaborClaimConsole", name)
ui.open()
-/obj/machinery/mineral/labor_claim_console/ui_static_data(mob/user)
- var/list/data = list()
- data["ores"] = GLOB.labor_sheet_values
- return data
-
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
var/list/data = list()
var/can_go_home = FALSE
@@ -155,8 +142,9 @@ GLOBAL_LIST(labor_sheet_values)
labor_console = null
return ..()
-/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
- points += inp.point_value * inp.amount
+/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/input)
+ if (input.manufactured && input.gulag_valid)
+ points += SHEET_POINT_VALUE * input.amount
return ..()
/obj/machinery/mineral/stacking_machine/laborstacker/attackby(obj/item/weapon, mob/user, params)
@@ -190,3 +178,5 @@ GLOBAL_LIST(labor_sheet_values)
say("ID: [prisoner_id.registered_name].")
say("Points Collected: [prisoner_id.points] / [prisoner_id.goal].")
say("Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.")
+
+#undef SHEET_POINT_VALUE
diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm
index 25214d2ae54..d0e5e08e15d 100644
--- a/code/modules/mining/lavaland/megafauna_loot.dm
+++ b/code/modules/mining/lavaland/megafauna_loot.dm
@@ -291,7 +291,10 @@
if(prob(7.5))
wearer.cause_hallucination(/datum/hallucination/oh_yeah, "H.E.C.K suit", haunt_them = TRUE)
else
- to_chat(wearer, span_warning("[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]"))
+ if(HAS_TRAIT(wearer, TRAIT_ANOSMIA)) //Anosmia quirk holder cannot fell any smell
+ to_chat(wearer, span_warning("[pick("You hear faint whispers.","You feel hot.","You hear a roar in the distance.")]"))
+ else
+ to_chat(wearer, span_warning("[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]"))
/obj/item/clothing/head/hooded/hostile_environment
name = "H.E.C.K. helmet"
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 11a941c4098..61318f63b92 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -143,6 +143,8 @@
var/datum/proximity_monitor/proximity_monitor
///Material container for materials
var/datum/component/material_container/materials
+ /// What can be input into the machine?
+ var/accepted_type = /obj/item/stack
/obj/machinery/mineral/processing_unit/Initialize(mapload)
. = ..()
@@ -153,7 +155,7 @@
SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \
INFINITY, \
MATCONTAINER_EXAMINE, \
- allowed_items = /obj/item/stack \
+ allowed_items = accepted_type \
)
if(!GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter])
GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter] = new /datum/techweb/autounlocking/smelter
@@ -166,7 +168,7 @@
stored_research = null
return ..()
-/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
+/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/O)
if(QDELETED(O))
return
var/material_amount = materials.get_item_material_amount(O)
@@ -225,7 +227,7 @@
/obj/machinery/mineral/processing_unit/pickup_item(datum/source, atom/movable/target, direction)
if(QDELETED(target))
return
- if(istype(target, /obj/item/stack/ore))
+ if(istype(target, accepted_type))
process_ore(target)
/obj/machinery/mineral/processing_unit/process(seconds_per_tick)
@@ -282,4 +284,8 @@
var/O = new P(src)
unload_mineral(O)
+/// Only accepts ore, for the work camp
+/obj/machinery/mineral/processing_unit/gulag
+ accepted_type = /obj/item/stack/ore
+
#undef SMELT_AMOUNT
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index 0b9b7895c6b..14460cffb1b 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -203,18 +203,16 @@
default_unfasten_wrench(user, tool)
return ITEM_INTERACT_SUCCESS
-/obj/machinery/mineral/ore_redemption/AltClick(mob/living/user)
- . = ..()
- if(!user.can_perform_action(src))
- return
- if(panel_open)
- input_dir = turn(input_dir, -90)
- output_dir = turn(output_dir, -90)
- to_chat(user, span_notice("You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)]."))
- unregister_input_turf() // someone just rotated the input and output directions, unregister the old turf
- register_input_turf() // register the new one
- update_appearance(UPDATE_OVERLAYS)
- return TRUE
+/obj/machinery/mineral/ore_redemption/click_alt(mob/living/user)
+ if(!panel_open)
+ return CLICK_ACTION_BLOCKING
+ input_dir = turn(input_dir, -90)
+ output_dir = turn(output_dir, -90)
+ to_chat(user, span_notice("You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)]."))
+ unregister_input_turf() // someone just rotated the input and output directions, unregister the old turf
+ register_input_turf() // register the new one
+ update_appearance(UPDATE_OVERLAYS)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/mineral/ore_redemption/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm
index 286317a5d74..1f9a29a6e37 100644
--- a/code/modules/mining/machine_stacking.dm
+++ b/code/modules/mining/machine_stacking.dm
@@ -137,26 +137,26 @@
if (input_dir == output_dir)
rotate(input)
-/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp)
- if(QDELETED(inp))
+/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/input)
+ if(QDELETED(input))
return
// Dump the sheets to the silo if attached
if(materials.silo && !materials.on_hold())
- var/matlist = inp.custom_materials & materials.mat_container.materials
+ var/matlist = input.custom_materials & materials.mat_container.materials
if (length(matlist))
- materials.mat_container.insert_item(inp, context = src)
+ materials.insert_item(input)
return
// No silo attached process to internal storage
- var/key = inp.merge_type
+ var/key = input.merge_type
var/obj/item/stack/sheet/storage = stack_list[key]
if(!storage) //It's the first of this sheet added
- stack_list[key] = storage = new inp.type(src, 0)
- storage.amount += inp.amount //Stack the sheets
- qdel(inp)
+ stack_list[key] = storage = new input.type(src, 0)
+ storage.amount += input.amount //Stack the sheets
+ qdel(input)
while(storage.amount >= stack_amt) //Get rid of excessive stackage
- var/obj/item/stack/sheet/out = new inp.type(null, stack_amt)
+ var/obj/item/stack/sheet/out = new input.type(null, stack_amt)
unload_mineral(out)
storage.amount -= stack_amt
diff --git a/code/modules/mob/dead/observer/observer_say.dm b/code/modules/mob/dead/observer/observer_say.dm
index e43086349b3..a8fd0094934 100644
--- a/code/modules/mob/dead/observer/observer_say.dm
+++ b/code/modules/mob/dead/observer/observer_say.dm
@@ -5,7 +5,7 @@
/mob/dead/observer/get_message_mods(message, list/mods)
var/key = message[1]
if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION])
- mods[RADIO_KEY] = lowertext(message[1 + length(key)])
+ mods[RADIO_KEY] = LOWER_TEXT(message[1 + length(key)])
mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]]
return message
@@ -44,9 +44,9 @@
message = trim_left(copytext_char(message, length(message_mods[RADIO_KEY]) + 2))
switch(message_mods[RADIO_EXTENSION])
if(MODE_ADMIN)
- client.cmd_admin_say(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message)
if(MODE_DEADMIN)
- client.dsay(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message)
if(MODE_PUPPET)
if(!mind.current.say(message))
to_chat(src, span_warning("Your linked body was unable to speak!"))
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index bf9e099e5c9..c1822ff0e51 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -19,7 +19,7 @@
param = copytext(act, custom_param + length(act[custom_param]))
act = copytext(act, 1, custom_param)
- act = lowertext(act)
+ act = LOWER_TEXT(act)
var/list/key_emotes = GLOB.emote_list[act]
if(!length(key_emotes))
diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm
index 8dccd198f26..6e42d2adc97 100644
--- a/code/modules/mob/living/basic/basic.dm
+++ b/code/modules/mob/living/basic/basic.dm
@@ -121,6 +121,7 @@
return
apply_atmos_requirements(mapload)
apply_temperature_requirements(mapload)
+ apply_target_randomisation()
/mob/living/basic/proc/on_ssair_init(datum/source)
SIGNAL_HANDLER
@@ -142,6 +143,11 @@
return
AddElement(/datum/element/body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage, mapload)
+/mob/living/basic/proc/apply_target_randomisation()
+ if (basic_mob_flags & PRECISE_ATTACK_ZONES)
+ return
+ AddElement(/datum/element/attack_zone_randomiser)
+
/mob/living/basic/Life(seconds_per_tick = SSMOBS_DT, times_fired)
. = ..()
if(staminaloss > 0)
diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm
index 206ba88b317..ccd4b0d617f 100644
--- a/code/modules/mob/living/basic/bots/_bots.dm
+++ b/code/modules/mob/living/basic/bots/_bots.dm
@@ -6,6 +6,8 @@ GLOBAL_LIST_INIT(command_strings, list(
"home" = "RETURN HOME",
))
+#define SENTIENT_BOT_RESET_TIMER 45 SECONDS
+
/mob/living/basic/bot
icon = 'icons/mob/silicon/aibots.dmi'
layer = MOB_LAYER
@@ -39,6 +41,7 @@ GLOBAL_LIST_INIT(command_strings, list(
light_power = 0.6
speed = 3
req_one_access = list(ACCESS_ROBOTICS)
+ interaction_flags_click = ALLOW_SILICON_REACH
///The Robot arm attached to this robot - has a 50% chance to drop on death.
var/robot_arm = /obj/item/bodypart/arm/right/robot
///The inserted (if any) pAI in this bot.
@@ -101,7 +104,7 @@ GLOBAL_LIST_INIT(command_strings, list(
AddElement(/datum/element/relay_attackers)
RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(handle_loop_movement))
RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(after_attacked))
- RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(attempt_access))
+ RegisterSignal(src, COMSIG_OBJ_ALLOWED, PROC_REF(attempt_access))
ADD_TRAIT(src, TRAIT_NO_GLIDE, INNATE_TRAIT)
GLOB.bots_list += src
@@ -360,13 +363,9 @@ GLOBAL_LIST_INIT(command_strings, list(
ui = new(user, src, "SimpleBot", name)
ui.open()
-/mob/living/basic/bot/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
+/mob/living/basic/bot/click_alt(mob/user)
unlock_with_id(user)
+ return CLICK_ACTION_SUCCESS
/mob/living/basic/bot/proc/unlock_with_id(mob/living/user)
if(bot_access_flags & BOT_COVER_EMAGGED)
@@ -758,9 +757,7 @@ GLOBAL_LIST_INIT(command_strings, list(
/mob/living/basic/bot/proc/attempt_access(mob/bot, obj/door_attempt)
SIGNAL_HANDLER
- if(door_attempt.check_access(access_card))
- return ACCESS_ALLOWED
- return ACCESS_DISALLOWED
+ return (door_attempt.check_access(access_card) ? COMPONENT_OBJ_ALLOW : COMPONENT_OBJ_DISALLOW)
/mob/living/basic/bot/proc/generate_speak_list()
return null
@@ -783,6 +780,8 @@ GLOBAL_LIST_INIT(command_strings, list(
access_card.set_access(access_to_grant)
speak("Responding.", radio_channel)
update_bot_mode(new_mode = BOT_SUMMON)
+ if(client) //if we're sentient, we reset ourselves after a short period
+ addtimer(CALLBACK(src, PROC_REF(bot_reset)), SENTIENT_BOT_RESET_TIMER)
return TRUE
/mob/living/basic/bot/proc/set_ai_caller(mob/living/caller)
@@ -809,3 +808,5 @@ GLOBAL_LIST_INIT(command_strings, list(
/mob/living/basic/bot/proc/on_bot_movement(atom/movable/source, atom/oldloc, dir, forced)
return
+
+#undef SENTIENT_BOT_RESET_TIMER
diff --git a/code/modules/mob/living/basic/bots/bot_ai.dm b/code/modules/mob/living/basic/bots/bot_ai.dm
index 36600f244e7..16ca5200308 100644
--- a/code/modules/mob/living/basic/bots/bot_ai.dm
+++ b/code/modules/mob/living/basic/bots/bot_ai.dm
@@ -34,6 +34,13 @@
if(. & AI_CONTROLLER_INCOMPATIBLE)
return
RegisterSignal(new_pawn, COMSIG_BOT_RESET, PROC_REF(reset_bot))
+ RegisterSignal(new_pawn, COMSIG_AI_BLACKBOARD_KEY_CLEARED(BB_BOT_SUMMON_TARGET), PROC_REF(clear_summon))
+
+/datum/ai_controller/basic_controller/bot/proc/clear_summon()
+ SIGNAL_HANDLER
+
+ var/mob/living/basic/bot/bot_pawn = pawn
+ bot_pawn.bot_reset()
/datum/ai_controller/basic_controller/bot/able_to_run()
var/mob/living/basic/bot/bot_pawn = pawn
diff --git a/code/modules/mob/living/basic/bots/medbot/medbot.dm b/code/modules/mob/living/basic/bots/medbot/medbot.dm
index e784aa6249e..e76e723e197 100644
--- a/code/modules/mob/living/basic/bots/medbot/medbot.dm
+++ b/code/modules/mob/living/basic/bots/medbot/medbot.dm
@@ -7,14 +7,13 @@
icon_state = "medibot0"
base_icon_state = "medibot"
density = FALSE
- anchored = FALSE
health = 20
maxHealth = 20
speed = 2
light_power = 0.8
light_color = "#99ccff"
pass_flags = PASSMOB | PASSFLAPS
- status_flags = CANSTUN
+ status_flags = (CANPUSH | CANSTUN)
ai_controller = /datum/ai_controller/basic_controller/bot/medbot
req_one_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
@@ -162,7 +161,6 @@
return INITIALIZE_HINT_LATELOAD
/mob/living/basic/bot/medbot/LateInitialize()
- . = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm
index 21169ffd368..61f31f7044d 100644
--- a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm
+++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm
@@ -44,7 +44,7 @@
StartCooldown()
return TRUE
- do_after(owner, delay = beam_duration, target = owner)
+ do_after(owner, delay = beam_duration, target = owner, hidden = TRUE)
extinguish_laser()
StartCooldown()
return TRUE
diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm
index 26e549cbcf9..3361330915f 100644
--- a/code/modules/mob/living/basic/minebots/minebot.dm
+++ b/code/modules/mob/living/basic/minebots/minebot.dm
@@ -203,12 +203,12 @@
combat_overlay.color = selected_color
update_appearance()
-/mob/living/basic/mining_drone/AltClick(mob/living/user)
- . = ..()
+/mob/living/basic/mining_drone/click_alt(mob/living/user)
if(user.combat_mode)
- return
+ return CLICK_ACTION_BLOCKING
set_combat_mode(!combat_mode)
balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]")
+ return CLICK_ACTION_SUCCESS
/mob/living/basic/mining_drone/RangedAttack(atom/target)
if(!combat_mode)
diff --git a/code/modules/mob/living/basic/ruin_defender/flesh.dm b/code/modules/mob/living/basic/ruin_defender/flesh.dm
index a80d6847a8a..a6087f08589 100644
--- a/code/modules/mob/living/basic/ruin_defender/flesh.dm
+++ b/code/modules/mob/living/basic/ruin_defender/flesh.dm
@@ -38,6 +38,9 @@
if(!isnull(limb))
register_to_limb(limb)
+/mob/living/basic/living_limb_flesh/apply_target_randomisation()
+ AddElement(/datum/element/attack_zone_randomiser, GLOB.limb_zones)
+
/mob/living/basic/living_limb_flesh/Destroy(force)
. = ..()
if(current_bodypart)
@@ -71,6 +74,8 @@
if(!victim.CanReach(movable))
continue
candidates += movable
+ if(!length(candidates))
+ return
var/atom/movable/candidate = pick(candidates)
if(isnull(candidate))
return
@@ -123,9 +128,9 @@
part_type = /obj/item/bodypart/leg/right/flesh
target.visible_message(span_danger("[src] [target_part ? "tears off and attaches itself" : "attaches itself"] to where [target][target.p_s()] limb used to be!"))
- var/obj/item/bodypart/new_bodypart = new part_type(TRUE) //dont_spawn_flesh, we cant use named arguments here
- new_bodypart.replace_limb(target, TRUE)
+ var/obj/item/bodypart/new_bodypart = new part_type()
forceMove(new_bodypart)
+ new_bodypart.replace_limb(target, TRUE)
register_to_limb(new_bodypart)
/mob/living/basic/living_limb_flesh/proc/owner_shocked(datum/source, shock_damage, shock_source, siemens_coeff, flags)
diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm
index 51379ce88a0..c0fb9b67e7f 100644
--- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm
+++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm
@@ -55,6 +55,7 @@
AddElementTrait(TRAIT_WADDLING, INNATE_TRAIT, /datum/element/waddling)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/door_pryer, pry_time = 5 SECONDS, interaction_key = REGALRAT_INTERACTION)
+ AddElement(/datum/element/poster_tearer, interaction_key = REGALRAT_INTERACTION)
AddComponent(\
/datum/component/ghost_direct_control,\
poll_candidates = poll_ghosts,\
diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
index 266e7b5b414..21943d39d3d 100644
--- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
+++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
@@ -204,7 +204,7 @@
ShiftClickOn(A)
return
if(LAZYACCESS(modifiers, ALT_CLICK))
- AltClickNoInteract(src, A)
+ base_click_alt(A)
return
if(LAZYACCESS(modifiers, RIGHT_CLICK))
ranged_secondary_attack(A, modifiers)
diff --git a/code/modules/mob/living/basic/trooper/syndicate.dm b/code/modules/mob/living/basic/trooper/syndicate.dm
index c4d1bbd3630..8f8d564693b 100644
--- a/code/modules/mob/living/basic/trooper/syndicate.dm
+++ b/code/modules/mob/living/basic/trooper/syndicate.dm
@@ -154,6 +154,13 @@
ranged_cooldown = 3 SECONDS
r_hand = /obj/item/gun/ballistic/automatic/c20r
+///Spawns from an emagged orion trail machine set to kill the player.
+/mob/living/basic/trooper/syndicate/ranged/smg/orion
+ name = "spaceport security"
+ desc = "Premier corporate security forces for all spaceports found along the Orion Trail."
+ faction = list(FACTION_ORION)
+ loot = list()
+
/mob/living/basic/trooper/syndicate/ranged/smg/pilot //caravan ambush ruin
name = "Syndicate Salvage Pilot"
loot = list(/obj/effect/mob_spawn/corpse/human/syndicatepilot)
diff --git a/code/modules/mob/living/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm
index 038763e0360..d90db60a473 100644
--- a/code/modules/mob/living/brain/posibrain.dm
+++ b/code/modules/mob/living/brain/posibrain.dm
@@ -75,17 +75,16 @@ GLOBAL_VAR(posibrain_notify_cooldown)
update_appearance()
addtimer(CALLBACK(src, PROC_REF(check_success)), ask_delay)
-/obj/item/mmi/posibrain/AltClick(mob/living/user)
- if(!istype(user) || !user.can_perform_action(src))
- return
+/obj/item/mmi/posibrain/click_alt(mob/living/user)
var/input_seed = tgui_input_text(user, "Enter a personality seed", "Enter seed", ask_role, MAX_NAME_LEN)
if(isnull(input_seed))
- return
- if(!istype(user) || !user.can_perform_action(src))
+ return CLICK_ACTION_BLOCKING
+ if(!user.can_perform_action(src))
return
to_chat(user, span_notice("You set the personality seed to \"[input_seed]\"."))
ask_role = input_seed
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/mmi/posibrain/proc/check_success()
searching = FALSE
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 982613f331c..97a222cdd95 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -240,25 +240,34 @@
return TRUE
return FALSE
+
/mob/living/carbon/resist_buckle()
- if(HAS_TRAIT(src, TRAIT_RESTRAINED))
- changeNext_move(CLICK_CD_BREAKOUT)
- last_special = world.time + CLICK_CD_BREAKOUT
- var/buckle_cd = 60 SECONDS
- if(handcuffed)
- var/obj/item/restraints/O = src.get_item_by_slot(ITEM_SLOT_HANDCUFFED)
- buckle_cd = O.breakouttime
- visible_message(span_warning("[src] attempts to unbuckle [p_them()]self!"), \
- span_notice("You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)"))
- if(do_after(src, buckle_cd, target = src, timed_action_flags = IGNORE_HELD_ITEM))
- if(!buckled)
- return
- buckled.user_unbuckle_mob(src,src)
- else
- if(src && buckled)
- to_chat(src, span_warning("You fail to unbuckle yourself!"))
- else
- buckled.user_unbuckle_mob(src,src)
+ if(!HAS_TRAIT(src, TRAIT_RESTRAINED))
+ buckled.user_unbuckle_mob(src, src)
+ return
+
+ changeNext_move(CLICK_CD_BREAKOUT)
+ last_special = world.time + CLICK_CD_BREAKOUT
+ var/buckle_cd = 1 MINUTES
+
+ if(handcuffed)
+ var/obj/item/restraints/cuffs = src.get_item_by_slot(ITEM_SLOT_HANDCUFFED)
+ buckle_cd = cuffs.breakouttime
+
+ visible_message(span_warning("[src] attempts to unbuckle [p_them()]self!"),
+ span_notice("You attempt to unbuckle yourself... \
+ (This will take around [DisplayTimeText(buckle_cd)] and you must stay still.)"))
+
+ if(!do_after(src, buckle_cd, target = src, timed_action_flags = IGNORE_HELD_ITEM, hidden = TRUE))
+ if(buckled)
+ to_chat(src, span_warning("You fail to unbuckle yourself!"))
+ return
+
+ if(QDELETED(src) || isnull(buckled))
+ return
+
+ buckled.user_unbuckle_mob(src, src)
+
/mob/living/carbon/resist_fire()
return !!apply_status_effect(/datum/status_effect/stop_drop_roll)
@@ -282,34 +291,40 @@
cuff_resist(I)
-/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 1 MINUTES, cuff_break = 0)
- if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, I) & COMSIG_MOB_BLOCK_CUFF_REMOVAL))
+/**
+ * Helper to break the cuffs from hands
+ * @param {obj/item} cuffs - The cuffs to break
+ * @param {number} breakouttime - The time it takes to break the cuffs. Use SECONDS/MINUTES defines
+ * @param {number} cuff_break - Speed multiplier, 0 is default, see _DEFINES\combat.dm
+ */
+/mob/living/carbon/proc/cuff_resist(obj/item/cuffs, breakouttime = 1 MINUTES, cuff_break = 0)
+ if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, cuffs) & COMSIG_MOB_BLOCK_CUFF_REMOVAL))
return //The blocking object should sent a fluff-appropriate to_chat about cuff removal being blocked
- if(I.item_flags & BEING_REMOVED)
- to_chat(src, span_warning("You're already attempting to remove [I]!"))
+ if(cuffs.item_flags & BEING_REMOVED)
+ to_chat(src, span_warning("You're already attempting to remove [cuffs]!"))
return
- I.item_flags |= BEING_REMOVED
- breakouttime = I.breakouttime
+ cuffs.item_flags |= BEING_REMOVED
+ breakouttime = cuffs.breakouttime
if(!cuff_break)
- visible_message(span_warning("[src] attempts to remove [I]!"))
- to_chat(src, span_notice("You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)"))
- if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM))
- . = clear_cuffs(I, cuff_break)
+ visible_message(span_warning("[src] attempts to remove [cuffs]!"))
+ to_chat(src, span_notice("You attempt to remove [cuffs]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)"))
+ if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM, hidden = TRUE))
+ . = clear_cuffs(cuffs, cuff_break)
else
- to_chat(src, span_warning("You fail to remove [I]!"))
+ to_chat(src, span_warning("You fail to remove [cuffs]!"))
else if(cuff_break == FAST_CUFFBREAK)
- breakouttime = 50
- visible_message(span_warning("[src] is trying to break [I]!"))
- to_chat(src, span_notice("You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)"))
+ breakouttime = 5 SECONDS
+ visible_message(span_warning("[src] is trying to break [cuffs]!"))
+ to_chat(src, span_notice("You attempt to break [cuffs]... (This will take around 5 seconds and you need to stand still.)"))
if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM))
- . = clear_cuffs(I, cuff_break)
+ . = clear_cuffs(cuffs, cuff_break)
else
- to_chat(src, span_warning("You fail to break [I]!"))
+ to_chat(src, span_warning("You fail to break [cuffs]!"))
else if(cuff_break == INSTANT_CUFFBREAK)
- . = clear_cuffs(I, cuff_break)
- I.item_flags &= ~BEING_REMOVED
+ . = clear_cuffs(cuffs, cuff_break)
+ cuffs.item_flags &= ~BEING_REMOVED
/mob/living/carbon/proc/uncuff()
if (handcuffed)
@@ -410,6 +425,9 @@
if((HAS_TRAIT(src, TRAIT_NOHUNGER) || HAS_TRAIT(src, TRAIT_TOXINLOVER)) && !force)
return TRUE
+ if(!force && HAS_TRAIT(src, TRAIT_STRONG_STOMACH))
+ lost_nutrition *= 0.5
+
SEND_SIGNAL(src, COMSIG_CARBON_VOMITED, distance, force)
// cache some stuff that we'll need later (at least multiple times)
@@ -426,7 +444,10 @@
span_userdanger("You try to throw up, but there's nothing in your stomach!"),
)
if(stun)
- Stun(20 SECONDS)
+ var/stun_time = 20 SECONDS
+ if(HAS_TRAIT(src, TRAIT_STRONG_STOMACH))
+ stun_time *= 0.5
+ Stun(stun_time)
if(knockdown)
Knockdown(20 SECONDS)
return TRUE
@@ -449,11 +470,14 @@
add_mood_event("vomit", /datum/mood_event/vomit)
if(stun)
- Stun(8 SECONDS)
+ var/stun_time = 8 SECONDS
+ if(!blood && HAS_TRAIT(src, TRAIT_STRONG_STOMACH))
+ stun_time *= 0.5
+ Stun(stun_time)
if(knockdown)
Knockdown(8 SECONDS)
- playsound(get_turf(src), 'sound/effects/splat.ogg', 50, TRUE)
+ playsound(src, 'sound/effects/splat.ogg', 50, TRUE)
var/need_mob_update = FALSE
var/turf/location = get_turf(src)
@@ -1161,9 +1185,7 @@
admin_ticket_log("[key_name_admin(usr)] has attempted to modify the bodyparts of [src]")
if(href_list[VV_HK_MODIFY_ORGANS])
- if(!check_rights(NONE))
- return
- usr.client.manipulate_organs(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/manipulate_organs, src)
if(href_list[VV_HK_MARTIAL_ART])
if(!check_rights(NONE))
@@ -1485,3 +1507,13 @@
if (!IS_ORGANIC_LIMB(target_part) || (target_part.bodypart_flags & BODYPART_PSEUDOPART))
return FALSE
return ..()
+
+/mob/living/carbon/ominous_nosebleed()
+ var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD)
+ if(isnull(head))
+ return ..()
+ if(HAS_TRAIT(src, TRAIT_NOBLOOD))
+ to_chat(src, span_notice("You get a headache."))
+ return
+ head.adjustBleedStacks(5)
+ visible_message(span_notice("[src] gets a nosebleed."), span_warning("You get a nosebleed."))
diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm
index f74c2c1ca21..41a958518c5 100644
--- a/code/modules/mob/living/carbon/death.dm
+++ b/code/modules/mob/living/carbon/death.dm
@@ -1,5 +1,5 @@
/mob/living/carbon/death(gibbed)
- if(stat == DEAD || HAS_TRAIT(src, TRAIT_NODEATH) && !gibbed)
+ if(stat == DEAD)
return
losebreath = 0
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index c534372d04c..154892d57ea 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -903,7 +903,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(!(I.slot_flags & slot))
var/excused = FALSE
// Anything that's small or smaller can fit into a pocket by default
- if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= WEIGHT_CLASS_SMALL)
+ if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= POCKET_WEIGHT_CLASS)
excused = TRUE
else if(slot & (ITEM_SLOT_SUITSTORE|ITEM_SLOT_BACKPACK|ITEM_SLOT_HANDS))
excused = TRUE
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index cf843c43b00..f63e692a118 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift)
new /obj/effect/decal/remains/human(loc)
/mob/living/carbon/human/death(gibbed)
- if(stat == DEAD || HAS_TRAIT(src, TRAIT_NODEATH) && !gibbed)
+ if(stat == DEAD)
return
stop_sound_channel(CHANNEL_HEARTBEAT)
var/obj/item/organ/internal/heart/human_heart = get_organ_slot(ORGAN_SLOT_HEART)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index ae67a379368..8786167e0dc 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -98,7 +98,7 @@
. += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DNA_LENGTH(src))
if(num_hands)
- . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a"] blood-stained hand[num_hands > 1 ? "s" : ""]!")
+ . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
diff --git a/code/modules/mob/living/carbon/human/human_stripping.dm b/code/modules/mob/living/carbon/human/human_stripping.dm
index fadca82ab11..6dccf98e5d5 100644
--- a/code/modules/mob/living/carbon/human/human_stripping.dm
+++ b/code/modules/mob/living/carbon/human/human_stripping.dm
@@ -222,7 +222,7 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
source.log_message("is being pickpocketed of [item] by [key_name(user)] ([pocket_side])", LOG_VICTIM, color="orange", log_globally=FALSE)
item.add_fingerprint(src)
- var/result = start_unequip_mob(item, source, user, POCKET_STRIP_DELAY)
+ var/result = start_unequip_mob(item, source, user, strip_delay = POCKET_STRIP_DELAY, hidden = TRUE)
if (!(result || HAS_TRAIT(user, TRAIT_STICKY_FINGERS))) //SKYRAT EDIT ADDITION original if (!result)
warn_owner(source)
diff --git a/code/modules/mob/living/carbon/human/init_signals.dm b/code/modules/mob/living/carbon/human/init_signals.dm
index 6e16781a59e..dc5ce972105 100644
--- a/code/modules/mob/living/carbon/human/init_signals.dm
+++ b/code/modules/mob/living/carbon/human/init_signals.dm
@@ -8,6 +8,8 @@
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_FAT), SIGNAL_REMOVETRAIT(TRAIT_FAT)), PROC_REF(on_fat))
RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NOHUNGER), SIGNAL_REMOVETRAIT(TRAIT_NOHUNGER)), PROC_REF(on_nohunger))
+ RegisterSignal(src, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(check_pocket_weght))
+
/// Gaining or losing [TRAIT_UNKNOWN] updates our name and our sechud
/mob/living/carbon/human/proc/on_unknown_trait(datum/source)
SIGNAL_HANDLER
@@ -63,3 +65,19 @@
else
hud_used?.hunger?.update_appearance()
mob_mood?.update_nutrition_moodlets()
+
+/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to check if an item is suddenly too heavy for our pockets
+/mob/living/carbon/human/proc/check_pocket_weght(datum/source, obj/item/changed, old_w_class, new_w_class)
+ SIGNAL_HANDLER
+ if(changed != r_store && changed != l_store)
+ return
+ if(new_w_class <= POCKET_WEIGHT_CLASS)
+ return
+ if(!dropItemToGround(changed, force = TRUE))
+ return
+ visible_message(
+ span_warning("[changed] falls out of [src]'s pockets!"),
+ span_warning("[changed] falls out of your pockets!"),
+ vision_distance = COMBAT_MESSAGE_RANGE,
+ )
+ playsound(src, SFX_RUSTLE, 50, TRUE, -5, frequency = 0.8)
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index a1c3a245034..5a1c632acd7 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -731,10 +731,13 @@
to_chat(telepath, span_warning("You don't see anyone to send your thought to."))
return
var/mob/living/recipient = tgui_input_list(telepath, "Choose a telepathic message recipient", "Telepathy", sort_names(recipient_options))
- if(isnull(recipient))
+ if(isnull(recipient) || telepath.stat == DEAD || !is_species(telepath, /datum/species/jelly/stargazer))
return
var/msg = tgui_input_text(telepath, title = "Telepathy")
- if(isnull(msg))
+ if(isnull(msg) || telepath.stat == DEAD || !is_species(telepath, /datum/species/jelly/stargazer))
+ return
+ if(!(recipient in oview(telepath)))
+ to_chat(telepath, span_warning("You can't see [recipient] anymore!"))
return
if(recipient.can_block_magic(MAGIC_RESISTANCE_MIND, charge_cost = 0))
to_chat(telepath, span_warning("As you reach into [recipient]'s mind, you are stopped by a mental blockage. It seems you've been foiled."))
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 7923d0de7a4..99d1f5bc8ea 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -280,7 +280,8 @@
if(!can_breathe_vacuum && (o2_pp < safe_oxygen_min))
// Breathe insufficient amount of O2.
oxygen_used = handle_suffocation(o2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen][MOLES])
- throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
+ if(!HAS_TRAIT(src, TRAIT_ANOSMIA))
+ throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
else
// Enough oxygen to breathe.
failed_last_breath = FALSE
@@ -307,7 +308,8 @@
if(!co2overloadtime)
co2overloadtime = world.time
else if((world.time - co2overloadtime) > 12 SECONDS)
- throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2)
+ if(!HAS_TRAIT(src, TRAIT_ANOSMIA))
+ throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2)
Unconscious(6 SECONDS)
// Lets hurt em a little, let them know we mean business.
adjustOxyLoss(3)
@@ -325,7 +327,8 @@
// Plasma side-effects.
var/ratio = (breath_gases[/datum/gas/plasma][MOLES] / safe_plas_max) * 10
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
- throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
+ if(!HAS_TRAIT(src, TRAIT_ANOSMIA))
+ throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
else
// Reset side-effects.
clear_alert(ALERT_TOO_MUCH_PLASMA)
@@ -356,6 +359,8 @@
miasma_disease.name = "Unknown"
ForceContractDisease(miasma_disease, make_copy = TRUE, del_on_fail = TRUE)
// Miasma side-effects.
+ if (HAS_TRAIT(src, TRAIT_ANOSMIA)) //We can't feel miasma without sense of smell
+ return
switch(miasma_pp)
if(0.25 to 5)
// At lower pp, give out a little warning
@@ -386,7 +391,8 @@
if(n2o_pp > n2o_para_min)
// More N2O, more severe side-effects. Causes stun/sleep.
n2o_euphoria = EUPHORIA_ACTIVE
- throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
+ if(!HAS_TRAIT(src, TRAIT_ANOSMIA))
+ throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
// give them one second of grace to wake up and run away a bit!
if(!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE))
Unconscious(6 SECONDS)
@@ -827,7 +833,7 @@
* Returns TRUE if heart status was changed (heart attack -> no heart attack, or visa versa)
*/
/mob/living/carbon/proc/set_heartattack(status)
- if(!can_heartattack())
+ if(status && !can_heartattack())
return FALSE
var/obj/item/organ/internal/heart/heart = get_organ_slot(ORGAN_SLOT_HEART)
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index 0819c285d9a..51fb86d73ad 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -108,7 +108,6 @@
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp")
set_stat(DEAD)
- unset_machine()
timeofdeath = world.time
station_timestamp_timeofdeath = station_time_timestamp()
var/turf/death_turf = get_turf(src)
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index 64a2de72f43..412a63c00eb 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -656,20 +656,20 @@
to_chat(user, span_warning("\"[input]\""))
REPORT_CHAT_FILTER_TO_USER(user, filter_result)
log_filter("IC Emote", input, filter_result)
- SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "ic_blocked_words", 1, LOWER_TEXT(config.ic_filter_regex.match))
return FALSE
filter_result = is_soft_ic_filtered(input)
if(filter_result)
if(tgui_alert(user,"Your emote contains \"[filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to emote it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
- SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match))
log_filter("Soft IC Emote", input, filter_result)
return FALSE
message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for emote \"[filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Emote: \"[input]\"")
log_admin_private("[key_name(user)] has passed the soft filter for emote \"[filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Emote: \"[input]\"")
- SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match))
log_filter("Soft IC Emote (Passed)", input, filter_result)
return TRUE
diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm
index b4c9fbd34aa..808c8973963 100644
--- a/code/modules/mob/living/inhand_holder.dm
+++ b/code/modules/mob/living/inhand_holder.dm
@@ -20,7 +20,7 @@
righthand_file = rh_icon
if(worn_slot_flags)
slot_flags = worn_slot_flags
- w_class = M.held_w_class
+ update_weight_class(M.held_w_class)
deposit(M)
. = ..()
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index ed496c0c84b..b8f1e60a612 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -157,7 +157,6 @@
/mob/living/proc/on_ui_blocked_trait_gain(datum/source)
SIGNAL_HANDLER
mobility_flags &= ~(MOBILITY_UI)
- unset_machine()
update_mob_action_buttons()
/// Called when [TRAIT_UI_BLOCKED] is removed from the mob.
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 35866514b79..dd7e8a17c9b 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -66,9 +66,6 @@
handle_wounds(seconds_per_tick, times_fired)
- if(machine)
- machine.check_eye(src)
-
if(stat != DEAD)
return 1
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b62aa1cde9d..d6c133ea3a8 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1407,9 +1407,14 @@
var/datum/dna/mob_DNA = has_dna()
if(!mob_DNA || !mob_DNA.check_mutation(/datum/mutation/human/telekinesis) || !tkMaxRangeCheck(src, target))
- to_chat(src, span_warning("You are too far away!"))
+ if(!(action_bitflags & SILENT_ADJACENCY))
+ to_chat(src, span_warning("You are too far away!"))
return FALSE
+ if((action_bitflags & NEED_VENTCRAWL) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_NUDE) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS))
+ to_chat(src, span_warning("You wouldn't fit!"))
+ return FALSE
+
if((action_bitflags & NEED_DEXTERITY) && !ISADVANCEDTOOLUSER(src))
to_chat(src, span_warning("You don't have the dexterity to do this!"))
return FALSE
@@ -1853,7 +1858,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
if(registered_z && old_level_new_clients == 0)
for(var/datum/ai_controller/controller as anything in SSai_controllers.ai_controllers_by_zlevel[registered_z])
controller.set_ai_status(AI_STATUS_OFF)
-
+
//Check the amount of clients exists on the Z level we're moving towards, excluding ourselves.
var/new_level_old_clients = SSmobs.clients_by_zlevel[new_z].len
@@ -2006,6 +2011,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
VV_DROPDOWN_OPTION(VV_HK_GIVE_HALLUCINATION, "Give Hallucination")
VV_DROPDOWN_OPTION(VV_HK_GIVE_DELUSION_HALLUCINATION, "Give Delusion Hallucination")
VV_DROPDOWN_OPTION(VV_HK_GIVE_GUARDIAN_SPIRIT, "Give Guardian Spirit")
+ VV_DROPDOWN_OPTION(VV_HK_ADMIN_RENAME, "Force Change Name")
/mob/living/vv_do_topic(list/href_list)
. = ..()
@@ -2043,6 +2049,29 @@ GLOBAL_LIST_EMPTY(fire_appearances)
return
admin_give_guardian(usr)
+ if(href_list[VV_HK_ADMIN_RENAME])
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/old_name = real_name
+ var/new_name = sanitize_name(tgui_input_text(usr, "Enter the new name.", "Admin Rename", real_name))
+ if(!new_name || new_name == real_name)
+ return
+
+ fully_replace_character_name(real_name, new_name)
+ var/replace_preferences = !isnull(client) && (tgui_alert(usr, "Would you like to update the client's preference with the new name?", "Pref Overwrite", list("Yes", "No")) == "Yes")
+ if(replace_preferences)
+ client.prefs.write_preference(GLOB.preference_entries[/datum/preference/name/real_name], new_name)
+
+ log_admin("forced rename", list(
+ "admin" = key_name(usr),
+ "player" = key_name(src),
+ "old_name" = old_name,
+ "new_name" = new_name,
+ "updated_prefs" = replace_preferences,
+ ))
+ message_admins("[key_name_admin(usr)] has forcibly changed the real name of [key_name(src)] from '[old_name]' to '[real_name]'[(replace_preferences ? " and their preferences" : "")]")
+
/mob/living/proc/move_to_error_room()
var/obj/effect/landmark/error/error_landmark = locate(/obj/effect/landmark/error) in GLOB.landmarks_list
if(error_landmark)
@@ -2505,6 +2534,10 @@ GLOBAL_LIST_EMPTY(fire_appearances)
apply_damage(rand(5,10), BRUTE, BODY_ZONE_CHEST)
lattice.deconstruct(FALSE)
+/// Prints an ominous message if something bad is going to happen to you
+/mob/living/proc/ominous_nosebleed()
+ to_chat(src, span_warning("You feel a bit nauseous for just a moment."))
+
/**
* Proc used by different station pets such as Ian and Poly so that some of their data can persist between rounds.
* This base definition only contains a trait and comsig to stop memory from being (over)written.
diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm
index a364c5691de..16705e90165 100644
--- a/code/modules/mob/living/living_say.dm
+++ b/code/modules/mob/living/living_say.dm
@@ -127,11 +127,11 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
return
if(message_mods[RADIO_EXTENSION] == MODE_ADMIN)
- client?.cmd_admin_say(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message)
return
if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN)
- client?.dsay(message)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message)
return
// dead is the only state you can never emote
diff --git a/code/modules/mob/living/silicon/ai/_preferences.dm b/code/modules/mob/living/silicon/ai/_preferences.dm
index 4b0aaaecc25..10958b2adc4 100644
--- a/code/modules/mob/living/silicon/ai/_preferences.dm
+++ b/code/modules/mob/living/silicon/ai/_preferences.dm
@@ -115,7 +115,7 @@ GLOBAL_LIST_INIT(ai_core_display_screens, sort_list(list(
else
if(input == "Random")
input = pick(GLOB.ai_core_display_screens - "Random")
- return "ai-[lowertext(input)]"
+ return "ai-[LOWER_TEXT(input)]"
/proc/resolve_ai_icon(input)
if (input == "Portrait")
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 5f7571186be..292b0f1d7c1 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -1,17 +1,5 @@
#define CALL_BOT_COOLDOWN 900
-//Not sure why this is necessary...
-/proc/AutoUpdateAI(obj/subject)
- var/is_in_use = 0
- if (subject != null)
- for(var/A in GLOB.ai_list)
- var/mob/living/silicon/ai/M = A
- if ((M.client && M.machine == subject))
- is_in_use = 1
- subject.attack_ai(M)
- return is_in_use
-
-
/mob/living/silicon/ai
name = "AI"
real_name = "AI"
@@ -645,7 +633,6 @@
/mob/living/silicon/ai/proc/ai_network_change()
set category = "AI Commands"
set name = "Jump To Network"
- unset_machine()
ai_tracking_tool.reset_tracking()
var/cameralist[0]
diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm
index d655ce03a33..2a8b8e6c4a0 100644
--- a/code/modules/mob/living/silicon/ai/ai_say.dm
+++ b/code/modules/mob/living/silicon/ai/ai_say.dm
@@ -126,7 +126,7 @@
words.len = 30
for(var/word in words)
- word = lowertext(trim(word))
+ word = LOWER_TEXT(trim(word))
if(!word)
words -= word
continue
@@ -156,7 +156,7 @@
/proc/play_vox_word(word, ai_turf, mob/only_listener)
- word = lowertext(word)
+ word = LOWER_TEXT(word)
if(GLOB.vox_sounds[word])
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index e8c1919b020..98a2e629776 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -202,7 +202,6 @@
current = null
if(ai_tracking_tool)
ai_tracking_tool.reset_tracking()
- unset_machine()
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 76f5c2eec93..b11f125d38c 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -12,9 +12,6 @@
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
view_core()
- if(machine)
- machine.check_eye(src)
-
// Handle power damage (oxy)
if(aiRestorePowerRoutine)
// Lost power
diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm
index 2f4f2d70f26..44207ee8948 100644
--- a/code/modules/mob/living/silicon/robot/robot_model.dm
+++ b/code/modules/mob/living/silicon/robot/robot_model.dm
@@ -393,7 +393,7 @@
/obj/item/analyzer,
/obj/item/holosign_creator/atmos, // Skyrat Edit - Adds Holofans to engineering borgos
/obj/item/assembly/signaler/cyborg,
- /obj/item/areaeditor/blueprints/cyborg,
+ /obj/item/blueprints/cyborg,
/obj/item/electroadaptive_pseudocircuit,
/obj/item/stack/sheet/iron,
/obj/item/stack/sheet/glass,
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 27bbec88292..ec204dbc82b 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -29,6 +29,7 @@
light_power = 0.6
del_on_death = TRUE
req_one_access = list(ACCESS_ROBOTICS)
+ interaction_flags_click = ALLOW_SILICON_REACH
///Cooldown between salutations for commissioned bots
COOLDOWN_DECLARE(next_salute_check)
@@ -411,13 +412,9 @@
ui = new(user, src, "SimpleBot", name)
ui.open()
-/mob/living/simple_animal/bot/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
+/mob/living/simple_animal/bot/click_alt(mob/user)
unlock_with_id(user)
+ return CLICK_ACTION_SUCCESS
/mob/living/simple_animal/bot/proc/unlock_with_id(mob/user)
if(bot_cover_flags & BOT_COVER_EMAGGED)
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index faa7d3a9edb..ae1c52d1652 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -140,7 +140,7 @@
return data
// Actions received from TGUI
-/mob/living/simple_animal/bot/floorbot/ui_act(action, params)
+/mob/living/simple_animal/bot/floorbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(. || (bot_cover_flags & BOT_COVER_LOCKED && !HAS_SILICON_ACCESS(usr)))
return
@@ -161,7 +161,7 @@
tilestack.forceMove(drop_location())
if("line_mode")
var/setdir = tgui_input_list(usr, "Select construction direction", "Direction", list("north", "east", "south", "west", "disable"))
- if(isnull(setdir))
+ if(isnull(setdir) || QDELETED(ui) || ui.status != UI_INTERACTIVE)
return
switch(setdir)
if("north")
diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm
index b8ceb33a37d..cf937e42bb7 100644
--- a/code/modules/mob/logout.dm
+++ b/code/modules/mob/logout.dm
@@ -2,7 +2,6 @@
SEND_SIGNAL(src, COMSIG_MOB_LOGOUT)
log_message("[key_name(src)] is no longer owning mob [src]([src.type])", LOG_OWNERSHIP)
SStgui.on_logout(src)
- unset_machine()
remove_from_player_list()
..()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 30d0a528b96..1142fff130b 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -30,7 +30,6 @@
else if(ckey)
stack_trace("Mob without client but with associated ckey, [ckey], has been deleted.")
- unset_machine()
remove_from_mob_list()
remove_from_dead_mob_list()
remove_from_alive_mob_list()
@@ -902,7 +901,6 @@
set name = "Cancel Camera View"
set category = "OOC"
reset_perspective(null)
- unset_machine()
//suppress the .click/dblclick macros so people can't use them to identify the location of items or aimbot
/mob/verb/DisClick(argu = null as anything, sec = "" as text, number1 = 0 as num , number2 = 0 as num)
@@ -1014,7 +1012,7 @@
selected_hand = (active_hand_index % held_items.len)+1
if(istext(selected_hand))
- selected_hand = lowertext(selected_hand)
+ selected_hand = LOWER_TEXT(selected_hand)
if(selected_hand == "right" || selected_hand == "r")
selected_hand = 2
if(selected_hand == "left" || selected_hand == "l")
@@ -1199,6 +1197,10 @@
* * FORBID_TELEKINESIS_REACH - If telekinesis is forbidden to perform action from a distance (ex. canisters are blacklisted from telekinesis manipulation)
* * ALLOW_SILICON_REACH - If silicons are allowed to perform action from a distance (silicons can operate airlocks from far away)
* * ALLOW_RESTING - If resting on the floor is allowed to perform action ()
+ * * ALLOW_VENTCRAWL - Mobs with ventcrawl traits can alt-click this to vent
+ *
+ * silence_adjacency: Sometimes we want to use this proc to check interaction without allowing it to throw errors for base case adjacency
+ * Alt click uses this, as otherwise you can detect what is interactable from a distance via the error message
**/
/mob/proc/can_perform_action(atom/movable/target, action_bitflags)
return
@@ -1477,9 +1479,7 @@
regenerate_icons()
if(href_list[VV_HK_PLAYER_PANEL])
- if(!check_rights(NONE))
- return
- usr.client.holder.show_player_panel(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, src)
if(href_list[VV_HK_GODMODE])
if(!check_rights(R_ADMIN))
@@ -1487,34 +1487,22 @@
usr.client.cmd_admin_godmode(src)
if(href_list[VV_HK_GIVE_MOB_ACTION])
- if(!check_rights(NONE))
- return
- usr.client.give_mob_action(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_mob_action, src)
if(href_list[VV_HK_REMOVE_MOB_ACTION])
- if(!check_rights(NONE))
- return
- usr.client.remove_mob_action(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/remove_mob_action, src)
if(href_list[VV_HK_GIVE_SPELL])
- if(!check_rights(NONE))
- return
- usr.client.give_spell(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_spell, src)
if(href_list[VV_HK_REMOVE_SPELL])
- if(!check_rights(NONE))
- return
- usr.client.remove_spell(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/remove_spell, src)
if(href_list[VV_HK_GIVE_DISEASE])
- if(!check_rights(NONE))
- return
- usr.client.give_disease(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_disease, src)
if(href_list[VV_HK_GIB])
- if(!check_rights(R_FUN))
- return
- usr.client.cmd_admin_gib(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/gib_them, src)
if(href_list[VV_HK_BUILDMODE])
if(!check_rights(R_BUILD))
@@ -1522,19 +1510,13 @@
togglebuildmode(src)
if(href_list[VV_HK_DROP_ALL])
- if(!check_rights(NONE))
- return
- usr.client.cmd_admin_drop_everything(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/drop_everything, src)
if(href_list[VV_HK_DIRECT_CONTROL])
- if(!check_rights(NONE))
- return
- usr.client.cmd_assume_direct_control(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_assume_direct_control, src)
if(href_list[VV_HK_GIVE_DIRECT_CONTROL])
- if(!check_rights(NONE))
- return
- usr.client.cmd_give_direct_control(src)
+ return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_give_direct_control, src)
if(href_list[VV_HK_OFFER_GHOSTS])
if(!check_rights(NONE))
@@ -1641,9 +1623,6 @@
/mob/vv_edit_var(var_name, var_value)
switch(var_name)
- if(NAMEOF(src, machine))
- set_machine(var_value)
- . = TRUE
if(NAMEOF(src, focus))
set_focus(var_value)
. = TRUE
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 44d0db90355..2a5be377ecd 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -79,9 +79,6 @@
var/computer_id = null
var/list/logging = list()
- /// The machine the mob is interacting with (this is very bad old code btw)
- var/obj/machinery/machine = null
-
/// Tick time the mob can next move
var/next_move = null
diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm
index 8f1398ce244..f634bd187a4 100644
--- a/code/modules/mob/mob_say.dm
+++ b/code/modules/mob/mob_say.dm
@@ -66,17 +66,17 @@
to_chat(src, span_warning("\"[message]\""))
REPORT_CHAT_FILTER_TO_USER(src, filter_result)
log_filter("IC", message, filter_result)
- SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "ic_blocked_words", 1, LOWER_TEXT(config.ic_filter_regex.match))
return FALSE
if(soft_filter_result && !filterproof)
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
- SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match))
log_filter("Soft IC", message, filter_result)
return FALSE
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"")
- SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match))
+ SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match))
log_filter("Soft IC (Passed)", message, filter_result)
if(client && !(ignore_spam || forced))
@@ -223,7 +223,7 @@
if(stat == CONSCIOUS) //necessary indentation so it gets stripped of the semicolon anyway.
mods[MODE_HEADSET] = TRUE
else if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION])
- mods[RADIO_KEY] = lowertext(message[1 + length(key)])
+ mods[RADIO_KEY] = LOWER_TEXT(message[1 + length(key)])
mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]]
chop_to = length(key) + 2
else if(key == "," && !mods[LANGUAGE_EXTENSION])
diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm
index 634b1dd648f..c3d5040c815 100644
--- a/code/modules/mod/mod_link.dm
+++ b/code/modules/mod/mod_link.dm
@@ -191,6 +191,8 @@
/obj/item/clothing/neck/link_scryer/attack_self(mob/user, modifiers)
var/new_label = reject_bad_text(tgui_input_text(user, "Change the visible name", "Set Name", label, MAX_NAME_LEN))
+ if(!user.is_holding(src))
+ return
if(!new_label)
balloon_alert(user, "invalid name!")
return
diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm
index 88f697ccd48..a408be23b1f 100644
--- a/code/modules/mod/mod_theme.dm
+++ b/code/modules/mod/mod_theme.dm
@@ -891,6 +891,7 @@
/obj/item/grown/bananapeel,
/obj/item/reagent_containers/spray/waterflower,
/obj/item/instrument,
+ /obj/item/toy/balloon_animal,
)
skins = list(
"cosmohonk" = list(
diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm
index 47f588eb80b..f0bca6b0980 100644
--- a/code/modules/mod/mod_types.dm
+++ b/code/modules/mod/mod_types.dm
@@ -212,6 +212,7 @@
/obj/item/mod/module/storage,
/obj/item/mod/module/waddle,
/obj/item/mod/module/bikehorn,
+ /obj/item/mod/module/balloon_advanced,
)
/obj/item/mod/control/pre_equipped/traitor
diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm
index 2462f62a3d3..bd96c5aec5f 100644
--- a/code/modules/mod/modules/modules_antag.dm
+++ b/code/modules/mod/modules/modules_antag.dm
@@ -460,10 +460,10 @@
/obj/item/mod/module/plate_compression/on_install()
old_size = mod.w_class
- mod.w_class = new_size
+ mod.update_weight_class(new_size)
/obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE)
- mod.w_class = old_size
+ mod.update_weight_class(old_size)
old_size = null
if(!mod.loc)
return
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index f80fd952cef..2aec3e361c4 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -506,9 +506,16 @@
if(!drain_power(use_energy_cost * levels))
return NONE
new /obj/effect/temp_visual/mook_dust(fell_on)
- mod.wearer.Stun(levels * 1 SECONDS)
+
+ /// Boolean that tracks whether we fell more than one z-level. If TRUE, we stagger our wearer.
+ var/extreme_fall = FALSE
+
+ if(levels >= 2)
+ extreme_fall = TRUE
+ mod.wearer.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH * levels, 10 SECONDS)
+
mod.wearer.visible_message(
- span_notice("[mod.wearer] lands on [fell_on] safely."),
+ span_notice("[mod.wearer] lands on [fell_on] safely[extreme_fall ? ", but barely manages to stay on [p_their()] feet." : ", and quite stylishly on [p_their()] feet" ]."),
span_notice("[src] protects you from the damage!"),
)
return ZIMPACT_CANCEL_DAMAGE|ZIMPACT_NO_MESSAGE|ZIMPACT_NO_SPIN
diff --git a/code/modules/mod/modules/modules_service.dm b/code/modules/mod/modules/modules_service.dm
index b4870a84ec5..be71c621802 100644
--- a/code/modules/mod/modules/modules_service.dm
+++ b/code/modules/mod/modules/modules_service.dm
@@ -19,6 +19,31 @@
playsound(src, 'sound/items/bikehorn.ogg', 100, FALSE)
drain_power(use_energy_cost)
+///Advanced Balloon Blower - Blows a long balloon.
+/obj/item/mod/module/balloon_advanced
+ name = "MOD advanced balloon blower module"
+ desc = "A relatively new piece of technology developed by finest clown engineers to make long balloons and balloon animals \
+ at party-appropriate rate."
+ icon_state = "bloon"
+ module_type = MODULE_USABLE
+ complexity = 1
+ use_energy_cost = DEFAULT_CHARGE_DRAIN * 0.5
+ incompatible_modules = list(/obj/item/mod/module/balloon_advanced)
+ cooldown_time = 15 SECONDS
+
+/obj/item/mod/module/balloon_advanced/on_use()
+ . = ..()
+ if(!.)
+ return
+ if(!do_after(mod.wearer, 15 SECONDS, target = mod))
+ return FALSE
+ mod.wearer.adjustOxyLoss(20)
+ playsound(src, 'sound/items/modsuit/inflate_bloon.ogg', 50, TRUE)
+ var/obj/item/toy/balloon/long/l_balloon = new(get_turf(src))
+ mod.wearer.put_in_hands(l_balloon)
+ drain_power(use_energy_cost)
+
+
///Microwave Beam - Microwaves items instantly.
/obj/item/mod/module/microwave_beam
name = "MOD microwave beam module"
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index c63441124ae..c7369724ee4 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -223,19 +223,18 @@
/obj/item/modular_computer/get_cell()
return internal_cell
-/obj/item/modular_computer/AltClick(mob/user)
- . = ..()
+/obj/item/modular_computer/click_alt(mob/user)
if(issilicon(user))
- return FALSE
- if(!user.can_perform_action(src))
- return FALSE
+ return NONE
if(RemoveID(user))
- return TRUE
+ return CLICK_ACTION_SUCCESS
if(istype(inserted_pai)) // Remove pAI
remove_pai(user)
- return TRUE
+ return CLICK_ACTION_SUCCESS
+
+ return CLICK_ACTION_BLOCKING
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. //guess what
/obj/item/modular_computer/GetAccess()
diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm
index d3b620cdfc9..b55fb6d2ee6 100644
--- a/code/modules/modular_computers/computers/item/laptop.dm
+++ b/code/modules/modular_computers/computers/item/laptop.dm
@@ -91,25 +91,22 @@
toggle_open(user)
-/obj/item/modular_computer/laptop/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
- if(screen_on) // Close it.
- try_toggle_open(user)
- else
- return ..()
+/obj/item/modular_computer/laptop/click_alt(mob/user)
+ if(!screen_on)
+ return CLICK_ACTION_BLOCKING
+ try_toggle_open(user) // Close it.
+ return CLICK_ACTION_SUCCESS
/obj/item/modular_computer/laptop/proc/toggle_open(mob/living/user=null)
if(screen_on)
to_chat(user, span_notice("You close \the [src]."))
slowdown = initial(slowdown)
- w_class = initial(w_class)
+ update_weight_class(initial(w_class))
drag_slowdown = initial(drag_slowdown)
else
to_chat(user, span_notice("You open \the [src]."))
slowdown = slowdown_open
- w_class = w_class_open
+ update_weight_class(w_class_open)
drag_slowdown = slowdown_open
if(isliving(loc))
var/mob/living/localmob = loc
diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm
index 37ef56a0626..b6efa629d5e 100644
--- a/code/modules/modular_computers/computers/item/pda.dm
+++ b/code/modules/modular_computers/computers/item/pda.dm
@@ -161,12 +161,6 @@
inserted_item = attacking_item
playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
-/obj/item/modular_computer/pda/AltClick(mob/user)
- . = ..()
- if(.)
- return
-
- remove_pen(user)
/obj/item/modular_computer/pda/CtrlClick(mob/user)
. = ..()
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index 18f394d6ee0..0ec80da4bbb 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -94,7 +94,7 @@
setup_starting_software()
REGISTER_REQUIRED_MAP_ITEM(1, 1)
if(department_type)
- name = "[lowertext(initial(department_type.department_name))] [name]"
+ name = "[LOWER_TEXT(initial(department_type.department_name))] [name]"
cpu.name = name
/obj/machinery/modular_computer/preset/cargochat/proc/add_starting_software()
@@ -105,7 +105,7 @@
return
var/datum/computer_file/program/chatclient/chatprogram = cpu.find_file_by_name("ntnrc_client")
- chatprogram.username = "[lowertext(initial(department_type.department_name))]_department"
+ chatprogram.username = "[LOWER_TEXT(initial(department_type.department_name))]_department"
cpu.idle_threads += chatprogram
var/datum/computer_file/program/department_order/orderprogram = cpu.find_file_by_name("dept_order")
@@ -144,7 +144,7 @@
update_appearance(UPDATE_ICON)
// Rest of the chat program setup is done in LateInit
-/obj/machinery/modular_computer/preset/cargochat/cargo/LateInitialize()
+/obj/machinery/modular_computer/preset/cargochat/cargo/post_machine_initialize()
. = ..()
var/datum/computer_file/program/chatclient/chatprogram = cpu.find_file_by_name("ntnrc_client")
chatprogram.username = "cargo_requests_operator"
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 0e17f012453..6f0050534cc 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -116,11 +116,11 @@
SIGNAL_HANDLER
return update_icon(updates)
-/obj/machinery/modular_computer/AltClick(mob/user)
- . = ..()
+/obj/machinery/modular_computer/click_alt(mob/user)
if(CPU_INTERACTABLE(user) || !can_interact(user))
- return
- cpu.AltClick(user)
+ return NONE
+ cpu.click_alt(user)
+ return CLICK_ACTION_SUCCESS
//ATTACK HAND IGNORING PARENT RETURN VALUE
// On-click handling. Turns on the computer if it's off and opens the GUI.
diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm
index 8f29af43510..7e260872859 100644
--- a/code/modules/modular_computers/file_system/programs/atmosscan.dm
+++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm
@@ -44,7 +44,7 @@
var/list/airs = islist(mixture) ? mixture : list(mixture)
var/list/new_gasmix_data = list()
for(var/datum/gas_mixture/air as anything in airs)
- var/mix_name = capitalize(lowertext(target.name))
+ var/mix_name = capitalize(LOWER_TEXT(target.name))
if(airs.len != 1) //not a unary gas mixture
mix_name += " - Node [airs.Find(air)]"
new_gasmix_data += list(gas_mixture_parser(air, mix_name))
diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm
index eee170e7c2c..aa3ed0e5828 100644
--- a/code/modules/modular_computers/file_system/programs/secureye.dm
+++ b/code/modules/modular_computers/file_system/programs/secureye.dm
@@ -70,7 +70,7 @@
// Convert networks to lowercase
for(var/i in network)
network -= i
- network += lowertext(i)
+ network += LOWER_TEXT(i)
// Initialize map objects
cam_screen = new
cam_screen.generate_view(map_name)
diff --git a/code/modules/pai/door_jack.dm b/code/modules/pai/door_jack.dm
index 182cdc10027..36220ecface 100644
--- a/code/modules/pai/door_jack.dm
+++ b/code/modules/pai/door_jack.dm
@@ -104,17 +104,17 @@
/mob/living/silicon/pai/proc/hack_door()
if(!hacking_cable)
return FALSE
- if(!hacking_cable.machine)
+ if(!hacking_cable.hacking_machine)
balloon_alert(src, "nothing connected")
return FALSE
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, TRUE)
balloon_alert(src, "overriding...")
// Now begin hacking
- if(!do_after(src, 15 SECONDS, hacking_cable.machine, timed_action_flags = NONE, progress = TRUE))
+ if(!do_after(src, 15 SECONDS, hacking_cable.hacking_machine, timed_action_flags = NONE, progress = TRUE))
balloon_alert(src, "failed! retracting...")
QDEL_NULL(hacking_cable)
return FALSE
- var/obj/machinery/door/door = hacking_cable.machine
+ var/obj/machinery/door/door = hacking_cable.hacking_machine
balloon_alert(src, "success")
door.open()
QDEL_NULL(hacking_cable)
diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm
index 1dfe4ea7821..9c8ec0b8640 100644
--- a/code/modules/paperwork/carbonpaper.dm
+++ b/code/modules/paperwork/carbonpaper.dm
@@ -20,11 +20,11 @@
return
. += span_notice("Right-click to tear off the carbon-copy (you must use both hands).")
-/obj/item/paper/carbon/AltClick(mob/living/user)
+/obj/item/paper/carbon/click_alt(mob/living/user)
if(!copied)
to_chat(user, span_notice("Take off the carbon copy first."))
- return
- return ..()
+ return CLICK_ACTION_BLOCKING
+ return CLICK_ACTION_SUCCESS
/obj/item/paper/carbon/proc/removecopy(mob/living/user)
if(copied)
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index 7285aa3172d..8b475ed6324 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -71,13 +71,16 @@
pen = null
update_icon()
-/obj/item/clipboard/AltClick(mob/user)
- ..()
- if(pen)
- if(integrated_pen)
- to_chat(user, span_warning("You can't seem to find a way to remove [src]'s [pen]."))
- else
- remove_pen(user)
+/obj/item/clipboard/click_alt(mob/user)
+ if(isnull(pen))
+ return CLICK_ACTION_BLOCKING
+
+ if(integrated_pen)
+ to_chat(user, span_warning("You can't seem to find a way to remove [src]'s [pen]."))
+ return CLICK_ACTION_BLOCKING
+
+ remove_pen(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/clipboard/update_overlays()
. = ..()
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index e4ac04a22b6..d89d74d7f8e 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -107,12 +107,9 @@
to_chat(user, span_notice("You turn off [src]."))
return TRUE
-/obj/item/hand_labeler/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- . = ..()
- if(. & ITEM_INTERACT_ANY_BLOCKER)
- return .
+/obj/item/hand_labeler/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/hand_labeler_refill))
- return .
+ return NONE
balloon_alert(user, "refilled")
qdel(tool)
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 5aac6d93bc3..e1bddd6feff 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -30,6 +30,7 @@
grind_results = list(/datum/reagent/cellulose = 3)
color = COLOR_WHITE
item_flags = SKIP_FANTASY_ON_SPAWN
+ interaction_flags_click = NEED_DEXTERITY|NEED_HANDS
/// Lazylist of raw, unsanitised, unparsed text inputs that have been made to the paper.
var/list/datum/paper_input/raw_text_inputs
@@ -359,13 +360,13 @@
return TRUE
return ..()
-/obj/item/paper/AltClick(mob/living/user)
- . = ..()
- if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS))
- return
+/obj/item/paper/click_alt(mob/living/user)
if(HAS_TRAIT(user, TRAIT_PAPER_MASTER))
- return make_plane(user, /obj/item/paperplane/syndicate)
- return make_plane(user, /obj/item/paperplane)
+ make_plane(user, /obj/item/paperplane/syndicate)
+ return CLICK_ACTION_SUCCESS
+ make_plane(user, /obj/item/paperplane)
+ return CLICK_ACTION_SUCCESS
+
/**
@@ -374,9 +375,9 @@
*
* Arguments:
* * mob/living/user - who's folding
- * * obj/item/paperplane/plane_type - what it will be folded into (path)
+ * * plane_type - what it will be folded into (path)
*/
-/obj/item/paper/proc/make_plane(mob/living/user, obj/item/paperplane/plane_type = /obj/item/paperplane)
+/obj/item/paper/proc/make_plane(mob/living/user, plane_type = /obj/item/paperplane)
balloon_alert(user, "folded into a plane")
user.temporarilyRemoveItemFromInventory(src)
var/obj/item/paperplane/new_plane = new plane_type(loc, src)
diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm
index ae93a1daad8..8e4fedf2fda 100644
--- a/code/modules/paperwork/paper_cutter.dm
+++ b/code/modules/paperwork/paper_cutter.dm
@@ -141,16 +141,14 @@
return ..()
-/obj/item/papercutter/AltClick(mob/user)
- if(!user.Adjacent(src))
- return ..()
-
+/obj/item/papercutter/click_alt(mob/user)
// can only remove one at a time; paper goes first, as its most likely what players will want to be taking out
if(!isnull(stored_paper))
user.put_in_hands(stored_paper)
else if(!isnull(stored_blade) && !blade_secured)
user.put_in_hands(stored_blade)
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/papercutter/attack_hand_secondary(mob/user, list/modifiers)
if(!stored_blade)
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 2a9e78e2489..ec71eda2e46 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -44,6 +44,7 @@
dart_insert_projectile_icon_state, \
CALLBACK(src, PROC_REF(get_dart_var_modifiers))\
)
+ AddElement(/datum/element/tool_renaming)
RegisterSignal(src, COMSIG_DART_INSERT_ADDED, PROC_REF(on_inserted_into_dart))
RegisterSignal(src, COMSIG_DART_INSERT_REMOVED, PROC_REF(on_removed_from_dart))
@@ -179,6 +180,7 @@
if(current_skin)
desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp."
+
/obj/item/pen/fountain/captain/proc/reskin_dart_insert(datum/component/dart_insert/insert_comp)
if(!istype(insert_comp)) //You really shouldn't be sending this signal from anything other than a dart_insert component
return
@@ -209,54 +211,6 @@
log_combat(user, M, "stabbed", src)
return TRUE
-/obj/item/pen/afterattack(obj/O, mob/living/user, proximity)
- . = ..()
-
- if (!proximity)
- return .
-
- . |= AFTERATTACK_PROCESSED_ITEM
-
- //Changing name/description of items. Only works if they have the UNIQUE_RENAME object flag set
- if(isobj(O) && (O.obj_flags & UNIQUE_RENAME))
- var/penchoice = tgui_input_list(user, "What would you like to edit?", "Pen Setting", list("Rename", "Description", "Reset"))
- if(QDELETED(O) || !user.can_perform_action(O))
- return
- if(penchoice == "Rename")
- var/input = tgui_input_text(user, "What do you want to name [O]?", "Object Name", "[O.name]", MAX_NAME_LEN)
- var/oldname = O.name
- if(QDELETED(O) || !user.can_perform_action(O))
- return
- if(input == oldname || !input)
- to_chat(user, span_notice("You changed [O] to... well... [O]."))
- else
- O.AddComponent(/datum/component/rename, input, O.desc)
- to_chat(user, span_notice("You have successfully renamed \the [oldname] to [O]."))
- ADD_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT)
- O.update_appearance(UPDATE_ICON)
-
- if(penchoice == "Description")
- var/input = tgui_input_text(user, "Describe [O]", "Description", "[O.desc]", 280)
- var/olddesc = O.desc
- if(QDELETED(O) || !user.can_perform_action(O))
- return
- if(input == olddesc || !input)
- to_chat(user, span_notice("You decide against changing [O]'s description."))
- else
- O.AddComponent(/datum/component/rename, O.name, input)
- to_chat(user, span_notice("You have successfully changed [O]'s description."))
- ADD_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT)
- O.update_appearance(UPDATE_ICON)
-
- if(penchoice == "Reset")
- if(QDELETED(O) || !user.can_perform_action(O))
- return
-
- qdel(O.GetComponent(/datum/component/rename))
- to_chat(user, span_notice("You have successfully reset [O]'s name and description."))
- REMOVE_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT)
- O.update_appearance(UPDATE_ICON)
-
/obj/item/pen/get_writing_implement_details()
return list(
interaction_mode = MODE_WRITING,
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 207b8351a58..0712e516de4 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -547,7 +547,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
toner_cartridge = object
balloon_alert(user, "cartridge inserted")
- else if(istype(object, /obj/item/areaeditor/blueprints))
+ else if(istype(object, /obj/item/blueprints))
to_chat(user, span_warning("\The [object] is too large to put into the copier. You need to find something else to record the document."))
else if(istype(object, /obj/item/paperwork))
diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index 0d5f37cb867..35462a24d86 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -72,10 +72,9 @@
picture_size_y = min(clamp(desired_y, picture_size_y_min, picture_size_y_max), CAMERA_PICTURE_SIZE_HARD_LIMIT)
return TRUE
-/obj/item/camera/AltClick(mob/user)
- if(!user.can_perform_action(src))
- return
+/obj/item/camera/click_alt(mob/user)
adjust_zoom(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/camera/attack(mob/living/carbon/human/M, mob/user)
return
@@ -206,7 +205,7 @@
turfs += placeholder
for(var/mob/M in placeholder)
mobs += M
- if(locate(/obj/item/areaeditor/blueprints) in placeholder)
+ if(locate(/obj/item/blueprints) in placeholder)
blueprints = TRUE
// do this before picture is taken so we can reveal revenants for the photo
@@ -251,11 +250,11 @@
to_chat(user, span_notice("[pictures_left] photos left."))
if(can_customise)
- var/customise = tgui_alert(user, "Do you want to customize the photo?", "Customization", list("Yes", "No"))
+ var/customise = user.is_holding(new_photo) && tgui_alert(user, "Do you want to customize the photo?", "Customization", list("Yes", "No"))
if(customise == "Yes")
- var/name1 = tgui_input_text(user, "Set a name for this photo, or leave blank.", "Name", max_length = 32)
- var/desc1 = tgui_input_text(user, "Set a description to add to photo, or leave blank.", "Description", max_length = 128)
- var/caption = tgui_input_text(user, "Set a caption for this photo, or leave blank.", "Caption", max_length = 256)
+ var/name1 = user.is_holding(new_photo) && tgui_input_text(user, "Set a name for this photo, or leave blank.", "Name", max_length = 32)
+ var/desc1 = user.is_holding(new_photo) && tgui_input_text(user, "Set a description to add to photo, or leave blank.", "Description", max_length = 128)
+ var/caption = user.is_holding(new_photo) && tgui_input_text(user, "Set a caption for this photo, or leave blank.", "Caption", max_length = 256)
if(name1)
picture.picture_name = name1
if(desc1)
diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm
index 33073ae910f..a7990f65ce5 100644
--- a/code/modules/plumbing/ducts.dm
+++ b/code/modules/plumbing/ducts.dm
@@ -343,9 +343,13 @@ All the important duct code:
/obj/item/stack/ducts/attack_self(mob/user)
var/new_layer = tgui_input_list(user, "Select a layer", "Layer", GLOB.plumbing_layers, duct_layer)
+ if(!user.is_holding(src))
+ return
if(new_layer)
duct_layer = new_layer
var/new_color = tgui_input_list(user, "Select a color", "Color", GLOB.pipe_paint_colors, duct_color)
+ if(!user.is_holding(src))
+ return
if(new_color)
duct_color = new_color
add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY)
diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm
index 418df177465..8baf59508b8 100644
--- a/code/modules/plumbing/plumbers/_plumb_machinery.dm
+++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm
@@ -26,8 +26,6 @@
. = ..()
. += span_notice("The maximum volume display reads: [reagents.maximum_volume] units.")
-/obj/machinery/plumbing/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/tool)
. = ..()
@@ -35,9 +33,9 @@
return ITEM_INTERACT_SUCCESS
/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
- to_chat(user, span_notice("You start furiously plunging [name]."))
+ user.balloon_alert_to_viewers("furiously plunging...")
if(do_after(user, 3 SECONDS, target = src))
- to_chat(user, span_notice("You finish plunging the [name]."))
+ user.balloon_alert_to_viewers("finished plunging")
reagents.expose(get_turf(src), TOUCH) //splash on the floor
reagents.clear_reagents()
diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm
index 633f70830f0..c4df35164f0 100644
--- a/code/modules/plumbing/plumbers/filter.dm
+++ b/code/modules/plumbing/plumbers/filter.dm
@@ -30,7 +30,7 @@
data["right"] = english_right
return data
-/obj/machinery/plumbing/filter/ui_act(action, params)
+/obj/machinery/plumbing/filter/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
@@ -42,6 +42,8 @@
var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.name2reagent)
if(!selected_reagent)
return TRUE
+ if(QDELETED(ui) || ui.status != UI_INTERACTIVE)
+ return FALSE
var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent]
if(!chem_id)
@@ -69,5 +71,3 @@
if(english_right.Find(chem_name))
english_right -= chem_name
right -= chem_id
-
-
diff --git a/code/modules/plumbing/plumbers/iv_drip.dm b/code/modules/plumbing/plumbers/iv_drip.dm
index 7275212ee76..f9a5ae47598 100644
--- a/code/modules/plumbing/plumbers/iv_drip.dm
+++ b/code/modules/plumbing/plumbers/iv_drip.dm
@@ -23,14 +23,12 @@
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/iv_drip/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
- to_chat(user, span_notice("You start furiously plunging [name]."))
+ user.balloon_alert_to_viewers("furiously plunging...", "plunging iv drip...")
if(do_after(user, 3 SECONDS, target = src))
- to_chat(user, span_notice("You finish plunging the [name]."))
+ user.balloon_alert_to_viewers("finished plunging")
reagents.expose(get_turf(src), TOUCH) //splash on the floor
reagents.clear_reagents()
-/obj/machinery/iv_drip/plumbing/can_use_alt_click(mob/user)
- return FALSE //Alt click is used for rotation
/obj/machinery/iv_drip/plumbing/wrench_act(mob/living/user, obj/item/tool)
if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN)
diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm
index 72caa603767..9bdac2f98b2 100644
--- a/code/modules/plumbing/plumbers/reaction_chamber.dm
+++ b/code/modules/plumbing/plumbers/reaction_chamber.dm
@@ -107,6 +107,8 @@
var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.name2reagent)
if(!selected_reagent)
return FALSE
+ if(QDELETED(ui) || ui.status != UI_INTERACTIVE)
+ return FALSE
var/datum/reagent/input_reagent = GLOB.name2reagent[selected_reagent]
if(!input_reagent)
diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm
index 00d3fc7a538..6a8835cd5b7 100644
--- a/code/modules/power/apc/apc_tool_act.dm
+++ b/code/modules/power/apc/apc_tool_act.dm
@@ -1,10 +1,7 @@
//attack with an item - open/close cover, insert cell, or (un)lock interface
-/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- . = ..()
- if(.)
- return .
-
+/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ . = NONE
if(HAS_TRAIT(tool, TRAIT_APC_SHOCKING))
. = fork_outlet_act(user, tool)
if(.)
@@ -17,7 +14,7 @@
if(istype(tool, /obj/item/stock_parts/cell))
. = cell_act(user, tool)
else if(istype(tool, /obj/item/stack/cable_coil))
- . = cable_act(user, tool, is_right_clicking)
+ . = cable_act(user, tool, LAZYACCESS(modifiers, RIGHT_CLICK))
else if(istype(tool, /obj/item/electronics/apc))
. = electronics_act(user, tool)
else if(istype(tool, /obj/item/electroadaptive_pseudocircuit))
@@ -26,7 +23,7 @@
. = wallframe_act(user, tool)
if(.)
return .
-
+
if(panel_open && !opened && is_wire_tool(tool))
wires.interact(user)
return ITEM_INTERACT_SUCCESS
@@ -73,44 +70,59 @@
update_appearance()
return ITEM_INTERACT_SUCCESS
+/// Checks if we can place a terminal on the APC
+/obj/machinery/power/apc/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE)
+ if(!opened)
+ return FALSE
+ var/turf/host_turf = get_turf(src)
+ if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
+ if(!silent && user)
+ balloon_alert(user, "remove the floor plating!")
+ return FALSE
+ if(!isnull(terminal))
+ if(!silent && user)
+ balloon_alert(user, "already wired!")
+ return FALSE
+ if(!has_electronics)
+ if(!silent && user)
+ balloon_alert(user, "no board to wire!")
+ return FALSE
+ if(panel_open)
+ if(!silent && user)
+ balloon_alert(user, "wires prevent placing a terminal!")
+ return FALSE
+ if(installing_cable.get_amount() < 10)
+ if(!silent && user)
+ balloon_alert(user, "need ten lengths of cable!")
+ return FALSE
+ return TRUE
+
/// Called when we interact with the APC with a cable, attempts to wire the APC and create a terminal
/obj/machinery/power/apc/proc/cable_act(mob/living/user, obj/item/stack/cable_coil/installing_cable, is_right_clicking)
if(!opened)
return NONE
-
- var/turf/host_turf = get_turf(src)
- if(!host_turf)
- CRASH("cable_act on APC when it's not on a turf")
- if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
- balloon_alert(user, "remove the floor plating!")
- return ITEM_INTERACT_BLOCKING
- if(terminal)
- balloon_alert(user, "already wired!")
- return ITEM_INTERACT_BLOCKING
- if(!has_electronics)
- balloon_alert(user, "no board to wire!")
- return ITEM_INTERACT_BLOCKING
-
- if(installing_cable.get_amount() < 10)
- balloon_alert(user, "need ten lengths of cable!")
+ if(!can_place_terminal(user, installing_cable, silent = FALSE))
return ITEM_INTERACT_BLOCKING
var/terminal_cable_layer = cable_layer // Default to machine's cable layer
if(is_right_clicking)
var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer)
- if(isnull(choice))
+ if(isnull(choice) \
+ || !user.is_holding(installing_cable) \
+ || !user.Adjacent(src) \
+ || user.incapacitated() \
+ || !can_place_terminal(user, installing_cable, silent = TRUE) \
+ )
return ITEM_INTERACT_BLOCKING
terminal_cable_layer = GLOB.cable_name_to_layer[choice]
- user.visible_message(span_notice("[user.name] adds cables to the APC frame."))
- balloon_alert(user, "adding cables to the frame...")
- playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
+ user.visible_message(span_notice("[user.name] starts addding cables to the APC frame."))
+ balloon_alert(user, "adding cables...")
+ playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
if(!do_after(user, 2 SECONDS, target = src))
return ITEM_INTERACT_BLOCKING
- if(installing_cable.get_amount() < 10 || !installing_cable)
- return ITEM_INTERACT_BLOCKING
- if(terminal || !opened || !has_electronics)
+ if(!can_place_terminal(user, installing_cable, silent = TRUE))
return ITEM_INTERACT_BLOCKING
var/turf/our_turf = get_turf(src)
var/obj/structure/cable/cable_node = our_turf.get_cable_node(terminal_cable_layer)
@@ -118,7 +130,8 @@
do_sparks(5, TRUE, src)
return ITEM_INTERACT_BLOCKING
installing_cable.use(10)
- balloon_alert(user, "cables added to the frame")
+ user.visible_message(span_notice("[user.name] adds cables to the APC frame."))
+ balloon_alert(user, "cables added")
make_terminal(terminal_cable_layer)
terminal.connect_to_network()
return ITEM_INTERACT_SUCCESS
@@ -127,7 +140,7 @@
/obj/machinery/power/apc/proc/electronics_act(mob/living/user, obj/item/electronics/apc/installing_board)
if(!opened)
return NONE
-
+
if(has_electronics)
balloon_alert(user, "there is already a board!")
return ITEM_INTERACT_BLOCKING
diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm
index a7013595543..0a698817602 100644
--- a/code/modules/power/lighting/light.dm
+++ b/code/modules/power/lighting/light.dm
@@ -118,9 +118,8 @@
RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur))
AddElement(/datum/element/atmos_sensitive, mapload)
find_and_hang_on_wall(custom_drop_callback = CALLBACK(src, PROC_REF(knock_down)))
- return INITIALIZE_HINT_LATELOAD
-/obj/machinery/light/LateInitialize()
+/obj/machinery/light/post_machine_initialize()
. = ..()
#ifndef MAP_TEST
switch(fitting)
diff --git a/code/modules/power/pipecleaners.dm b/code/modules/power/pipecleaners.dm
index 2a41c70bdfe..7f1ef8fc2e3 100644
--- a/code/modules/power/pipecleaners.dm
+++ b/code/modules/power/pipecleaners.dm
@@ -163,10 +163,9 @@ By design, d1 is the smallest direction and d2 is the highest
stored.color = colorC
stored.update_appearance()
-/obj/structure/pipe_cleaner/AltClick(mob/living/user)
- if(!user.can_perform_action(src))
- return
+/obj/structure/pipe_cleaner/click_alt(mob/living/user)
cut_pipe_cleaner(user)
+ return CLICK_ACTION_SUCCESS
///////////////////////////////////////////////
// The pipe cleaner coil object, used for laying pipe cleaner
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index 84542805d48..e4c1617c0f0 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -98,7 +98,7 @@
var/obj/S = sheet_path
sheet_name = initial(S.name)
-/obj/machinery/power/port_gen/pacman/Destroy()
+/obj/machinery/power/port_gen/pacman/on_deconstruction(disassembled)
DropFuel()
return ..()
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index ce912027225..c9cbb0d3ecc 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -50,9 +50,9 @@
. = ..()
if(can_change_cable_layer)
if(!QDELETED(powernet))
- . += span_notice("It's operating on the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].")
+ . += span_notice("It's operating on the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].")
else
- . += span_warning("It's disconnected from the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].")
+ . += span_warning("It's disconnected from the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].")
. += span_notice("It's power line can be changed with a [EXAMINE_HINT("multitool")].")
/obj/machinery/power/multitool_act(mob/living/user, obj/item/tool)
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index 9f19774cc61..932aef0e8e5 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -29,6 +29,7 @@
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
+ AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
/obj/machinery/field/containment/Destroy()
if(field_gen_1)
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index a360fc12145..38f18d7d627 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -346,8 +346,6 @@
return
return ..()
-/obj/machinery/power/emitter/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/machinery/power/emitter/proc/integrate(obj/item/gun/energy/energy_gun, mob/user)
if(!istype(energy_gun, /obj/item/gun/energy))
diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm
index 527ce9c560b..ba9fde43d49 100644
--- a/code/modules/power/singularity/field_generator.dm
+++ b/code/modules/power/singularity/field_generator.dm
@@ -208,6 +208,7 @@ no power level overlay is currently in the overlays list.
air_update_turf(TRUE, FALSE)
INVOKE_ASYNC(src, PROC_REF(cleanup))
addtimer(CALLBACK(src, PROC_REF(cool_down)), 5 SECONDS)
+ RemoveElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
/obj/machinery/field/generator/proc/cool_down()
if(active || warming_up <= 0)
@@ -220,6 +221,7 @@ no power level overlay is currently in the overlays list.
/obj/machinery/field/generator/proc/turn_on()
active = FG_CHARGING
addtimer(CALLBACK(src, PROC_REF(warm_up)), 5 SECONDS)
+ AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD)))
/obj/machinery/field/generator/proc/warm_up()
if(!active)
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 5b712d52da2..d47d7536094 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -386,16 +386,8 @@
/obj/singularity/proc/can_move(turf/considered_turf)
if(!considered_turf)
return FALSE
- if((locate(/obj/machinery/field/containment) in considered_turf) || (locate(/obj/machinery/shieldwall) in considered_turf))
+ if (HAS_TRAIT(considered_turf, TRAIT_CONTAINMENT_FIELD))
return FALSE
- else if(locate(/obj/machinery/field/generator) in considered_turf)
- var/obj/machinery/field/generator/check_generator = locate(/obj/machinery/field/generator) in considered_turf
- if(check_generator?.active)
- return FALSE
- else if(locate(/obj/machinery/power/shieldwallgen) in considered_turf)
- var/obj/machinery/power/shieldwallgen/check_shield = locate(/obj/machinery/power/shieldwallgen) in considered_turf
- if(check_shield?.active)
- return FALSE
return TRUE
/obj/singularity/proc/event()
@@ -482,3 +474,16 @@
/// Special singularity that spawns for shuttle events only
/obj/singularity/shuttle_event
anchored = FALSE
+
+/// Special singularity spawned by being sucked into a black hole during emagged orion trail.
+/obj/singularity/orion
+ move_self = FALSE
+
+/obj/singularity/orion/Initialize(mapload)
+ . = ..()
+ var/datum/component/singularity/singularity = singularity_component.resolve()
+ singularity?.grav_pull = 1
+
+/obj/singularity/orion/process(seconds_per_tick)
+ if(SPT_PROB(0.5, seconds_per_tick))
+ mezzer()
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index c6fa9274cb3..2aa5247451d 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -112,55 +112,42 @@
//building and linking a terminal
if(istype(item, /obj/item/stack/cable_coil))
- var/dir = get_dir(user,src)
- if(dir & (dir-1))//we don't want diagonal click
- return
-
- if(terminal) //is there already a terminal ?
- to_chat(user, span_warning("This SMES already has a power terminal!"))
- return
-
- if(!panel_open) //is the panel open ?
- to_chat(user, span_warning("You must open the maintenance panel first!"))
- return
-
- var/turf/turf = get_turf(user)
- if (turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can we get to the underfloor?
- to_chat(user, span_warning("You must first remove the floor plating!"))
- return
-
-
- var/obj/item/stack/cable_coil/cable = item
- if(cable.get_amount() < 10)
- to_chat(user, span_warning("You need more wires!"))
+ if(!can_place_terminal(user, item, silent = FALSE))
return
var/terminal_cable_layer
if(LAZYACCESS(params2list(params), RIGHT_CLICK))
var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer)
- if(isnull(choice))
+ if(isnull(choice) \
+ || !user.is_holding(item) \
+ || !user.Adjacent(src) \
+ || user.incapacitated() \
+ || !can_place_terminal(user, item, silent = TRUE) \
+ )
return
terminal_cable_layer = GLOB.cable_name_to_layer[choice]
- to_chat(user, span_notice("You start building the power terminal..."))
- playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
+ user.visible_message(span_notice("[user.name] starts adding cables to [src]."))
+ balloon_alert(user, "adding cables...")
+ playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
- if(do_after(user, 2 SECONDS, target = src))
- if(cable.get_amount() < 10 || !cable)
- return
- var/obj/structure/cable/connected_cable = turf.get_cable_node(terminal_cable_layer) //get the connecting node cable, if there's one
- if (prob(50) && electrocute_mob(user, connected_cable, connected_cable, 1, TRUE)) //animate the electrocution if uncautious and unlucky
- do_sparks(5, TRUE, src)
- return
- if(!terminal)
- cable.use(10)
- user.visible_message(span_notice("[user.name] builds a power terminal."),\
- span_notice("You build the power terminal."))
-
- //build the terminal and link it to the network
- make_terminal(turf, terminal_cable_layer)
- terminal.connect_to_network()
- connect_to_network()
+ if(!do_after(user, 2 SECONDS, target = src))
+ return
+ if(!can_place_terminal(user, item, silent = TRUE))
+ return
+ var/obj/item/stack/cable_coil/cable = item
+ var/turf/turf = get_turf(user)
+ var/obj/structure/cable/connected_cable = turf.get_cable_node(terminal_cable_layer) //get the connecting node cable, if there's one
+ if (prob(50) && electrocute_mob(user, connected_cable, connected_cable, 1, TRUE)) //animate the electrocution if uncautious and unlucky
+ do_sparks(5, TRUE, src)
+ return
+ cable.use(10)
+ user.visible_message(span_notice("[user.name] adds cables to [src]"))
+ balloon_alert(user, "cables added")
+ //build the terminal and link it to the network
+ make_terminal(turf, terminal_cable_layer)
+ terminal.connect_to_network()
+ connect_to_network()
return
//crowbarring it !
@@ -175,6 +162,31 @@
return ..()
+/// Checks if we're in a valid state to place a terminal
+/obj/machinery/power/smes/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE)
+ var/set_dir = get_dir(user, src)
+ if(set_dir & (set_dir - 1))//we don't want diagonal click
+ return FALSE
+
+ var/turf/terminal_turf = get_turf(user)
+ if(!panel_open)
+ if(!silent && user)
+ balloon_alert(user, "open the maintenance panel!")
+ return FALSE
+ if(terminal_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
+ if(!silent && user)
+ balloon_alert(user, "remove the floor plating!")
+ return FALSE
+ if(terminal)
+ if(!silent && user)
+ balloon_alert(user, "already wired!")
+ return FALSE
+ if(installing_cable.get_amount() < 10)
+ if(!silent && user)
+ balloon_alert(user, "need ten lengths of cable!")
+ return FALSE
+ return TRUE
+
/obj/machinery/power/smes/wirecutter_act(mob/living/user, obj/item/item)
//disassembling the terminal
. = ..()
diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm
index 4c861a4bb4b..04b9ab8798b 100644
--- a/code/modules/power/terminal.dm
+++ b/code/modules/power/terminal.dm
@@ -26,9 +26,9 @@
/obj/machinery/power/terminal/examine(mob/user)
. = ..()
if(!QDELETED(powernet))
- . += span_notice("It's operating on the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].")
+ . += span_notice("It's operating on the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].")
else
- . += span_warning("It's disconnected from the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].")
+ . += span_warning("It's disconnected from the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].")
/obj/machinery/power/terminal/should_have_node()
return TRUE
diff --git a/code/modules/power/turbine/turbine.dm b/code/modules/power/turbine/turbine.dm
index 21269c90d37..590b135ad9a 100644
--- a/code/modules/power/turbine/turbine.dm
+++ b/code/modules/power/turbine/turbine.dm
@@ -43,7 +43,7 @@
register_context()
-/obj/machinery/power/turbine/LateInitialize()
+/obj/machinery/power/turbine/post_machine_initialize()
. = ..()
activate_parts()
diff --git a/code/modules/power/turbine/turbine_computer.dm b/code/modules/power/turbine/turbine_computer.dm
index 9e0f5bdaa46..f983e11c1f1 100644
--- a/code/modules/power/turbine/turbine_computer.dm
+++ b/code/modules/power/turbine/turbine_computer.dm
@@ -9,11 +9,7 @@
///Easy way to connect a computer and a turbine roundstart by setting an id on both this and the core_rotor
var/mapping_id
-/obj/machinery/computer/turbine_computer/Initialize(mapload)
- . = ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/computer/turbine_computer/LateInitialize()
+/obj/machinery/computer/turbine_computer/post_machine_initialize()
. = ..()
locate_machinery()
diff --git a/code/modules/procedural_mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm
index 420ac9c8d79..58ff5641907 100644
--- a/code/modules/procedural_mapping/mapGenerator.dm
+++ b/code/modules/procedural_mapping/mapGenerator.dm
@@ -136,40 +136,36 @@
// HERE BE DEBUG DRAGONS //
///////////////////////////
-/client/proc/debugNatureMapGenerator()
- set name = "Test Nature Map Generator"
- set category = "Debug"
-
+ADMIN_VERB(debug_nature_map_generator, R_DEBUG, "Test Nature Map Generator", "Test the nature map generator", ADMIN_CATEGORY_DEBUG)
var/datum/map_generator/nature/N = new()
- var/startInput = input(usr, "Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text|null
+ var/startInput = input(user, "Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text|null
if (isnull(startInput))
return
- var/endInput = input(usr, "End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[mob ? mob.z : 1]") as text|null
-
+ var/endInput = input(user, "End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[user.mob.z]") as text|null
if (isnull(endInput))
return
//maxx maxy and current z so that if you fuck up, you only fuck up one entire z level instead of the entire universe
if(!startInput || !endInput)
- to_chat(src, "Missing Input")
+ to_chat(user, "Missing Input")
return
var/list/startCoords = splittext(startInput, ";")
var/list/endCoords = splittext(endInput, ";")
if(!startCoords || !endCoords)
- to_chat(src, "Invalid Coords")
- to_chat(src, "Start Input: [startInput]")
- to_chat(src, "End Input: [endInput]")
+ to_chat(user, "Invalid Coords")
+ to_chat(user, "Start Input: [startInput]")
+ to_chat(user, "End Input: [endInput]")
return
var/turf/Start = locate(text2num(startCoords[1]),text2num(startCoords[2]),text2num(startCoords[3]))
var/turf/End = locate(text2num(endCoords[1]),text2num(endCoords[2]),text2num(endCoords[3]))
if(!Start || !End)
- to_chat(src, "Invalid Turfs")
- to_chat(src, "Start Coords: [startCoords[1]] - [startCoords[2]] - [startCoords[3]]")
- to_chat(src, "End Coords: [endCoords[1]] - [endCoords[2]] - [endCoords[3]]")
+ to_chat(user, "Invalid Turfs")
+ to_chat(user, "Start Coords: [startCoords[1]] - [startCoords[2]] - [startCoords[3]]")
+ to_chat(user, "End Coords: [endCoords[1]] - [endCoords[2]] - [endCoords[3]]")
return
var/static/list/clusters = list(
@@ -191,7 +187,7 @@
var/theCluster = 0
if(moduleClusters != "None")
if(!clusters[moduleClusters])
- to_chat(src, "Invalid Cluster Flags")
+ to_chat(user, "Invalid Cluster Flags")
return
theCluster = clusters[moduleClusters]
else
@@ -202,9 +198,9 @@
M.clusterCheckFlags = theCluster
- to_chat(src, "Defining Region")
+ to_chat(user, "Defining Region")
N.defineRegion(Start, End)
- to_chat(src, "Region Defined")
- to_chat(src, "Generating Region")
+ to_chat(user, "Region Defined")
+ to_chat(user, "Generating Region")
N.generate()
- to_chat(src, "Generated Region")
+ to_chat(user, "Generated Region")
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 791055fd2d2..b206e1977f4 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -485,7 +485,7 @@
///Installs a new suppressor, assumes that the suppressor is already in the contents of src
/obj/item/gun/ballistic/proc/install_suppressor(obj/item/suppressor/S)
suppressed = S
- w_class += S.w_class //so pistols do not fit in pockets when suppressed
+ update_weight_class(w_class + S.w_class) //so pistols do not fit in pockets when suppressed
update_appearance()
/obj/item/gun/ballistic/clear_suppressor()
@@ -493,21 +493,19 @@
return
if(isitem(suppressed))
var/obj/item/I = suppressed
- w_class -= I.w_class
+ update_weight_class(w_class - I.w_class)
return ..()
-/obj/item/gun/ballistic/AltClick(mob/user)
- if (unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
- return
- if(loc == user)
- if(suppressed && can_unsuppress)
- var/obj/item/suppressor/S = suppressed
- if(!user.is_holding(src))
- return ..()
- balloon_alert(user, "[S.name] removed")
- user.put_in_hands(S)
- clear_suppressor()
+/obj/item/gun/ballistic/click_alt(mob/user)
+ if(!suppressed || !can_unsuppress)
+ return CLICK_ACTION_BLOCKING
+ var/obj/item/suppressor/S = suppressed
+ if(!user.is_holding(src))
+ return CLICK_ACTION_BLOCKING
+ balloon_alert(user, "[S.name] removed")
+ user.put_in_hands(S)
+ clear_suppressor()
+ return CLICK_ACTION_SUCCESS
///Prefire empty checks for the bolt drop
/obj/item/gun/ballistic/proc/prefire_empty_checks()
@@ -666,7 +664,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list(
if(handle_modifications)
name = "sawn-off [src.name]"
desc = sawn_desc
- w_class = WEIGHT_CLASS_NORMAL
+ update_weight_class(WEIGHT_CLASS_NORMAL)
//The file might not have a "gun" icon, let's prepare for this
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 3d6940692d8..8c6e2ae7cbd 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -260,13 +260,12 @@
. += span_notice("It seems like you could use an empty hand to remove the magazine.")
-/obj/item/gun/ballistic/automatic/l6_saw/AltClick(mob/user)
- if(!user.can_perform_action(src))
- return
+/obj/item/gun/ballistic/automatic/l6_saw/click_alt(mob/user)
cover_open = !cover_open
balloon_alert(user, "cover [cover_open ? "opened" : "closed"]")
playsound(src, 'sound/weapons/gun/l6/l6_door.ogg', 60, TRUE)
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/gun/ballistic/automatic/l6_saw/update_icon_state()
. = ..()
diff --git a/code/modules/projectiles/guns/ballistic/bows/_bow.dm b/code/modules/projectiles/guns/ballistic/bows/_bow.dm
index c356d5b266c..86094d0fe17 100644
--- a/code/modules/projectiles/guns/ballistic/bows/_bow.dm
+++ b/code/modules/projectiles/guns/ballistic/bows/_bow.dm
@@ -29,13 +29,14 @@
. = ..()
icon_state = chambered ? "[base_icon_state]_[drawn ? "drawn" : "nocked"]" : "[base_icon_state]"
-/obj/item/gun/ballistic/bow/AltClick(mob/user)
+/obj/item/gun/ballistic/bow/click_alt(mob/user)
if(isnull(chambered))
- return ..()
+ return CLICK_ACTION_BLOCKING
user.put_in_hands(chambered)
chambered = magazine.get_round()
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/gun/ballistic/bow/proc/drop_arrow()
chambered.forceMove(drop_location())
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index 373607e53dd..e142616cbd4 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -37,9 +37,9 @@
..()
chamber_round()
-/obj/item/gun/ballistic/revolver/AltClick(mob/user)
- ..()
+/obj/item/gun/ballistic/revolver/click_alt(mob/user)
spin()
+ return CLICK_ACTION_SUCCESS
/obj/item/gun/ballistic/revolver/fire_sounds()
var/frequency_to_use = sin((90/magazine?.max_ammo) * get_ammo(TRUE, FALSE)) // fucking REVOLVERS
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index 37990971138..c584359b8ce 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -85,6 +85,7 @@
w_class = WEIGHT_CLASS_HUGE
semi_auto = TRUE
accepted_magazine_type = /obj/item/ammo_box/magazine/internal/shot/tube
+ interaction_flags_click = NEED_DEXTERITY|NEED_HANDS
/// If defined, the secondary tube is this type, if you want different shell loads
var/alt_mag_type
/// If TRUE, we're drawing from the alternate_magazine
@@ -131,10 +132,9 @@
else
balloon_alert(user, "switched to tube A")
-/obj/item/gun/ballistic/shotgun/automatic/dual_tube/AltClick(mob/living/user)
- if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS))
- return
+/obj/item/gun/ballistic/shotgun/automatic/dual_tube/click_alt(mob/living/user)
rack()
+ return CLICK_ACTION_SUCCESS
// Bulldog shotgun //
@@ -288,10 +288,6 @@
can_be_sawn_off = TRUE
pb_knockback = 3 // it's a super shotgun!
-/obj/item/gun/ballistic/shotgun/doublebarrel/AltClick(mob/user)
- . = ..()
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
/obj/item/gun/ballistic/shotgun/doublebarrel/sawoff(mob/user)
. = ..()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 27e93653a77..1d53eff0f9b 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -475,7 +475,7 @@
if(!trajectory)
qdel(src)
return FALSE
- if(impacted[A]) // NEVER doublehit
+ if(impacted[A.weak_reference]) // NEVER doublehit
return FALSE
var/datum/point/point_cache = trajectory.copy_to()
var/turf/T = get_turf(A)
@@ -528,7 +528,7 @@
if(QDELETED(src) || !T || !target)
return
// 2.
- impacted[target] = TRUE //hash lookup > in for performance in hit-checking
+ impacted[WEAKREF(target)] = TRUE //hash lookup > in for performance in hit-checking
// 3.
var/mode = prehit_pierce(target)
if(mode == PROJECTILE_DELETE_WITHOUT_HITTING)
@@ -605,7 +605,7 @@
//Returns true if the target atom is on our current turf and above the right layer
//If direct target is true it's the originally clicked target.
/obj/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE, cross_failed = FALSE)
- if(QDELETED(target) || impacted[target])
+ if(QDELETED(target) || impacted[target.weak_reference])
return FALSE
if(!ignore_loc && (loc != target.loc) && !(can_hit_turfs && direct_target && loc == target))
return FALSE
@@ -693,7 +693,7 @@
* Used to not even attempt to Bump() or fail to Cross() anything we already hit.
*/
/obj/projectile/CanPassThrough(atom/blocker, movement_dir, blocker_opinion)
- return impacted[blocker] ? TRUE : ..()
+ return ..() || impacted[blocker.weak_reference]
/**
* Projectile moved:
@@ -1204,10 +1204,8 @@
var/turf/startloc = get_turf(src)
var/obj/projectile/bullet = new projectile_type(startloc)
bullet.starting = startloc
- var/list/ignore = list()
for (var/atom/thing as anything in ignore_targets)
- ignore[thing] = TRUE
- bullet.impacted += ignore
+ bullet.impacted[WEAKREF(thing)] = TRUE
bullet.firer = firer || src
bullet.fired_from = src
bullet.yo = target.y - startloc.y
diff --git a/code/modules/reagents/chemistry/chem_wiki_render.dm b/code/modules/reagents/chemistry/chem_wiki_render.dm
index a2ac0af8ffb..99116adc84b 100644
--- a/code/modules/reagents/chemistry/chem_wiki_render.dm
+++ b/code/modules/reagents/chemistry/chem_wiki_render.dm
@@ -1,10 +1,6 @@
-//Generates a wikitable txt file for use with the wiki - does not support productless reactions at the moment
-/client/proc/generate_wikichem_list()
- set category = "Debug"
- set name = "Parse Wikichems"
-
+ADMIN_VERB(generate_wikichem_list, R_DEBUG, "Parse Wikichems", "Parse and generate a text file for wikichem.", ADMIN_CATEGORY_DEBUG)
//If we're a reaction product
- var/prefix_reaction = {"{| class=\"wikitable sortable\" style=\"width:100%; text-align:left; border: 3px solid #FFDD66; cellspacing=0; cellpadding=2; background-color:white;\"
+ var/static/prefix_reaction = {"{| class=\"wikitable sortable\" style=\"width:100%; text-align:left; border: 3px solid #FFDD66; cellspacing=0; cellpadding=2; background-color:white;\"
! scope=\"col\" style='width:150px; background-color:#FFDD66;'|Name
! scope=\"col\" class=\"unsortable\" style='background-color:#FFDD66;'|Formula
! scope=\"col\" class=\"unsortable\" style='background-color:#FFDD66; width:170px;'|Reaction conditions
@@ -13,9 +9,9 @@
|-
"}
- var/input_text = tgui_input_text(usr, "Input a name of a reagent, or a series of reagents split with a comma (no spaces) to get it's wiki table entry", "Recipe") //95% of the time, the reagent type is a lowercase, no spaces / underscored version of the name
+ var/input_text = tgui_input_text(user, "Input a name of a reagent, or a series of reagents split with a comma (no spaces) to get it's wiki table entry", "Recipe") //95% of the time, the reagent type is a lowercase, no spaces / underscored version of the name
if(!input_text)
- to_chat(usr, "Input was blank!")
+ to_chat(user, "Input was blank!")
return
text2file(prefix_reaction, "[GLOB.log_directory]/chem_parse.txt")
var/list/names = splittext("[input_text]", ",")
@@ -23,13 +19,13 @@
for(var/name in names)
var/datum/reagent/reagent = find_reagent_object_from_type(get_chem_id(name))
if(!reagent)
- to_chat(usr, "Could not find [name]. Skipping.")
+ to_chat(user, "Could not find [name]. Skipping.")
continue
//Get reaction
var/list/reactions = GLOB.chemical_reactions_list_product_index[reagent.type]
if(!length(reactions))
- to_chat(usr, "Could not find [name] reaction! Continuing anyways.")
+ to_chat(user, "Could not find [name] reaction! Continuing anyways.")
var/single_parse = generate_chemwiki_line(reagent, null)
text2file(single_parse, "[GLOB.log_directory]/chem_parse.txt")
continue
@@ -38,8 +34,7 @@
var/single_parse = generate_chemwiki_line(reagent, reaction)
text2file(single_parse, "[GLOB.log_directory]/chem_parse.txt")
text2file("|}", "[GLOB.log_directory]/chem_parse.txt") //Cap off the table
- to_chat(usr, "Done! Saved file to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.txt OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .txt default program! Try downloading it instead, and use that file to set a default program! Have a nice day!")
-
+ to_chat(user, "Done! Saved file to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.txt OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .txt default program! Try downloading it instead, and use that file to set a default program! Have a nice day!")
/// Generate the big list of reagent based reactions.
/proc/generate_chemwiki_line(datum/reagent/reagent, datum/chemical_reaction/reaction)
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 80afcc534b0..6984c042f55 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -458,7 +458,7 @@
return ITEM_INTERACT_SUCCESS
return ITEM_INTERACT_BLOCKING
-/obj/machinery/chem_dispenser/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/chem_dispenser/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(is_reagent_container(tool) && !(tool.item_flags & ABSTRACT) && tool.is_open_container())
//SKYRAT EDIT ADDITION START - CHEMISTRY QOL
var/obj/item/reagent_containers/container = tool
@@ -467,12 +467,12 @@
transferAmounts = container.possible_transfer_amounts
//SKYRAT EDIT ADDITION END
if(!user.transferItemToLoc(tool, src))
- return ..()
+ return ITEM_INTERACT_BLOCKING
replace_beaker(user, tool)
ui_interact(user)
return ITEM_INTERACT_SUCCESS
- return ..()
+ return NONE
/obj/machinery/chem_dispenser/get_cell()
return cell
@@ -569,8 +569,6 @@
/obj/machinery/chem_dispenser/attack_ai_secondary(mob/user, list/modifiers)
return attack_hand_secondary(user, modifiers)
-/obj/machinery/chem_dispenser/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/machinery/chem_dispenser/drinks
name = "soda dispenser"
diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm
index 857cd5bd221..76b2dbf7f96 100644
--- a/code/modules/reagents/chemistry/machinery/chem_heater.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm
@@ -94,9 +94,9 @@
heater_coefficient *= micro_laser.tier
-/obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers, is_right_clicking)
+/obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers)
if((held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1))
- return ..()
+ return NONE
if(QDELETED(beaker))
if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe))
@@ -110,7 +110,7 @@
balloon_alert(user, "beaker added")
return ITEM_INTERACT_SUCCESS
- return ..()
+ return NONE
/obj/machinery/chem_heater/wrench_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
diff --git a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm
index 298fe259814..ca75736db03 100644
--- a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm
@@ -147,9 +147,9 @@
for(var/datum/stock_part/micro_laser/laser in component_parts)
cms_coefficient /= laser.tier
-/obj/machinery/chem_mass_spec/item_interaction(mob/living/user, obj/item/item, list/modifiers, is_right_clicking)
+/obj/machinery/chem_mass_spec/item_interaction(mob/living/user, obj/item/item, list/modifiers)
if((item.item_flags & ABSTRACT) || (item.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return ..()
+ return NONE
if(is_reagent_container(item) && item.is_open_container())
if(processing_reagents)
@@ -160,13 +160,14 @@
if(!user.transferItemToLoc(beaker, src))
return ITEM_INTERACT_BLOCKING
+ var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK)
replace_beaker(user, !is_right_clicking, beaker)
to_chat(user, span_notice("You add [beaker] to [is_right_clicking ? "output" : "input"] slot."))
update_appearance()
ui_interact(user)
return ITEM_INTERACT_SUCCESS
- return ..()
+ return NONE
/obj/machinery/chem_mass_spec/wrench_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
@@ -433,14 +434,12 @@
replace_beaker(ui.user, FALSE)
return TRUE
-/obj/machinery/chem_mass_spec/AltClick(mob/living/user)
- . = ..()
- if(!can_interact(user))
- return
+/obj/machinery/chem_mass_spec/click_alt(mob/living/user)
if(processing_reagents)
balloon_alert(user, "still processing!")
- return ..()
+ return CLICK_ACTION_BLOCKING
replace_beaker(user, TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/chem_mass_spec/alt_click_secondary(mob/living/user)
. = ..()
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 092443db8d0..9f210e12ee4 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -1,84 +1,94 @@
-#define TRANSFER_MODE_DESTROY 0
-#define TRANSFER_MODE_MOVE 1
-#define TARGET_BEAKER "beaker"
-#define TARGET_BUFFER "buffer"
-
/obj/machinery/chem_master
name = "ChemMaster 3000"
desc = "Used to separate chemicals and distribute them in a variety of forms."
- density = TRUE
- layer = BELOW_OBJ_LAYER
icon = 'icons/obj/medical/chemical.dmi'
icon_state = "chemmaster"
base_icon_state = "chemmaster"
+ density = TRUE
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.2
+ active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.2
resistance_flags = FIRE_PROOF | ACID_PROOF
circuit = /obj/item/circuitboard/machine/chem_master
- /// Icons for different percentages of buffer reagents
- var/fill_icon = 'icons/obj/medical/reagent_fillings.dmi'
- var/fill_icon_state = "chemmaster"
- var/static/list/fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
+
/// Inserted reagent container
var/obj/item/reagent_containers/beaker
/// Whether separated reagents should be moved back to container or destroyed.
- var/transfer_mode = TRANSFER_MODE_MOVE
- /// Whether reagent analysis screen is active
- var/reagent_analysis_mode = FALSE
- /// Reagent being analyzed
- var/datum/reagent/analyzed_reagent
+ var/is_transfering = TRUE
/// List of printable container types
- var/list/printable_containers = list()
- /// Container used by default to reset to (REF)
- var/default_container
- /// Selected printable container type (REF)
- var/selected_container
- /// Whether the machine has an option to suggest container
- var/has_container_suggestion = FALSE
- /// Whether to suggest container or not
- var/do_suggest_container = FALSE
- /// The container suggested by main reagent in the buffer
- var/suggested_container
+ var/list/printable_containers
+ /// Container used by default to reset to
+ var/obj/item/reagent_containers/default_container
+ /// Selected printable container type
+ var/obj/item/reagent_containers/selected_container
/// Whether the machine is busy with printing containers
var/is_printing = FALSE
- /// Number of printed containers in the current printing cycle for UI progress bar
+ /// Number of containers printed so far
var/printing_progress
+ /// Number of containers to be printed
var/printing_total
- /// Default duration of printing cycle
- var/printing_speed = 0.75 SECONDS // Duration of animation
- /// The amount of containers printed in one cycle
+ /// The amount of containers that can be printed in 1 cycle
var/printing_amount = 1
/obj/machinery/chem_master/Initialize(mapload)
create_reagents(100)
- load_printable_containers()
- default_container = REF(printable_containers[printable_containers[1]][1])
+
+ printable_containers = load_printable_containers()
+ default_container = printable_containers[printable_containers[1]][1]
selected_container = default_container
- return ..()
+
+ register_context()
+
+ . = ..()
+
+ var/obj/item/circuitboard/machine/chem_master/board = circuit
+ board.build_path = type
+ board.name = name
/obj/machinery/chem_master/Destroy()
QDEL_NULL(beaker)
return ..()
-/obj/machinery/chem_master/on_deconstruction(disassembled)
- replace_beaker()
- return ..()
+/obj/machinery/chem_master/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = NONE
+ if(isnull(held_item) || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1))
+ if(isnull(held_item))
+ context[SCREENTIP_CONTEXT_RMB] = "Remove beaker"
+ . = CONTEXTUAL_SCREENTIP_SET
+ return .
-/obj/machinery/chem_master/Exited(atom/movable/gone, direction)
+ if(is_reagent_container(held_item) && held_item.is_open_container())
+ if(!QDELETED(beaker))
+ context[SCREENTIP_CONTEXT_LMB] = "Replace beaker"
+ else
+ context[SCREENTIP_CONTEXT_LMB] = "Insert beaker"
+ return CONTEXTUAL_SCREENTIP_SET
+
+ if(held_item.tool_behaviour == TOOL_SCREWDRIVER)
+ context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel"
+ return CONTEXTUAL_SCREENTIP_SET
+ else if(held_item.tool_behaviour == TOOL_WRENCH)
+ context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""] anchor"
+ return CONTEXTUAL_SCREENTIP_SET
+ else if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR)
+ context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/machinery/chem_master/examine(mob/user)
. = ..()
- if(gone == beaker)
- beaker = null
- update_appearance(UPDATE_ICON)
+ if(in_range(user, src) || isobserver(user))
+ . += span_notice("The status display reads: Reagent buffer capacity: [reagents.maximum_volume] units. Number of containers printed per cycle [printing_amount].")
+ if(!QDELETED(beaker))
+ . += span_notice("[beaker] of [beaker.reagents.maximum_volume]u capacity inserted")
+ . += span_notice("Right click with empty hand to remove beaker")
+ else
+ . += span_warning("Missing input beaker")
-/obj/machinery/chem_master/RefreshParts()
- . = ..()
- reagents.maximum_volume = 0
- for(var/obj/item/reagent_containers/cup/beaker/beaker in component_parts)
- reagents.maximum_volume += beaker.reagents.maximum_volume
- printing_amount = 0
- for(var/datum/stock_part/servo/servo in component_parts)
- printing_amount += servo.tier
+ . += span_notice("It can be [EXAMINE_HINT("wrenched")] [anchored ? "loose" : "in place"]")
+ . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "close" : "open"]")
+ if(panel_open)
+ . += span_notice("The machine can be [EXAMINE_HINT("pried")] apart.")
-/obj/machinery/chem_master/update_appearance(updates=ALL)
+/obj/machinery/chem_master/update_appearance(updates)
. = ..()
if(panel_open || (machine_stat & (NOPOWER|BROKEN)))
set_light(0)
@@ -102,9 +112,7 @@
// Screen overlay
if(!panel_open && !(machine_stat & (NOPOWER | BROKEN)))
var/screen_overlay = base_icon_state + "_overlay_screen"
- if(reagent_analysis_mode)
- screen_overlay += "_analysis"
- else if(is_printing)
+ if(is_printing)
screen_overlay += "_active"
else if(reagents.total_volume > 0)
screen_overlay += "_main"
@@ -114,46 +122,130 @@
// Buffer reagents overlay
if(reagents.total_volume)
var/threshold = null
+ var/static/list/fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for(var/i in 1 to fill_icon_thresholds.len)
- if(ROUND_UP(100 * reagents.total_volume / reagents.maximum_volume) >= fill_icon_thresholds[i])
+ if(ROUND_UP(100 * (reagents.total_volume / reagents.maximum_volume)) >= fill_icon_thresholds[i])
threshold = i
if(threshold)
- var/fill_name = "[fill_icon_state][fill_icon_thresholds[threshold]]"
- var/mutable_appearance/filling = mutable_appearance(fill_icon, fill_name)
+ var/fill_name = "chemmaster[fill_icon_thresholds[threshold]]"
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/medical/reagent_fillings.dmi', fill_name)
filling.color = mix_color_from_reagents(reagents.reagent_list)
. += filling
-/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool)
+/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool) //SKYRAT ADDITION START
if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN)
return ITEM_INTERACT_SUCCESS
- return ITEM_INTERACT_BLOCKING
+ return ITEM_INTERACT_BLOCKING //SKYRAT ADDITION END
-/obj/machinery/chem_master/screwdriver_act(mob/living/user, obj/item/tool)
- if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
- update_appearance(UPDATE_ICON)
- return ITEM_INTERACT_SUCCESS
- return ITEM_INTERACT_BLOCKING
+/obj/machinery/chem_master/Exited(atom/movable/gone, direction)
+ . = ..()
+ if(gone == beaker)
+ beaker = null
+ update_appearance(UPDATE_OVERLAYS)
-/obj/machinery/chem_master/crowbar_act(mob/living/user, obj/item/tool)
- if(default_deconstruction_crowbar(tool))
- return ITEM_INTERACT_SUCCESS
- return ITEM_INTERACT_BLOCKING
+/obj/machinery/chem_master/on_set_is_operational(old_value)
+ if(!is_operational)
+ is_printing = FALSE
+ update_appearance(UPDATE_OVERLAYS)
-/obj/machinery/chem_master/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- if(is_reagent_container(tool) && !(tool.item_flags & ABSTRACT) && tool.is_open_container())
+/obj/machinery/chem_master/RefreshParts()
+ . = ..()
+ reagents.maximum_volume = 0
+ for(var/obj/item/reagent_containers/cup/beaker/beaker in component_parts)
+ reagents.maximum_volume += beaker.reagents.maximum_volume
+
+ printing_amount = 0
+ for(var/datum/stock_part/servo/servo in component_parts)
+ printing_amount += servo.tier * 12.5
+ printing_amount = min(50, ROUND_UP(printing_amount))
+
+///Return a map of category->list of containers this machine can print
+/obj/machinery/chem_master/proc/load_printable_containers()
+ PROTECTED_PROC(TRUE)
+ SHOULD_BE_PURE(TRUE)
+
+ var/static/list/containers
+ if(!length(containers))
+ containers = list(
+ CAT_TUBES = GLOB.reagent_containers[CAT_TUBES],
+ CAT_PILLS = GLOB.reagent_containers[CAT_PILLS],
+ CAT_PATCHES = GLOB.reagent_containers[CAT_PATCHES],
+ )
+ return containers
+
+/obj/machinery/chem_master/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(user.combat_mode || (tool.item_flags & ABSTRACT) || (tool.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH))
+ return NONE
+
+ if(is_reagent_container(tool) && tool.is_open_container())
replace_beaker(user, tool)
if(!panel_open)
ui_interact(user)
+ return ITEM_INTERACT_SUCCESS
+ else
+ return ITEM_INTERACT_BLOCKING
+
+ return NONE
+
+/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool)
+ if(user.combat_mode)
+ return NONE
+
+ . = ITEM_INTERACT_BLOCKING
+ if(is_printing)
+ balloon_alert(user, "still printing!")
+ return .
+
+ if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN)
return ITEM_INTERACT_SUCCESS
- return ..()
+/obj/machinery/chem_master/screwdriver_act(mob/living/user, obj/item/tool)
+ if(user.combat_mode)
+ return NONE
+
+ . = ITEM_INTERACT_BLOCKING
+ if(is_printing)
+ balloon_alert(user, "still printing!")
+ return .
+
+ if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
+ update_appearance(UPDATE_OVERLAYS)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/machinery/chem_master/crowbar_act(mob/living/user, obj/item/tool)
+ if(user.combat_mode)
+ return NONE
+
+ . = ITEM_INTERACT_BLOCKING
+ if(is_printing)
+ balloon_alert(user, "still printing!")
+ return .
+
+ if(default_deconstruction_crowbar(tool))
+ return ITEM_INTERACT_SUCCESS
+
+/**
+ * Insert, remove, replace the existig beaker
+ * Arguments
+ *
+ * * mob/living/user - the player trying to replace the beaker
+ * * obj/item/reagent_containers/new_beaker - the beaker we are trying to insert, swap with existing or remove if null
+ */
+/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
+ PRIVATE_PROC(TRUE)
+
+ if(!QDELETED(beaker))
+ try_put_in_hand(beaker, user)
+ if(!QDELETED(new_beaker) && user.transferItemToLoc(new_beaker, src))
+ beaker = new_beaker
+ update_appearance(UPDATE_OVERLAYS)
/obj/machinery/chem_master/attack_hand_secondary(mob/user, list/modifiers)
. = ..()
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return .
- if(!can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH|FORBID_TELEKINESIS_REACH))
+ if(!can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH))
return .
replace_beaker(user)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
@@ -164,27 +256,6 @@
/obj/machinery/chem_master/attack_ai_secondary(mob/user, list/modifiers)
return attack_hand_secondary(user, modifiers)
-/// Insert new beaker and/or eject the inserted one
-/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
- if(new_beaker && user && !user.transferItemToLoc(new_beaker, src))
- return FALSE
- if(beaker)
- try_put_in_hand(beaker, user)
- beaker = null
- if(new_beaker)
- beaker = new_beaker
- update_appearance(UPDATE_ICON)
- return TRUE
-
-/obj/machinery/chem_master/proc/load_printable_containers()
- printable_containers = list(
- CAT_TUBES = GLOB.reagent_containers[CAT_TUBES],
- CAT_PILLS = GLOB.reagent_containers[CAT_PILLS],
- CAT_PATCHES = GLOB.reagent_containers[CAT_PATCHES],
- CAT_HYPOS = GLOB.reagent_containers[CAT_HYPOS], // SKYRAT EDIT ADDITION
- CAT_DARTS = GLOB.reagent_containers[CAT_DARTS], // SKYRAT EDIT ADDITION
- )
-
/obj/machinery/chem_master/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/chemmaster)
@@ -198,269 +269,284 @@
/obj/machinery/chem_master/ui_static_data(mob/user)
var/list/data = list()
+
data["categories"] = list()
for(var/category in printable_containers)
- var/container_data = list()
+ //make the category
+ var/list/category_list = list(
+ "name" = category,
+ "containers" = list(),
+ )
+
+ //add containers to this category
for(var/obj/item/reagent_containers/container as anything in printable_containers[category])
- container_data += list(list(
+ category_list["containers"] += list(list(
"icon" = sanitize_css_class_name("[container]"),
"ref" = REF(container),
"name" = initial(container.name),
"volume" = initial(container.volume),
))
- data["categories"]+= list(list(
- "name" = category,
- "containers" = container_data,
- ))
+
+ //add the category
+ data["categories"] += list(category_list)
return data
/obj/machinery/chem_master/ui_data(mob/user)
- var/list/data = list()
+ . = list()
- data["reagentAnalysisMode"] = reagent_analysis_mode
- if(reagent_analysis_mode && analyzed_reagent)
- var/state
- switch(analyzed_reagent.reagent_state)
- if(SOLID)
- state = "Solid"
- if(LIQUID)
- state = "Liquid"
- if(GAS)
- state = "Gas"
- else
- state = "Unknown"
- data["analysisData"] = list(
- "name" = analyzed_reagent.name,
- "state" = state,
- "pH" = analyzed_reagent.ph,
- "color" = analyzed_reagent.color,
- "description" = analyzed_reagent.description,
- "purity" = analyzed_reagent.purity,
- "metaRate" = analyzed_reagent.metabolization_rate,
- "overdose" = analyzed_reagent.overdose_threshold,
- "addictionTypes" = reagents.parse_addictions(analyzed_reagent),
- )
- else
- data["isPrinting"] = is_printing
- data["printingProgress"] = printing_progress
- data["printingTotal"] = printing_total
- data["hasBeaker"] = beaker ? TRUE : FALSE
- data["beakerCurrentVolume"] = beaker ? round(beaker.reagents.total_volume, 0.01) : null
- data["beakerMaxVolume"] = beaker ? beaker.volume : null
- var/list/beaker_contents = list()
- if(beaker)
- for(var/datum/reagent/reagent in beaker.reagents.reagent_list)
- beaker_contents.Add(list(list("name" = reagent.name, "ref" = REF(reagent), "volume" = round(reagent.volume, 0.01))))
- data["beakerContents"] = beaker_contents
+ //printing statictics
+ .["isPrinting"] = is_printing
+ .["printingProgress"] = printing_progress
+ .["printingTotal"] = printing_total
+ .["maxPrintable"] = printing_amount
- var/list/buffer_contents = list()
- if(reagents.total_volume)
- for(var/datum/reagent/reagent in reagents.reagent_list)
- buffer_contents.Add(list(list("name" = reagent.name, "ref" = REF(reagent), "volume" = round(reagent.volume, 0.01))))
- data["bufferContents"] = buffer_contents
- data["bufferCurrentVolume"] = round(reagents.total_volume, 0.01)
- data["bufferMaxVolume"] = reagents.maximum_volume
+ //contents of source beaker
+ var/list/beaker_data = null
+ if(!QDELETED(beaker))
+ beaker_data = list()
+ beaker_data["maxVolume"] = beaker.volume
+ beaker_data["currentVolume"] = round(beaker.reagents.total_volume, CHEMICAL_VOLUME_ROUNDING)
+ var/list/beakerContents = list()
+ if(length(beaker.reagents.reagent_list))
+ for(var/datum/reagent/reagent as anything in beaker.reagents.reagent_list)
+ beakerContents += list(list(
+ "ref" = "[reagent.type]",
+ "name" = reagent.name,
+ "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING),
+ "pH" = reagent.ph,
+ "color" = reagent.color,
+ "description" = reagent.description,
+ "purity" = reagent.purity,
+ "metaRate" = reagent.metabolization_rate,
+ "overdose" = reagent.overdose_threshold,
+ "addictionTypes" = reagents.parse_addictions(reagent),
+ ))
+ beaker_data["contents"] = beakerContents
+ .["beaker"] = beaker_data
- data["transferMode"] = transfer_mode
+ //contents of buffer
+ beaker_data = list()
+ beaker_data["maxVolume"] = reagents.maximum_volume
+ beaker_data["currentVolume"] = round(reagents.total_volume, CHEMICAL_VOLUME_ROUNDING)
+ var/list/beakerContents = list()
+ if(length(reagents.reagent_list))
+ for(var/datum/reagent/reagent as anything in reagents.reagent_list)
+ beakerContents += list(list(
+ "ref" = "[reagent.type]",
+ "name" = reagent.name,
+ "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING),
+ "pH" = reagent.ph,
+ "color" = reagent.color,
+ "description" = reagent.description,
+ "purity" = reagent.purity,
+ "metaRate" = reagent.metabolization_rate,
+ "overdose" = reagent.overdose_threshold,
+ "addictionTypes" = reagents.parse_addictions(reagent),
+ ))
+ beaker_data["contents"] = beakerContents
+ .["buffer"] = beaker_data
- data["hasContainerSuggestion"] = !!has_container_suggestion
- if(has_container_suggestion)
- data["doSuggestContainer"] = !!do_suggest_container
- if(do_suggest_container)
- if(reagents.total_volume > 0)
- var/master_reagent = reagents.get_master_reagent()
- suggested_container = get_suggested_container(master_reagent)
- else
- suggested_container = default_container
- data["suggestedContainer"] = suggested_container
- selected_container = suggested_container
- else if (isnull(selected_container))
- selected_container = default_container
+ //is transfering or destroying reagents. applied only for buffer
+ .["isTransfering"] = is_transfering
- data["selectedContainerRef"] = selected_container
- var/obj/item/reagent_containers/container = locate(selected_container)
- data["selectedContainerVolume"] = initial(container.volume)
+ //container along with the suggested type
+ var/obj/item/reagent_containers/suggested_container = default_container
+ if(reagents.total_volume > 0)
+ var/datum/reagent/master_reagent = reagents.get_master_reagent()
+ var/container_found = FALSE
+ suggested_container = master_reagent.default_container
+ for(var/category in printable_containers)
+ for(var/obj/item/reagent_containers/container as anything in printable_containers[category])
+ if(container == suggested_container)
+ suggested_container = REF(container)
+ container_found = TRUE
+ break
+ if(!container_found)
+ suggested_container = REF(default_container)
+ .["suggestedContainerRef"] = suggested_container
- return data
+ //selected container
+ .["selectedContainerRef"] = REF(selected_container)
+ .["selectedContainerVolume"] = initial(selected_container.volume)
-/obj/machinery/chem_master/ui_act(action, params)
+/**
+ * Transfers a single reagent between buffer & beaker
+ * Arguments
+ *
+ * * mob/user - the player who is attempting the transfer
+ * * datum/reagents/source - the holder we are transferring from
+ * * datum/reagents/target - the holder we are transferring to
+ * * datum/reagent/path - the reagent typepath we are transfering
+ * * amount - volume to transfer -1 means custom amount
+ * * do_transfer - transfer the reagents else destroy them
+ */
+/obj/machinery/chem_master/proc/transfer_reagent(mob/user, datum/reagents/source, datum/reagents/target, datum/reagent/path, amount, do_transfer)
+ PRIVATE_PROC(TRUE)
+
+ //sanity checks for transfer amount
+ if(isnull(amount))
+ return FALSE
+ amount = text2num(amount)
+ if(isnull(amount))
+ return FALSE
+ if(amount == -1)
+ var/target_amount = tgui_input_number(user, "Enter amount to transfer", "Transfer amount")
+ if(!target_amount)
+ return FALSE
+ amount = text2num(target_amount)
+ if(isnull(amount))
+ return FALSE
+ if(amount <= 0)
+ return FALSE
+
+ //sanity checks for reagent path
+ var/datum/reagent/reagent = text2path(path)
+ if (!reagent)
+ return FALSE
+
+ //use energy
+ if(!use_energy(active_power_usage, force = FALSE))
+ return FALSE
+
+ //do the operation
+ . = FALSE
+ if(do_transfer)
+ if(target.is_reacting)
+ return FALSE
+ if(source.trans_to(target, amount, target_id = reagent))
+ . = TRUE
+ else if(source.remove_reagent(reagent, amount))
+ . = TRUE
+ if(. && !QDELETED(src)) //transferring volatile reagents can cause a explosion & destory us
+ update_appearance(UPDATE_OVERLAYS)
+ return .
+
+/obj/machinery/chem_master/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
- if(action == "eject")
- replace_beaker(usr)
- return TRUE
-
- if(action == "transfer")
- var/reagent_ref = params["reagentRef"]
- var/amount = text2num(params["amount"])
- var/target = params["target"]
- return transfer_reagent(reagent_ref, amount, target)
-
- if(action == "toggleTransferMode")
- transfer_mode = !transfer_mode
- return TRUE
-
- if(action == "analyze")
- analyzed_reagent = locate(params["reagentRef"])
- if(analyzed_reagent)
- reagent_analysis_mode = TRUE
- update_appearance(UPDATE_ICON)
+ switch(action)
+ if("eject")
+ replace_beaker(ui.user)
return TRUE
- if(action == "stopAnalysis")
- reagent_analysis_mode = FALSE
- analyzed_reagent = null
- update_appearance(UPDATE_ICON)
- return TRUE
+ if("transfer")
+ if(is_printing)
+ say("buffer locked while printing!")
+ return
- if(action == "stopPrinting")
+ var/reagent_ref = params["reagentRef"]
+ var/amount = params["amount"]
+ var/target = params["target"]
+
+ if(target == "buffer")
+ return transfer_reagent(ui.user, beaker.reagents, reagents, reagent_ref, amount, TRUE)
+ else if(target == "beaker")
+ return transfer_reagent(ui.user, reagents, beaker.reagents, reagent_ref, amount, is_transfering)
+ return FALSE
+
+ if("toggleTransferMode")
+ is_transfering = !is_transfering
+ return TRUE
+
+ if("stopPrinting")
+ is_printing = FALSE
+ update_appearance(UPDATE_OVERLAYS)
+ return TRUE
+
+ if("selectContainer")
+ var/obj/item/reagent_containers/target = locate(params["ref"])
+ if(!ispath(target))
+ return FALSE
+
+ selected_container = target
+ return TRUE
+
+ if("create")
+ if(!reagents.total_volume || is_printing)
+ return FALSE
+
+ //validate print count
+ var/item_count = params["itemCount"]
+ if(isnull(item_count))
+ return FALSE
+ item_count = text2num(item_count)
+ if(isnull(item_count) || item_count <= 0)
+ return FALSE
+ item_count = min(item_count, printing_amount)
+ var/volume_in_each = round(reagents.total_volume / item_count, CHEMICAL_VOLUME_ROUNDING)
+
+ // Generate item name
+ var/item_name_default = initial(selected_container.name)
+ var/datum/reagent/master_reagent = reagents.get_master_reagent()
+ if(selected_container == default_container) // Tubes and bottles gain reagent name
+ item_name_default = "[master_reagent.name] [item_name_default]"
+ if(!(initial(selected_container.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name
+ item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)"
+ var/item_name = tgui_input_text(usr,
+ "Container name",
+ "Name",
+ item_name_default,
+ MAX_NAME_LEN)
+ if(!item_name)
+ return FALSE
+
+ //start printing
+ is_printing = TRUE
+ printing_progress = 0
+ printing_total = item_count
+ update_appearance(UPDATE_OVERLAYS)
+ create_containers(ui.user, item_count, item_name, volume_in_each)
+ return TRUE
+
+/**
+ * Create N selected containers with reagents from buffer split between them
+ * Arguments
+ *
+ * * mob/user - the player printing these containers
+ * * item_count - number of containers to print
+ * * item_name - the name for each container printed
+ * * volume_in_each - volume in each container created
+ */
+/obj/machinery/chem_master/proc/create_containers(mob/user, item_count, item_name, volume_in_each)
+ PRIVATE_PROC(TRUE)
+
+ //lost power or manually stopped
+ if(!is_printing)
+ return
+
+ //use power
+ if(!use_energy(active_power_usage, force = FALSE))
is_printing = FALSE
- return TRUE
+ update_appearance(UPDATE_OVERLAYS)
+ return
- if(action == "toggleContainerSuggestion")
- do_suggest_container = !do_suggest_container
- return TRUE
+ //print the stuff
+ var/obj/item/reagent_containers/item = new selected_container(drop_location())
+ adjust_item_drop_location(item)
+ item.name = item_name
+ item.reagents.clear_reagents()
+ reagents.trans_to(item, volume_in_each, transferred_by = user)
+ printing_progress++
+ update_appearance(UPDATE_OVERLAYS)
- if(action == "selectContainer")
- selected_container = params["ref"]
- return TRUE
-
- if(action == "create")
- if(reagents.total_volume == 0)
- return FALSE
- var/item_count = text2num(params["itemCount"])
- if(item_count <= 0)
- return FALSE
- create_containers(item_count)
- return TRUE
-
-/// Create N selected containers with reagents from buffer split between them
-/obj/machinery/chem_master/proc/create_containers(item_count = 1)
- var/obj/item/reagent_containers/container_style = locate(selected_container)
- var/is_pill_subtype = ispath(container_style, /obj/item/reagent_containers/pill)
- var/volume_in_each = reagents.total_volume / item_count
- var/printing_amount_current = is_pill_subtype ? printing_amount * 2 : printing_amount
-
- // Generate item name
- var/item_name_default = initial(container_style.name)
- var/datum/reagent/master_reagent = reagents.get_master_reagent()
- if(selected_container == default_container) // Tubes and bottles gain reagent name
- item_name_default = "[master_reagent.name] [item_name_default]"
- if(!(initial(container_style.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name
- item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)"
- var/item_name = tgui_input_text(usr,
- "Container name",
- "Name",
- item_name_default,
- MAX_NAME_LEN)
-
- if(!item_name || !reagents.total_volume || QDELETED(src) || !usr.can_perform_action(src, ALLOW_SILICON_REACH))
- return FALSE
-
- // Print and fill containers
- is_printing = TRUE
- update_appearance(UPDATE_ICON)
- printing_progress = 0
- printing_total = item_count
- while(item_count > 0)
- if(!is_printing)
- break
- use_energy(active_power_usage)
- stoplag(printing_speed)
- for(var/i in 1 to printing_amount_current)
- if(!item_count)
- continue
- var/obj/item/reagent_containers/item = new container_style(drop_location())
- adjust_item_drop_location(item)
- item.name = item_name
- item.reagents.clear_reagents()
- reagents.trans_to(item, volume_in_each, transferred_by = src)
- printing_progress++
- item_count--
- update_appearance(UPDATE_ICON)
- is_printing = FALSE
- update_appearance(UPDATE_ICON)
- return TRUE
-
-/// Transfer reagents to specified target from the opposite source
-/obj/machinery/chem_master/proc/transfer_reagent(reagent_ref, amount, target)
- if (amount == -1)
- amount = text2num(input("Enter the amount you want to transfer:", name, ""))
- if (amount == null || amount <= 0)
- return FALSE
- if (!beaker && target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_MOVE)
- return FALSE
- var/datum/reagent/reagent = locate(reagent_ref)
- if (!reagent)
- return FALSE
-
- use_energy(active_power_usage)
-
- if (target == TARGET_BUFFER)
- if(!check_reactions(reagent, beaker.reagents))
- return FALSE
- beaker.reagents.trans_to(src, amount, target_id = reagent.type)
- update_appearance(UPDATE_ICON)
- return TRUE
-
- if (target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_DESTROY)
- reagents.remove_reagent(reagent.type, amount)
- update_appearance(UPDATE_ICON)
- return TRUE
- if (target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_MOVE)
- if(!check_reactions(reagent, reagents))
- return FALSE
- reagents.trans_to(beaker, amount, target_id = reagent.type)
- update_appearance(UPDATE_ICON)
- return TRUE
-
- return FALSE
-
-/// Checks to see if the target reagent is being created (reacting) and if so prevents transfer
-/// Only prevents reactant from being moved so that people can still manlipulate input reagents
-/obj/machinery/chem_master/proc/check_reactions(datum/reagent/reagent, datum/reagents/holder)
- if(!reagent)
- return FALSE
- var/canMove = TRUE
- for(var/datum/equilibrium/equilibrium as anything in holder.reaction_list)
- if(equilibrium.reaction.reaction_flags & REACTION_COMPETITIVE)
- continue
- for(var/datum/reagent/result as anything in equilibrium.reaction.required_reagents)
- if(result == reagent.type)
- canMove = FALSE
- if(!canMove)
- say("Cannot move reagent during reaction!")
- return canMove
-
-/// Retrieve REF to the best container for provided reagent
-/obj/machinery/chem_master/proc/get_suggested_container(datum/reagent/reagent)
- var/preferred_container = reagent.default_container
- for(var/category in printable_containers)
- for(var/container in printable_containers[category])
- if(container == preferred_container)
- return REF(container)
- return default_container
-
-/obj/machinery/chem_master/examine(mob/user)
- . = ..()
- if(in_range(user, src) || isobserver(user))
- . += span_notice("The status display reads: Reagent buffer capacity: [reagents.maximum_volume] units. Number of containers printed at once increased by [100 * (printing_amount / initial(printing_amount)) - 100]%.")
+ //print more items
+ item_count --
+ if(item_count > 0)
+ addtimer(CALLBACK(src, PROC_REF(create_containers), user, item_count, item_name, volume_in_each), 0.75 SECONDS)
+ else
+ is_printing = FALSE
+ update_appearance(UPDATE_OVERLAYS)
/obj/machinery/chem_master/condimaster
name = "CondiMaster 3000"
desc = "Used to create condiments and other cooking supplies."
icon_state = "condimaster"
- has_container_suggestion = TRUE
/obj/machinery/chem_master/condimaster/load_printable_containers()
- printable_containers = list(
- CAT_CONDIMENTS = GLOB.reagent_containers[CAT_CONDIMENTS],
- )
-
-#undef TRANSFER_MODE_DESTROY
-#undef TRANSFER_MODE_MOVE
-#undef TARGET_BEAKER
-#undef TARGET_BUFFER
+ var/static/list/containers
+ if(!length(containers))
+ containers = list(CAT_CONDIMENTS = GLOB.reagent_containers[CAT_CONDIMENTS])
+ return containers
diff --git a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm
index c0cb45dda2a..552bfe48650 100644
--- a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm
@@ -6,14 +6,16 @@
base_icon_state = "dispenser"
amount = 10
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
use_power = NO_POWER_USE
- var/static/list/shortcuts = list(
- "meth" = /datum/reagent/drug/methamphetamine
- )
///The purity of the created reagent in % (purity uses 0-1 values)
var/purity = 100
+/obj/machinery/chem_dispenser/chem_synthesizer/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/machinery/chem_dispenser/chem_synthesizer/crowbar_act(mob/living/user, obj/item/tool)
+ return NONE
+
/obj/machinery/chem_dispenser/chem_synthesizer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
diff --git a/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm
index a6113d2f0c6..25a7eecbd37 100644
--- a/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm
+++ b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm
@@ -9,6 +9,7 @@
slot_flags = ITEM_SLOT_BELT
custom_price = PAYCHECK_CREW * 10
custom_premium_price = PAYCHECK_CREW * 14
+ interaction_flags_click = FORBID_TELEKINESIS_REACH
///Creating an empty slot for a beaker that can be added to dispense into
var/obj/item/reagent_containers/beaker
@@ -105,14 +106,14 @@
/obj/item/storage/portable_chem_mixer/ex_act(severity, target)
return severity > EXPLODE_LIGHT ? ..() : FALSE
-/obj/item/storage/portable_chem_mixer/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking)
+/obj/item/storage/portable_chem_mixer/item_interaction(mob/living/user, obj/item/weapon, list/modifiers)
if (!atom_storage.locked || \
(weapon.item_flags & ABSTRACT) || \
(weapon.flags_1 & HOLOGRAM_1) || \
!is_reagent_container(weapon) || \
!weapon.is_open_container() \
)
- return ..()
+ return NONE
replace_beaker(user, weapon)
update_appearance()
@@ -250,15 +251,14 @@
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
-/obj/item/storage/portable_chem_mixer/AltClick(mob/living/user)
+/obj/item/storage/portable_chem_mixer/click_alt(mob/living/user)
if(!atom_storage.locked)
balloon_alert(user, "lock first to use alt eject!")
- return ..()
- if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return
+ return CLICK_ACTION_BLOCKING
replace_beaker(user)
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/storage/portable_chem_mixer/CtrlClick(mob/living/user)
if(atom_storage.locked == STORAGE_FULLY_LOCKED)
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index bdd4f125075..e206ffebbc9 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -99,7 +99,12 @@
. += span_notice("Filled to [round((total_weight / maximum_weight) * 100)]% capacity.")
if(!QDELETED(beaker))
- . += span_notice("A beaker of [beaker.reagents.maximum_volume]u capacity is present.")
+ . += span_notice("A beaker of [beaker.reagents.maximum_volume]u capacity is present. Contains:")
+ if(beaker.reagents.total_volume)
+ for(var/datum/reagent/reg as anything in beaker.reagents.reagent_list)
+ . += span_notice("[round(reg.volume, CHEMICAL_VOLUME_ROUNDING)]u of [reg.name]")
+ else
+ . += span_notice("Nothing.")
. += span_notice("[EXAMINE_HINT("Right click")] with empty hand to remove beaker.")
else
. += span_warning("It's missing a beaker.")
@@ -206,9 +211,9 @@
return items_transfered
-/obj/machinery/reagentgrinder/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/reagentgrinder/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(user.combat_mode || (tool.item_flags & ABSTRACT) || (tool.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH))
- return ..()
+ return NONE
//add the beaker
if (is_reagent_container(tool) && tool.is_open_container())
@@ -257,7 +262,7 @@
to_chat(user, span_warning("You must drag & dump contents of [tool] into [src]."))
return ITEM_INTERACT_BLOCKING
- return ..()
+ return NONE
/obj/machinery/reagentgrinder/wrench_act(mob/living/user, obj/item/tool)
if(user.combat_mode)
diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
index 17b3f236e95..f6e5f74c9bc 100644
--- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
@@ -1658,7 +1658,7 @@
need_mob_update += drinker.adjustStaminaLoss(-heal_amt, updating_stamina = FALSE, required_biotype = affected_biotype)
if(need_mob_update)
drinker.updatehealth()
- drinker.visible_message(span_warning("[drinker] shivers with renewed vigor!"), span_notice("One taste of [lowertext(name)] fills you with energy!"))
+ drinker.visible_message(span_warning("[drinker] shivers with renewed vigor!"), span_notice("One taste of [LOWER_TEXT(name)] fills you with energy!"))
if(!drinker.stat && heal_points == 20) //brought us out of softcrit
drinker.visible_message(span_danger("[drinker] lurches to [drinker.p_their()] feet!"), span_boldnotice("Up and at 'em, kid."))
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 90bd7e14a86..a072166ab86 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -488,13 +488,13 @@
adjust_blood_flow(-0.06 * reac_volume, initial_flow * 0.6) // 20u of a salt shacker * 0.1 = -1.6~ blood flow, but is always clamped to, at best, third blood loss from that wound.
// Crystal irritation worsening recovery.
gauzed_clot_rate *= 0.65
- to_chat(carbies, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin but soaking up most of the blood."))
+ to_chat(carbies, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin but soaking up most of the blood."))
/datum/wound/slash/flesh/on_salt(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.1 * reac_volume, initial_flow * 0.5) // 20u of a salt shacker * 0.1 = -2~ blood flow, but is always clamped to, at best, halve blood loss from that wound.
// Crystal irritation worsening recovery.
clot_rate *= 0.75
- to_chat(carbies, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin but soaking up most of the blood."))
+ to_chat(carbies, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin but soaking up most of the blood."))
/datum/wound/burn/flesh/on_salt(reac_volume)
// Slightly sanitizes and disinfects, but also increases infestation rate (some bacteria are aided by salt), and decreases flesh healing (can damage the skin from moisture absorption)
@@ -502,7 +502,7 @@
infestation -= max(VALUE_PER(0.3, 30) * reac_volume, 0)
infestation_rate += VALUE_PER(0.12, 30) * reac_volume
flesh_healing -= max(VALUE_PER(5, 30) * reac_volume, 0)
- to_chat(victim, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin! After a few moments, it feels marginally better."))
+ to_chat(victim, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin! After a few moments, it feels marginally better."))
/datum/reagent/consumable/blackpepper
name = "Black Pepper"
@@ -535,7 +535,10 @@
. = ..()
if(isvampire(affected_mob)) //incapacitating but not lethal. Unfortunately, vampires cannot vomit.
if(SPT_PROB(min((current_cycle-1)/2, 12.5), seconds_per_tick))
- to_chat(affected_mob, span_danger("You can't get the scent of garlic out of your nose! You can barely think..."))
+ if(HAS_TRAIT(affected_mob, TRAIT_ANOSMIA))
+ to_chat(affected_mob, span_danger("You feel that something is wrong, your strength is leaving you! You can barely think..."))
+ else
+ to_chat(affected_mob, span_danger("You can't get the scent of garlic out of your nose! You can barely think..."))
affected_mob.Paralyze(10)
affected_mob.set_jitter_if_lower(20 SECONDS)
else
@@ -653,18 +656,18 @@
/datum/wound/pierce/bleed/on_flour(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.015 * reac_volume) // 30u of a flour sack * 0.015 = -0.45~ blood flow, prettay good
- to_chat(carbies, span_notice("The flour seeps into [lowertext(src)], painfully drying it up and absorbing some of the blood."))
+ to_chat(carbies, span_notice("The flour seeps into [LOWER_TEXT(src)], painfully drying it up and absorbing some of the blood."))
// When some nerd adds infection for wounds, make this increase the infection
/datum/wound/slash/flesh/on_flour(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.04 * reac_volume) // 30u of a flour sack * 0.04 = -1.25~ blood flow, pretty good!
- to_chat(carbies, span_notice("The flour seeps into [lowertext(src)], painfully drying some of it up and absorbing a little blood."))
+ to_chat(carbies, span_notice("The flour seeps into [LOWER_TEXT(src)], painfully drying some of it up and absorbing a little blood."))
// When some nerd adds infection for wounds, make this increase the infection
// Don't pour flour onto burn wounds, it increases infection risk! Very unwise. Backed up by REAL info from REAL professionals.
// https://www.reuters.com/article/uk-factcheck-flour-burn-idUSKCN26F2N3
/datum/wound/burn/flesh/on_flour(reac_volume)
- to_chat(victim, span_notice("The flour seeps into [lowertext(src)], spiking you with intense pain! That probably wasn't a good idea..."))
+ to_chat(victim, span_notice("The flour seeps into [LOWER_TEXT(src)], spiking you with intense pain! That probably wasn't a good idea..."))
sanitization -= min(0, 1)
infestation += 0.2
return
@@ -759,18 +762,18 @@
/datum/wound/pierce/bleed/on_starch(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.03 * reac_volume)
- to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], painfully drying some of it up and absorbing a little blood."))
+ to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], painfully drying some of it up and absorbing a little blood."))
// When some nerd adds infection for wounds, make this increase the infection
return
/datum/wound/slash/flesh/on_starch(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.06 * reac_volume)
- to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], painfully drying it up and absorbing some of the blood."))
+ to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], painfully drying it up and absorbing some of the blood."))
// When some nerd adds infection for wounds, make this increase the infection
return
/datum/wound/burn/flesh/on_starch(reac_volume, mob/living/carbon/carbies)
- to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], spiking you with intense pain! That probably wasn't a good idea..."))
+ to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], spiking you with intense pain! That probably wasn't a good idea..."))
sanitization -= min(0, 0.5)
infestation += 0.1
return
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 6b6af30612c..8c5a513f69e 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -350,18 +350,18 @@
/datum/wound/pierce/bleed/on_saltwater(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.06 * reac_volume, initial_flow * 0.6)
- to_chat(carbies, span_notice("The salt water splashes over [lowertext(src)], soaking up the blood."))
+ to_chat(carbies, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the blood."))
/datum/wound/slash/flesh/on_saltwater(reac_volume, mob/living/carbon/carbies)
adjust_blood_flow(-0.1 * reac_volume, initial_flow * 0.5)
- to_chat(carbies, span_notice("The salt water splashes over [lowertext(src)], soaking up the blood."))
+ to_chat(carbies, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the blood."))
/datum/wound/burn/flesh/on_saltwater(reac_volume)
// Similar but better stats from normal salt.
sanitization += VALUE_PER(0.6, 30) * reac_volume
infestation -= max(VALUE_PER(0.5, 30) * reac_volume, 0)
infestation_rate += VALUE_PER(0.07, 30) * reac_volume
- to_chat(victim, span_notice("The salt water splashes over [lowertext(src)], soaking up the... miscellaneous fluids. It feels somewhat better afterwards."))
+ to_chat(victim, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the... miscellaneous fluids. It feels somewhat better afterwards."))
return
/datum/reagent/water/holywater
@@ -737,7 +737,7 @@
//affected_mob.set_species(species_type) //ORIGINAL
affected_mob.set_species(species_type, TRUE, FALSE, null, null, null, null, TRUE) //SKYRAT EDIT CHANGE - CUSTOMIZATION
holder.del_reagent(type)
- to_chat(affected_mob, span_warning("You've become \a [lowertext(initial(species_type.name))]!"))
+ to_chat(affected_mob, span_warning("You've become \a [LOWER_TEXT(initial(species_type.name))]!"))
return
/datum/reagent/mutationtoxin/classic //The one from plasma on green slimes
diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
index ce13c9c70de..6407ff0fb8b 100644
--- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm
+++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
@@ -456,7 +456,7 @@
required_container = /obj/item/slime_extract/cerulean
/datum/chemical_reaction/slime/slime_territory/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume)
- new /obj/item/areaeditor/blueprints/slime(get_turf(holder.my_atom))
+ new /obj/item/blueprints/slime(get_turf(holder.my_atom))
..()
//Sepia
diff --git a/code/modules/reagents/reagent_containers/chem_pack.dm b/code/modules/reagents/reagent_containers/chem_pack.dm
index 3345f1e99ef..98ffa2e596e 100644
--- a/code/modules/reagents/reagent_containers/chem_pack.dm
+++ b/code/modules/reagents/reagent_containers/chem_pack.dm
@@ -8,23 +8,29 @@
spillable = TRUE
obj_flags = UNIQUE_RENAME
resistance_flags = ACID_PROOF
- var/sealed = FALSE
fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
has_variable_transfer_amount = FALSE
+ interaction_flags_click = NEED_DEXTERITY
+ /// Whether this has been sealed shut
+ var/sealed = FALSE
-/obj/item/reagent_containers/chem_pack/AltClick(mob/living/user)
- if(user.can_perform_action(src, NEED_DEXTERITY) && !sealed)
- if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)))
- to_chat(user, span_warning("Uh... whoops! You accidentally spill the content of the bag onto yourself."))
- SplashReagents(user)
- return
+/obj/item/reagent_containers/chem_pack/click_alt(mob/living/user)
+ if(sealed)
+ balloon_alert(user, "sealed!")
+ return CLICK_ACTION_BLOCKING
- reagents.flags = NONE
- reagent_flags = DRAWABLE | INJECTABLE //To allow for sabotage or ghetto use.
- reagents.flags = reagent_flags
- spillable = FALSE
- sealed = TRUE
- to_chat(user, span_notice("You seal the bag."))
+ if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)))
+ to_chat(user, span_warning("Uh... whoops! You accidentally spill the content of the bag onto yourself."))
+ SplashReagents(user)
+ return CLICK_ACTION_BLOCKING
+
+ reagents.flags = NONE
+ reagent_flags = DRAWABLE | INJECTABLE //To allow for sabotage or ghetto use.
+ reagents.flags = reagent_flags
+ spillable = FALSE
+ sealed = TRUE
+ balloon_alert(user, "sealed")
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/chem_pack/examine()
. = ..()
diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm
index 31948c5cc1e..ea0eaf989dd 100644
--- a/code/modules/reagents/reagent_containers/cups/_cup.dm
+++ b/code/modules/reagents/reagent_containers/cups/_cup.dm
@@ -23,7 +23,7 @@
. = ..()
if(drink_type)
var/list/types = bitfield_to_list(drink_type, FOOD_FLAGS)
- . += span_notice("It is [lowertext(english_list(types))].")
+ . += span_notice("It is [LOWER_TEXT(english_list(types))].")
/**
* Checks if the mob actually liked drinking this cup.
@@ -481,11 +481,13 @@
spillable = TRUE
var/obj/item/grinded
-/obj/item/reagent_containers/cup/mortar/AltClick(mob/user)
- if(grinded)
- grinded.forceMove(drop_location())
- grinded = null
- to_chat(user, span_notice("You eject the item inside."))
+/obj/item/reagent_containers/cup/mortar/click_alt(mob/user)
+ if(!grinded)
+ return CLICK_ACTION_BLOCKING
+ grinded.forceMove(drop_location())
+ grinded = null
+ balloon_alert(user, "ejected")
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/cup/mortar/attackby(obj/item/I, mob/living/carbon/human/user)
..()
diff --git a/code/modules/reagents/reagent_containers/cups/bottle.dm b/code/modules/reagents/reagent_containers/cups/bottle.dm
index 1e4466da8c3..75bc79c5a6a 100644
--- a/code/modules/reagents/reagent_containers/cups/bottle.dm
+++ b/code/modules/reagents/reagent_containers/cups/bottle.dm
@@ -513,7 +513,7 @@
return TRUE
-/obj/item/reagent_containers/cup/bottle/syrup_bottle/AltClick(mob/user)
+/obj/item/reagent_containers/cup/bottle/syrup_bottle/click_alt(mob/user)
cap_on = !cap_on
if(!cap_on)
icon_state = "syrup_open"
@@ -522,7 +522,7 @@
icon_state = "syrup"
balloon_alert(user, "put pump cap on")
update_icon_state()
- return ..()
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/cup/bottle/syrup_bottle/proc/rename(mob/user, obj/item/writing_instrument)
if(!user.can_write(writing_instrument))
diff --git a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm
index adcd2ff79fa..7441614682c 100644
--- a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm
+++ b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm
@@ -35,7 +35,7 @@
/obj/item/reagent_containers/cup/glass/drinkingglass/on_reagent_change(datum/reagents/holder, ...)
. = ..()
if(!length(reagents.reagent_list))
- REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) //so new drinks can rename the glass
+ REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) //so new drinks can rename the glass
// Having our icon state change removes fill thresholds
/obj/item/reagent_containers/cup/glass/drinkingglass/on_cup_change(datum/glass_style/style)
@@ -58,7 +58,7 @@
return
REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, SHAKER_LABEL_TRAIT)
- REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT)
+ REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT)
name = initial(name)
desc = initial(desc)
update_appearance(UPDATE_NAME | UPDATE_DESC)
diff --git a/code/modules/reagents/reagent_containers/cups/drinks.dm b/code/modules/reagents/reagent_containers/cups/drinks.dm
index cba2f937da4..5a3ed446f60 100644
--- a/code/modules/reagents/reagent_containers/cups/drinks.dm
+++ b/code/modules/reagents/reagent_containers/cups/drinks.dm
@@ -122,10 +122,10 @@
. += span_notice("Alt-click to toggle cup lid.")
return
-/obj/item/reagent_containers/cup/glass/coffee/AltClick(mob/user)
+/obj/item/reagent_containers/cup/glass/coffee/click_alt(mob/user)
lid_open = !lid_open
update_icon_state()
- return ..()
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/cup/glass/coffee/update_icon_state()
if(lid_open)
@@ -248,11 +248,10 @@
else
. += span_notice("The cap has been taken off. Alt-click to put a cap on.")
-/obj/item/reagent_containers/cup/glass/waterbottle/AltClick(mob/user)
- . = ..()
+/obj/item/reagent_containers/cup/glass/waterbottle/click_alt(mob/user)
if(cap_lost)
to_chat(user, span_warning("The cap seems to be missing! Where did it go?"))
- return
+ return CLICK_ACTION_BLOCKING
var/fumbled = HAS_TRAIT(user, TRAIT_CLUMSY) && prob(5)
if(cap_on || fumbled)
@@ -270,6 +269,7 @@
spillable = FALSE
to_chat(user, span_notice("You put the cap on [src]."))
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/cup/glass/waterbottle/is_refillable()
if(cap_on)
@@ -436,6 +436,7 @@
amount_per_transfer_from_this = 10
volume = 100
isGlass = FALSE
+ interaction_flags_click = NEED_HANDS|FORBID_TELEKINESIS_REACH
/// Whether or not poured drinks should use custom names and descriptions
var/using_custom_drinks = FALSE
/// Name custom drinks will have
@@ -463,34 +464,30 @@
. += span_notice("Drinks poured from this shaker will have the following name: [custom_drink_name]")
. += span_notice("Drinks poured from this shaker will have the following description: [custom_drink_desc]")
-/obj/item/reagent_containers/cup/glass/shaker/AltClick(mob/user)
- . = ..()
- if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH))
- return
-
+/obj/item/reagent_containers/cup/glass/shaker/click_alt(mob/user)
if(using_custom_drinks)
using_custom_drinks = FALSE
disable_custom_drinks()
balloon_alert(user, "custom drinks disabled")
- return
+ return CLICK_ACTION_BLOCKING
var/new_name = reject_bad_text(tgui_input_text(user, "Drink name", "Set drink name", custom_drink_name, 45, FALSE), 64)
if(!new_name)
balloon_alert(user, "invalid drink name!")
using_custom_drinks = FALSE
- return
+ return CLICK_ACTION_BLOCKING
if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH))
- return
+ return CLICK_ACTION_BLOCKING
var/new_desc = reject_bad_text(tgui_input_text(user, "Drink description", "Set drink description", custom_drink_desc, 64, TRUE), 128)
if(!new_desc)
balloon_alert(user, "invalid drink description!")
using_custom_drinks = FALSE
- return
+ return CLICK_ACTION_BLOCKING
if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH))
- return
+ return CLICK_ACTION_BLOCKING
using_custom_drinks = TRUE
custom_drink_name = new_name
@@ -498,6 +495,7 @@
enable_custom_drinks()
balloon_alert(user, "now pouring custom drinks")
+ return CLICK_ACTION_SUCCESS
/obj/item/reagent_containers/cup/glass/shaker/proc/enable_custom_drinks()
RegisterSignal(src, COMSIG_REAGENTS_CUP_TRANSFER_TO, PROC_REF(handle_transfer))
diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm
index 4f7abbe6f20..a293aac7aa1 100644
--- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm
+++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm
@@ -894,7 +894,8 @@
desc = "Fermented prison wine made from fruit, sugar, and despair. You probably shouldn't drink this around Security."
icon_state = "trashbag1" // pruno releases air as it ferments, we don't want to simulate this in atmos, but we can make it look like it did
for (var/mob/living/M in view(2, get_turf(src))) // letting people and/or narcs know when the pruno is done
- to_chat(M, span_info("A pungent smell emanates from [src], like fruit puking out its guts."))
+ if(HAS_TRAIT(M, TRAIT_ANOSMIA))
+ to_chat(M, span_info("A pungent smell emanates from [src], like fruit puking out its guts."))
playsound(get_turf(src), 'sound/effects/bubbles2.ogg', 25, TRUE)
/**
diff --git a/code/modules/reagents/reagent_containers/medigel.dm b/code/modules/reagents/reagent_containers/medigel.dm
index e6836c7a4c2..f6d7b116eff 100644
--- a/code/modules/reagents/reagent_containers/medigel.dm
+++ b/code/modules/reagents/reagent_containers/medigel.dm
@@ -32,6 +32,7 @@
"Purple" = "medigel_purple"
)
+
/obj/item/reagent_containers/medigel/mode_change_message(mob/user)
var/squirt_mode = amount_per_transfer_from_this == initial(amount_per_transfer_from_this)
to_chat(user, span_notice("You will now apply the medigel's contents in [squirt_mode ? "extended sprays":"short bursts"]. You'll now use [amount_per_transfer_from_this] units per use."))
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index ee512224184..98ba3a13ed2 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -314,6 +314,12 @@
list_reagents = list(/datum/reagent/gravitum = 5)
rename_with_volume = TRUE
+/obj/item/reagent_containers/pill/ondansetron
+ name = "ondansetron pill"
+ desc = "Alleviates nausea. May cause drowsiness."
+ icon_state = "pill11"
+ list_reagents = list(/datum/reagent/medicine/ondansetron = 10)
+
// Pill styles for chem master
/obj/item/reagent_containers/pill/style
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index a554dca6a84..350f51492cf 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -437,9 +437,14 @@
"Yellow" = "sprayer_med_yellow",
"Blue" = "sprayer_med_blue")
-/obj/item/reagent_containers/spray/medical/AltClick(mob/user)
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
+
+/obj/item/reagent_containers/spray/medical/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+
+ if(!current_skin)
+ context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin"
+ return CONTEXTUAL_SCREENTIP_SET
+
/obj/item/reagent_containers/spray/medical/reskin_obj(mob/M)
..()
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index d9ce792f1a0..a25b3936a35 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -454,8 +454,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30
. = ..()
AddComponent(/datum/component/simple_rotation)
-/obj/structure/reagent_dispensers/plumbed/storage/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/structure/reagent_dispensers/plumbed/storage/update_overlays()
. = ..()
diff --git a/code/modules/reagents/withdrawal/generic_addictions.dm b/code/modules/reagents/withdrawal/generic_addictions.dm
index 4eabfa1095a..c7977435f4d 100644
--- a/code/modules/reagents/withdrawal/generic_addictions.dm
+++ b/code/modules/reagents/withdrawal/generic_addictions.dm
@@ -183,7 +183,7 @@
/datum/addiction/medicine/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, seconds_per_tick)
. = ..()
- if(SPT_PROB(10, seconds_per_tick))
+ if(SPT_PROB(1, seconds_per_tick))
affected_carbon.emote("cough")
/datum/addiction/medicine/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon)
@@ -216,6 +216,9 @@
/datum/addiction/medicine/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, seconds_per_tick)
. = ..()
+ if(SPT_PROB(2, seconds_per_tick))
+ affected_carbon.emote("cough")
+
var/datum/hallucination/fake_health_doll/hallucination = health_doll_ref?.resolve()
if(QDELETED(hallucination))
health_doll_ref = null
@@ -235,15 +238,14 @@
/datum/addiction/medicine/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, seconds_per_tick)
. = ..()
+ if(SPT_PROB(5, seconds_per_tick))
+ affected_carbon.emote("cough")
+
var/datum/hallucination/fake_health_doll/hallucination = health_doll_ref?.resolve()
if(!QDELETED(hallucination) && SPT_PROB(5, seconds_per_tick))
hallucination.increment_fake_damage()
return
- if(SPT_PROB(15, seconds_per_tick))
- affected_carbon.emote("cough")
- return
-
if(SPT_PROB(65, seconds_per_tick))
return
@@ -284,12 +286,12 @@
/datum/addiction/nicotine/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, seconds_per_tick)
. = ..()
affected_carbon.set_jitter_if_lower(20 SECONDS * seconds_per_tick)
- if(SPT_PROB(10, seconds_per_tick))
+ if(SPT_PROB(2, seconds_per_tick))
affected_carbon.emote("cough")
/datum/addiction/nicotine/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, seconds_per_tick)
. = ..()
affected_carbon.set_jitter_if_lower(30 SECONDS * seconds_per_tick)
- if(SPT_PROB(15, seconds_per_tick))
+ if(SPT_PROB(5, seconds_per_tick))
affected_carbon.emote("cough")
*/
diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm
index cb008252037..3c04bd924ec 100644
--- a/code/modules/recycling/conveyor.dm
+++ b/code/modules/recycling/conveyor.dm
@@ -37,13 +37,29 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
//Direction -> if we have a conveyor belt in that direction
var/list/neighbors
-/obj/machinery/conveyor/Initialize(mapload)
+/obj/machinery/conveyor/Initialize(mapload, new_dir, new_id)
. = ..()
AddElement(/datum/element/footstep_override, priority = STEP_SOUND_CONVEYOR_PRIORITY)
var/static/list/give_turf_traits = list(TRAIT_TURF_IGNORE_SLOWDOWN)
AddElement(/datum/element/give_turf_traits, give_turf_traits)
register_context()
+ if(new_dir)
+ setDir(new_dir)
+ if(new_id)
+ id = new_id
+ neighbors = list()
+ ///Leaving onto conveyor detection won't work at this point, but that's alright since it's an optimization anyway
+ ///Should be fine without it
+ var/static/list/loc_connections = list(
+ COMSIG_ATOM_EXITED = PROC_REF(conveyable_exit),
+ COMSIG_ATOM_ENTERED = PROC_REF(conveyable_enter),
+ COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(conveyable_enter)
+ )
+ AddElement(/datum/element/connect_loc, loc_connections)
+ update_move_direction()
+ LAZYADD(GLOB.conveyors_by_id[id], src)
+
/obj/machinery/conveyor/examine(mob/user)
. = ..()
if(inverted)
@@ -96,27 +112,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
icon_state = "conveyor_map_inverted"
flipped = TRUE
-// create a conveyor
-/obj/machinery/conveyor/Initialize(mapload, new_dir, new_id)
- ..()
- if(new_dir)
- setDir(new_dir)
- if(new_id)
- id = new_id
- neighbors = list()
- ///Leaving onto conveyor detection won't work at this point, but that's alright since it's an optimization anyway
- ///Should be fine without it
- var/static/list/loc_connections = list(
- COMSIG_ATOM_EXITED = PROC_REF(conveyable_exit),
- COMSIG_ATOM_ENTERED = PROC_REF(conveyable_enter),
- COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(conveyable_enter)
- )
- AddElement(/datum/element/connect_loc, loc_connections)
- update_move_direction()
- LAZYADD(GLOB.conveyors_by_id[id], src)
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/conveyor/LateInitialize()
+/obj/machinery/conveyor/post_machine_initialize()
. = ..()
build_neighbors()
@@ -619,9 +615,9 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
if(!attached_switch)
return
- INVOKE_ASYNC(src, PROC_REF(update_conveyers), port)
+ INVOKE_ASYNC(src, PROC_REF(update_conveyors), port)
-/obj/item/circuit_component/conveyor_switch/proc/update_conveyers(datum/port/input/port)
+/obj/item/circuit_component/conveyor_switch/proc/update_conveyors(datum/port/input/port)
if(!attached_switch)
return
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 9bd89517bb8..bc40b1d0394 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -10,6 +10,7 @@
resistance_flags = FIRE_PROOF
interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON
obj_flags = CAN_BE_HIT
+ use_power = NO_POWER_USE
/// The internal air reservoir of the disposal
var/datum/gas_mixture/air_contents
@@ -99,7 +100,8 @@
if(current_size >= STAGE_FIVE)
deconstruct()
-/obj/machinery/disposal/LateInitialize()
+/obj/machinery/disposal/post_machine_initialize()
+ . = ..()
//this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
var/atom/L = loc
var/datum/gas_mixture/env = new
diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm
index 4b8fef12924..903a59a9305 100644
--- a/code/modules/recycling/disposal/construction.dm
+++ b/code/modules/recycling/disposal/construction.dm
@@ -95,8 +95,6 @@
pipe_type = initial(temp.flip_type)
update_appearance()
-/obj/structure/disposalconstruct/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
// construction/deconstruction
// wrench: (un)anchor
diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm
index 2d964d0f8fb..fff78f74bef 100644
--- a/code/modules/recycling/disposal/holder.dm
+++ b/code/modules/recycling/disposal/holder.dm
@@ -172,7 +172,7 @@
for(var/obj/structure/disposalpipe/P in T)
if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
if(QDELING(P))
- to_chat(world, "DEBUG -- [src] here, new pipe is being thanos'd")
+ CRASH("Pipe is being deleted while being used by a disposal holder at ([P.x], [P.y], [P.z]")
return P
// if no matching pipe, return null
return null
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index f11ad91e002..2497af7e54c 100644
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -400,10 +400,10 @@
payments_acc = null
to_chat(user, span_notice("You clear the registered account."))
-/obj/item/sales_tagger/AltClick(mob/user)
- . = ..()
+/obj/item/sales_tagger/click_alt(mob/user)
var/potential_cut = input("How much would you like to pay out to the registered card?","Percentage Profit ([round(cut_min*100)]% - [round(cut_max*100)]%)") as num|null
if(!potential_cut)
cut_multiplier = initial(cut_multiplier)
cut_multiplier = clamp(round(potential_cut/100, cut_min), cut_min, cut_max)
to_chat(user, span_notice("[round(cut_multiplier*100)]% profit will be received if a package with a barcode is sold."))
+ return CLICK_ACTION_SUCCESS
diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm
index bd063dea439..1531d07f5ea 100644
--- a/code/modules/religion/burdened/psyker.dm
+++ b/code/modules/religion/burdened/psyker.dm
@@ -341,7 +341,7 @@
else
times_dry_fired = 0
var/turf/target_turf = get_offset_target_turf(get_ranged_target_turf(owner, owner.dir, 7), dx = rand(-1, 1), dy = rand(-1, 1))
- held_gun.process_fire(target_turf, owner, TRUE, null, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
+ held_gun.process_fire(target_turf, owner, TRUE, null, pick(GLOB.all_body_zones))
held_gun.semicd = FALSE
/datum/action/cooldown/spell/charged/psychic_booster
diff --git a/code/modules/requests/request_manager.dm b/code/modules/requests/request_manager.dm
index dd6d8d42a48..74a40304f7a 100644
--- a/code/modules/requests/request_manager.dm
+++ b/code/modules/requests/request_manager.dm
@@ -163,17 +163,18 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)
switch(action)
if ("pp")
- var/mob/M = request.owner?.mob
- usr.client.holder.show_player_panel(M)
+ SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/show_player_panel, request.owner?.mob)
return TRUE
+
if ("vv")
var/mob/M = request.owner?.mob
usr.client.debug_variables(M)
return TRUE
+
if ("sm")
- var/mob/M = request.owner?.mob
- usr.client.cmd_admin_subtle_message(M)
+ SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/cmd_admin_subtle_message, request.owner?.mob)
return TRUE
+
if ("flw")
var/mob/M = request.owner?.mob
usr.client.admin_follow(M)
@@ -192,8 +193,9 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)
D.traitor_panel()
return TRUE
else
- usr.client.holder.show_traitor_panel(M)
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_traitor_panel, M)
return TRUE
+
if ("logs")
var/mob/M = request.owner?.mob
if(!ismob(M))
@@ -201,16 +203,11 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)
return TRUE
show_individual_logging_panel(M, null, null)
return TRUE
+
if ("smite")
- if(!check_rights(R_FUN))
- to_chat(usr, "Insufficient permissions to smite, you require +FUN", confidential = TRUE)
- return TRUE
- var/mob/living/carbon/human/H = request.owner?.mob
- if (!H || !istype(H))
- to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE)
- return TRUE
- usr.client.smite(H)
+ SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/admin_smite, request.owner?.mob)
return TRUE
+
if ("rply")
if (request.req_type == REQUEST_PRAYER)
to_chat(usr, "Cannot reply to a prayer", confidential = TRUE)
diff --git a/code/modules/research/designs/autolathe/service_designs.dm b/code/modules/research/designs/autolathe/service_designs.dm
index 6b8d7f474fc..e34fc5166c8 100644
--- a/code/modules/research/designs/autolathe/service_designs.dm
+++ b/code/modules/research/designs/autolathe/service_designs.dm
@@ -190,6 +190,19 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+/datum/design/soup_pot
+ name = "Soup Pot"
+ id = "souppot"
+ build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
+ materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT*5, /datum/material/bluespace =SMALL_MATERIAL_AMOUNT*4)
+ category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_EQUIPMENT)
+ build_path = /obj/item/reagent_containers/cup/soup_pot
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN,
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+
/datum/design/bowl
name = "Bowl"
id = "bowl"
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index e17b53da692..84dcb67233d 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -189,6 +189,17 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+/datum/design/water_balloon
+ name = "Water Balloon"
+ id = "water_balloon"
+ build_type = PROTOLATHE | AWAY_LATHE
+ materials = list(/datum/material/plastic =SMALL_MATERIAL_AMOUNT*5)
+ build_path = /obj/item/toy/waterballoon
+ category = list(
+ RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SERVICE
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+
/datum/design/mesons
name = "Optical Meson Scanners"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm
index ee1e09b1143..392921795b9 100644
--- a/code/modules/research/designs/tool_designs.dm
+++ b/code/modules/research/designs/tool_designs.dm
@@ -137,7 +137,7 @@
name = "RCD anti disruption designs upgrade"
desc = "Prevents interruption of RCD construction and deconstruction."
id = "rcd_upgrade_anti_interrupt"
- build_type = PROTOLATHE
+ build_type = PROTOLATHE | AWAY_LATHE
materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
/datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.25,
@@ -154,7 +154,7 @@
name = "RCD cooling upgrade"
desc = "Allows the RCD to more quickly perform multiple actions at once."
id = "rcd_upgrade_cooling"
- build_type = PROTOLATHE
+ build_type = PROTOLATHE | AWAY_LATHE
materials = list(
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2,
/datum/material/glass = SHEET_MATERIAL_AMOUNT,
diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm
index 03fffcec8ca..021c282958d 100644
--- a/code/modules/research/destructive_analyzer.dm
+++ b/code/modules/research/destructive_analyzer.dm
@@ -53,9 +53,9 @@
addtimer(CALLBACK(src, PROC_REF(finish_loading)), 1 SECONDS)
return TRUE
-/obj/machinery/rnd/destructive_analyzer/AltClick(mob/user)
- . = ..()
+/obj/machinery/rnd/destructive_analyzer/click_alt(mob/user)
unload_item()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/rnd/destructive_analyzer/update_icon_state()
icon_state = "[base_icon_state][loaded_item ? "_l" : null]"
@@ -115,11 +115,11 @@
say("Destructive analysis failed!")
return TRUE
-//Let emags in on a right click
-/obj/machinery/rnd/destructive_analyzer/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
- if(is_right_clicking && istype(tool, /obj/item/card/emag))
- return NONE
- return ..()
+/obj/machinery/rnd/destructive_analyzer/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers)
+ // Cringe way to let emags insert on RMB because we still use attackby to insert
+ if(istype(tool, /obj/item/card/emag))
+ return ITEM_INTERACT_SKIP_TO_ATTACK
+ return NONE
//This allows people to put syndicate screwdrivers in the machine. Secondary act still passes.
/obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool)
diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm
index 8ed6ef04df0..c7a7b320345 100644
--- a/code/modules/research/machinery/_production.dm
+++ b/code/modules/research/machinery/_production.dm
@@ -452,12 +452,12 @@
drop_direction = direction
balloon_alert(usr, "dropping [dir2text(drop_direction)]")
-/obj/machinery/rnd/production/AltClick(mob/user)
- . = ..()
- if(!drop_direction || !can_interact(user))
- return
+/obj/machinery/rnd/production/click_alt(mob/user)
+ if(drop_direction == 0)
+ return CLICK_ACTION_BLOCKING
if(busy)
balloon_alert(user, "busy printing!")
- return
+ return CLICK_ACTION_BLOCKING
balloon_alert(user, "drop direction reset")
drop_direction = 0
+ return CLICK_ACTION_SUCCESS
diff --git a/code/modules/research/ordnance/doppler_array.dm b/code/modules/research/ordnance/doppler_array.dm
index 7afe201f360..5e44c2dc703 100644
--- a/code/modules/research/ordnance/doppler_array.dm
+++ b/code/modules/research/ordnance/doppler_array.dm
@@ -250,8 +250,6 @@
SIGNAL_HANDLER
set_light_on(!(machine_stat & NOPOWER))
-/obj/machinery/doppler_array/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/machinery/doppler_array/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index e529f97eb0c..04d0c30d9e0 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -45,7 +45,7 @@ Nothing else in the console has ID requirements.
return reagent.name
return ID
-/obj/machinery/computer/rdconsole/LateInitialize()
+/obj/machinery/computer/rdconsole/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm
index 58d7f1f29cf..60dcc8716cc 100644
--- a/code/modules/research/rdmachines.dm
+++ b/code/modules/research/rdmachines.dm
@@ -24,7 +24,7 @@
set_wires(new /datum/wires/rnd(src))
register_context()
-/obj/machinery/rnd/LateInitialize()
+/obj/machinery/rnd/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index e446672bc33..1bd0d3560be 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -154,17 +154,16 @@
if(HDD_OVERLOADED)
. += "The front panel is dangling open. The hdd inside is destroyed and the wires are all burned."
-/obj/machinery/rnd/server/master/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking)
+/obj/machinery/rnd/server/master/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!tool.tool_behaviour)
- return ..()
- // Only antags are given the training and knowledge to disassemble this thing.
- if(is_special_character(user))
- return ..()
- if(user.combat_mode)
return NONE
-
- balloon_alert(user, "you can't find an obvious maintenance hatch!")
- return ITEM_INTERACT_BLOCKING
+ // Only antags are given the training and knowledge to disassemble this thing.
+ if(!is_special_character(user))
+ if(user.combat_mode)
+ return ITEM_INTERACT_SKIP_TO_ATTACK
+ balloon_alert(user, "you can't find an obvious maintenance hatch!")
+ return ITEM_INTERACT_BLOCKING
+ return NONE
/obj/machinery/rnd/server/master/attackby(obj/item/attacking_item, mob/user, params)
if(istype(attacking_item, /obj/item/computer_disk/hdd_theft))
diff --git a/code/modules/research/server_control.dm b/code/modules/research/server_control.dm
index 94a429dc6d7..24327a731a6 100644
--- a/code/modules/research/server_control.dm
+++ b/code/modules/research/server_control.dm
@@ -9,7 +9,7 @@
///Connected techweb node the server is connected to.
var/datum/techweb/stored_research
-/obj/machinery/computer/rdservercontrol/LateInitialize()
+/obj/machinery/computer/rdservercontrol/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 7b01536034c..7d64e1878b8 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -106,6 +106,7 @@
"slime_scanner",
"solar_panel",
"solar_tracker",
+ "souppot",
"space_heater",
"spoon",
"status_display_frame",
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index de97ea7bf69..9724bd776d8 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -58,7 +58,7 @@
stored_slimes = list()
-/obj/machinery/computer/camera_advanced/xenobio/LateInitialize(mapload)
+/obj/machinery/computer/camera_advanced/xenobio/post_machine_initialize()
. = ..()
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
if(get_area(recycler.loc) == get_area(loc))
@@ -360,9 +360,9 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo
// Alternate clicks for slime, monkey and open turf if using a xenobio console
-/mob/living/basic/slime/AltClick(mob/user)
+/mob/living/basic/slime/click_alt(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src)
- ..()
+ return CLICK_ACTION_SUCCESS
/mob/living/basic/slime/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src)
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 1551d6eb952..7f87a08b85b 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -705,10 +705,9 @@
context[SCREENTIP_CONTEXT_ALT_LMB] = "Set potion offer reason"
return CONTEXTUAL_SCREENTIP_SET
-/obj/item/slimepotion/slime/sentience/AltClick(mob/living/user)
- if(!can_interact(user))
- return
+/obj/item/slimepotion/slime/sentience/click_alt(mob/living/user)
potion_reason = tgui_input_text(user, "Enter reason for offering potion", "Intelligence Potion", potion_reason, multiline = TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/item/slimepotion/slime/sentience/attack(mob/living/dumb_mob, mob/user)
if(being_used || !isliving(dumb_mob))
@@ -1082,17 +1081,3 @@
turf_type = /turf/open/floor/sepia
merge_type = /obj/item/stack/tile/sepia
-/obj/item/areaeditor/blueprints/slime
- name = "cerulean prints"
- desc = "A one use yet of blueprints made of jelly like organic material. Extends the reach of the management console."
- color = "#2956B2"
-
-/obj/item/areaeditor/blueprints/slime/edit_area()
- ..()
- var/area/area = get_area(src)
- for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists())
- for(var/turf/area_turf as anything in zlevel_turfs)
- area_turf.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- area_turf.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY)
- area.area_flags |= XENOBIOLOGY_COMPATIBLE
- qdel(src)
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index ff2da672213..28f344873ff 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -201,9 +201,11 @@
shuttle.setTimer(shuttle.timeLeft(1) + hijack_flight_time_increase) //give the guy more time to hijack if it's already in flight.
return shuttle.hijack_status
-/obj/machinery/computer/emergency_shuttle/AltClick(user)
- if(isliving(user))
- attempt_hijack_stage(user)
+/obj/machinery/computer/emergency_shuttle/click_alt(mob/living/user)
+ if(!isliving(user))
+ return NONE
+ attempt_hijack_stage(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/computer/emergency_shuttle/proc/attempt_hijack_stage(mob/living/user)
if(!user.CanReach(src))
@@ -826,10 +828,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/pod, 32)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
-/obj/item/storage/pod/AltClick(mob/user)
- if(!can_interact(user))
- return
- return ..()
+/obj/item/storage/pod/click_alt(mob/user)
+ return CLICK_ACTION_SUCCESS
/obj/item/storage/pod/can_interact(mob/user)
if(!..())
diff --git a/code/modules/shuttle/spaceship_navigation_beacon.dm b/code/modules/shuttle/spaceship_navigation_beacon.dm
index eb613be54de..41b3f5e39ed 100644
--- a/code/modules/shuttle/spaceship_navigation_beacon.dm
+++ b/code/modules/shuttle/spaceship_navigation_beacon.dm
@@ -5,7 +5,6 @@
icon_state = "beacon_active"
base_icon_state = "beacon"
density = TRUE
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
/// Locked beacons cannot be jumped to by ships.
var/locked = FALSE
diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm
index 989ab4edc94..e5b4b0eb024 100644
--- a/code/modules/shuttle/special.dm
+++ b/code/modules/shuttle/special.dm
@@ -79,7 +79,6 @@
var/obj/machinery/power/emitter/energycannon/magical/our_statue
var/list/mob/living/sleepers = list()
var/never_spoken = TRUE
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
/obj/structure/table/abductor/wabbajack/Initialize(mapload)
. = ..()
@@ -89,6 +88,12 @@
STOP_PROCESSING(SSobj, src)
. = ..()
+/obj/structure/table/abductor/wabbajack/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/structure/table/abductor/wabbajack/wrench_act(mob/living/user, obj/item/tool)
+ return NONE
+
/obj/structure/table/abductor/wabbajack/process()
if(isnull(our_statue))
our_statue = locate() in orange(4, src)
@@ -173,7 +178,6 @@
/obj/structure/table/wood/shuttle_bar
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
max_integrity = 1000
var/boot_dir = 1
@@ -184,6 +188,12 @@
)
AddElement(/datum/element/connect_loc, loc_connections)
+/obj/structure/table/wood/shuttle_bar/screwdriver_act(mob/living/user, obj/item/tool)
+ return NONE
+
+/obj/structure/table/wood/shuttle_bar/wrench_act(mob/living/user, obj/item/tool)
+ return NONE
+
/obj/structure/table/wood/shuttle_bar/proc/on_entered(datum/source, atom/movable/AM)
SIGNAL_HANDLER
var/mob/living/M = AM
diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm
index 402a87bf6d4..08e0b0d2699 100644
--- a/code/modules/shuttle/syndicate.dm
+++ b/code/modules/shuttle/syndicate.dm
@@ -11,7 +11,9 @@
shuttleId = "syndicate"
possible_destinations = "syndicate_away;syndicate_z5;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s;syndicate_custom"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+
+/obj/machinery/computer/shuttle/syndicate/screwdriver_act(mob/living/user, obj/item/I)
+ return NONE
/obj/machinery/computer/shuttle/syndicate/launch_check(mob/user)
. = ..()
diff --git a/code/modules/spells/spell_types/jaunt/shadow_walk.dm b/code/modules/spells/spell_types/jaunt/shadow_walk.dm
index c5a47cd1740..c869fb19913 100644
--- a/code/modules/spells/spell_types/jaunt/shadow_walk.dm
+++ b/code/modules/spells/spell_types/jaunt/shadow_walk.dm
@@ -45,7 +45,7 @@
exit_jaunt(cast_on)
return
- playsound(get_turf(owner), 'sound/magic/ethereal_enter.ogg', 50, TRUE, -1)
+ playsound(get_turf(owner), 'sound/effects/nightmare_poof.ogg', 50, TRUE, -1, ignore_walls = FALSE)
cast_on.visible_message(span_boldwarning("[cast_on] melts into the shadows!"))
cast_on.SetAllImmobility(0)
cast_on.setStaminaLoss(0, FALSE)
@@ -107,7 +107,7 @@
reveal_turf.visible_message(span_boldwarning("[jaunter] is revealed by the light!"))
else
reveal_turf.visible_message(span_boldwarning("[jaunter] emerges from the darkness!"))
- playsound(reveal_turf, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1)
+ playsound(reveal_turf, 'sound/effects/nightmare_reappear.ogg', 50, TRUE, -1, ignore_walls = FALSE)
return ..()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 03f87b6d741..abf3575f39e 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -344,16 +344,16 @@
for(var/datum/wound/wound as anything in wounds)
switch(wound.severity)
if(WOUND_SEVERITY_TRIVIAL)
- // check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)].")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
+ // check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)].")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)].")]" // SKYRAT EDIT - Medical overhaul-ish
if(WOUND_SEVERITY_MODERATE)
- // check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
+ // check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!")]" // SKYRAT EDIT - Medical overhaul-ish
if(WOUND_SEVERITY_SEVERE)
- // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
+ // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lLOWER_TEXT(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!")]" // SKYRAT EDIT - Medical overhaul-ish
if(WOUND_SEVERITY_CRITICAL)
- // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
+ // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)]!!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL
check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!!")]" // SKYRAT EDIT - Medical overhaul-ish
for(var/obj/item/embedded_thing in embedded_objects)
@@ -771,14 +771,14 @@
if(owner == new_owner)
return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made.
- SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner)
-
if(owner)
. = owner //return value is old owner
clear_ownership(owner)
if(new_owner)
apply_ownership(new_owner)
+ SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner)
+
refresh_bleed_rate()
return .
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 783c0292bc5..7390dd84ac9 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -381,7 +381,7 @@
/mob/living/carbon/proc/regenerate_limbs(list/excluded_zones = list())
SEND_SIGNAL(src, COMSIG_CARBON_REGENERATE_LIMBS, excluded_zones)
- var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
+ var/list/zone_list = GLOB.all_body_zones.Copy()
var/list/dismembered_by_copy = body_zone_dismembered_by?.Copy()
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index 126bd3db33a..fb0647d0fb5 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -83,7 +83,7 @@
/mob/living/carbon/proc/get_missing_limbs()
RETURN_TYPE(/list)
- var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
+ var/list/full = GLOB.all_body_zones.Copy()
for(var/zone in full)
if(get_bodypart(zone))
full -= zone
@@ -100,7 +100,7 @@
return list()
/mob/living/carbon/get_disabled_limbs()
- var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
+ var/list/full = GLOB.all_body_zones.Copy()
var/list/disabled = list()
for(var/zone in full)
var/obj/item/bodypart/affecting = get_bodypart(zone)
diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
index a5569d803b0..9cbb786d7e6 100644
--- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm
@@ -584,38 +584,34 @@
limb_id = BODYPART_ID_MEAT
should_draw_greyscale = FALSE
-/obj/item/bodypart/arm/left/flesh/Initialize(mapload, dont_spawn_flesh = FALSE)
+/obj/item/bodypart/arm/left/flesh/Initialize(mapload)
. = ..()
- if(!dont_spawn_flesh)
- new /mob/living/basic/living_limb_flesh(src, src)
ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT)
+ AddElement(/datum/element/living_limb_initialiser)
/obj/item/bodypart/arm/right/flesh
limb_id = BODYPART_ID_MEAT
should_draw_greyscale = FALSE
-/obj/item/bodypart/arm/right/flesh/Initialize(mapload, dont_spawn_flesh = FALSE)
+/obj/item/bodypart/arm/right/flesh/Initialize(mapload)
. = ..()
- if(!dont_spawn_flesh)
- new /mob/living/basic/living_limb_flesh(src, src)
ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT)
+ AddElement(/datum/element/living_limb_initialiser)
/obj/item/bodypart/leg/left/flesh
limb_id = BODYPART_ID_MEAT
should_draw_greyscale = FALSE
-/obj/item/bodypart/leg/left/flesh/Initialize(mapload, dont_spawn_flesh = FALSE)
+/obj/item/bodypart/leg/left/flesh/Initialize(mapload)
. = ..()
- if(!dont_spawn_flesh)
- new /mob/living/basic/living_limb_flesh(src, src)
ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT)
+ AddElement(/datum/element/living_limb_initialiser)
/obj/item/bodypart/leg/right/flesh
limb_id = BODYPART_ID_MEAT
should_draw_greyscale = FALSE
-/obj/item/bodypart/leg/right/flesh/Initialize(mapload, dont_spawn_flesh = FALSE)
+/obj/item/bodypart/leg/right/flesh/Initialize(mapload)
. = ..()
- if(!dont_spawn_flesh)
- new /mob/living/basic/living_limb_flesh(src, src)
ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT)
+ AddElement(/datum/element/living_limb_initialiser)
diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm
index 8e9c7ae70a7..6bdf093dd47 100644
--- a/code/modules/surgery/organs/internal/ears/_ears.dm
+++ b/code/modules/surgery/organs/internal/ears/_ears.dm
@@ -15,17 +15,16 @@
now_fixed = "Noise slowly begins filling your ears once more."
low_threshold_cleared = "The ringing in your ears has died down."
- // `deaf` measures "ticks" of deafness. While > 0, the person is unable
- // to hear anything.
+ /// `deaf` measures "ticks" of deafness. While > 0, the person is unable to hear anything.
var/deaf = 0
// `damage` in this case measures long term damage to the ears, if too high,
// the person will not have either `deaf` or `ear_damage` decrease
// without external aid (earmuffs, drugs)
- //Resistance against loud noises
+ /// Resistance against loud noises
var/bang_protect = 0
- // Multiplier for both long term and short term ear damage
+ /// Multiplier for both long term and short term ear damage
var/damage_multiplier = 1
/obj/item/organ/internal/ears/on_life(seconds_per_tick, times_fired)
@@ -34,28 +33,98 @@
to_chat(owner, span_warning("The ringing in your ears grows louder, blocking out any external noises for a moment."))
. = ..()
- // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here. Ear healing from earmuffs or chems happen elsewhere
+ // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here.
+ // Ear healing from earmuffs or chems happen elsewhere
if(HAS_TRAIT_NOT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
return
+ // no healing if failing
+ if(organ_flags & ORGAN_FAILING)
+ return
+ adjustEarDamage(0, -0.5 * seconds_per_tick)
+ if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick))
+ adjustEarDamage(0, 4)
+ SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg'))
- if((organ_flags & ORGAN_FAILING))
- deaf = max(deaf, 1) // if we're failing we always have at least 1 deaf stack (and thus deafness)
- else // only clear deaf stacks if we're not failing
- deaf = max(deaf - (0.5 * seconds_per_tick), 0)
- if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick))
- adjustEarDamage(0, 4)
- SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg'))
+/obj/item/organ/internal/ears/apply_organ_damage(damage_amount, maximum, required_organ_flag)
+ . = ..()
+ update_temp_deafness()
- if(deaf)
- ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
+/obj/item/organ/internal/ears/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
+ . = ..()
+ update_temp_deafness()
+
+/obj/item/organ/internal/ears/on_mob_remove(mob/living/carbon/organ_owner, special)
+ . = ..()
+ UnregisterSignal(organ_owner, COMSIG_MOB_SAY)
+ REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE)
+
+/**
+ * Snowflake proc to handle temporary deafness
+ *
+ * * ddmg: Handles normal organ damage
+ * * ddeaf: Handles temporary deafness, 1 ddeaf = 2 seconds of deafness, by default (with no multiplier)
+ */
+/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg = 0, ddeaf = 0)
+ if(owner.status_flags & GODMODE)
+ update_temp_deafness()
+ return
+
+ var/mod_damage = ddmg > 0 ? (ddmg * damage_multiplier) : ddmg
+ if(mod_damage)
+ apply_organ_damage(mod_damage)
+ var/mod_deaf = ddeaf > 0 ? (ddeaf * damage_multiplier) : ddeaf
+ if(mod_deaf)
+ deaf = max(deaf + mod_deaf, 0)
+ update_temp_deafness()
+
+/// Updates status of deafness
+/obj/item/organ/internal/ears/proc/update_temp_deafness()
+ // if we're failing we always have at least some deaf stacks (and thus deafness)
+ if(organ_flags & ORGAN_FAILING)
+ deaf = max(deaf, 1 * damage_multiplier)
+
+ if(isnull(owner))
+ return
+
+ if(owner.status_flags & GODMODE)
+ deaf = 0
+
+ if(deaf > 0)
+ if(!HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE))
+ RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(adjust_speech))
+ ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
else
REMOVE_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE)
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
-/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg, ddeaf)
- if(owner.status_flags & GODMODE)
+/// Being deafened by loud noises makes you shout
+/obj/item/organ/internal/ears/proc/adjust_speech(datum/source, list/speech_args)
+ SIGNAL_HANDLER
+
+ if(HAS_TRAIT_NOT_FROM(source, TRAIT_DEAF, EAR_DAMAGE))
return
- set_organ_damage(clamp(damage + (ddmg * damage_multiplier), 0, maxHealth))
- deaf = max(deaf + (ddeaf * damage_multiplier), 0)
+ if(HAS_TRAIT(source, TRAIT_SIGN_LANG))
+ return
+
+ var/message = speech_args[SPEECH_MESSAGE]
+ // Replace only end-of-sentence punctuation with exclamation marks (hence the empty space)
+ // We don't wanna mess with things like ellipses
+ message = replacetext(message, ". ", "! ")
+ message = replacetext(message, "? ", "?! ")
+ // Special case for the last character
+ switch(copytext_char(message, -1))
+ if(".")
+ if(copytext_char(message, -2) != "..") // Once again ignoring ellipses, let people trail off
+ message = copytext_char(message, 1, -1) + "!"
+ if("?")
+ message = copytext_char(message, 1, -1) + "?!"
+ if("!")
+ pass()
+ else
+ message += "!"
+
+ speech_args[SPEECH_MESSAGE] = message
+ return COMPONENT_UPPERCASE_SPEECH
/obj/item/organ/internal/ears/invincible
damage_multiplier = 0
diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm
index 08fbd4e955a..7ab37382a55 100644
--- a/code/modules/surgery/organs/internal/eyes/_eyes.dm
+++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm
@@ -527,7 +527,7 @@
set_beam_color(new_color, to_update)
return TRUE
if("enter_color")
- var/new_color = lowertext(params["new_color"])
+ var/new_color = LOWER_TEXT(params["new_color"])
var/to_update = params["to_update"]
set_beam_color(new_color, to_update, sanitize = TRUE)
return TRUE
diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm
index 6df5047f4af..a7d30c2aa03 100644
--- a/code/modules/surgery/organs/internal/lungs/_lungs.dm
+++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm
@@ -266,7 +266,8 @@
var/ratio = (breath.gases[/datum/gas/oxygen][MOLES] / safe_oxygen_max) * 10
breather.apply_damage(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type, spread_damage = TRUE)
- breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy)
/// Handles NOT having too much o2. only relevant if safe_oxygen_max has a value
/obj/item/organ/internal/lungs/proc/safe_oxygen(mob/living/carbon/breather, datum/gas_mixture/breath, old_o2_pp)
@@ -285,7 +286,8 @@
if(nitro_pp < safe_nitro_min && !HAS_TRAIT(src, TRAIT_SPACEBREATHING))
// Suffocation side-effects.
// Not safe to check the old pp because of can_breath_vacuum
- breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro)
var/gas_breathed = handle_suffocation(breather, nitro_pp, safe_nitro_min, breath.gases[/datum/gas/nitrogen][MOLES])
if(nitro_pp)
breathe_gas_volume(breath, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, volume = gas_breathed)
@@ -318,7 +320,8 @@
breather.emote("cough")
if((world.time - breather.co2overloadtime) > 12 SECONDS)
- breather.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2)
breather.Unconscious(6 SECONDS)
// Lets hurt em a little, let them know we mean business.
breather.apply_damage(3, co2_damage_type, spread_damage = TRUE)
@@ -337,7 +340,8 @@
// Suffocation side-effects.
if(plasma_pp < safe_plasma_min && !HAS_TRAIT(src, TRAIT_SPACEBREATHING))
// Could check old_plasma_pp but vacuum breathing hates me
- breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas)
// Breathe insufficient amount of Plasma, exhale CO2.
var/gas_breathed = handle_suffocation(breather, plasma_pp, safe_plasma_min, breath.gases[/datum/gas/plasma][MOLES])
if(plasma_pp)
@@ -362,7 +366,8 @@
// If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so.
if(old_plasma_pp < safe_plasma_max)
- breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas)
var/ratio = (breath.gases[/datum/gas/plasma][MOLES] / safe_plasma_max) * 10
breather.apply_damage(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type, spread_damage = TRUE)
@@ -466,6 +471,8 @@
miasma_disease.name = "Unknown"
breather.AirborneContractDisease(miasma_disease, TRUE)
// Miasma side effects
+ if (HAS_TRAIT(breather, TRAIT_ANOSMIA)) //Anosmia quirk holder cannot smell miasma, but can get diseases from it.
+ return
switch(miasma_pp)
if(0.25 to 5)
// At lower pp, give out a little warning
@@ -522,7 +529,8 @@
// More N2O, more severe side-effects. Causes stun/sleep.
if(old_n2o_pp < n2o_para_min)
- breather.throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
+ if(!HAS_TRAIT(breather, TRAIT_ANOSMIA))
+ breather.throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o)
n2o_euphoria = EUPHORIA_ACTIVE
// give them one second of grace to wake up and run away a bit!
diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm
index 5807e1d5c2d..c01b5938124 100644
--- a/code/modules/surgery/organs/internal/tongue/_tongue.dm
+++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm
@@ -462,7 +462,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list())
var/list/message_word_list = splittext(message, " ")
var/list/translated_word_list = list()
for(var/word in message_word_list)
- word = GLOB.english_to_zombie[lowertext(word)]
+ word = GLOB.english_to_zombie[LOWER_TEXT(word)]
translated_word_list += word ? word : FALSE
// all occurrences of characters "eiou" (case-insensitive) are replaced with "r"
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index 64bd496f2bb..754335494f9 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -118,6 +118,8 @@
/datum/asset/simple/namespaced/fontawesome))
flush_queue |= window.send_asset(get_asset_datum(
/datum/asset/simple/namespaced/tgfont))
+ flush_queue |= window.send_asset(get_asset_datum(
+ /datum/asset/json/icon_ref_map))
for(var/datum/asset/asset in src_object.ui_assets(user))
flush_queue |= window.send_asset(asset)
if (flush_queue)
diff --git a/code/modules/tgui_input/say_modal/speech.dm b/code/modules/tgui_input/say_modal/speech.dm
index 3cdfb5057d0..8fff832477c 100644
--- a/code/modules/tgui_input/say_modal/speech.dm
+++ b/code/modules/tgui_input/say_modal/speech.dm
@@ -45,7 +45,7 @@
client.ooc(entry)
return TRUE
if(ADMIN_CHANNEL)
- client.cmd_admin_say(entry)
+ SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, entry)
return TRUE
// SKYRAT EDIT ADDITION START - CUSTOMIZATION
if(LOOC_CHANNEL)
diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm
index 4b9514aa38c..9956305db26 100644
--- a/code/modules/tooltip/tooltip.dm
+++ b/code/modules/tooltip/tooltip.dm
@@ -112,7 +112,7 @@ Notes:
return
var/ui_style = user.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)
if(!theme && ui_style)
- theme = lowertext(ui_style)
+ theme = LOWER_TEXT(ui_style)
if(!theme)
theme = "default"
user.client.tooltips.show(tip_src, params, title, content, theme)
diff --git a/code/modules/transport/admin.dm b/code/modules/transport/admin.dm
index 9d68d967e60..63f1fbfd55a 100644
--- a/code/modules/transport/admin.dm
+++ b/code/modules/transport/admin.dm
@@ -1,23 +1,14 @@
-/**
- * Helper tool to try and resolve tram controller errors, or reset the contents if someone put a million chickens on the tram
- * and now it's slow as hell and lagging things.
- */
-/datum/admins/proc/reset_tram()
- set name = "Reset Tram"
- set category = "Debug"
+ADMIN_VERB(reset_tram, R_DEBUG|R_ADMIN, "Reset Tram", "Reset a tram controller or its contents.", ADMIN_CATEGORY_DEBUG)
var/static/list/debug_tram_list = list(
- TRAMSTATION_LINE_1,
- BIRDSHOT_LINE_1,
- BIRDSHOT_LINE_2,
- HILBERT_LINE_1,
+ TRAMSTATION_LINE_1,
+ BIRDSHOT_LINE_1,
+ BIRDSHOT_LINE_2,
+ HILBERT_LINE_1,
)
- if(!check_rights(R_DEBUG))
- return
-
var/datum/transport_controller/linear/tram/broken_controller
- var/selected_transport_id = tgui_input_list(usr, "Which tram?", "Off the rails", debug_tram_list)
- var/reset_type = tgui_input_list(usr, "How hard of a reset?", "How bad is it screwed up", list("Clear Tram Contents", "Controller", "Controller and Contents", "Delete Datum", "Cancel"))
+ var/selected_transport_id = tgui_input_list(user, "Which tram?", "Off the rails", debug_tram_list)
+ var/reset_type = tgui_input_list(user, "How hard of a reset?", "How bad is it screwed up", list("Clear Tram Contents", "Controller", "Controller and Contents", "Delete Datum", "Cancel"))
if(isnull(reset_type) || reset_type == "Cancel")
return
@@ -28,40 +19,40 @@
break
if(isnull(broken_controller))
- to_chat(usr, span_warning("Couldn't find a transport controller datum with ID [selected_transport_id]!"))
+ to_chat(user, span_warning("Couldn't find a transport controller datum with ID [selected_transport_id]!"))
return
switch(reset_type)
if("Clear Tram Contents")
- var/selection = tgui_alert(usr, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel"))
+ var/selection = tgui_alert(user, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel"))
switch(selection)
if("Contents")
broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = FALSE)
- message_admins("[key_name_admin(usr)] performed a contents reset of tram ID [selected_transport_id].")
- log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents reset.")
+ message_admins("[key_name_admin(user)] performed a contents reset of tram ID [selected_transport_id].")
+ log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents reset.")
if("Contents and Players")
broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = TRUE)
- message_admins("[key_name_admin(usr)] performed a contents and player mob reset of tram ID [selected_transport_id].")
- log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents and player mob reset.")
+ message_admins("[key_name_admin(user)] performed a contents and player mob reset of tram ID [selected_transport_id].")
+ log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents and player mob reset.")
else
return
if("Controller")
- log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a controller reset, force operational.")
- message_admins("[key_name_admin(usr)] performed a controller reset of tram ID [selected_transport_id].")
+ log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a controller reset, force operational.")
+ message_admins("[key_name_admin(user)] performed a controller reset of tram ID [selected_transport_id].")
broken_controller.set_operational(TRUE)
broken_controller.reset_position()
if("Controller and Contents")
- var/selection = tgui_alert(usr, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel"))
+ var/selection = tgui_alert(user, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel"))
switch(selection)
if("Contents")
- message_admins("[key_name_admin(usr)] performed a contents and controller reset of tram ID [selected_transport_id].")
- log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents reset. Controller reset, force operational.")
+ message_admins("[key_name_admin(user)] performed a contents and controller reset of tram ID [selected_transport_id].")
+ log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents reset. Controller reset, force operational.")
broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = FALSE)
if("Contents and Players")
- message_admins("[key_name_admin(usr)] performed a contents/player/controller reset of tram ID [selected_transport_id].")
- log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents and player mob reset. Controller reset, force operational.")
+ message_admins("[key_name_admin(user)] performed a contents/player/controller reset of tram ID [selected_transport_id].")
+ log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents and player mob reset. Controller reset, force operational.")
broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = TRUE)
else
return
@@ -70,7 +61,7 @@
broken_controller.reset_position()
if("Delete Datum")
- var/confirm = tgui_alert(usr, "Deleting [selected_transport_id] will make it unrecoverable this round. Are you sure?", "Delete tram ID [selected_transport_id]", list("Yes", "Cancel"))
+ var/confirm = tgui_alert(user, "Deleting [selected_transport_id] will make it unrecoverable this round. Are you sure?", "Delete tram ID [selected_transport_id]", list("Yes", "Cancel"))
if(confirm != "Yes")
return
@@ -82,4 +73,4 @@
broken_controller.cycle_doors(CYCLE_OPEN, BYPASS_DOOR_CHECKS)
broken_controller.estop()
qdel(broken_controller)
- message_admins("[key_name_admin(usr)] performed a datum delete of tram ID [selected_transport_id].")
+ message_admins("[key_name_admin(user)] performed a datum delete of tram ID [selected_transport_id].")
diff --git a/code/modules/transport/elevator/elev_indicator.dm b/code/modules/transport/elevator/elev_indicator.dm
index 7b34f2d6105..22b9334be5a 100644
--- a/code/modules/transport/elevator/elev_indicator.dm
+++ b/code/modules/transport/elevator/elev_indicator.dm
@@ -36,11 +36,7 @@
/// The elevator's current floor relative to its lowest floor being 1
var/current_lift_floor = 1
-/obj/machinery/lift_indicator/Initialize(mapload)
- . = ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/lift_indicator/LateInitialize()
+/obj/machinery/lift_indicator/post_machine_initialize()
. = ..()
for(var/datum/transport_controller/linear/possible_match as anything in SStransport.transports_by_type[TRANSPORT_TYPE_ELEVATOR])
diff --git a/code/modules/transport/elevator/elev_panel.dm b/code/modules/transport/elevator/elev_panel.dm
index 24b6e0fa317..76b95922dfe 100644
--- a/code/modules/transport/elevator/elev_panel.dm
+++ b/code/modules/transport/elevator/elev_panel.dm
@@ -60,19 +60,15 @@
AddElement(/datum/element/contextual_screentip_tools, tool_behaviors)
AddElement(/datum/element/contextual_screentip_bare_hands, lmb_text = "Send Elevator")
- // Machinery returns lateload by default via parent,
- // this is just here for redundancy's sake.
- . = INITIALIZE_HINT_LATELOAD
-
maploaded = mapload
- // Maploaded panels link in LateInitialize...
+ // Maploaded panels link in post_machine_initialize...
if(mapload)
return
// And non-mapload panels link in Initialize
link_with_lift(log_error = FALSE)
-/obj/machinery/elevator_control_panel/LateInitialize()
+/obj/machinery/elevator_control_panel/post_machine_initialize()
. = ..()
// If we weren't maploaded, we probably already linked (or tried to link) in Initialize().
if(!maploaded)
diff --git a/code/modules/transport/tram/tram_controller.dm b/code/modules/transport/tram/tram_controller.dm
index 351ceab596e..624325f4996 100644
--- a/code/modules/transport/tram/tram_controller.dm
+++ b/code/modules/transport/tram/tram_controller.dm
@@ -708,19 +708,20 @@
/obj/machinery/transport/tram_controller/hilbert
configured_transport_id = HILBERT_LINE_1
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+
+/obj/machinery/transport/tram_controller/wrench_act_secondary(mob/living/user, obj/item/tool)
+ return NONE
/obj/machinery/transport/tram_controller/Initialize(mapload)
. = ..()
register_context()
if(!id_tag)
id_tag = assign_random_name()
- return INITIALIZE_HINT_LATELOAD
/**
* Mapped or built tram cabinet isn't located on a transport module.
*/
-/obj/machinery/transport/tram_controller/LateInitialize(mapload)
+/obj/machinery/transport/tram_controller/post_machine_initialize()
. = ..()
SStransport.hello(src, name, id_tag)
find_controller()
@@ -848,7 +849,7 @@
return
playsound(loc, 'sound/items/deconstruct.ogg', 50, vary = TRUE)
balloon_alert(user, "unsecured")
- deconstruct()
+ deconstruct(TRUE)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/machinery/transport/tram_controller/screwdriver_act_secondary(mob/living/user, obj/item/tool)
diff --git a/code/modules/transport/tram/tram_controls.dm b/code/modules/transport/tram/tram_controls.dm
index 435b47f9d1b..0bfce56aa5c 100644
--- a/code/modules/transport/tram/tram_controls.dm
+++ b/code/modules/transport/tram/tram_controls.dm
@@ -54,7 +54,7 @@
var/obj/item/circuitboard/computer/tram_controls/my_circuit = circuit
split_mode = my_circuit.split_mode
-/obj/machinery/computer/tram_controls/LateInitialize()
+/obj/machinery/computer/tram_controls/post_machine_initialize()
. = ..()
if(!id_tag)
id_tag = assign_random_name()
diff --git a/code/modules/transport/tram/tram_displays.dm b/code/modules/transport/tram/tram_displays.dm
index 47fe21f2ff1..b228bb38e9b 100644
--- a/code/modules/transport/tram/tram_displays.dm
+++ b/code/modules/transport/tram/tram_displays.dm
@@ -51,7 +51,6 @@
TRAMSTATION_LINE_1,
)
set_light(l_dir = REVERSE_DIR(dir))
- return INITIALIZE_HINT_LATELOAD
/obj/machinery/transport/destination_sign/Destroy()
SStransport.displays -= src
@@ -61,7 +60,7 @@
. = ..()
set_light(l_dir = REVERSE_DIR(dir))
-/obj/machinery/transport/destination_sign/indicator/LateInitialize(mapload)
+/obj/machinery/transport/destination_sign/indicator/post_machine_initialize()
. = ..()
link_tram()
diff --git a/code/modules/transport/tram/tram_doors.dm b/code/modules/transport/tram/tram_doors.dm
index 7e21b936791..ea6fe8d32c9 100644
--- a/code/modules/transport/tram/tram_doors.dm
+++ b/code/modules/transport/tram/tram_doors.dm
@@ -184,7 +184,7 @@
RemoveElement(/datum/element/atmos_sensitive, mapload)
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/door/airlock/tram/LateInitialize(mapload)
+/obj/machinery/door/airlock/tram/post_machine_initialize()
. = ..()
INVOKE_ASYNC(src, PROC_REF(open))
SStransport.doors += src
diff --git a/code/modules/transport/tram/tram_machinery.dm b/code/modules/transport/tram/tram_machinery.dm
index 7371447d082..99375bfbaf5 100644
--- a/code/modules/transport/tram/tram_machinery.dm
+++ b/code/modules/transport/tram/tram_machinery.dm
@@ -37,8 +37,7 @@
. = ..()
return INITIALIZE_HINT_LATELOAD
-/obj/item/assembly/control/transport/call_button/LateInitialize(mapload)
- . = ..()
+/obj/item/assembly/control/transport/call_button/LateInitialize()
if(!id_tag)
id_tag = assign_random_name()
SStransport.hello(src, name, id_tag)
diff --git a/code/modules/transport/tram/tram_power.dm b/code/modules/transport/tram/tram_power.dm
index ff0251e9090..45c48766db8 100644
--- a/code/modules/transport/tram/tram_power.dm
+++ b/code/modules/transport/tram/tram_power.dm
@@ -15,11 +15,7 @@
/// The tram platform we're connected to and providing power
var/obj/effect/landmark/transport/nav_beacon/tram/platform/connected_platform
-/obj/machinery/transport/power_rectifier/Initialize(mapload)
- . = ..()
- return INITIALIZE_HINT_LATELOAD
-
-/obj/machinery/transport/power_rectifier/LateInitialize(mapload)
+/obj/machinery/transport/power_rectifier/post_machine_initialize()
. = ..()
RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(power_tram))
find_platform()
diff --git a/code/modules/transport/tram/tram_remote.dm b/code/modules/transport/tram/tram_remote.dm
index 4176117d8b2..3a45ec4e665 100644
--- a/code/modules/transport/tram/tram_remote.dm
+++ b/code/modules/transport/tram/tram_remote.dm
@@ -107,12 +107,9 @@
SEND_SIGNAL(src, COMSIG_TRANSPORT_REQUEST, specific_transport_id, destination, options)
-/obj/item/assembly/control/transport/remote/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
-
+/obj/item/assembly/control/transport/remote/click_alt(mob/user)
link_tram(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/assembly/control/transport/remote/proc/link_tram(mob/user)
specific_transport_id = null
diff --git a/code/modules/transport/tram/tram_signals.dm b/code/modules/transport/tram/tram_signals.dm
index 101ae1027a3..eb648666030 100644
--- a/code/modules/transport/tram/tram_signals.dm
+++ b/code/modules/transport/tram/tram_signals.dm
@@ -107,9 +107,8 @@
RegisterSignal(SStransport, COMSIG_COMMS_STATUS, PROC_REF(comms_change))
SStransport.crossing_signals += src
register_context()
- return INITIALIZE_HINT_LATELOAD
-/obj/machinery/transport/crossing_signal/LateInitialize(mapload)
+/obj/machinery/transport/crossing_signal/post_machine_initialize()
. = ..()
link_tram()
link_sensor()
@@ -170,20 +169,16 @@
obj_flags |= EMAGGED
return TRUE
-/obj/machinery/transport/crossing_signal/AltClick(mob/living/user)
- . = ..()
- if(!can_interact(user))
- return
-
+/obj/machinery/transport/crossing_signal/click_alt(mob/living/user)
var/obj/item/tool = user.get_active_held_item()
if(!panel_open || tool?.tool_behaviour != TOOL_WRENCH)
- return FALSE
+ return CLICK_ACTION_BLOCKING
tool.play_tool_sound(src, 50)
setDir(turn(dir,-90))
- to_chat(user, span_notice("You rotate [src]."))
+ balloon_alert(user, "rotated")
find_uplink()
- return TRUE
+ return CLICK_ACTION_SUCCESS
/obj/machinery/transport/crossing_signal/attackby_secondary(obj/item/weapon, mob/user, params)
. = ..()
@@ -510,9 +505,8 @@
/obj/machinery/transport/guideway_sensor/Initialize(mapload)
. = ..()
SStransport.sensors += src
- return INITIALIZE_HINT_LATELOAD
-/obj/machinery/transport/guideway_sensor/LateInitialize(mapload)
+/obj/machinery/transport/guideway_sensor/post_machine_initialize()
. = ..()
pair_sensor()
RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(wake_up))
diff --git a/code/modules/transport/tram/tram_structures.dm b/code/modules/transport/tram/tram_structures.dm
index f868fe21c48..368223d1165 100644
--- a/code/modules/transport/tram/tram_structures.dm
+++ b/code/modules/transport/tram/tram_structures.dm
@@ -486,7 +486,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/tram/spoiler/LateInitialize()
- . = ..()
RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(set_spoiler))
/obj/structure/tram/spoiler/add_context(atom/source, list/context, obj/item/held_item, mob/user)
diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm
index d027cf7ba6d..a2ba6f5167b 100644
--- a/code/modules/transport/transport_module.dm
+++ b/code/modules/transport/transport_module.dm
@@ -96,7 +96,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/structure/transport/linear/LateInitialize()
- . = ..()
//after everything is initialized the transport controller can order everything
transport_controller_datum.order_platforms_by_z_level()
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 1b5c1f931bc..fb82c4fd748 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -117,6 +117,7 @@
#include "closets.dm"
#include "clothing_under_armor_subtype_check.dm"
#include "combat.dm"
+#include "combat_welder.dm"
#include "component_tests.dm"
#include "confusion.dm"
#include "connect_loc.dm"
@@ -168,6 +169,7 @@
#include "ling_decap.dm"
#include "liver.dm"
#include "load_map_security.dm"
+#include "lootpanel.dm"
#include "lungs.dm"
#include "machine_disassembly.dm"
#include "mafia.dm"
@@ -255,6 +257,7 @@
#include "station_trait_tests.dm"
#include "status_effect_ticks.dm"
#include "stomach.dm"
+#include "storage.dm"
#include "strange_reagent.dm"
#include "strippable.dm"
#include "stuns.dm"
diff --git a/code/modules/unit_tests/combat_welder.dm b/code/modules/unit_tests/combat_welder.dm
new file mode 100644
index 00000000000..2fa9052d6fb
--- /dev/null
+++ b/code/modules/unit_tests/combat_welder.dm
@@ -0,0 +1,26 @@
+/datum/unit_test/welder_combat
+
+/datum/unit_test/welder_combat/Run()
+ var/mob/living/carbon/human/tider = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+ var/mob/living/carbon/human/victim = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+ var/obj/item/weldingtool/weapon = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+
+ tider.put_in_active_hand(weapon, forced = TRUE)
+ tider.set_combat_mode(TRUE)
+ weapon.attack_self(tider)
+ weapon.melee_attack_chain(tider, victim)
+
+ TEST_ASSERT_NOTEQUAL(victim.getFireLoss(), 0, "Victim did not get burned by welder.")
+ TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 1, "Welder did not consume fuel on attacking a mob")
+
+ var/obj/structure/blob/blobby = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+ weapon.melee_attack_chain(tider, blobby)
+
+ TEST_ASSERT_NOTEQUAL(blobby.get_integrity(), blobby.max_integrity, "Blob did not get burned by welder.")
+ TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 2, "Welder did not consume fuel on attacking a blob")
+
+ weapon.force = 999
+ weapon.melee_attack_chain(tider, blobby)
+
+ TEST_ASSERT(QDELETED(blobby), "Blob was not destroyed by welder.")
+ TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 3, "Welder did not consume fuel on deleting a blob")
diff --git a/code/modules/unit_tests/lootpanel.dm b/code/modules/unit_tests/lootpanel.dm
new file mode 100644
index 00000000000..c0bec13288c
--- /dev/null
+++ b/code/modules/unit_tests/lootpanel.dm
@@ -0,0 +1,34 @@
+/datum/unit_test/lootpanel
+ abstract_type = /datum/unit_test/lootpanel
+
+/datum/unit_test/lootpanel/contents/Run()
+ var/datum/client_interface/mock_client = new()
+ var/datum/lootpanel/panel = new(mock_client)
+ var/mob/living/carbon/human/labrat = allocate(/mob/living/carbon/human/consistent)
+ mock_client.mob = labrat
+ var/turf/one_over = locate(run_loc_floor_bottom_left.x + 1, run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z)
+ var/obj/item/storage/toolbox/box = allocate(/obj/item/storage/toolbox, one_over)
+
+ panel.open(one_over)
+ TEST_ASSERT_EQUAL(length(panel.contents), 2, "Contents should populate on open")
+ TEST_ASSERT_EQUAL(length(panel.to_image), 2, "to_image should've populated (unit testing)")
+ TEST_ASSERT_EQUAL(panel.contents[1].item, one_over, "First item should be the source turf")
+
+ var/datum/search_object/searchable = panel.contents[2]
+ TEST_ASSERT_EQUAL(searchable.item, box, "Second item should be the box")
+
+ qdel(box)
+ TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents should update on searchobj deleted")
+ TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image should update on searchobj deleted")
+
+ var/obj/item/storage/toolbox/new_box = allocate(/obj/item/storage/toolbox, one_over)
+ TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents shouldn't update, we're dumb")
+ TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image shouldn't update, we're dumb")
+
+ panel.populate_contents() // this also calls reset_contents bc length(contents)
+ TEST_ASSERT_EQUAL(length(panel.contents), 2, "Contents should repopulate with the new toolbox")
+
+ panel.populate_contents()
+ TEST_ASSERT_EQUAL(length(panel.contents), 2, "Panel shouldnt dupe searchables if reopened")
+
+ mock_client.mob = null
diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png
index 262353dc0a9..83afcbc2a48 100644
Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png differ
diff --git a/code/modules/unit_tests/storage.dm b/code/modules/unit_tests/storage.dm
new file mode 100644
index 00000000000..82ac035ed7e
--- /dev/null
+++ b/code/modules/unit_tests/storage.dm
@@ -0,0 +1,22 @@
+/// Test storage datums
+/datum/unit_test/storage
+
+/datum/unit_test/storage/Run()
+ var/obj/item/big_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+ big_thing.w_class = WEIGHT_CLASS_BULKY
+ var/obj/item/small_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+ small_thing.w_class = WEIGHT_CLASS_SMALL
+
+ var/obj/item/storage/backpack/storage_item = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left)
+
+ storage_item.atom_storage.attempt_insert(big_thing)
+ TEST_ASSERT_NOTEQUAL(big_thing.loc, storage_item, "A bulky item should have failed to insert into a backpack")
+
+ storage_item.atom_storage.attempt_insert(small_thing)
+ TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item should have successfully inserted into a backpack")
+
+ small_thing.update_weight_class(WEIGHT_CLASS_NORMAL)
+ TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item changed into normal size should not have ejected from the backpack")
+
+ small_thing.update_weight_class(WEIGHT_CLASS_BULKY)
+ TEST_ASSERT_NOTEQUAL(small_thing.loc, storage_item, "A small item changed back into bulky size should have ejected from the backpack")
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 7cee1b6541c..995764e0bb7 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -272,7 +272,7 @@
/// If the former occupants get polymorphed, mutated, chestburstered,
/// or otherwise replaced by another mob, that mob is no longer in .occupants
/// and gets deleted with the mech. However, they do remain in .contents
- var/list/potential_occupants = contents ^ occupants
+ var/list/potential_occupants = contents | occupants
for(var/mob/buggy_ejectee in potential_occupants)
mob_exit(buggy_ejectee, silent = TRUE)
diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm
index 54acd183aff..2dce26624ad 100644
--- a/code/modules/vehicles/mecha/mech_fabricator.dm
+++ b/code/modules/vehicles/mecha/mech_fabricator.dm
@@ -55,7 +55,7 @@
RefreshParts() //Recalculating local material sizes if the fab isn't linked
return ..()
-/obj/machinery/mecha_part_fabricator/LateInitialize()
+/obj/machinery/mecha_part_fabricator/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
@@ -127,14 +127,12 @@
if(panel_open)
. += span_notice("Alt-click to rotate the output direction.")
-/obj/machinery/mecha_part_fabricator/AltClick(mob/user)
- . = ..()
- if(!user.can_perform_action(src))
- return
- if(panel_open)
- dir = turn(dir, -90)
- balloon_alert(user, "rotated to [dir2text(dir)].")
- return TRUE
+/obj/machinery/mecha_part_fabricator/click_alt(mob/user)
+ if(!panel_open)
+ return CLICK_ACTION_BLOCKING
+ dir = turn(dir, -90)
+ balloon_alert(user, "rotated to [dir2text(dir)].")
+ return CLICK_ACTION_SUCCESS
/**
* Updates the `final_sets` and `buildable_parts` for the current mecha fabricator.
diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm
index 2b410bd60c7..d544c829667 100644
--- a/code/modules/vehicles/mecha/mecha_actions.dm
+++ b/code/modules/vehicles/mecha/mecha_actions.dm
@@ -91,14 +91,15 @@
chassis.toggle_strafe()
-/obj/vehicle/sealed/mecha/AltClick(mob/living/user)
- if(!(user in occupants) || !user.can_perform_action(src))
- return
+/obj/vehicle/sealed/mecha/click_alt(mob/living/user)
+ if(!(user in occupants))
+ return CLICK_ACTION_BLOCKING
if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE)))
to_chat(user, span_warning("You're in the wrong seat to control movement."))
- return
+ return CLICK_ACTION_BLOCKING
toggle_strafe()
+ return CLICK_ACTION_SUCCESS
/obj/vehicle/sealed/mecha/proc/toggle_strafe()
if(!(mecha_flags & CAN_STRAFE))
diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm
index 33f81184e9a..52c7924d72f 100644
--- a/code/modules/vehicles/ridden.dm
+++ b/code/modules/vehicles/ridden.dm
@@ -5,6 +5,7 @@
buckle_lying = 0
pass_flags_self = PASSTABLE
COOLDOWN_DECLARE(message_cooldown)
+ interaction_flags_click = NEED_DEXTERITY
/obj/vehicle/ridden/examine(mob/user)
. = ..()
@@ -39,16 +40,17 @@
inserted_key.forceMove(drop_location())
inserted_key = I
-/obj/vehicle/ridden/AltClick(mob/user)
- if(!inserted_key || !user.can_perform_action(src, NEED_DEXTERITY))
- return ..()
+/obj/vehicle/ridden/click_alt(mob/user)
+ if(!inserted_key)
+ return CLICK_ACTION_BLOCKING
if(!is_occupant(user))
to_chat(user, span_warning("You must be riding the [src] to remove [src]'s key!"))
- return
+ return CLICK_ACTION_BLOCKING
to_chat(user, span_notice("You remove \the [inserted_key] from \the [src]."))
inserted_key.forceMove(drop_location())
user.put_in_hands(inserted_key)
inserted_key = null
+ return CLICK_ACTION_SUCCESS
/obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
if(!in_range(user, src) || !in_range(M, src))
diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm
index e7b3d9b3a56..92fcb995f76 100644
--- a/code/modules/vehicles/wheelchair.dm
+++ b/code/modules/vehicles/wheelchair.dm
@@ -63,8 +63,6 @@
qdel(src)
return ITEM_INTERACT_SUCCESS
-/obj/vehicle/ridden/wheelchair/AltClick(mob/user)
- return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
/obj/vehicle/ridden/wheelchair/update_overlays()
. = ..()
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index 42f6ff2a436..29641441e67 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -1157,8 +1157,6 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
/obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer)
if(!istype(replacer))
return FALSE
- if(!replacer.works_from_distance)
- return FALSE
if(!component_parts || !refill_canister)
return FALSE
diff --git a/code/modules/vending/runic_vendor.dm b/code/modules/vending/runic_vendor.dm
index 3edb5b27264..f338340c8b1 100644
--- a/code/modules/vending/runic_vendor.dm
+++ b/code/modules/vending/runic_vendor.dm
@@ -9,6 +9,7 @@
vend_reply = "Please, stand still near the vending machine for your special package!"
resistance_flags = FIRE_PROOF
light_mask = "RunicVendor-light-mask"
+ obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION
/// How long the vendor stays up before it decays.
var/time_to_decay = 30 SECONDS
/// Area around the vendor that will pushback nearby mobs.
@@ -60,15 +61,16 @@
return .
+/obj/machinery/vending/runic_vendor/handle_deconstruct(disassembled)
+ SHOULD_NOT_OVERRIDE(TRUE)
-/obj/machinery/vending/runic_vendor/Destroy()
visible_message(span_warning("[src] flickers and disappears!"))
playsound(src,'sound/weapons/resonator_blast.ogg',25,TRUE)
return ..()
/obj/machinery/vending/runic_vendor/proc/runic_explosion()
explosion(src, light_impact_range = 2)
- qdel(src)
+ deconstruct(FALSE)
/obj/machinery/vending/runic_vendor/proc/runic_pulse()
var/pulse_locs = spiral_range_turfs(pulse_distance, get_turf(src))
@@ -82,10 +84,9 @@
mob_to_be_pulsed_back.throw_at(target, 4, 4)
/obj/machinery/vending/runic_vendor/screwdriver_act(mob/living/user, obj/item/I)
- explosion(src, light_impact_range = 2)
- qdel(src)
+ runic_explosion()
/obj/machinery/vending/runic_vendor/proc/decay()
- qdel(src)
+ deconstruct(FALSE)
#undef PULSE_DISTANCE_RANGE
diff --git a/code/modules/wiremod/components/action/equpiment_action.dm b/code/modules/wiremod/components/action/equpiment_action.dm
index 54150ca44d6..641722c595b 100644
--- a/code/modules/wiremod/components/action/equpiment_action.dm
+++ b/code/modules/wiremod/components/action/equpiment_action.dm
@@ -89,4 +89,4 @@
for(var/ref in granted_to)
var/datum/action/granted_action = granted_to[ref]
granted_action.name = button_name.value || "Action"
- granted_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.value), " ", "_")]"
+ granted_action.button_icon_state = "bci_[replacetextEx(LOWER_TEXT(icon_options.value), " ", "_")]"
diff --git a/code/modules/wiremod/components/string/textcase.dm b/code/modules/wiremod/components/string/textcase.dm
index ac289654236..70b67740b41 100644
--- a/code/modules/wiremod/components/string/textcase.dm
+++ b/code/modules/wiremod/components/string/textcase.dm
@@ -41,7 +41,7 @@
var/result
switch(textcase_options.value)
if(COMP_TEXT_LOWER)
- result = lowertext(value)
+ result = LOWER_TEXT(value)
if(COMP_TEXT_UPPER)
result = uppertext(value)
diff --git a/code/modules/wiremod/core/admin_panel.dm b/code/modules/wiremod/core/admin_panel.dm
index 74e72ad5efe..9a262cb5e4c 100644
--- a/code/modules/wiremod/core/admin_panel.dm
+++ b/code/modules/wiremod/core/admin_panel.dm
@@ -1,10 +1,7 @@
-/// An admin verb to view all circuits, plus useful information
-/datum/admins/proc/view_all_circuits()
- set category = "Admin.Game"
- set name = "View All Circuits"
+ADMIN_VERB(view_all_circuits, R_ADMIN, "View All Circuits", "List all circuits in the game.", ADMIN_CATEGORY_GAME)
var/static/datum/circuit_admin_panel/circuit_admin_panel = new
- circuit_admin_panel.ui_interact(usr)
+ circuit_admin_panel.ui_interact(user.mob)
/datum/circuit_admin_panel
@@ -66,9 +63,10 @@
usr.client?.debug_variables(circuit)
if ("open_circuit")
circuit.ui_interact(usr)
+
if ("open_player_panel")
var/datum/mind/inserter = circuit.inserter_mind?.resolve()
- usr.client?.holder?.show_player_panel(inserter?.current)
+ SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, inserter?.current)
return TRUE
diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm
index 530f73ded8c..4d8344e1e6a 100644
--- a/code/modules/wiremod/core/component.dm
+++ b/code/modules/wiremod/core/component.dm
@@ -77,7 +77,7 @@
/obj/item/circuit_component/Initialize(mapload)
. = ..()
if(name == COMPONENT_DEFAULT_NAME)
- name = "[lowertext(display_name)] [COMPONENT_DEFAULT_NAME]"
+ name = "[LOWER_TEXT(display_name)] [COMPONENT_DEFAULT_NAME]"
populate_options()
populate_ports()
if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !trigger_input)
diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm
index 7c691e3a4c4..370a6cfea52 100644
--- a/code/modules/wiremod/core/component_printer.dm
+++ b/code/modules/wiremod/core/component_printer.dm
@@ -24,7 +24,7 @@
. = ..()
materials = AddComponent(/datum/component/remote_materials, mapload)
-/obj/machinery/component_printer/LateInitialize()
+/obj/machinery/component_printer/post_machine_initialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !techweb)
CONNECT_TO_RND_SERVER_ROUNDSTART(techweb, src)
diff --git a/code/modules/wiremod/core/duplicator.dm b/code/modules/wiremod/core/duplicator.dm
index 2f248d11a89..25e83326804 100644
--- a/code/modules/wiremod/core/duplicator.dm
+++ b/code/modules/wiremod/core/duplicator.dm
@@ -220,30 +220,24 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
rel_x = component_data["rel_x"]
rel_y = component_data["rel_y"]
-/client/proc/load_circuit()
- set name = "Load Circuit"
- set category = "Admin.Fun"
-
- if(!check_rights(R_VAREDIT))
- return
-
+ADMIN_VERB(load_circuit, R_VAREDIT, "Load Circuit", "Loads a circuit from a file or direct input.", ADMIN_CATEGORY_FUN)
var/list/errors = list()
- var/option = alert(usr, "Load by file or direct input?", "Load by file or string", "File", "Direct Input")
+ var/option = alert(user, "Load by file or direct input?", "Load by file or string", "File", "Direct Input")
var/txt
switch(option)
if("File")
- txt = file2text(input(usr, "Input File") as null|file)
+ txt = file2text(input(user, "Input File") as null|file)
if("Direct Input")
- txt = input(usr, "Input JSON", "Input JSON") as text|null
+ txt = input(user, "Input JSON", "Input JSON") as text|null
if(!txt)
return
- var/obj/item/integrated_circuit/loaded/circuit = new(mob.drop_location())
+ var/obj/item/integrated_circuit/loaded/circuit = new(user.mob.drop_location())
circuit.load_circuit_data(txt, errors)
if(length(errors))
- to_chat(src, span_warning("The following errors were found whilst compiling the circuit data:"))
+ to_chat(user, span_warning("The following errors were found whilst compiling the circuit data:"))
for(var/error in errors)
- to_chat(src, span_warning(error))
+ to_chat(user, span_warning(error))
diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm
index ad03867b89b..b46dad3673f 100644
--- a/code/modules/wiremod/shell/controller.dm
+++ b/code/modules/wiremod/shell/controller.dm
@@ -71,9 +71,9 @@
*/
/obj/item/circuit_component/controller/proc/send_alternate_signal(atom/source, mob/user)
SIGNAL_HANDLER
- if(!user.Adjacent(source))
- return
+
handle_trigger(source, user, "alternate", alt)
+ return CLICK_ACTION_SUCCESS
/**
diff --git a/code/modules/wiremod/shell/module.dm b/code/modules/wiremod/shell/module.dm
index 6f9a3dda93b..9061bac3e30 100644
--- a/code/modules/wiremod/shell/module.dm
+++ b/code/modules/wiremod/shell/module.dm
@@ -106,7 +106,7 @@
action_comp.granted_to[REF(user)] = src
circuit_component = action_comp
name = action_comp.button_name.value
- button_icon_state = "bci_[replacetextEx(lowertext(action_comp.icon_options.value), " ", "_")]"
+ button_icon_state = "bci_[replacetextEx(LOWER_TEXT(action_comp.icon_options.value), " ", "_")]"
/datum/action/item_action/mod/pinnable/circuit/Destroy()
circuit_component.granted_to -= REF(pinner)
diff --git a/html/changelogs/AutoChangeLog-pr-1367.yml b/html/changelogs/AutoChangeLog-pr-1367.yml
deleted file mode 100644
index 7cd89d745b8..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1367.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "kaylexis"
-delete-after: True
-changes:
- - rscadd: "Adds Plant Gene disk to biogen"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1383.yml b/html/changelogs/AutoChangeLog-pr-1383.yml
deleted file mode 100644
index 15d8e67d88e..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1383.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Swiftfeather"
-delete-after: True
-changes:
- - rscadd: "Blind crew are no longer barred from being heads of staff (except HoS)."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1396.yml b/html/changelogs/AutoChangeLog-pr-1396.yml
deleted file mode 100644
index cecb32dea0b..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1396.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "PhazeJump"
-delete-after: True
-changes:
- - rscadd: "wings: Moth (Bluespace)"
- - rscadd: "wings: Moth (Strawberry)"
- - rscadd: "wings: Moth (Clockwork)"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1402.yml b/html/changelogs/AutoChangeLog-pr-1402.yml
deleted file mode 100644
index 12e59dfc31a..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1402.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Swiftfeather"
-delete-after: True
-changes:
- - balance: "Makes bluespace crystal teleportation take time."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1403.yml b/html/changelogs/AutoChangeLog-pr-1403.yml
deleted file mode 100644
index 27deb45b99e..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1403.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "VrazzleDazzle"
-delete-after: True
-changes:
- - image: "Added a new UI theme, Blue-98!"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1408.yml b/html/changelogs/AutoChangeLog-pr-1408.yml
deleted file mode 100644
index 4ed53bced4b..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1408.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-author: "tmyqlfpir"
-delete-after: True
-changes:
- - qol: "Various tweaks to Dauntless service and medical"
- - rscadd: "Add new camera kill switches to the Dauntless"
- - rscadd: "Add (non-spawned) space version of Dauntless"
- - rscadd: "Add new storage room to Dauntless"
- - balance: "Dauntless cyborgs will have their cameras automatically removed"
- - balance: "Interdyne Powerator has 2x efficiency"
- - rscadd: "Created Interdyne injectors to assign non-spawned crew as Syndicate faction"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1413.yml b/html/changelogs/AutoChangeLog-pr-1413.yml
deleted file mode 100644
index 8f3c1420951..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1413.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "BurgerBB"
-delete-after: True
-changes:
- - rscadd: "Moonstation Upstream Merge and Bonuses"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1418.yml b/html/changelogs/AutoChangeLog-pr-1418.yml
deleted file mode 100644
index b867cb07070..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1418.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "StrangeWeirdKitten"
-delete-after: True
-changes:
- - balance: "Abductor sleep is 30 seconds instead of 2 minutes"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1421.yml b/html/changelogs/AutoChangeLog-pr-1421.yml
deleted file mode 100644
index b7709e1c40c..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1421.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Iamgoofball"
-delete-after: True
-changes:
- - balance: "Takes the ashwalker translation necklace out of the loadout; ashwalker translation is supposed to be rare/craftable with resource/Curator, not a roundstart thing any crewmember can have."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1423.yml b/html/changelogs/AutoChangeLog-pr-1423.yml
deleted file mode 100644
index 94d661edb5a..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1423.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Majkl-J"
-delete-after: True
-changes:
- - bugfix: "Fixes horrendous ui design"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1427.yml b/html/changelogs/AutoChangeLog-pr-1427.yml
deleted file mode 100644
index 2d6007e48ca..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1427.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "VrazzleDazzle"
-delete-after: True
-changes:
- - rscdel: "The PKA variants have been temporarily pruned due to a licensing issue with Kahraman Industries."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1428.yml b/html/changelogs/AutoChangeLog-pr-1428.yml
deleted file mode 100644
index 1700687f86a..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1428.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "BurgerBB"
-delete-after: True
-changes:
- - bugfix: "Fixes assistants always spawning at the Interlink roundstart."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1432.yml b/html/changelogs/AutoChangeLog-pr-1432.yml
deleted file mode 100644
index a45a60ee4d8..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1432.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Swiftfeather"
-delete-after: True
-changes:
- - code_imp: "The way mobs idle has been refactored, please report any issues with non-reactive mobs"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1434.yml b/html/changelogs/AutoChangeLog-pr-1434.yml
deleted file mode 100644
index 404e9d76fa8..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1434.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "BurgerBB"
-delete-after: True
-changes:
- - rscadd: "Improves Moonstation Disposals + Fixes missing wires for Medical Storage and NTRep office."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1435.yml b/html/changelogs/AutoChangeLog-pr-1435.yml
deleted file mode 100644
index 54851828cd7..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1435.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "IgiariValkyr"
-delete-after: True
-changes:
- - rscadd: "Latex Heels to loadout"
- - qol: "Filing cabinets in the Interlink office are now actually stacked together"
- - bugfix: "PLAP capsule now has the colors actually described in the description"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1436.yml b/html/changelogs/AutoChangeLog-pr-1436.yml
deleted file mode 100644
index 2f1e0314163..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1436.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "pixelkitty286"
-delete-after: True
-changes:
- - rscadd: "The PKA variants."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-1439.yml b/html/changelogs/AutoChangeLog-pr-1439.yml
deleted file mode 100644
index 2280eb2ed32..00000000000
--- a/html/changelogs/AutoChangeLog-pr-1439.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "destrucktoid"
-delete-after: True
-changes:
- - balance: "Bloodsuckers can no longer kill or hurt people by drinking from them without at least a passive grab."
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-04.yml b/html/changelogs/archive/2024-04.yml
index f6e6ba8c939..f37015b57d3 100644
--- a/html/changelogs/archive/2024-04.yml
+++ b/html/changelogs/archive/2024-04.yml
@@ -397,167 +397,7 @@
- rscadd: added the research skill
- balance: experisci scanner affected by research skill
- balance: xenoarch affected by research skill
-2024-04-20:
- '@Crumpaloo, @Majkl-J':
- - image: New foxtrot peacekeeper borg model, sprites by Crumpaloo
- - code_imp: Moved around cyborg dmi defines to give the precompiler a break
- - config: Development config now has both sec and peace cyborg modules enabled
- Arturlang:
- - rscadd: Adds backup ways for the book of kindred to spawn, either spawning on
- a curator or on the codex gigas
- - rscadd: Decapacitated bloodsuckers can now talk!
- - rscadd: The stat bar will show you the threshold for exiting frenzy now too when
- you are frenzying.
- - rscadd: Bloodsucker abilities now will show their level when you hover over them.
- Trust me, this was really neccessary.
- - rscadd: Tremere now also get informed of how much blood they need to pay for level
- ups.
- - rscadd: At level 3, haste will now remove stuns and do a non-stunning dash
- - rscadd: Bloodsucker blood display now always updates when a bloodsucker's blood
- level is changed
- - rscadd: Bloodsuckers can now examine hearts to see if they are valid for the heart
- thief objective
- - rscadd: Bloodsucker vassals now clean up any traits gained from their tenure as
- a vampire's minion.
- - rscadd: Favorite vassals now properly clean up their effects once the antag datum
- is lost.
- - rscadd: Bloodsucker synths will be able to heal their prosthetic limbs, but normal
- bloodsuckers still cannot.
- - rscadd: When you exiit torpor as a bloodsucker, you will completely heal any toxin
- and oxygen damage, as you should already be immune to it. This is a safety feature.
- - rscadd: Entering a coffin will normalize your temperature and extinguish you if
- you're on fire, if you are a bloodsucker.
- - bugfix: bloodsucker vampire bats will no longer /list you when attacking
- - bugfix: Hopefully fixes some torpor loops related to frenzy
- - bugfix: Hopefully fixes bloodsuckers cryoing not removing vassal datums
- - bugfix: Bloodsuckers can no longer use veil of many faces while unconcious
- - bugfix: lizard bloodsuckers will no longer suffer from heat for a long time
- - bugfix: The ventrue objective now properly succeeds if you have sired a vampire
- - bugfix: Livers are no longer required for bloodsuckers to live, as it caused them
- toxin damage which overrode the trait that made them immune to toxins.
- - bugfix: Entering torpor now accounts for all damage types, even when you should
- be immune to them. This is to ensure you enter torpor to heal those damage types
- in the case of odd behaviour.
- - balance: coffins should now set your temperature to normal and extinguish you.
- - balance: bloodsucker level up cost is now 15% of max blood, down from 20%
- - balance: Caps humantiy loss at 50 humanity/500 blood to frenzy, and makes it remove
- your masquerade ability.
- - balance: Bloodsucker bats now have human runspeed
- - balance: Blood cost for vassalizing was almost completely removed, now only taking
- tiny amounts of blood to do so.
- - balance: Fortitude now gives you burn resistance, just 20% less than brute resistance
- - balance: Can no longer gut bloodsuckers
- - balance: Bloodsuckers loosing their heart will make the vampire unable to use
- their abilities or even regenerateor revive via torpor, you can however regain
- your heart if you sleep in a coffin with a heart.
- - balance: Stakes now have different properties, the normal stake is fast to stick
- in someone, but can fall out on it's own, the burnt one takes longer to be put
- in, but doesn't fall out, the silver stake is the slowest to be stuffed in someone's
- heart, and is the only stake to be able to cause a Final Death to a sleeping
- or dead bloodsucker
- - rscdel: Dullahans can't be bloodsuckers since... their head isn't attached
- - admin: Bloodsuckers and vassals can now be banned like other antags.
- - bugfix: Borers no longer get wasted by ash storms while inside a host
- - rscadd: Adds the hemophage-only quirk, Sol weakness
- - code_imp: Refactors the sol subsystem so that itself decides if it should run
- or not based on if anyone is using it.
- - code_imp: Refactors bloodsucker UI elements so that they can function fine outside
- a bloodsucker antag datum
- - code_imp: bloodsucker_blood_volume, humanity_lost, bloodsucker_level and bloodsucker_level_unspent
- are now private variables due to them being used for UI updates, if you need
- to change them, use the procs that are written in the autodoc
- - code_imp: Quirk species whitelists no longer use bitflags, but use the species
- ID's. Easily allowing you to add new whitelists without having to mess around
- with making a new bitfield
- - bugfix: Ventrue sired bloodsuckers will no longer have a copy of their abilities
- - rscadd: Bloodsuckers that start out with no heart will be able to regain one,
- but it now properly checks if they have one or not, and disables their abiltiies
- accordingly, go into a coffin with a heart if you want to gain one.
- - rscadd: Lunge can now take out any organ out of a dead corpse, based on where
- you are aiming in the targeting doll, it will still prioritize a heart if aimed
- at chest
- - bugfix: bloodsucker sol quirk removal is now silent
- - bugfix: You can no longer unwrench lair coffins
- - bugfix: gohome will no longer render you stuck in a coffin if it cannot close
- - bugfix: Malkavians should now spout nonsense less often if you've not lost humantiy
- yet
- - bugfix: 'Lunge can now actually stun people if you lunge at them from behind.
-
- fix; You can no longer spam drink from blood bags.'
- - code_imp: clan_life now has seconds_per_tick and times_fired
- - bugfix: Book of kindred display cases should now spawn properly on TG maps.
- - bugfix: Duplicate books of kindred won't spawn on new curators
- Azarak:
- - admin: administrators can now toggle job playtime exemption by job basis for players
- Boviro:
- - rscadd: Added butler as assistant title
- BurgerB:
- - bugfix: Fixes Moonstation Ministation not counting blob tiles.
- BurgerBB:
- - balance: The RBMK can now handle more power generation before going into meltdown
- with upgraded parts, and also generates less power with upgraded parts.
- - bugfix: Fixes the RBMK having an infinite meltdown state when safeties trigger
- at the same time as a meltdown.
- - balance: After 3 Lichdom resurrections, announcements will be made about your
- general phylactery location (the area) when you die. Phylactery binding now
- requires the object to be at least bulky in size, and it cannot be fireproof,
- lava proof, or indestructible.
- - rscadd: Adds REAL banhammers send people to the void temporarily (similar to immortality
- talisman or void genetic power) on hit. Hitting someone on combat mode with
- it sends them to permabrig instead, if they're not already in the permabrig.
- - rscdel: Replaces the High Frequency Blade the wizard gets with a REAL banhammer,
- and reduces the spell cost from 3 to 2.
- - rscadd: Makes Moon Station actually a moon now because people made fun of me.
- - bugfix: Hopefully fixes the error handler throwing errors too early.
- - bugfix: Fixes early runtime issue with loadouts.
- - bugfix: Fixes fake lattice linters when they spawn on lava
- - bugfix: Sandstorms on Moon Station are less annoying in terms of notifications
- and sound. Adds missing miner GPSs to lockers + table. Fixes typo in Moon Station
- plaque. External airlocks to public areas no longer have access.
- - rscdel: Removes some over the top abductor victim objectives and adds some new
- ones.
- - bugfix: Remaps Moon Station's robotics. Fixes some misplaced objects.
- - rscdel: Removes Ash Storms from Moon Station Lavaland
- - rscdel: Disables Lance Shuttle on Moon Station because it caused the crew to get
- stuck on station for 5 hours once.
- - rscdel: Replaces the Meteor Shuttle with THE CUBE. It's an emag only emergency
- shuttle that is literally just a 16x16 cube with some engines on it.
- - balance: Adds Sex holographic barriers to warn people that there is sex in the
- next room. It doesn't block air or movement, but it does warn people, and knowing
- is half the battle. They can be purchased in the LustWish under the premium
- section.
- - bugfix: Fixes planetary atmos getting created when turfs inside the station are
- destroyed.
- - bugfix: Fixes some Moon Station bugs, such as the funny engineering bridge access
- bug and a lack of cigarette/coffee vendors.
- - bugfix: Fixes Moonstation radstorms affecting some places it's not supposed to.
- - rscdel: Limits Powersinks + Crab-17 purchases to once each per traitor per round.
- - rscadd: Adds Ashwalkers to Moonstation
- - bugfix: Fixes traitor announcer double-sanitizing.
- - rscdel: Removes Xeno Organs from Roundstart Xenomorph Hybrids. They no longer
- have plasma vessels, resin spinners, or hive nodes.
- - bugfix: Fixes missing telecomms wire in Moonstation
- - bugfix: Fixes an atmos oversight with the Voxbox on Moonstation that can lead
- to superheated distro.
- - rscadd: Assigns a bunch of code levels for ERT that didn't have it or I thought
- should have a different one. The changes itself can be seen in the file.
- - bugfix: The default code for any ERT is now "Green" so it will no longer show
- a missing word when calling ERT.
- - bugfix: Fixes various Moon Station issues.
- - qol: Allows Ashwalkers to Breathe on Station
- - bugfix: Fixes a few moonstation bugs.
- - bugfix: Atmos optimization.
- - bugfix: Oh Hi Daniel shuttle no longer throws.
- - balance: Reworks the Gifted quirk and just gives everyone 6 free quirk points.
- - bugfix: Fixes Moonstation Xenobiology Shield Walls
- - rscdel: Disables Station Blackout and Random Machine Languages Station Traits
- - rscadd: Adds Moonstation public mining.
- - bugfix: Fixes various Moonstation bugs.
- - balance: Xenos can only devour mobs that have a ventcrawler trait (Monkeys, most
- Simplemobs), assuming all other checks have passed.
- - balance: Heads can only be dismembered if they have a critical-tier (Compound)
- fracture. If a head was supposed to be dismembered from a blow, a compound fracture
- will be applied.
+2024-04-21:
CliffracerX:
- rscadd: you can mount Mk. II Hyposprays onto the underside of Hypospray Kits &
quickdraw them
@@ -572,212 +412,139 @@
- admin: icspawning supports quirks & loadout items now
- admin: bluespace technician RPED has been significantly upgraded
- bugfix: hotfix for loadout wallets not filling properly
- Erol509:
- - rscadd: RB-MK2 now has its own tgui panel.
- - rscadd: Added the icewalker areas to the radstorm protected areas.
- - bugfix: Bloodsucker braincheck was missing a null check causing runetimes, its
- been fixed.
- - rscadd: Added back TEG to techwebs and engineering protolathe
- - image: Changed TEG sprites from YogStation. Credits to original author.
- EspeciallyStrange:
- - bugfix: IDMA donor clothing being improperly offsetted and not correctly
- Iamgoofball:
- - rscadd: Re-enables the Galactic Materials Market as it's been fixed upstream.
- IgiariValkyr:
- - config: Relocked some donator items from Skyrat on request
- - config: Relocks another skyrat donor item per request.
- - rscadd: New Traitor Item (10TC) - Portable Listening Advanced Post
- Jinshee:
- - rscadd: Added rattlesnake tail
- Kegdo:
- - rscadd: 'more markings: Chestplate, hip, elbow, shoulder, glove, sleeve, sock,
- longsock, vertical stripe, fangs, lips, facemask, facedisc.'
- LT3:
- - balance: Rebalanced alcohol intoxication effects. A unit of alcohol will now produce
- the same intoxication regardless if you chug it all at once or sip it over a
- few minutes
- - qol: Airlocks don't flash constantly on engineering override, override/overlay
- added for fire alarm
- - bugfix: Airlock lighting should no longer render on top of player characters
- - bugfix: Airlock emissives no longer overlap firedoors
- - bugfix: Fixed missing overlays on various airlock types
- - bugfix: Fixed status display for epsilon alert
- - bugfix: Fixed fire alarm for epsilon alert
- - bugfix: Fixed ineligible airlocks from receiving engineering override when activated
- from the communications console
- - bugfix: Various airlock/firelock overlay fixes
- - code_imp: Parts of firelock code updated to parity with TG
- - image: Added Moonstation specific tram sprites
- - bugfix: Fixed Moonstation references to Tramstation's tram
- - qol: Catbox and Imgbox are now supported hosting services for headshots
- - qol: 'New moodlet: Status if you''re still processing alcohol you''ve drank previously
- (and getting more drunk)'
- - qol: 'New moodlet: Current drunk level'
- - bugfix: Light drinker quirk should no longer floor you near instantly
+2024-04-24:
Majkl-J:
- - rscadd: Ghosts without clients get sent back into the menu after a while.
- - bugfix: NSFW Headshots no longer override regular ones
- - bugfix: 'lathes now use moderate power for printing operations /:cl:'
- - code_imp: Bubber modular greyscale files permitted
- - bugfix: you can now rightclick to flag in minesweeper
- - bugfix: Void raptor now has the secmed locker
- - rscadd: Zombie can now have hair
- - bugfix: Secmeds no longer limit a few items to themselves only
- - bugfix: Dauntless frames are no longer broken
- - bugfix: False walls appear again
- - balance: Bodyless ghosts and ghostroles can no longer transfervote
- - refactor: Added support for vote mob conditions
- - balance: Reagent weapons now get damaged upon reagent transfer
- - balance: Imbuing once again needs actual skill
- - bugfix: Minesweeper now properly gives moodlets
- - bugfix: teshvali no longer have you wear human sprites
- - image: New rockfruit sprites
- - code_imp: Modularized hydroponics
- Makeshift-coder:
- - rscadd: adds an unpacked colony fabricator
- - rscadd: replaces the four bluespace beakers on a table with a bluespace beaker
- box for ease of access
- - rscdel: Removed a single sink to put the unpacked fabricator on it
- Odairu:
- - config: changes law 2 wording
- PhazeJump:
- - rscadd: Added Harpy (large) wings
- ReturnToZender:
- - balance: NTR's ACCESS_CREMATORIUM replaced with ACCESS_SERVICE
- - rscadd: Assistants on-station may be pleased to hear that they can now wear Head
- of Staff pet collars again. ...Again.
- - rscadd: Nanotrasen has deemed it fit to order an upgrade to all Consultant offices
- on stations in the Spinward Sector. Check them out!
- - rscdel: Donors' graceful trenchcoat
- - rscadd: NTC offices have had their carpet changed out to something less over-the-top.
- The windows have been expanded as well.
- ReturnToZender (Writing), LT3, Waterpig (Code assistance):
- - bugfix: If you have no custom species set, it will now show your default description.
- ReturnToZender (code):
- - bugfix: Character Directory sorting now works on all variables.
- - bugfix: autopunctuation respects prefs again
- - qol: Advert settings have been moved to a new category, ADVERT.
- - rscadd: Character directory now has a search function on the name var.
- - rscadd: Character directory now shows on the Main Menu under the Crew Manifest.
- - rscadd: Character directory now has a randomizer, which will open a random player's
- flavor text when clicked. Click if you dare.
- - rscadd: F-list headshots are now accepted
- - rscadd: Kiboko 25mm to Armory tab
- - rscadd: Mini E-Gun to goodies and armory
- - balance: Reduces the cost of the d'Elite rifle as it is more of a side-grade now
- ReturnToZender (quirk code), TeshariEnjoer (original PR):
- - rscadd: New positive trait, featherweight. Allows you to be picked up instead
- of fireman's carried. This dipshit yours?
- Shayoki:
- - rscadd: Adds Boxstation
- - rscadd: Players can now choose a voice for their characters.
- - sound: Added a lot of 'borrowed' sounds to use as voices.
- - admin: Admins can globally disable Bloopers
- Spicelet:
- - rscadd: new dogborg shirt
- StrangeWeirdKitten:
- - rscdel: Removes the Dauntless cameras
- - rscdel: Removes the blast cannon from the traitor scientist uplink
- - rscdel: Removes Dauntless self destruct and dense rock surrounding the base
- - balance: Dauntless exterior turrets shoot fauna, not people
- - config: Removes Akula Lore protection (Allows edit to species)
- - bugfix: Humanoid and Hemophage sprites no longer have base skin tone issues. Added
- human greyscale sprites.
- - bugfix: Colossus will properly deaggro when you lose
- - balance: But colossus bolts will gut you as a consiquence
- - image: Removes the east and west sprite on the Lips bodymarking
- - rscadd: Sauna survival pods. Found in mining vendor and occasionally maintenance
- Swiftfeather:
- - admin: Will no longer receive supermatter ate a pipe spam in the log.
- - rscdel: Removed gun safeties.
- Sylphet:
- - rscadd: adds lunchboxes that hold food and drinks to the loadout
- - image: added lunchbox sprites
- - balance: scrubbers do not overflow with carpet and rainbow stuff anymore
- Tupina:
- - balance: Energy weapons can now fire roughly 1.3x more lasers per charge across
- the board.
- VrazzleDazzle:
- - rscadd: Scrying Lens Disks are now available in the loadout.
- - qol: The ashwalkers' ashen necklaces are now fireproof.
- - rscdel: Death bolts no longer dust you on death.
- - rscadd: Six new PKA variants, now in a mining vendor near you.
- - rscdel: Prybars are no longer available in the Rapid Construction Fabricator.
- Vynzill:
- - rscadd: Added more perfumes to loadout.
- YakumoChen:
- - balance: Xeno Hybrids take normal heat damage, again.
- Yanziko:
- - balance: pet owner is free
+ - bugfix: Basicmob xenos no longer die to lack of heating
+ SkyratBot:
+ - balance: The Bioscrambler will now actively attempt to get closer to living targets
+ rather than chilling in a closet nobody goes into (unless you trap it in a containment
+ field).
+ - balance: Because it can now travel through walls, the Bioscrambler will no longer
+ transform you THROUGH walls.
+ TreePizza:
+ - rscadd: Added a fax machine to the Tarkon bridge, as well as it's unique contact
+ for Tarkon TB (Top Brass).
+ - rscadd: The station can now fax the Tarkon bridge. The Ensign can now finally
+ do their job without having to leave their chair.
+ - rscadd: Added an Ectosniffer to the science lab so ghosts may now request a brain
+ to possess.
+ - rscadd: ~1 "hidden" Xenoplush for Monophobia characters.~ Goodnight sweet prince
+ you were too good for this world.
+ - rscadd: Added a light to the freezer and an additional one to the kitchen.
+ - bugfix: Added that awkwardly missing window to the top airlock and deleted the
+ equally awkward single disposal pipe that was underneath it.
+ - bugfix: 'Moved the glowing resin in the cargo_warehouse variation (the infested
+ one) so that it is no longer under the glass wall.
+
+ ### Charlie:'
+ - qol: 'Charlie pods now have pref and loadout spawning.
+
+ :cl:'
+2024-04-26:
+ Jacquerel and Melbert:
+ - rscadd: A new achievement for moving a boulder from one place to another, at great
+ effort.
+ - balance: Hauling a boulder around makes you move slower, as it does when dragging
+ it.
+ Majkl-J:
+ - bugfix: Medicells now correctly use power
+ - bugfix: MCRs now correctly use power
+ - bugfix: Infinite powercells now have infinite power that's useful and not 2500
+ Joules
+ - qol: slimes will stay active without needing any one to watch over
+ - code_imp: The way mobs idle has been refactored, please report any issues with
+ non-reactive mobs
+ Melbert:
+ - bugfix: Playing Cards memory now reads better
+ SkyratBot:
+ - bugfix: Fixes AI lag by re-adding idle mode to all AI that was lost with the simple
+ mob to basic mob conversion.
+ - bugfix: AI controllers with no clients around for 14 tiles will move into idle
+ mode and stop planning or acting.
+ - bugfix: AI controllers will now record how much time was spent on planning or
+ un-idling AI controllers.
+ - bugfix: The rebar crossbows now properly loosen their bowstring upon firing.
+ - balance: Longfall modules no logner stun you when they activate.
+ - balance: Falling from a height greater than one z-level while using the longfall
+ module will still stagger you.
+ - bugfix: The plasma flower modsuit core now actually contains a reasonable quantity
+ of power.
+2024-04-27:
aKromatopzia:
- - rscadd: Unamored versions of the syndicate utility uniforms & half-mask
- - bugfix: icecats and ashliz can spawn on the ghost cafe.
- - image: icon was wrongly offset for cybernetic digitigrade right legs
+ - rscadd: Chaplains can be "Clerics"
+2024-04-28:
+ BurgerBB:
+ - rscadd: Moonstation Upstream Merge and Bonuses
+ - bugfix: Fixes assistants always spawning at the Interlink roundstart.
+ - rscadd: Improves Moonstation Disposals + Fixes missing wires for Medical Storage
+ and NTRep office.
+ Iamgoofball:
+ - balance: Takes the ashwalker translation necklace out of the loadout; ashwalker
+ translation is supposed to be rare/craftable with resource/Curator, not a roundstart
+ thing any crewmember can have.
+ IgiariValkyr:
+ - rscadd: Latex Heels to loadout
+ - qol: Filing cabinets in the Interlink office are now actually stacked together
+ - bugfix: PLAP capsule now has the colors actually described in the description
+ Majkl-J:
+ - bugfix: Fixes horrendous ui design
+ - bugfix: Synth recharging in mechchargers is now fixed
+ - bugfix: Crank cell can now be cranked for 1MJ of energy instead of 100J. How a
+ human manages to pull that off shall not be discussed
+ Melbert:
+ - qol: Tuberculosis makes you cough more
+ - qol: Nicotine Addiciton makes you cough less
+ - qol: Medicine Addiction maybe makes you cough more, maybe makes you cough less
+ - rscadd: Being deafnened from a loud sound (flashbang, explosions) will now force
+ people not naturally deaf to shout
+ - rscadd: Ear damage multiplier now only applies to taking damage, not healing damage,
+ meaning Felinids (who take 2x the ear damage) will no longer heal ear damage
+ 2x faster.
+ - refactor: Ears have been refactored slightly, ear deafness should now update more
+ snappily
+ PhazeJump:
+ - rscadd: 'wings: Moth (Bluespace)'
+ - rscadd: 'wings: Moth (Strawberry)'
+ - rscadd: 'wings: Moth (Clockwork)'
+ Rhials:
+ - qol: Water tiles now extinguish fires on items and people.
+ SkyratBot:
+ - bugfix: basic bots no longer start with all access
+ - bugfix: being revived with a cyber-heart now properly restarts the cyber heart
+ - rscadd: miners can now purchase grapple guns
+ - bugfix: Fixes clipping in the ESC menu between buttons and long station names.
+ - bugfix: brimbeams no longer make a cog appear above the mob
+ - bugfix: cooling and anti-disruption RCD upgrades can now be printed in ancient
+ protolathes
+ - qol: There's a bit more user feedback when it comes to attempting to handcuff
+ someone.
+ StrangeWeirdKitten:
+ - balance: Abductor sleep is 30 seconds instead of 2 minutes
+ Swiftfeather:
+ - rscadd: Blind crew are no longer barred from being heads of staff (except HoS).
+ - balance: Makes bluespace crystal teleportation take time.
+ - code_imp: The way mobs idle has been refactored, please report any issues with
+ non-reactive mobs
+ VexingRaven:
+ - bugfix: The debug box no longer spills its contents everywhere
+ VrazzleDazzle:
+ - image: Added a new UI theme, Blue-98!
+ - rscdel: The PKA variants have been temporarily pruned due to a licensing issue
+ with Kahraman Industries.
destrucktoid:
- - bugfix: Syndicate/Ninja Borg Restorative Nanites now heal Slimepeople just as
- well as they do other people.
- - rscadd: Borers back in uplink
- - bugfix: Slimeperson Clockwork Cultists now heal toxins from the prosperity prism
- properly.
- - balance: Ventrue cannot benefit from bloodbags if their blood exceeds BLOOD_VOLUME_NORMAL
- - refactor: Changed reac_volume to use AddBloodVolume() for consistency reasons
- iskawhiskers:
- - image: added monster2_head, monster3_head, weight2_chest_m, weight2_chest_f
- nevimer:
- - balance: you now hug and pat lightgeists
- - admin: added public log folder, and logging.
- - balance: contractor and ninja modsuits have DNA locked microbombs
- nikothedude:
- - bugfix: Death degradation properly DNRs
- - bugfix: DNR icon has been restored
- - rscadd: Robos now have a pamphlet in their bag that tells them tips and tricks
- on how treat synth wounds
- - rscadd: Roboticists now spawn with synthetic medkits to make their jobs a bit
- easier
- - rscadd: New cargo packs for synthetic medkits
- - balance: Roboticists now spawn with diag huds, welding helmets, and black gloves
- - balance: Synthetic burn kits now have extra bottles
- - rscadd: You can now set your characters height
+ - balance: Bloodsuckers can no longer kill or hurt people by drinking from them
+ without at least a passive grab.
+ grungussuss:
+ - bugfix: fixed being able to install multiple of the same upgrade to medical cyborgs
+ kaylexis:
+ - rscadd: Adds Plant Gene disk to biogen
pixelkitty286:
- - rscadd: +Peacekeeper cat borg sprites, Spider clan cat borg sprites, Engineer
- cat borg refreshed sprites
- - bugfix: Cat cyborg panels not working
- - image: +Peacekeeper cat borg sprites, Spider clan cat borg sprites, Engineer cat
- borg refreshed sprites
- - code_imp: -Duplicate code
- - rscadd: Added night vision and cold resistance to tajara with their respective
- debuffs and gave them sensitive hearing. tajara own meat type and cat animal
- hide when gibed. Cat like grace to tajara.
- - rscadd: Added modular tajaran.dm, siikmaas.dm, and meatslab.dmi
- - qol: The Tajara DLC.
- - balance: rebalanced how the Tajaran species works.
- - image: added a Tajaran ass picture. Added adhomian_meat (Credit goes to Aurora.3
- on the sprite)
- - spellcheck: Corrected siik'tajr to be siik'maas.
- - code_imp: modular code for tajaran species changes.
- - refactor: Does refactoring Tajara as a species count?
- projectkepler-ru:
- - rscadd: Marketable IDMA Plushie, selectable as ironmoon tajaran plushie
- - rscadd: Contract from Colt has been secured with NT and now we can buy m1911
- - image: icon updated for the reshi revolver
- - balance: Colt reevaluated their contract, the M1911 is cheaper now
+ - rscadd: The PKA variants.
tmyqlfpir:
- - qol: Tweak layout of Dauntless kitchen, dorms and medbay
- - rscadd: Slapping glass tables have a 15% chance (cursed 30%) of breaking on 3rd
- slap
- - rscadd: Adds cargo ordering functionality for dauntless base
- - rscadd: Add bitden to dauntless brig area
- - rscadd: Add door lock to dauntless restroom, and various map tweaks
- - rscadd: Dauntless - Add exterior cameras to dauntless, removed many interior ones
- - bugfix: Dauntless - Removed incorrectly placed decals under hull objects and tweaked
- brig/dorms
- - balance: Interdyne powerator is now maxcapped to 1MW
- - rscadd: Dauntless - Added new bounty pad and bounty console
- - rscadd: Dauntless - Added new produce order console
- xXPawnStarrXx:
- - image: added GAGS versions of command stripper outfits.
- - code_imp: removed donator requirement from loadout flowers.
- - qol: made DeForest medipens refillable.
- - rscadd: Blood filtering now restores toxins.
- - bugfix: korve skinned advanced tools being invisible.
- - qol: made endurogrow boost lifespan.
+ - qol: Various tweaks to Dauntless service and medical
+ - rscadd: Add new camera kill switches to the Dauntless
+ - rscadd: Add (non-spawned) space version of Dauntless
+ - rscadd: Add new storage room to Dauntless
+ - balance: Dauntless cyborgs will have their cameras automatically removed
+ - balance: Interdyne Powerator has 2x efficiency
+ - rscadd: Created Interdyne injectors to assign non-spawned crew as Syndicate faction
diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi
index 12e3ce9f7d5..fd7bee8ed60 100644
Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ
diff --git a/icons/hud/radial.dmi b/icons/hud/radial.dmi
index 90813b4d7d2..e4a1693fb57 100644
Binary files a/icons/hud/radial.dmi and b/icons/hud/radial.dmi differ
diff --git a/icons/mob/clothing/head/hats.dmi b/icons/mob/clothing/head/hats.dmi
index bdf9980b9f2..8ed78b1c161 100644
Binary files a/icons/mob/clothing/head/hats.dmi and b/icons/mob/clothing/head/hats.dmi differ
diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi
index 49edcf8422f..317edb56796 100644
Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ
diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi
index be2ba8f3730..90be12b694a 100644
Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ
diff --git a/icons/mob/inhands/clothing/hats_lefthand.dmi b/icons/mob/inhands/clothing/hats_lefthand.dmi
index 191c85cf482..1d6461fb39d 100644
Binary files a/icons/mob/inhands/clothing/hats_lefthand.dmi and b/icons/mob/inhands/clothing/hats_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing/hats_righthand.dmi b/icons/mob/inhands/clothing/hats_righthand.dmi
index 8038e7474ee..4d9710bf901 100644
Binary files a/icons/mob/inhands/clothing/hats_righthand.dmi and b/icons/mob/inhands/clothing/hats_righthand.dmi differ
diff --git a/icons/mob/inhands/clothing/suits_lefthand.dmi b/icons/mob/inhands/clothing/suits_lefthand.dmi
index a43756d743a..02b1e2cbff2 100644
Binary files a/icons/mob/inhands/clothing/suits_lefthand.dmi and b/icons/mob/inhands/clothing/suits_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing/suits_righthand.dmi b/icons/mob/inhands/clothing/suits_righthand.dmi
index da837fdd857..7dd047b7345 100644
Binary files a/icons/mob/inhands/clothing/suits_righthand.dmi and b/icons/mob/inhands/clothing/suits_righthand.dmi differ
diff --git a/icons/mob/inhands/items/balloons_lefthand.dmi b/icons/mob/inhands/items/balloons_lefthand.dmi
index cf51ac313e2..7fed45fc590 100644
Binary files a/icons/mob/inhands/items/balloons_lefthand.dmi and b/icons/mob/inhands/items/balloons_lefthand.dmi differ
diff --git a/icons/mob/inhands/items/balloons_righthand.dmi b/icons/mob/inhands/items/balloons_righthand.dmi
index 606f2007fd7..c1856b2260b 100644
Binary files a/icons/mob/inhands/items/balloons_righthand.dmi and b/icons/mob/inhands/items/balloons_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi
index 7f6985e1de5..5856bd8b0f8 100644
Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi
index 2dd4f4b64c5..c6e8a0215ea 100644
Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ
diff --git a/icons/obj/clothing/head/hats.dmi b/icons/obj/clothing/head/hats.dmi
index 14b0fdf8b4c..938090ec82e 100644
Binary files a/icons/obj/clothing/head/hats.dmi and b/icons/obj/clothing/head/hats.dmi differ
diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi
index 94d11e6b820..3bea00dcdc3 100644
Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ
diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi
index 5ff4e25df86..4fb7248dbd8 100644
Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ
diff --git a/icons/obj/machines/computer.dmi b/icons/obj/machines/computer.dmi
index f8fb31c9ba0..9fcc46bf9b4 100644
Binary files a/icons/obj/machines/computer.dmi and b/icons/obj/machines/computer.dmi differ
diff --git a/icons/obj/medical/chemical.dmi b/icons/obj/medical/chemical.dmi
index b4b26e4f848..84dfd01d2d4 100644
Binary files a/icons/obj/medical/chemical.dmi and b/icons/obj/medical/chemical.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index ca97d91561b..1f6393a8c51 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/obj/storage/box.dmi b/icons/obj/storage/box.dmi
index 8b037860144..c0a327d7df6 100644
Binary files a/icons/obj/storage/box.dmi and b/icons/obj/storage/box.dmi differ
diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi
index 85367e1c47b..1bb6689becf 100644
Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index 4e26f75aa99..2c2aae54de3 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/obj/toys/balloons.dmi b/icons/obj/toys/balloons.dmi
index 0ed6f471bfb..96afdaea2c0 100644
Binary files a/icons/obj/toys/balloons.dmi and b/icons/obj/toys/balloons.dmi differ
diff --git a/icons/obj/toys/toy.dmi b/icons/obj/toys/toy.dmi
index 9ac61738fad..f53b0781f6e 100644
Binary files a/icons/obj/toys/toy.dmi and b/icons/obj/toys/toy.dmi differ
diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi
index 11b9af13a2c..b2579d58bf2 100644
Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ
diff --git a/icons/obj/weapons/hammer.dmi b/icons/obj/weapons/hammer.dmi
index 965fd0b37ef..751e6267798 100644
Binary files a/icons/obj/weapons/hammer.dmi and b/icons/obj/weapons/hammer.dmi differ
diff --git a/icons/turf/composite.dmi b/icons/turf/composite.dmi
index 7bb2d471788..a40c4121d25 100644
Binary files a/icons/turf/composite.dmi and b/icons/turf/composite.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 89b4876c0ce..03dd1bcbfc3 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/ui_icons/arcade/fireplace.png b/icons/ui_icons/arcade/fireplace.png
new file mode 100644
index 00000000000..080cadbebf0
Binary files /dev/null and b/icons/ui_icons/arcade/fireplace.png differ
diff --git a/icons/ui_icons/arcade/shopkeeper.png b/icons/ui_icons/arcade/shopkeeper.png
new file mode 100644
index 00000000000..e5eca14d856
Binary files /dev/null and b/icons/ui_icons/arcade/shopkeeper.png differ
diff --git a/modular_skyrat/master_files/code/datums/traits/neutral.dm b/modular_skyrat/master_files/code/datums/traits/neutral.dm
index 09020832304..2e66d536685 100644
--- a/modular_skyrat/master_files/code/datums/traits/neutral.dm
+++ b/modular_skyrat/master_files/code/datums/traits/neutral.dm
@@ -205,7 +205,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay())
..()
icon_state = "joker"
-/obj/item/paper/joker/AltClick(mob/living/carbon/user, obj/item/card)
+/obj/item/paper/joker/click_alt(mob/user)
var/list/datum/paper_input/old_raw_text_inputs = raw_text_inputs
var/list/datum/paper_stamp/old_raw_stamp_data = raw_stamp_data
var/list/datum/paper_stamp/old_raw_field_input_data = raw_field_input_data
@@ -225,6 +225,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay())
update_static_data()
balloon_alert(user, "card flipped")
+ return CLICK_ACTION_SUCCESS
/datum/quirk/feline_aspect
name = "Feline Traits"
diff --git a/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm b/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm
index c37193a6fe8..1f73f708edf 100644
--- a/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm
+++ b/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm
@@ -1,7 +1,4 @@
-/obj/machinery/door/firedoor/AltClick(mob/user)
- . = ..()
- if(!user.can_perform_action(src))
- return
+/obj/machinery/door/firedoor/click_alt(mob/user)
try_manual_override(user)
/obj/machinery/door/firedoor/examine(mob/user)
diff --git a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm
index 93cd93f1a50..c399c7272d5 100644
--- a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -78,10 +78,10 @@ GLOBAL_LIST_INIT(skyrat_wood_recipes, list(
new/datum/stack_recipe("large wooden mortar", /obj/structure/large_mortar, 10, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS),
new/datum/stack_recipe("wooden cutting board", /obj/item/cutting_board, 5, time = 2 SECONDS, check_density = FALSE, category = CAT_TOOLS),
new/datum/stack_recipe("wooden shelf", /obj/structure/rack/wooden, 2, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = FALSE, category = CAT_STRUCTURE),
- new/datum/stack_recipe("seed shelf", /obj/machinery/smartfridge/seedshelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
- new/datum/stack_recipe("produce bin", /obj/machinery/smartfridge/producebin, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
- new/datum/stack_recipe("produce display", /obj/machinery/smartfridge/producedisplay, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
- new/datum/stack_recipe("ration shelf", /obj/machinery/smartfridge/rationshelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
+ new/datum/stack_recipe("seed shelf", /obj/machinery/smartfridge/wooden/seed_shelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
+ new/datum/stack_recipe("produce bin", /obj/machinery/smartfridge/wooden/produce_bin, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
+ new/datum/stack_recipe("produce display", /obj/machinery/smartfridge/wooden/produce_display, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
+ new/datum/stack_recipe("ration shelf", /obj/machinery/smartfridge/wooden/ration_shelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
new/datum/stack_recipe("storage barrel", /obj/structure/closet/crate/wooden/storage_barrel, 4, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = FALSE, category = CAT_STRUCTURE),
new/datum/stack_recipe("worm barrel", /obj/structure/wormfarm, 5, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS),
new/datum/stack_recipe("gutlunch trough", /obj/structure/ore_container/gutlunch_trough, 5, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE),
diff --git a/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm b/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm
index adf8066b6e3..21996590ed4 100644
--- a/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm
+++ b/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm
@@ -48,9 +48,6 @@
/obj/structure/towel_bin/screwdriver_act(mob/living/user, obj/item/tool)
- if(obj_flags & NO_DECONSTRUCTION)
- return FALSE
-
if(amount)
to_chat(user, span_warning("[src] must be empty first!"))
return ITEM_INTERACT_SUCCESS
@@ -60,7 +57,8 @@
new /obj/item/stack/rods(loc, 2)
qdel(src)
return ITEM_INTERACT_SUCCESS
-
+ if(!(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION))
+ new /obj/item/stack/rods(loc, 2)
/obj/structure/towel_bin/wrench_act(mob/living/user, obj/item/tool)
. = ..()
diff --git a/modular_skyrat/master_files/code/modules/admin/admin.dm b/modular_skyrat/master_files/code/modules/admin/admin.dm
index 86f86bc7e12..91afc0def67 100644
--- a/modular_skyrat/master_files/code/modules/admin/admin.dm
+++ b/modular_skyrat/master_files/code/modules/admin/admin.dm
@@ -1,9 +1,6 @@
GLOBAL_VAR_INIT(dchat_allowed, TRUE)
-/datum/admins/proc/toggledchat()
- set category = "Server"
- set desc = "Toggle dis bitch"
- set name = "Toggle Dead Chat"
+ADMIN_VERB(toggledchat, R_ADMIN, "Toggle Dead Chat", "Toggle dis bitch.", ADMIN_CATEGORY_SERVER)
toggle_dchat()
log_admin("[key_name(usr)] toggled dead chat.")
message_admins("[key_name_admin(usr)] toggled dead chat.")
@@ -66,12 +63,12 @@ GLOBAL_VAR_INIT(dchat_allowed, TRUE)
/datum/admin_help/proc/convert_to_mentorhelp(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return FALSE
-
+
if(handler && handler != usr.ckey)
var/response = tgui_alert(usr, "This ticket is already being handled by [handler]. Do you want to continue?", "Ticket already assigned", list("Yes", "No"))
if(!response || response == "No")
return FALSE
-
+
add_verb(initiator, /client/verb/mentorhelp) // Way to override mentorhelp cooldown.
to_chat(initiator, span_adminhelp("Your ticket was converted to Mentorhelp"))
diff --git a/modular_skyrat/master_files/code/modules/clothing/towels.dm b/modular_skyrat/master_files/code/modules/clothing/towels.dm
index a8f2199a619..4add82d6a41 100644
--- a/modular_skyrat/master_files/code/modules/clothing/towels.dm
+++ b/modular_skyrat/master_files/code/modules/clothing/towels.dm
@@ -236,17 +236,12 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
-/obj/item/towel/AltClick(mob/user)
- . = ..()
-
- if(. == FALSE)
- return
-
+/obj/item/towel/click_alt(mob/user)
if(!(shape == TOWEL_FULL || shape == TOWEL_WAIST))
- return FALSE
+ return CLICK_ACTION_BLOCKING
if(!ishuman(user))
- return FALSE
+ return CLICK_ACTION_BLOCKING
var/mob/living/carbon/human/towel_user = user
var/worn = towel_user.wear_suit == src
@@ -258,6 +253,7 @@
return
to_chat(user, span_notice(shape == TOWEL_FULL ? "You raise \the [src] over your [shape]." : "You lower \the [src] down to your [shape]."))
+ return CLICK_ACTION_SUCCESS
/obj/item/towel/CtrlClick(mob/user)
diff --git a/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm b/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm
index c4f79461fd9..eb187857d7b 100644
--- a/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm
+++ b/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm
@@ -1,5 +1,4 @@
-/obj/item/reagent_containers/AltClick(mob/user)
- . = ..()
+/obj/item/reagent_containers/click_alt(mob/living/user)
if(length(possible_transfer_amounts) <= 2) // If there's only two choices, just swap between them.
change_transfer_amount(user, FORWARD)
return
diff --git a/modular_skyrat/modules/SiliconQoL/code/_onclick.dm b/modular_skyrat/modules/SiliconQoL/code/_onclick.dm
index 9589c8d40ab..9c926537895 100644
--- a/modular_skyrat/modules/SiliconQoL/code/_onclick.dm
+++ b/modular_skyrat/modules/SiliconQoL/code/_onclick.dm
@@ -4,7 +4,7 @@
/mob/living/silicon/ai/CtrlShiftClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.AICtrlShiftClick(src)
else
@@ -12,7 +12,7 @@
/mob/living/silicon/ai/ShiftClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.AIShiftClick(src)
else
@@ -21,19 +21,19 @@
/mob/living/silicon/ai/CtrlClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.AICtrlClick(src)
else
A.AICtrlClick(src)
-/mob/living/silicon/ai/AltClickOn(atom/A)
- if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A
- if(airlock)
- airlock.AIAltClick(src)
- else
- A.AIAltClick(src)
+/turf/ai_click_alt(mob/living/silicon/ai/user)
+ var/obj/machinery/door/airlock/airlock = locate() in src
+ if(airlock)
+ airlock.ai_click_alt(user)
+ return
+ return ..()
+
/atom/proc/AIExamine() // Used for AI specific examines .Currently only employed to stop door examines.
usr.examinate(src)
@@ -45,10 +45,10 @@
/mob/living/silicon/ai/ClickOn(atom/A, params)
..()
var/list/modifiers = params2list(params)
- if(isturf(A)&&(!modifiers)) // Have to check for modifiers.
- var/obj/machinery/door/firedoor/TheDoor = locate(/obj/machinery/door/firedoor) in A
- if(TheDoor)
- TheDoor.attack_ai(usr)
+ if(isturf(A) && !modifiers) // Have to check for modifiers.
+ var/obj/machinery/door/firedoor/the_door = locate() in A
+ if(the_door)
+ the_door.attack_ai(usr)
/*
* CYBORG CHANGES
@@ -56,7 +56,7 @@
/mob/living/silicon/robot/CtrlShiftClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.BorgCtrlShiftClick(src)
else
@@ -64,7 +64,7 @@
/mob/living/silicon/robot/ShiftClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.BorgShiftClick(src)
else
@@ -72,16 +72,15 @@
/mob/living/silicon/robot/CtrlClickOn(atom/A)
if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit
+ var/obj/machinery/door/airlock/airlock = locate() in A
if(airlock)
airlock.BorgCtrlClick(src)
else
A.BorgCtrlClick(src) // End of skyrat edit
-/mob/living/silicon/robot/AltClickOn(atom/A)
- if(isturf(A))
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit
- if(airlock)
- airlock.BorgAltClick(src)
- else
- A.BorgAltClick(src)
+/turf/borg_click_alt(mob/living/silicon/robot/user)
+ var/obj/machinery/door/airlock/airlock = locate() in src
+ if(airlock)
+ airlock.borg_click_alt(user)
+ return
+ return ..()
diff --git a/modular_skyrat/modules/admin/code/aooc.dm b/modular_skyrat/modules/admin/code/aooc.dm
index b679f5c8e0d..b3bfb8be52e 100644
--- a/modular_skyrat/modules/admin/code/aooc.dm
+++ b/modular_skyrat/modules/admin/code/aooc.dm
@@ -102,9 +102,7 @@ GLOBAL_LIST_EMPTY(ckey_to_aooc_name)
var/client/iterated_client = iterated_listener
to_chat(iterated_client, span_oocplain("The AOOC channel has been globally [GLOB.aooc_allowed ? "enabled" : "disabled"]."))
-/datum/admins/proc/toggleaooc()
- set category = "Server"
- set name = "Toggle Antag OOC"
+ADMIN_VERB(toggleaooc, R_ADMIN, "Toggle Antag OOC", "Toggles Antag OOC.", ADMIN_CATEGORY_SERVER)
toggle_aooc()
log_admin("[key_name(usr)] toggled Antagonist OOC.")
message_admins("[key_name_admin(usr)] toggled Antagonist OOC.")
diff --git a/modular_skyrat/modules/admin/code/fix_chat.dm b/modular_skyrat/modules/admin/code/fix_chat.dm
index e82c3cf73d7..25649f480b8 100644
--- a/modular_skyrat/modules/admin/code/fix_chat.dm
+++ b/modular_skyrat/modules/admin/code/fix_chat.dm
@@ -1,6 +1,4 @@
-/client/proc/fix_say()
- set name = "Fix say for players"
- set category = "Admin"
+ADMIN_VERB(fix_say, R_ADMIN, "Fix say", "Fix say for the players.", ADMIN_CATEGORY_MAIN)
for(var/player in GLOB.player_list)
if(!isnull(player))
continue
diff --git a/modular_skyrat/modules/admin/code/loud_say.dm b/modular_skyrat/modules/admin/code/loud_say.dm
index 82d73fc3723..15c8c025fc3 100644
--- a/modular_skyrat/modules/admin/code/loud_say.dm
+++ b/modular_skyrat/modules/admin/code/loud_say.dm
@@ -1,22 +1,16 @@
-/client/proc/cmd_loud_admin_say(msg as text)
- set category = "Admin"
- set name = "loudAsay"
- set hidden = TRUE
- if(!check_rights(0))
- return
-
+ADMIN_VERB(cmd_loud_admin_say, R_NONE, "loudAsay", "Send a message to other admins (loudly).", ADMIN_CATEGORY_MAIN, msg as text)
msg = emoji_parse(copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN))
if(!msg)
return
msg = emoji_parse(msg)
- mob.log_talk(msg, LOG_ASAY)
+ user.mob.log_talk(msg, LOG_ASAY)
- send_asay_to_other_server(ckey, span_command_headset(msg))
+ send_asay_to_other_server(user.ckey, span_command_headset(msg))
msg = keywords_lookup(msg)
- var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && prefs?.read_preference(/datum/preference/color/asay_color)) ? "" : ""
- msg = span_command_headset("ADMIN:[key_name(usr, 1)] [ADMIN_FLW(mob)]: [custom_asay_color][msg][custom_asay_color ? "":null]")
+ var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && user.mob.client?.prefs?.read_preference(/datum/preference/color/asay_color)) ? "" : ""
+ msg = span_command_headset("ADMIN:[key_name(user, 1)] [ADMIN_FLW(user.mob)]: [custom_asay_color][msg][custom_asay_color ? "":null]")
to_chat(GLOB.admins,
type = MESSAGE_TYPE_ADMINCHAT,
diff --git a/modular_skyrat/modules/admin/code/player_ranks.dm b/modular_skyrat/modules/admin/code/player_ranks.dm
index 6e05a42f7d8..242fe92cccb 100644
--- a/modular_skyrat/modules/admin/code/player_ranks.dm
+++ b/modular_skyrat/modules/admin/code/player_ranks.dm
@@ -1,11 +1,7 @@
/// The list of the available special player ranks
#define SKYRAT_PLAYER_RANKS list("Donator", "Mentor", "Veteran")
-/client/proc/manage_player_ranks()
- set category = "Admin"
- set name = "Manage Player Ranks"
- set desc = "Manage who has the special player ranks while the server is running."
-
+ADMIN_VERB(manage_player_ranks, R_PERMISSIONS, "Manage Player Ranks", "Manage who has the special player ranks while the server is running.", ADMIN_CATEGORY_MAIN)
if(!check_rights(R_PERMISSIONS))
return
@@ -86,16 +82,8 @@
-/client/proc/migrate_player_ranks()
- set category = "Debug"
- set name = "Migrate Player Ranks"
- set desc = "Individually migrate the various player ranks from their legacy system to the SQL-based one."
-
- if(!check_rights(R_PERMISSIONS | R_DEBUG | R_SERVER))
- return
-
- usr.client?.holder.migrate_player_ranks()
-
+ADMIN_VERB(migrate_player_ranks, R_PERMISSIONS|R_DEBUG|R_SERVER, "Migrate Player Ranks", "Individually migrate the various player ranks from their legacy system to the SQL-based one.", ADMIN_CATEGORY_DEBUG)
+ user.mob.client?.holder.migrate_player_ranks()
/datum/admins/proc/migrate_player_ranks()
if(IsAdminAdvancedProcCall())
diff --git a/modular_skyrat/modules/admin/code/sooc.dm b/modular_skyrat/modules/admin/code/sooc.dm
index 518e8508f06..4ef6ec8a702 100644
--- a/modular_skyrat/modules/admin/code/sooc.dm
+++ b/modular_skyrat/modules/admin/code/sooc.dm
@@ -109,9 +109,7 @@ GLOBAL_LIST_EMPTY(ckey_to_sooc_name)
var/client/iterated_client = iterated_listener
to_chat(iterated_client, span_oocplain("The SOOC channel has been globally [GLOB.sooc_allowed ? "enabled" : "disabled"]."))
-/datum/admins/proc/togglesooc()
- set category = "Server"
- set name = "Toggle Security OOC"
+ADMIN_VERB(togglesooc, R_ADMIN, "Toggle Security OOC", "Toggles Security OOC.", ADMIN_CATEGORY_SERVER)
toggle_sooc()
log_admin("[key_name(usr)] toggled Security OOC.")
message_admins("[key_name_admin(usr)] toggled Security OOC.")
diff --git a/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm b/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm
index 78ffdffd034..ebcbf017b3b 100644
--- a/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm
+++ b/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm
@@ -27,7 +27,6 @@
return INITIALIZE_HINT_LATELOAD
/obj/docking_port/mobile/arrivals_skyrat/LateInitialize()
- . = ..()
console = get_control_console()
/obj/docking_port/mobile/arrivals_skyrat/check()
diff --git a/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm b/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm
index 684ce00919b..db83853d657 100644
--- a/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm
+++ b/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm
@@ -16,7 +16,7 @@
/obj/structure/sign/flag/MouseDrop(over_object, src_location, over_location)
. = ..()
if(over_object == usr && Adjacent(usr))
- if(!item_flag || src.obj_flags & NO_DECONSTRUCTION)
+ if(!item_flag || src.obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)
return
if(!usr.can_perform_action(src, NEED_DEXTERITY))
return
diff --git a/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm b/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm
index 64e1e5536b7..a0cc10497e2 100644
--- a/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm
+++ b/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm
@@ -112,8 +112,8 @@
return FALSE
-/obj/machinery/door/airlock/keyed/AIAltClick()
- return FALSE
+/obj/machinery/door/airlock/keyed/ai_click_alt(mob/living/silicon/ai/user)
+ return
/obj/machinery/door/airlock/keyed/AIShiftClick()
@@ -128,7 +128,7 @@
return FALSE
-/obj/machinery/door/airlock/keyed/BorgAltClick(mob/living/silicon/robot/user)
+/obj/machinery/door/airlock/keyed/borg_click_alt(mob/living/silicon/robot/user)
return FALSE
diff --git a/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm b/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm
index bdf0001cf17..61df62cf143 100644
--- a/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm
+++ b/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm
@@ -6,7 +6,7 @@
playsound(src, 'modular_skyrat/modules/aesthetics/lightswitch/sound/lightswitch.ogg', 100, 1)
#ifndef UNIT_TESTS
-/obj/machinery/light_switch/LateInitialize()
+/obj/machinery/light_switch/post_machine_initialize()
. = ..()
if(prob(50) && area.lightswitch) //50% chance for area to start with lights off.
turn_off()
diff --git a/modular_skyrat/modules/aesthetics/rack/code/rack.dm b/modular_skyrat/modules/aesthetics/rack/code/rack.dm
index 23b0beaba07..082e01bb40c 100644
--- a/modular_skyrat/modules/aesthetics/rack/code/rack.dm
+++ b/modular_skyrat/modules/aesthetics/rack/code/rack.dm
@@ -41,7 +41,7 @@
/obj/structure/rack/gunrack/attackby(obj/item/W, mob/living/user, params)
var/list/modifiers = params2list(params)
- if (W.tool_behaviour == TOOL_WRENCH && !(obj_flags & NO_DECONSTRUCTION) && LAZYACCESS(modifiers, RIGHT_CLICK))
+ if (W.tool_behaviour == TOOL_WRENCH && LAZYACCESS(modifiers, RIGHT_CLICK))
W.play_tool_sound(src)
deconstruct(TRUE)
return
diff --git a/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm b/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm
index 1258addd90f..1d34585dad9 100644
--- a/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm
+++ b/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm
@@ -1,13 +1,13 @@
/obj/machinery/status_display
icon = 'modular_skyrat/modules/aesthetics/status_display/icons/status_display.dmi'
-/obj/machinery/status_display/LateInitialize()
+/obj/machinery/status_display/post_machine_initialize()
. = ..()
set_picture("default")
/obj/machinery/status_display/syndie
name = "syndicate status display"
-/obj/machinery/status_display/syndie/LateInitialize()
+/obj/machinery/status_display/syndie/post_machine_initialize()
. = ..()
set_picture("synd")
diff --git a/modular_skyrat/modules/aesthetics/storage/storage.dmi b/modular_skyrat/modules/aesthetics/storage/storage.dmi
index febe4b01547..8a7e15587e6 100644
Binary files a/modular_skyrat/modules/aesthetics/storage/storage.dmi and b/modular_skyrat/modules/aesthetics/storage/storage.dmi differ
diff --git a/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm b/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm
index 5917558c519..c6ae2743a91 100644
--- a/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm
+++ b/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm
@@ -139,6 +139,7 @@
"Pontifex",
"Rabbi",
"Reverend",
+ "Cleric",
)
/datum/job/chemist
diff --git a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm
index ad93830a0b3..64e199150f2 100644
--- a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm
+++ b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm
@@ -385,12 +385,12 @@
error_type = "good"
return
- updateDialog()
+ SStgui.update_uis(src)
timer_id = addtimer(CALLBACK(src, PROC_REF(fill_round), casing_type), time_per_round, TIMER_STOPPABLE)
/obj/machinery/ammo_workbench/proc/ammo_fill_finish(successfully = TRUE)
- updateDialog()
+ SStgui.update_uis(src)
if(successfully)
playsound(loc, 'sound/machines/ping.ogg', 40, TRUE)
else
diff --git a/modular_skyrat/modules/apc_arcing/code/apc.dm b/modular_skyrat/modules/apc_arcing/code/apc.dm
index 9e74d86d157..60413cceae4 100644
--- a/modular_skyrat/modules/apc_arcing/code/apc.dm
+++ b/modular_skyrat/modules/apc_arcing/code/apc.dm
@@ -35,19 +35,22 @@
playsound(get_turf(living_target), 'sound/magic/lightningshock.ogg', 75, TRUE)
Beam(living_target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/beam.dmi', time = 5)
-/obj/machinery/power/apc/attackby(obj/item/attacking_object, mob/living/user, params)
+/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
. = ..()
- if(istype(attacking_object, /obj/item/stack/sheet/bronze) && panel_open)
- if(arc_shielded)
- balloon_alert(user, "already arc shielded!")
- return
- var/obj/item/stack/sheet/bronze/bronze = attacking_object
- bronze.use(1)
- balloon_alert(user, "installed arc shielding")
- arc_shielded = TRUE
- playsound(src, 'sound/items/rped.ogg', 20)
- return
-
+ if(.)
+ return .
+ if(istype(tool, /obj/item/stack/sheet/bronze) && panel_open)
+ . = bronze_act(user, tool)
+/// Handles interaction of adding arc shielding to apc with bronze
+/obj/machinery/power/apc/proc/bronze_act(mob/living/user, obj/item/stack/sheet/bronze/bronze)
+ if(arc_shielded)
+ balloon_alert(user, "already arc shielded!")
+ return ITEM_INTERACT_BLOCKING
+ bronze.use(1)
+ balloon_alert(user, "installed arc shielding")
+ arc_shielded = TRUE
+ playsound(src, 'sound/items/rped.ogg', 20)
+ return ITEM_INTERACT_SUCCESS
/obj/machinery/power/apc/wrench_act(mob/living/user, obj/item/tool)
. = ..()
if(panel_open && arc_shielded)
diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm b/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm
index 862d311e16e..be8756b1cf6 100644
--- a/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm
+++ b/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm
@@ -21,7 +21,7 @@
/obj/structure/sink/fuel_well/attackby(obj/item/O, mob/living/user, params)
flick("puddle-oil-splash",src)
- if(O.tool_behaviour == TOOL_SHOVEL && !(obj_flags & NO_DECONSTRUCTION)) //attempt to deconstruct the puddle with a shovel
+ if(O.tool_behaviour == TOOL_SHOVEL) //attempt to deconstruct the puddle with a shovel //attempt to deconstruct the puddle with a shovel
to_chat(user, "You fill in the fuel well with soil.")
O.play_tool_sound(src)
deconstruct()
diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm
index f75ea5248e2..b0b821d7668 100644
--- a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm
+++ b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm
@@ -102,9 +102,9 @@
return relaydrive(user, direction)
return FALSE
-/obj/vehicle/ridden/rail_cart/AltClick(mob/user)
- . = ..()
+/obj/vehicle/ridden/rail_cart/click_alt(mob/user)
attach_trailer()
+ return CLICK_ACTION_SUCCESS
/obj/vehicle/ridden/rail_cart/attack_hand(mob/living/user, list/modifiers)
. = ..()
diff --git a/modular_skyrat/modules/assault_operatives/code/interrogator.dm b/modular_skyrat/modules/assault_operatives/code/interrogator.dm
index 94811938186..6c61caaf498 100644
--- a/modular_skyrat/modules/assault_operatives/code/interrogator.dm
+++ b/modular_skyrat/modules/assault_operatives/code/interrogator.dm
@@ -36,7 +36,7 @@
. = ..()
. += "It requies a direct link to a Nanotrasen defence network, stay near a Nanotrasen comms sat!"
-/obj/machinery/interrogator/AltClick(mob/user)
+/obj/machinery/interrogator/click_alt(mob/user)
. = ..()
if(!can_interact(user))
return
diff --git a/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm b/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm
index f0e8af0cdba..ccc2cbbb132 100644
--- a/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm
+++ b/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm
@@ -358,11 +358,7 @@ SUBSYSTEM_DEF(area_spawn)
/**
* Show overlay over area of priorities. Wall priority over open priority.
*/
-/client/proc/test_area_spawner(area/area)
- set category = "Debug"
- set name = "Test Area Spawner"
- set desc = "Show area spawner placement candidates as an overlay."
-
+ADMIN_VERB(test_area_spawner, R_DEBUG, "Test Area Spawner", "Show area spawner placement candidates as an overlay.", ADMIN_CATEGORY_DEBUG, area/area)
for(var/obj/effect/turf_test/old_test in area)
qdel(old_test)
diff --git a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm
index 7fb36157062..78616bbbf62 100644
--- a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm
+++ b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm
@@ -5,8 +5,8 @@
icon_state = "alienpaper_words"
show_written_words = FALSE
-/obj/item/paper/fluff/awaymissions/astrum/AltClick()
- return //no folding these
+/obj/item/paper/fluff/awaymissions/astrum/click_alt(mob/user)
+ return NONE //no folding these
/obj/item/paper/fluff/awaymissions/astrum/combat
name = "Report: Combat Holodeck"
diff --git a/modular_skyrat/modules/barricades/code/barricade.dm b/modular_skyrat/modules/barricades/code/barricade.dm
index fca6f627624..a3faa5ebef9 100644
--- a/modular_skyrat/modules/barricades/code/barricade.dm
+++ b/modular_skyrat/modules/barricades/code/barricade.dm
@@ -361,34 +361,34 @@
fire = 80
acid = 40
-/obj/structure/deployable_barricade/metal/AltClick(mob/user)
+/obj/structure/deployable_barricade/metal/click_alt(mob/user)
if(portable_type)
if(anchored)
to_chat(user, span_warning("[src] cannot be folded up while anchored to the ground!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
if(barricade_upgrade_type)
to_chat(user, span_warning("[src] cannot be folded up with upgrades attached, remove them first!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
if(get_integrity() < max_integrity)
to_chat(user, span_warning("[src] cannot be folded up while damaged!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
user.visible_message(span_notice("[user] starts folding [src] up!"), span_notice("You start folding [src] up!"))
if(do_after(user, 5 SECONDS, src))
if(QDELETED(src)) //Copied encase we change states.
return
if(anchored)
to_chat(user, span_warning("[src] cannot be folded up while anchored to the ground!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
if(barricade_upgrade_type)
to_chat(user, span_warning("[src] cannot be folded up with upgrades attached, remove them first!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
if(get_integrity() < max_integrity)
to_chat(user, span_warning("[src] cannot be folded up while damaged!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
user.visible_message(span_notice("[user] folds [src] up!"), span_notice("You neatly fold [src] up!"))
playsound(src, 'sound/items/ratchet.ogg', 25, TRUE)
fold_up()
- return TRUE
+ return CLICK_ACTION_SUCCESS
return ..()
/obj/structure/deployable_barricade/metal/proc/fold_up()
diff --git a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
index fe34135c88d..58deaca1d8a 100644
--- a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
+++ b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm
@@ -111,9 +111,10 @@
to_chat(patron, span_notice("[user] dispenses [snack] into your empty hand and you reflexively grasp it."))
to_chat(user, span_notice("You dispense [snack] into the hand of [user]."))
-/obj/item/borg_snack_dispenser/AltClick(mob/user)
+/obj/item/borg_snack_dispenser/click_alt(mob/user)
launch_mode = !launch_mode
to_chat(user, span_notice("[src] is [(launch_mode ? "now" : "no longer")] launching snacks at a distance."))
+ return CLICK_ACTION_SUCCESS
/obj/item/borg_snack_dispenser/afterattack(atom/target, mob/living/silicon/robot/user, proximity_flag, click_parameters)
if(Adjacent(target) || !launch_mode)
diff --git a/modular_skyrat/modules/borgs/code/robot_items.dm b/modular_skyrat/modules/borgs/code/robot_items.dm
index 638fc046676..b5ead250f31 100644
--- a/modular_skyrat/modules/borgs/code/robot_items.dm
+++ b/modular_skyrat/modules/borgs/code/robot_items.dm
@@ -32,20 +32,20 @@
/obj/item/clipboard/cyborg/examine()
. = ..()
- . += "Alt-click to synthetize a piece of paper."
+ . += "Alt-click to synthesize a piece of paper."
if(!COOLDOWN_FINISHED(src, printer_cooldown))
- . += "Its integrated paper synthetizer seems to still be on cooldown."
+ . += "Its integrated paper synthesizer seems to still be on cooldown."
-/obj/item/clipboard/cyborg/AltClick(mob/user)
+/obj/item/clipboard/cyborg/click_alt(mob/user)
if(!iscyborg(user))
to_chat(user, span_warning("You do not seem to understand how to use [src]."))
- return
+ return CLICK_ACTION_BLOCKING
var/mob/living/silicon/robot/cyborg_user = user
// Not enough charge? Tough luck.
if(cyborg_user?.cell.charge < paper_charge_cost)
to_chat(user, span_warning("Your internal cell doesn't have enough charge left to use [src]'s integrated printer."))
- return
+ return CLICK_ACTION_BLOCKING
// Check for cooldown to avoid paper spamming
if(COOLDOWN_FINISHED(src, printer_cooldown))
// If there's not too much paper already, let's go
@@ -61,10 +61,12 @@
toppaper_ref = WEAKREF(new_paper)
update_appearance()
to_chat(user, span_notice("[src]'s integrated printer whirs to life, spitting out a fresh piece of paper and clipping it into place."))
+ return CLICK_ACTION_SUCCESS
else
to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, as [src] already contains enough paper."))
else
- to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, its bluespace paper synthetizer not having finished recovering from its last synthesis."))
+ to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, its bluespace paper synthesizer not having finished recovering from its last synthesis."))
+ return CLICK_ACTION_BLOCKING
/obj/item/hand_labeler/cyborg
diff --git a/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm b/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm
index aa0082ad244..f0d731c4579 100644
--- a/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm
+++ b/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm
@@ -1,10 +1,6 @@
-/client/proc/toggle_bsa()
- set category = "Admin.Fun"
- set name = "Toggle BSA Control"
- set desc = "Toggles the BSA control lock on and off."
-
+ADMIN_VERB(toggle_bsa, R_ADMIN, "Toggle BSA Control", "Toggles the BSA control lock on and off.", ADMIN_CATEGORY_FUN)
GLOB.bsa_unlock = !GLOB.bsa_unlock
minor_announce("Bluespace Artillery firing protocols have been [GLOB.bsa_unlock? "unlocked" : "locked"]", "Weapons Systems Update:")
message_admins("[ADMIN_LOOKUPFLW(usr)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.")
- log_admin("[key_name(usr)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.")
+ log_admin("[key_name(user)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.")
diff --git a/modular_skyrat/modules/bsrpd/code/bsrpd.dm b/modular_skyrat/modules/bsrpd/code/bsrpd.dm
index d7493ee1f46..23daac59efa 100644
--- a/modular_skyrat/modules/bsrpd/code/bsrpd.dm
+++ b/modular_skyrat/modules/bsrpd/code/bsrpd.dm
@@ -48,13 +48,11 @@
. += span_notice("Alt-Click to toggle remote piping.")
-/obj/item/pipe_dispenser/bluespace/AltClick(mob/user)
- . = ..()
- if(. == FALSE)
- return // too far away
+/obj/item/pipe_dispenser/bluespace/click_alt(mob/user)
remote_piping_toggle = !remote_piping_toggle
balloon_alert(user, "remote piping [remote_piping_toggle ? "on" : "off"]")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+ return CLICK_ACTION_SUCCESS
/obj/item/pipe_dispenser/bluespace/afterattack(atom/target, mob/user, prox)
if(prox || !remote_piping_toggle) // If we are in proximity to the target or have our safety on, don't use charge and don't call this shitcode.
diff --git a/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm b/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm
index c5e0916f5e9..2efccbe8174 100644
--- a/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm
+++ b/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm
@@ -32,10 +32,11 @@ GLOBAL_LIST_EMPTY(cargo_marks)
spawned_marker.parent_item = src
marker_children += spawned_marker
-/obj/item/cargo_teleporter/AltClick(mob/user)
+/obj/item/cargo_teleporter/click_alt(mob/user)
if(length(marker_children))
for(var/obj/effect/decal/cleanable/cargo_mark/destroy_children in marker_children)
qdel(destroy_children)
+ return CLICK_ACTION_SUCCESS
/obj/item/cargo_teleporter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
diff --git a/modular_skyrat/modules/cellguns/code/cellguns.dm b/modular_skyrat/modules/cellguns/code/cellguns.dm
index eaeaee29cc2..cce7b4435ef 100644
--- a/modular_skyrat/modules/cellguns/code/cellguns.dm
+++ b/modular_skyrat/modules/cellguns/code/cellguns.dm
@@ -72,10 +72,10 @@
charge_overlay.pixel_y = ammo_y_offset * (i - 1)
. += new /mutable_appearance(charge_overlay)
-/obj/item/gun/energy/cell_loaded/AltClick(mob/user, modifiers)
+/obj/item/gun/energy/cell_loaded/click_alt(mob/user, modifiers)
if(!installedcells.len) //Checks to see if there is a cell inside of the gun, before removal.
to_chat(user, span_notice("The [src] has no cells inside"))
- return ..()
+ return CLICK_ACTION_BLOCKING
to_chat(user, span_notice("You remove a cell"))
var/obj/item/last_cell = installedcells[installedcells.len]
@@ -87,6 +87,7 @@
installedcells -= last_cell
ammo_type.len--
select_fire(user)
+ return CLICK_ACTION_SUCCESS
/// A cellgun used for debug, it is able to use any weaponcell.
/obj/item/gun/energy/cell_loaded/alltypes
diff --git a/modular_skyrat/modules/cellguns/code/medigun_cells.dm b/modular_skyrat/modules/cellguns/code/medigun_cells.dm
index 274a523a7d4..4c58e129fb7 100644
--- a/modular_skyrat/modules/cellguns/code/medigun_cells.dm
+++ b/modular_skyrat/modules/cellguns/code/medigun_cells.dm
@@ -538,7 +538,6 @@
icon_state = "hardlight_down"
base_icon_state = "hardlight"
max_integrity = 1
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION //Made from nothing, can't deconstruct
build_stack_type = null //It would not be good if people could use this to farm materials.
var/deploy_time = 20 SECONDS //How long the roller beds lasts for without someone buckled to it.
@@ -546,6 +545,10 @@
. = ..()
addtimer(CALLBACK(src, PROC_REF(check_bed)), deploy_time)
+// previously NO_DECONSTRUCTION
+/obj/structure/bed/medical/medigun/wrench_act_secondary(mob/living/user, obj/item/weapon)
+ return NONE
+
/obj/structure/bed/medical/medigun/proc/check_bed() //Checks to see if anyone is buckled to the bed, if not the bed will qdel itself.
if(!has_buckled_mobs())
qdel(src) //Deletes the roller bed, mostly meant to prevent stockpiling and clutter
diff --git a/modular_skyrat/modules/cellguns/code/mediguns.dm b/modular_skyrat/modules/cellguns/code/mediguns.dm
index 3a79fce401b..deb6e02b0c4 100644
--- a/modular_skyrat/modules/cellguns/code/mediguns.dm
+++ b/modular_skyrat/modules/cellguns/code/mediguns.dm
@@ -49,18 +49,18 @@
// Medigun power cells
/obj/item/stock_parts/cell/medigun // This is the cell that mediguns from cargo will come with
name = "basic medigun cell"
- maxcharge = 1200
- chargerate = 40
+ maxcharge = STANDARD_CELL_CHARGE
+ chargerate = STANDARD_CELL_CHARGE * 0.03
/obj/item/stock_parts/cell/medigun/upgraded
name = "upgraded medigun cell"
- maxcharge = 1500
- chargerate = 80
+ maxcharge = STANDARD_CELL_CHARGE * 1.4
+ chargerate = STANDARD_CELL_CHARGE * 0.06
/obj/item/stock_parts/cell/medigun/experimental // This cell type is meant to be used in self charging mediguns like CMO and ERT one.
name = "experiemental medigun cell"
- maxcharge = 1800
- chargerate = 100
+ maxcharge = STANDARD_CELL_CHARGE * 2
+ chargerate = STANDARD_CELL_CHARGE * 0.1
// End of power cells
// Upgrade Kit
diff --git a/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm b/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm
index a1464e08d3e..9b488fd561f 100644
--- a/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm
+++ b/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm
@@ -47,8 +47,6 @@
if(machine_stat & (NOPOWER|BROKEN|MAINT))
return
- usr.set_machine(src)
-
var/selected_goal = href_list["selected_goal"]
if(href_list["close"])
@@ -62,4 +60,4 @@
SSstation.goals_by_type[iterating_goal] = goal_to_set
goal_assigned = TRUE
break
- updateUsrDialog()
+ SStgui.update_uis(src)
diff --git a/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm b/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm
index 8434a730f1d..e126baca3d0 100644
--- a/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm
@@ -5,7 +5,6 @@
icon_state = "wall_charger"
base_icon_state = "wall_charger"
circuit = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
max_batteries = 3
charge_rate = 900 KILO WATTS
/// The item we turn into when repacked
@@ -27,6 +26,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/cell_charger_multi/wall_mounted, 29)
deconstruct(TRUE)
return
+// previously NO_DECONSTRUCTION
+/obj/machinery/cell_charger_multi/wall_mounted/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/cell_charger_multi/wall_mounted/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/cell_charger_multi/wall_mounted/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
/obj/machinery/cell_charger_multi/wall_mounted/on_deconstruction(disassembled)
if(disassembled)
new repacked_type(drop_location())
diff --git a/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm b/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm
index f7d7eede0ac..1eb2a4627e1 100644
--- a/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm
@@ -9,7 +9,6 @@
production_animation = null
circuit = null
production_animation = "colony_lathe_n"
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
light_color = LIGHT_COLOR_BRIGHT_YELLOW
light_power = 5
allowed_buildtypes = COLONY_FABRICATOR
@@ -33,6 +32,16 @@
QDEL_NULL(soundloop)
return ..()
+// previously NO_DECONSTRUCTION
+/obj/machinery/rnd/production/colony_lathe/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/rnd/production/colony_lathe/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/rnd/production/colony_lathe/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
/obj/machinery/rnd/production/colony_lathe/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if (. && action == "build")
diff --git a/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm b/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm
index a7efee044b8..c600019f7de 100644
--- a/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm
@@ -18,7 +18,6 @@
"portable_lil_pump",
"portable_scrubbs",
"survival_knife", // I just don't want to make a whole new node for this one sorry
- "soup_pot", // This one too
"water_synth",
"hydro_synth",
"frontier_sustenance_dispenser",
diff --git a/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm b/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm
index 067b0084046..d2c0f8887f2 100644
--- a/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm
@@ -12,16 +12,8 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
-/datum/design/soup_pot
- name = "Soup Pot"
- id = "soup_pot"
- build_type = COLONY_FABRICATOR
- materials = list(
- /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5,
- )
- build_path = /obj/item/reagent_containers/cup/soup_pot
- category = list(
- RND_CATEGORY_INITIAL,
- RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN,
- )
- departmental_flags = DEPARTMENT_BITFLAG_SERVICE
+// Lets colony fabricators make soup pots, removes bluespace crystal requirement.
+/datum/design/soup_pot/New()
+ build_type |= COLONY_FABRICATOR
+ materials -= /datum/material/bluespace
+ return ..()
diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm b/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm
index acf3d2af90f..6d692728674 100644
--- a/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm
@@ -18,7 +18,6 @@
circuit = null
light_color = LIGHT_COLOR_BRIGHT_YELLOW
light_power = 10
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 10 // This baby consumes so much power
/// The item we turn into when repacked
var/repacked_type = /obj/item/flatpacked_machine/arc_furnace
@@ -46,6 +45,16 @@
if(length(contents))
. += span_notice("It has [contents[1]] sitting in it.")
+// previously NO_DECONSTRUCTION
+/obj/machinery/arc_furnace/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/arc_furnace/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/arc_furnace/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
/obj/machinery/arc_furnace/on_deconstruction(disassembled)
eject_contents()
@@ -98,7 +107,6 @@
if(isAI(user) && (machine_stat & NOPOWER))
return
- usr.set_machine(src) // What does this even do??
switch(choice)
if(RADIAL_CHOICE_EJECT)
eject_contents()
diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm b/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm
index cd2da64f8e4..4d6fc605a79 100644
--- a/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm
@@ -9,7 +9,6 @@
input_level_max = 400 * 1000
output_level_max = 400 * 1000
circuit = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/// The item we turn into when repacked
var/repacked_type = /obj/item/flatpacked_machine/station_battery
@@ -34,6 +33,13 @@
to_chat(user, span_notice("You close the maintenance hatch of [src]."))
return TRUE
+// previously NO_DECONSTRUCTION
+/obj/machinery/power/smes/battery_pack/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/smes/battery_pack/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
// We don't care about the parts updates because we don't want them to change
/obj/machinery/power/smes/battery_pack/RefreshParts()
return
diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm b/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm
index c01724200ac..5690e26884a 100644
--- a/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm
@@ -6,7 +6,6 @@
application."
icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi'
circuit = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
power_gen = 7500
/// What we turn into when we are repacked
var/repacked_type = /obj/item/flatpacked_machine/rtg
@@ -19,8 +18,17 @@
if(!mapload)
flick("rtg_deploy", src)
-// Item for creating the arc furnace or carrying it around
+// previously NO_DECONSTRUCTION
+/obj/machinery/power/rtg/portable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+/obj/machinery/power/rtg/portable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/rtg/portable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
+// Item for creating the arc furnace or carrying it around
/obj/item/flatpacked_machine/rtg
name = "flat-packed radioisotope thermoelectric generator"
icon_state = "rtg_packed"
diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm b/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm
index c965d5ab169..9b8f02db090 100644
--- a/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm
@@ -2,7 +2,6 @@
/obj/machinery/power/solar/deployable
icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi'
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/// The item we turn into when repacked
var/repacked_type = /obj/item/flatpacked_machine/solar
@@ -20,6 +19,16 @@
qdel(assembly)
return ..()
+// previously NO_DECONSTRUCTION
+/obj/machinery/power/solar/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/solar/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/solar/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
// Solar panel deployable item
/obj/item/flatpacked_machine/solar
@@ -37,7 +46,6 @@
/obj/machinery/power/tracker/deployable
icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi'
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/// The item we turn into when repacked
var/repacked_type = /obj/item/flatpacked_machine/solar_tracker
@@ -47,7 +55,17 @@
AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER)
/obj/machinery/power/tracker/deployable/crowbar_act(mob/user, obj/item/item_acting)
- return
+ return NONE
+
+// previously NO_DECONSTRUCTION
+/obj/machinery/power/tracker/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/tracker/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/tracker/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
/obj/machinery/power/tracker/deployable/on_deconstruction(disassembled)
var/obj/item/solar_assembly/assembly = locate() in src
diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm b/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm
index a3ac75a0825..e082b8bea0a 100644
--- a/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm
+++ b/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm
@@ -11,7 +11,6 @@
icon_state = "fuel_generator_0"
base_icon_state = "fuel_generator"
circuit = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
anchored = TRUE
max_sheets = 25
time_per_sheet = 100
@@ -28,6 +27,16 @@
if(!mapload)
flick("fuel_generator_deploy", src)
+// previously NO_DECONSTRUCTION
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/power/port_gen/pacman/solid_fuel/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
// We don't need to worry about the board, this machine doesn't have one!
/obj/machinery/power/port_gen/pacman/solid_fuel/on_construction(mob/user)
return
diff --git a/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm b/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm
index 550de51f205..a5306c96bd2 100644
--- a/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm
+++ b/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm
@@ -53,10 +53,11 @@
current_sort += target.type
to_chat(user, span_notice("[target] has been added to [src]'s sorting list."))
-/obj/item/conveyor_sorter/AltClick(mob/user)
+/obj/item/conveyor_sorter/click_alt(mob/user)
visible_message("[src] pings, resetting its sorting list!")
playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
current_sort = list()
+ return CLICK_ACTION_SUCCESS
/obj/effect/decal/conveyor_sorter
name = "conveyor sorter"
@@ -122,10 +123,11 @@
else
return ..()
-/obj/effect/decal/conveyor_sorter/AltClick(mob/user)
+/obj/effect/decal/conveyor_sorter/click_alt(mob/user)
visible_message("[src] pings, resetting its sorting list!")
playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
sorting_list = list()
+ return CLICK_ACTION_SUCCESS
/obj/effect/decal/conveyor_sorter/CtrlClick(mob/user)
visible_message("[src] begins to ping violently!")
diff --git a/modular_skyrat/modules/cryosleep/code/cryopod.dm b/modular_skyrat/modules/cryosleep/code/cryopod.dm
index baf3ec481c0..ea5cc83c3ec 100644
--- a/modular_skyrat/modules/cryosleep/code/cryopod.dm
+++ b/modular_skyrat/modules/cryosleep/code/cryopod.dm
@@ -179,7 +179,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32)
GLOB.valid_cryopods += src
return INITIALIZE_HINT_LATELOAD //Gotta populate the cryopod computer GLOB first
-/obj/machinery/cryopod/LateInitialize()
+/obj/machinery/cryopod/post_machine_initialize()
+ . = ..()
update_icon()
find_control_computer()
diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm
index e141f569004..b9ff2f16cc8 100644
--- a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm
@@ -57,7 +57,6 @@
/obj/item/clothing/mask/paper/Initialize(mapload)
. = ..()
- register_context()
if(wear_hair_over)
alternate_worn_layer = BACK_LAYER
diff --git a/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm b/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm
index 75c95556f6d..0135ef01d82 100644
--- a/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm
@@ -103,12 +103,12 @@
. = ..()
AddComponent(/datum/component/toggle_icon, toggle_noun = "scarf")
-/obj/item/clothing/neck/face_scarf/AltClick(mob/user) //Make sure that toggling actually hides the snout so that it doesn't clip
- . = ..()
+/obj/item/clothing/neck/face_scarf/click_alt(mob/user) //Make sure that toggling actually hides the snout so that it doesn't clip
if(icon_state != "face_scarf_t")
flags_inv = HIDEFACIALHAIR | HIDESNOUT
else
flags_inv = HIDEFACIALHAIR
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/neck/maid_neck_cover
name = "maid neck cover"
diff --git a/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm b/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm
index fa4052d1119..322e438374c 100644
--- a/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm
@@ -7,6 +7,7 @@
worn_icon_state = "crusader_belt"
inhand_icon_state = "utility"
w_class = WEIGHT_CLASS_BULKY //Cant fit a sheath in your bag
+ interaction_flags_click = NEED_DEXTERITY
/obj/item/storage/belt/crusader/Initialize(mapload)
. = ..()
@@ -64,9 +65,7 @@
atom_storage.show_contents(user)
return
-/obj/item/storage/belt/crusader/AltClick(mob/user) //This is basically the same as the normal sheath, but because there's always an item locked in the first slot it uses the second slot for swords
- if(!user.can_perform_action(src, NEED_DEXTERITY))
- return
+/obj/item/storage/belt/crusader/click_alt(mob/user) //This is basically the same as the normal sheath, but because there's always an item locked in the first slot it uses the second slot for swords
if(contents.len == 2)
var/obj/item/drawn_item = contents[2]
add_fingerprint(user)
@@ -74,12 +73,12 @@
if(!user.put_in_hands(drawn_item))
to_chat(user, span_notice("You fumble for [drawn_item] and it falls on the floor."))
update_appearance()
- return
+ return CLICK_ACTION_SUCCESS
user.visible_message(span_notice("[user] takes [drawn_item] out of [src]."), span_notice("You take [drawn_item] out of [src]."))
update_appearance()
else
to_chat(user, span_warning("[src] is empty!"))
- . = ..()
+ return CLICK_ACTION_SUCCESS
/obj/item/storage/belt/crusader/update_icon(updates)
if(contents.len == 2) //Checks for a sword/rod in the sheath slot, changes the sprite accordingly
diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm
index 8ecb31de46c..51c37671727 100644
--- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm
@@ -280,14 +280,14 @@
visor_flags_inv = HIDESNOUT // | HIDEFACE // bubber edit // BUBBER TODO: Modularity
w_class = WEIGHT_CLASS_SMALL
tint = 0
+ interaction_flags_click = NEED_DEXTERITY
/obj/item/clothing/mask/gas/nightlight/attack_self(mob/user)
adjustmask(user)
-/obj/item/clothing/mask/gas/nightlight/AltClick(mob/user)
- ..()
- if(user.can_perform_action(src, NEED_DEXTERITY))
- adjustmask(user)
+/obj/item/clothing/mask/gas/nightlight/click_alt(mob/user)
+ adjustmask(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/mask/gas/nightlight/examine(mob/user)
. = ..()
@@ -798,7 +798,6 @@
worn_icon = 'modular_skyrat/master_files/icons/donator/mob/clothing/head.dmi'
icon_state = "emissionhelm"
-
// Donation reward for CandleJax
/obj/item/clothing/head/helmet/space/plasmaman/candlejax2
name = "azulean's environment helmet"
diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm
index 6455bba4255..4cd4695d2fb 100644
--- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm
+++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm
@@ -256,11 +256,11 @@
else
icon_state = "catear_headphone[song?.playing ? "_on" : null]"
-/obj/item/instrument/piano_synth/headphones/catear_headphone/AltClick(mob/user)
- . = ..()
+/obj/item/instrument/piano_synth/headphones/catear_headphone/click_alt(mob/user)
catTailToggled = !catTailToggled
user.update_worn_head()
update_icon(UPDATE_OVERLAYS)
+ return CLICK_ACTION_SUCCESS
/obj/item/instrument/piano_synth/headphones/catear_headphone/update_overlays()
. = ..()
diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
index 44f5dc23227..98bda575348 100644
--- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
+++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm
@@ -137,9 +137,7 @@ GLOBAL_LIST_EMPTY(customizable_races)
if(eye_organ)
eye_organ.refresh(call_update = FALSE)
- for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human))
- eye_overlay.pixel_y += height_offset
- standing += eye_overlay
+ standing += eye_organ.generate_body_overlay(species_human)
//Underwear, Undershirts & Socks
if(!HAS_TRAIT(species_human, TRAIT_NO_UNDERWEAR))
diff --git a/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm b/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm
index 5ab0c9a713b..9227b8582b2 100644
--- a/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm
+++ b/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm
@@ -1,9 +1,5 @@
-/client/proc/spawn_mob_spawner()
- set category = "Admin.Fun"
- set name = "Spawn mob spawner"
- set desc = "Spawns a mob spawner structure below the user."
-
- holder?.spawn_mob_spawner()
+ADMIN_VERB(spawn_mob_spawner, R_ADMIN, "Spawn mob spawner", "Spawns a mob spawner structure at your location.", ADMIN_CATEGORY_FUN)
+ user.holder?.spawn_mob_spawner()
/datum/admins/proc/spawn_mob_spawner(chosen_mob as text)
if(!check_rights(R_SPAWN))
diff --git a/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm b/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm
index fc338d7b214..0d4a99627c3 100644
--- a/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm
+++ b/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm
@@ -1,12 +1,7 @@
/// Lets an admin activate the delam suppression system
-/client/proc/try_stop_delam()
- set name = "Delam Emergency Stop"
- set category = "Admin.Events"
+ADMIN_VERB(try_stop_delam, R_ADMIN, "Delam Emergency Stop", "Activate the delam suppression system.", ADMIN_CATEGORY_EVENTS)
var/obj/machinery/atmospherics/components/unary/delam_scram/suppression_system = null
- if(!holder || !check_rights(R_FUN))
- return
-
suppression_system = validate_suppression_status()
if(!suppression_system)
@@ -14,19 +9,19 @@
// Warn them if they're intervening in the work of God
if(world.time - SSticker.round_start_time < 30 MINUTES)
- var/go_early = tgui_alert(usr, "The [suppression_system.name] is set to automatically start at the programmed time. \
+ var/go_early = tgui_alert(user, "The [suppression_system.name] is set to automatically start at the programmed time. \
Are you sure you want to override this and fire it early? It's less scary that way.", "Suffering premature delamination?", list("No", "Yes"))
if(go_early != "Yes")
return FALSE
- var/double_check = tgui_alert(usr, "You really sure that you want to push this?", "Reticulating Splines", list("No", "Yes"))
+ var/double_check = tgui_alert(user, "You really sure that you want to push this?", "Reticulating Splines", list("No", "Yes"))
if(double_check != "Yes")
return FALSE
// Send the signal to start, unlock the temp emergency exits
- log_admin("[key_name_admin(usr)] started a supermatter emergency stop!")
- message_admins("[ADMIN_LOOKUPFLW(usr)] started a supermatter emergency stop! [ADMIN_COORDJMP(suppression_system)]")
- suppression_system.investigate_log("[key_name_admin(usr)] started a supermatter emergency stop!", INVESTIGATE_ATMOS)
+ log_admin("[key_name_admin(user)] started a supermatter emergency stop!")
+ message_admins("[ADMIN_LOOKUPFLW(user)] started a supermatter emergency stop! [ADMIN_COORDJMP(suppression_system)]")
+ suppression_system.investigate_log("[key_name_admin(user)] started a supermatter emergency stop!", INVESTIGATE_ATMOS)
SEND_GLOBAL_SIGNAL(COMSIG_MAIN_SM_DELAMINATING, DIVINE_INTERVENTION)
for(var/obj/machinery/door/airlock/escape_route in range(14, suppression_system)) // a little more space here due to positioning
if(istype(escape_route, /obj/machinery/door/airlock/command))
@@ -34,13 +29,10 @@
INVOKE_ASYNC(escape_route, TYPE_PROC_REF(/obj/machinery/door/airlock, temp_emergency_exit), 45 SECONDS)
/// Lets admins disable/enable the delam suppression system
+ADMIN_VERB(toggle_delam_suppression, R_FUN, "Delam Suppression Toggle", "Disable/enable the delam suppression system.", ADMIN_CATEGORY_EVENTS)
+ user.mob.client?.toggle_delam_suppression()
+
/client/proc/toggle_delam_suppression()
- set name = "Delam Suppression Toggle"
- set category = "Admin.Events"
-
- if(!holder || !check_rights(R_FUN))
- return
-
var/obj/machinery/atmospherics/components/unary/delam_scram/suppression_system = validate_suppression_status()
if(!suppression_system)
diff --git a/modular_skyrat/modules/delam_emergency_stop/code/scram.dm b/modular_skyrat/modules/delam_emergency_stop/code/scram.dm
index c83856bfb1c..2d5481b2747 100644
--- a/modular_skyrat/modules/delam_emergency_stop/code/scram.dm
+++ b/modular_skyrat/modules/delam_emergency_stop/code/scram.dm
@@ -63,7 +63,7 @@
return INITIALIZE_HINT_LATELOAD
-/obj/machinery/atmospherics/components/unary/delam_scram/LateInitialize()
+/obj/machinery/atmospherics/components/unary/delam_scram/post_machine_initialize()
. = ..()
if(isnull(id_tag))
id_tag = "SCRAM"
@@ -387,7 +387,7 @@
else if(machine_stat & (NOPOWER|BROKEN))
icon_state += "-nopower"
-/obj/machinery/power/emitter/LateInitialize(mapload)
+/obj/machinery/power/emitter/post_machine_initialize()
. = ..()
RegisterSignal(SSdcs, COMSIG_MAIN_SM_DELAMINATING, PROC_REF(emergency_stop))
diff --git a/modular_skyrat/modules/electric_welder/code/electric_welder.dm b/modular_skyrat/modules/electric_welder/code/electric_welder.dm
index a3426e2cf78..c61e8333ef9 100644
--- a/modular_skyrat/modules/electric_welder/code/electric_welder.dm
+++ b/modular_skyrat/modules/electric_welder/code/electric_welder.dm
@@ -71,10 +71,6 @@
/obj/item/weldingtool/electric/use(used = 0)
return isOn()
-// This is what starts fires. Overriding it stops it starting fires
-/obj/item/weldingtool/electric/handle_fuel_and_temps(used = 0, mob/living/user)
- return
-
/obj/item/weldingtool/electric/examine()
. = ..()
. += "[src] is currently [powered ? "powered" : "unpowered"]."
diff --git a/modular_skyrat/modules/events/code/event_spawner_menu.dm b/modular_skyrat/modules/events/code/event_spawner_menu.dm
index 94be670b8ed..7f839bcfc13 100644
--- a/modular_skyrat/modules/events/code/event_spawner_menu.dm
+++ b/modular_skyrat/modules/events/code/event_spawner_menu.dm
@@ -366,13 +366,7 @@
ShowPanel(usr, null)
return
-/client/proc/admin_open_event_spawners_menu()
- set category = "Admin.Events"
- set name = "Event Spawners Menu"
-
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(admin_open_event_spawners_menu, R_ADMIN, "Event Spawners Menu", "Event Spawners Menu.", ADMIN_CATEGORY_EVENTS)
var/datum/event_spawner_manager/ESM = GLOB.event_spawner_manager
ESM.ShowPanel(usr, null)
diff --git a/modular_skyrat/modules/exp_corps/code/clothing.dm b/modular_skyrat/modules/exp_corps/code/clothing.dm
index 66e5422f012..d932d13b3ad 100644
--- a/modular_skyrat/modules/exp_corps/code/clothing.dm
+++ b/modular_skyrat/modules/exp_corps/code/clothing.dm
@@ -240,12 +240,9 @@
current_user.remove_client_colour(/datum/client_colour/glass_colour/lightgreen)
current_user.update_sight()
-/obj/item/clothing/head/helmet/expeditionary_corps/AltClick(mob/user)
- . = ..()
+/obj/item/clothing/head/helmet/expeditionary_corps/click_alt(mob/user)
if(!current_user)
return
- if(!can_interact(user))
- return
nightvision = !nightvision
if(nightvision)
@@ -255,6 +252,7 @@
to_chat(user, span_notice("You flip the NV goggles up."))
disable_nv()
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/head/helmet/expeditionary_corps/dropped(mob/user)
. = ..()
diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
index 5d2f0d34e72..70ae903aa63 100644
--- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
+++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm
@@ -392,11 +392,11 @@
),
)
-/obj/item/clothing/neck/security_cape/AltClick(mob/user)
- . = ..()
+/obj/item/clothing/neck/security_cape/click_alt(mob/user)
swapped = !swapped
to_chat(user, span_notice("You swap which arm [src] will lay over."))
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/neck/security_cape/update_appearance(updates)
. = ..()
diff --git a/modular_skyrat/modules/hev_suit/code/hev_suit.dm b/modular_skyrat/modules/hev_suit/code/hev_suit.dm
index 1dbce983d32..eff170f0c7a 100644
--- a/modular_skyrat/modules/hev_suit/code/hev_suit.dm
+++ b/modular_skyrat/modules/hev_suit/code/hev_suit.dm
@@ -843,9 +843,11 @@
acid_static_cooldown = PCV_COOLDOWN_ACID
suit_name = "PCV MARK II"
-/obj/item/clothing/suit/space/hev_suit/pcv/AltClick(mob/living/user)
- reskin_obj(user)
+/obj/item/clothing/suit/space/hev_suit/pcv/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
+ if(!current_skin)
+ context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin"
+ return CONTEXTUAL_SCREENTIP_SET
#undef HEV_COLOR_GREEN
#undef HEV_COLOR_RED
diff --git a/modular_skyrat/modules/ices_events/code/ICES_tgui.dm b/modular_skyrat/modules/ices_events/code/ICES_tgui.dm
index fb4c04a3678..6d28556209d 100644
--- a/modular_skyrat/modules/ices_events/code/ICES_tgui.dm
+++ b/modular_skyrat/modules/ices_events/code/ICES_tgui.dm
@@ -1,12 +1,6 @@
///Allows an admin to open the panel
-/client/proc/intensity_credits_panel()
- set name = "ICES Events Panel"
- set category = "Admin.Events"
-
- if(!holder || !check_rights(R_FUN))
- return
-
- holder.intensity_credits_panel()
+ADMIN_VERB(intensity_credits_panel, R_FUN, "ICES Events Panel", "Opens up the ICES panel.", ADMIN_CATEGORY_EVENTS)
+ user.holder?.intensity_credits_panel()
///Opens up the ICES panel
/datum/admins/proc/intensity_credits_panel()
diff --git a/modular_skyrat/modules/inflatables/code/inflatable.dm b/modular_skyrat/modules/inflatables/code/inflatable.dm
index f58b4dde172..47cfef36777 100644
--- a/modular_skyrat/modules/inflatables/code/inflatable.dm
+++ b/modular_skyrat/modules/inflatables/code/inflatable.dm
@@ -53,11 +53,9 @@
return
return ..()
-/obj/structure/inflatable/AltClick(mob/user)
- . = ..()
- if(!user.can_interact_with(src))
- return
+/obj/structure/inflatable/click_alt(mob/user)
deflate(FALSE)
+ return CLICK_ACTION_SUCCESS
/obj/structure/inflatable/play_attack_sound(damage_amount, damage_type, damage_flag)
playsound(src, hit_sound, 75, TRUE)
diff --git a/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm b/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm
index 6f83d6b41b8..d28aec8e8b0 100644
--- a/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm
+++ b/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm
@@ -261,11 +261,5 @@ GLOBAL_LIST_EMPTY_TYPED(interaction_instances, /datum/interaction)
GLOB.interaction_instances[iname] = interaction
-/client/proc/reload_interactions()
- set category = "Debug"
- set name = "Reload Interactions"
- set desc = "Force reload interactions"
- if(!check_rights(R_DEBUG))
- return
-
+ADMIN_VERB(reload_interactions, R_DEBUG, "Reload Interactions", "Force reload interactions.", ADMIN_CATEGORY_DEBUG)
populate_interaction_instances()
diff --git a/modular_skyrat/modules/jukebox/code/dance_machine.dm b/modular_skyrat/modules/jukebox/code/dance_machine.dm
index 09d335f4460..54c8e27ed89 100644
--- a/modular_skyrat/modules/jukebox/code/dance_machine.dm
+++ b/modular_skyrat/modules/jukebox/code/dance_machine.dm
@@ -37,8 +37,6 @@
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
-
/obj/machinery/jukebox/public
req_access = list()
falloff_dist_offset = 10
@@ -55,7 +53,7 @@
return ..()
/obj/machinery/jukebox/attackby(obj/item/O, mob/user, params)
- if(!active && !(obj_flags & NO_DECONSTRUCTION))
+ if(!active)
if(O.tool_behaviour == TOOL_WRENCH)
if(!anchored && !isinspace())
to_chat(user,span_notice("You secure [src] to the floor."))
diff --git a/modular_skyrat/modules/knives/knives.dm b/modular_skyrat/modules/knives/knives.dm
index 4a7439d3e76..d177a3a24d9 100644
--- a/modular_skyrat/modules/knives/knives.dm
+++ b/modular_skyrat/modules/knives/knives.dm
@@ -24,25 +24,26 @@
slot_flags = ITEM_SLOT_POCKETS
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
+ interaction_flags_click = NEED_DEXTERITY
/obj/item/storage/belt/bowie_sheath/Initialize(mapload)
. = ..()
atom_storage.max_slots = 1
atom_storage.max_total_storage = WEIGHT_CLASS_BULKY
atom_storage.set_holdable(list(
- /obj/item/knife/bowie
+ /obj/item/knife/bowie,
))
-/obj/item/storage/belt/bowie_sheath/AltClick(mob/user)
- if(!user.can_perform_action(src, NEED_DEXTERITY))
- return
+/obj/item/storage/belt/bowie_sheath/click_alt(mob/user)
if(length(contents))
var/obj/item/knife = contents[1]
user.visible_message(span_notice("[user] takes [knife] out of [src]."), span_notice("You take [knife] out of [src]."))
user.put_in_hands(knife)
update_appearance()
+ return CLICK_ACTION_SUCCESS
else
to_chat(user, span_warning("[src] is empty!"))
+ return CLICK_ACTION_BLOCKING
/obj/item/storage/belt/bowie_sheath/update_icon_state()
icon_state = initial(icon_state)
diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm
index ed462fceaf5..b53cbc3bf04 100644
--- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm
+++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm
@@ -112,10 +112,5 @@ SUBSYSTEM_DEF(liquids)
if(T.lgroup)
T.lgroup.amount_of_active_turfs--
-/client/proc/toggle_liquid_debug()
- set category = "Debug"
- set name = "Liquid Groups Color Debug"
- set desc = "Liquid Groups Color Debug."
- if(!holder)
- return
+ADMIN_VERB(toggle_liquid_debug, R_DEBUG, "Liquid Groups Color Debug", "Liquid Groups Color Debug.", ADMIN_CATEGORY_DEBUG)
GLOB.liquid_debug_colors = !GLOB.liquid_debug_colors
diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm
index 17d6c87f284..c97f06140c0 100644
--- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm
+++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm
@@ -8,6 +8,7 @@
max_integrity = 500
anchored = FALSE
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ interaction_flags_click = NEED_DEXTERITY
/// How many reagents at maximum can it hold
var/max_volume = 10000
/// Whether spewing reagents out, instead of siphoning them
@@ -33,12 +34,11 @@
to_chat(user, span_notice("You turn [src] [turned_on ? "off" : "on"]."))
toggle_working()
-/obj/structure/liquid_pump/AltClick(mob/living/user)
- if(!user.can_perform_action(src, NEED_DEXTERITY))
- return
+/obj/structure/liquid_pump/click_alt(mob/living/user)
to_chat(user, span_notice("You flick [src]'s spewing mode [spewing_mode ? "off" : "on"]."))
spewing_mode = !spewing_mode
update_icon()
+ return CLICK_ACTION_SUCCESS
/obj/structure/liquid_pump/examine(mob/user)
. = ..()
diff --git a/modular_skyrat/modules/liquids/code/tools.dm b/modular_skyrat/modules/liquids/code/tools.dm
index 1ee43b78a37..2252835f2b2 100644
--- a/modular_skyrat/modules/liquids/code/tools.dm
+++ b/modular_skyrat/modules/liquids/code/tools.dm
@@ -1,12 +1,8 @@
-/client/proc/spawn_liquid()
- set category = "Admin.Fun"
- set name = "Spawn Liquid"
- set desc = "Spawns an amount of chosen liquid at your current location."
-
+ADMIN_VERB(spawn_liquid, R_ADMIN, "Spawn Liquid", "Spawns an amount of chosen liquid at your current location.", ADMIN_CATEGORY_FUN)
var/choice
var/valid_id
while(!valid_id)
- choice = tgui_input_text(usr, "Enter the ID of the reagent you want to add.", "Search reagents")
+ choice = tgui_input_text(user, "Enter the ID of the reagent you want to add.", "Search reagents")
if(isnull(choice)) //Get me out of here!
break
if (!ispath(text2path(choice)))
@@ -16,26 +12,21 @@
else
valid_id = TRUE
if(!valid_id)
- to_chat(usr, span_warning("A reagent with that ID doesn't exist!"))
+ to_chat(user, span_warning("A reagent with that ID doesn't exist!"))
if(!choice)
return
- var/volume = tgui_input_number(usr, "Volume:", "Choose volume")
+ var/volume = tgui_input_number(user, "Volume:", "Choose volume")
if(!volume)
return
- var/turf/epicenter = get_turf(mob)
+ var/turf/epicenter = get_turf(user.mob)
epicenter.add_liquid(choice, volume)
- message_admins("[ADMIN_LOOKUPFLW(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
- log_admin("[key_name(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
+ message_admins("[ADMIN_LOOKUPFLW(user)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
+ log_admin("[key_name(user)] spawned liquid at [epicenter.loc] ([choice] - [volume]).")
-/client/proc/remove_liquid(turf/epicenter in world)
- set name = "Remove Liquids"
- set category = "Admin.Game"
- set desc = "Fixes air in specified radius."
-
- var/range = tgui_input_number(usr, "Enter range:", "Range selection", 2)
+ADMIN_VERB_AND_CONTEXT_MENU(remove_liquid, R_ADMIN, "Remove liquids", "Removes all liquids in specified radius.", ADMIN_CATEGORY_GAME, turf/epicenter in world)
+ var/range = tgui_input_number(user, "Enter range:", "Range selection", 2)
for(var/obj/effect/abstract/liquid_turf/liquid in range(range, epicenter))
qdel(liquid, TRUE)
- message_admins("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]")
- log_game("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]")
+ message_admins("[key_name_admin(user)] removed liquids with range [range] in [epicenter.loc.name]")
diff --git a/modular_skyrat/modules/lorecaster/code/story_manager.dm b/modular_skyrat/modules/lorecaster/code/story_manager.dm
index 3b60915bb69..5bb613c7030 100644
--- a/modular_skyrat/modules/lorecaster/code/story_manager.dm
+++ b/modular_skyrat/modules/lorecaster/code/story_manager.dm
@@ -1,10 +1,4 @@
-/client/proc/lorecaster_story_manager()
- set category = "Admin.Events"
- set name = "Lorecaster Stories"
-
- if(!check_rights(R_ADMIN))
- return
-
+ADMIN_VERB(lorecaster_story_manager, R_ADMIN, "Lorecaster Stories", "Open the Lorecaster Story Manager.", ADMIN_CATEGORY_EVENTS)
var/datum/story_manager_interface/ui = new(usr)
ui.ui_interact(usr)
diff --git a/modular_skyrat/modules/mapping/code/machinery.dm b/modular_skyrat/modules/mapping/code/machinery.dm
index 53500a29628..04fc7cca5f2 100644
--- a/modular_skyrat/modules/mapping/code/machinery.dm
+++ b/modular_skyrat/modules/mapping/code/machinery.dm
@@ -13,9 +13,6 @@
/obj/item/gps/computer/space/wrench_act(mob/living/user, obj/item/I)
. = ..()
- if(obj_flags & NO_DECONSTRUCTION)
- return TRUE
-
if(I.use_tool(src, user, 20, volume=50))
user.visible_message(span_warning("[user] disassembles [src]."),
span_notice("You start to disassemble [src]..."), span_hear("You hear clanking and banging noises."))
diff --git a/modular_skyrat/modules/mapping/code/shuttles.dm b/modular_skyrat/modules/mapping/code/shuttles.dm
index d50ae38bc5c..89d0aade9c7 100644
--- a/modular_skyrat/modules/mapping/code/shuttles.dm
+++ b/modular_skyrat/modules/mapping/code/shuttles.dm
@@ -69,7 +69,16 @@
shuttleId = "slaver_syndie"
possible_destinations = "syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
+
+// previously NO_DECONSTRUCTION
+/obj/machinery/computer/shuttle/slaver/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/computer/shuttle/slaver/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/computer/shuttle/slaver/default_pry_open(obj/item/crowbar, close_after_pry = FALSE, open_density = FALSE, closed_density = TRUE)
+ return NONE
/datum/map_template/shuttle/slaver_ship
port_id = "slaver ship"
diff --git a/modular_skyrat/modules/medical/code/anesthetic_machine.dm b/modular_skyrat/modules/medical/code/anesthetic_machine.dm
index 69b1bab7b70..eb42dda946e 100644
--- a/modular_skyrat/modules/medical/code/anesthetic_machine.dm
+++ b/modular_skyrat/modules/medical/code/anesthetic_machine.dm
@@ -78,10 +78,9 @@
attached_tank = attacking_item
update_icon()
-/obj/machinery/anesthetic_machine/AltClick(mob/user)
- . = ..()
+/obj/machinery/anesthetic_machine/click_alt(mob/user)
if(!attached_tank)
- return
+ return CLICK_ACTION_BLOCKING
attached_tank.forceMove(loc)
to_chat(user, span_notice("You remove the [attached_tank]."))
@@ -89,6 +88,7 @@
update_icon()
if(mask_out)
retract_mask()
+ return CLICK_ACTION_SUCCESS
///Retracts the attached_mask back into the machine
/obj/machinery/anesthetic_machine/proc/retract_mask()
diff --git a/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm b/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm
index b44acde2567..d130ad30829 100644
--- a/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm
+++ b/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm
@@ -1,41 +1,8 @@
-/// The amount of cell charge drained during a drain failure.
-#define MICROFUSION_CELL_DRAIN_FAILURE 500
-/// The heavy EMP range for when a cell suffers an EMP failure.
-#define MICROFUSION_CELL_EMP_HEAVY_FAILURE 2
-/// The light EMP range for when a cell suffers an EMP failure.
-#define MICROFUSION_CELL_EMP_LIGHT_FAILURE 4
-/// The radiation range for when a cell suffers a radiation failure.
-#define MICROFUSION_CELL_RADIATION_RANGE_FAILURE 1
-
-/// The lower most time for a microfusion cell meltdown.
-#define MICROFUSION_CELL_FAILURE_LOWER (10 SECONDS)
-/// The upper most time for a microfusion cell meltdown.
-#define MICROFUSION_CELL_FAILURE_UPPER (15 SECONDS)
-
-/// A charge drain failure.
-#define MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN 1
-/// A small explosion failure.
-#define MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION 2
-/// EMP failure.
-#define MICROFUSION_CELL_FAILURE_TYPE_EMP 3
-/// Radiation failure.
-#define MICROFUSION_CELL_FAILURE_TYPE_RADIATION 4
-
/// Returned when the phase emtiter process is successful.
#define SHOT_SUCCESS "success"
/// Returned when a gun is fired but there is no phase emitter.
#define SHOT_FAILURE_NO_EMITTER "no phase emitter!"
-/// The error message returned when the phase emitter is processed but damaged.
-#define PHASE_FAILURE_DAMAGED "PHASE EMITTER: Emitter damaged!"
-/// The error message returned when the phase emitter has reached it's htermal throttle.
-#define PHASE_FAILURE_THROTTLE "PHASE EMITTER: Thermal throttle active!"
-
-/// The heat dissipation bonus of an emitter being in space!
-#define PHASE_HEAT_DISSIPATION_BONUS_SPACE 30
-/// The heat dissipation bonus of an emitter being in air!
-#define PHASE_HEAT_DISSIPATION_BONUS_AIR 10
-
// Slot defines for the gun.
/// The gun barrel slot.
#define GUN_SLOT_BARREL "barrel"
@@ -47,8 +14,3 @@
#define GUN_SLOT_UNIQUE "unique"
/// Camo slot. Because why would you put four overlapping camos on your gun?
#define GUN_SLOT_CAMO "camo"
-
-/// Max name size for changing names
-#define GUN_MAX_NAME_CHARS 20
-/// Min name size for changing names
-#define GUN_MIN_NAME_CHARS 3
diff --git a/modular_skyrat/modules/microfusion/code/microfusion_cell.dm b/modular_skyrat/modules/microfusion/code/microfusion_cell.dm
index 09d403e3fa5..515dc89f174 100644
--- a/modular_skyrat/modules/microfusion/code/microfusion_cell.dm
+++ b/modular_skyrat/modules/microfusion/code/microfusion_cell.dm
@@ -6,6 +6,29 @@ Microfusion cells are small battery units that house controlled nuclear fusion w
Essentially, power cells that malfunction if not used in an MCR, and should only be able to charge inside of one
*/
+/// The amount of cell charge drained during a drain failure.
+#define MICROFUSION_CELL_DRAIN_FAILURE STANDARD_CELL_CHARGE * 0.5
+/// The heavy EMP range for when a cell suffers an EMP failure.
+#define MICROFUSION_CELL_EMP_HEAVY_FAILURE 2
+/// The light EMP range for when a cell suffers an EMP failure.
+#define MICROFUSION_CELL_EMP_LIGHT_FAILURE 4
+/// The radiation range for when a cell suffers a radiation failure.
+#define MICROFUSION_CELL_RADIATION_RANGE_FAILURE 1
+
+/// The lower most time for a microfusion cell meltdown.
+#define MICROFUSION_CELL_FAILURE_LOWER (10 SECONDS)
+/// The upper most time for a microfusion cell meltdown.
+#define MICROFUSION_CELL_FAILURE_UPPER (15 SECONDS)
+
+/// A charge drain failure.
+#define MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN 1
+/// A small explosion failure.
+#define MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION 2
+/// EMP failure.
+#define MICROFUSION_CELL_FAILURE_TYPE_EMP 3
+/// Radiation failure.
+#define MICROFUSION_CELL_FAILURE_TYPE_RADIATION 4
+
/obj/item/stock_parts/cell/microfusion //Just a standard cell.
name = "microfusion cell"
desc = "A standard-issue microfusion cell, produced by Micron Control Systems. For safety reasons, they cannot be charged unless they are inside of a compatible Micron Control Systems firearm."
@@ -13,7 +36,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only
charging_icon = "mf_in" //This is stored in cell.dmi in the aesthetics module
icon_state = "microfusion"
w_class = WEIGHT_CLASS_NORMAL
- maxcharge = 1200 //12 shots
+ maxcharge = STANDARD_CELL_CHARGE
chargerate = 0 //MF cells should be unable to recharge if they are not currently inside of an MCR
microfusion_readout = TRUE
empty = TRUE //MF cells should start empty
@@ -153,7 +176,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only
update_appearance()
/obj/item/stock_parts/cell/microfusion/proc/inserted_into_weapon()
- chargerate = 300
+ chargerate = STANDARD_CELL_CHARGE * 0.2
/obj/item/stock_parts/cell/microfusion/proc/cell_removal_discharge()
chargerate = 0
@@ -176,7 +199,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only
name = "makeshift microfusion cell"
desc = "An... Apparatus, comprised of an everyday aluminum can with several civilian-grade batteries tightly packed together and plugged in. This vaguely resembles a microfusion cell, if you tilt your head to a precise fifty degree angle. While the effects on enemy combatants may be dubious, it will certainly do incredible damage to the gun's warranty. What the hell were you thinking when you came up with this?"
icon_state = "microfusion_makeshift"
- maxcharge = 600
+ maxcharge = STANDARD_CELL_CHARGE * 0.5
max_attachments = 0
/obj/item/stock_parts/cell/microfusion/makeshift/use(amount, force = FALSE)
@@ -188,26 +211,39 @@ Essentially, power cells that malfunction if not used in an MCR, and should only
name = "enhanced microfusion cell"
desc = "A second generation microfusion cell, weighing about the same as the standard-issue cell and having the same space for attachments; however, it has a higher capacity."
icon_state = "microfusion_enhanced"
- maxcharge = 1500
+ maxcharge = STANDARD_CELL_CHARGE * 1.4
/obj/item/stock_parts/cell/microfusion/advanced
name = "advanced microfusion cell"
desc = "A third generation microfusion cell, boasting a much higher shot count. Additionally, these come with support for up to three modifications to the cell itself."
icon_state = "microfusion_advanced"
- maxcharge = 1700
+ maxcharge = STANDARD_CELL_CHARGE * 1.5
max_attachments = 3
/obj/item/stock_parts/cell/microfusion/bluespace
name = "bluespace microfusion cell"
desc = "A fourth generation microfusion cell, employing bluespace technology to store power in a medium that's bigger on the inside. This has capacity for four modifications to the cell."
icon_state = "microfusion_bluespace"
- maxcharge = 2000
+ maxcharge = STANDARD_CELL_CHARGE * 1.6
max_attachments = 4
/obj/item/stock_parts/cell/microfusion/nanocarbon
name = "nanocarbon fusion cell"
desc = "This cell combines both top-of-the-line nanotech and advanced microfusion power to brute force the most common issue of Nanotrasen Asset Protection operatives, ammunition, through sheer volume. Intended for use with Nanotrasen-brand capacitor arrays only. Warranty void if dropped in toilet."
icon_state = "microfusion_nanocarbon"
- maxcharge = 30000
+ maxcharge = STANDARD_CELL_CHARGE * 60 // Wanted to put 69 here to fit with the 420 but eh this werks too
max_attachments = 420
+
+#undef MICROFUSION_CELL_DRAIN_FAILURE
+#undef MICROFUSION_CELL_EMP_HEAVY_FAILURE
+#undef MICROFUSION_CELL_EMP_LIGHT_FAILURE
+#undef MICROFUSION_CELL_RADIATION_RANGE_FAILURE
+
+#undef MICROFUSION_CELL_FAILURE_LOWER
+#undef MICROFUSION_CELL_FAILURE_UPPER
+
+#undef MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN
+#undef MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION
+#undef MICROFUSION_CELL_FAILURE_TYPE_EMP
+#undef MICROFUSION_CELL_FAILURE_TYPE_RADIATION
diff --git a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm
index e242cebbc1c..6dce4269ef8 100644
--- a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm
+++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm
@@ -91,7 +91,7 @@
else
cell = new(src)
cell.parent_gun = src
- cell.chargerate = 300
+ cell.chargerate = STANDARD_CELL_CHARGE * 0.2
if(!dead_cell)
cell.give(cell.maxcharge)
if(phase_emitter_type)
@@ -263,13 +263,12 @@
playsound(src, 'sound/items/crowbar.ogg', 70, TRUE)
remove_emitter()
-/obj/item/gun/microfusion/AltClick(mob/user)
- . = ..()
- if(can_interact(user))
- var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments)
- if(!to_remove)
- return
- remove_attachment(to_remove, user)
+/obj/item/gun/microfusion/click_alt(mob/user)
+ var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments)
+ if(!to_remove)
+ return CLICK_ACTION_BLOCKING
+ remove_attachment(to_remove, user)
+ return CLICK_ACTION_SUCCESS
/obj/item/gun/microfusion/proc/remove_all_attachments()
if(attachments.len)
diff --git a/modular_skyrat/modules/microfusion/code/phase_emitter.dm b/modular_skyrat/modules/microfusion/code/phase_emitter.dm
index f213ff4896f..eade9e3407b 100644
--- a/modular_skyrat/modules/microfusion/code/phase_emitter.dm
+++ b/modular_skyrat/modules/microfusion/code/phase_emitter.dm
@@ -2,6 +2,16 @@
* PHASE EMITTERS
*/
+/// The error message returned when the phase emitter is processed but damaged.
+#define PHASE_FAILURE_DAMAGED "PHASE EMITTER: Emitter damaged!"
+/// The error message returned when the phase emitter has reached it's htermal throttle.
+#define PHASE_FAILURE_THROTTLE "PHASE EMITTER: Thermal throttle active!"
+
+/// The heat dissipation bonus of an emitter being in space!
+#define PHASE_HEAT_DISSIPATION_BONUS_SPACE 30
+/// The heat dissipation bonus of an emitter being in air!
+#define PHASE_HEAT_DISSIPATION_BONUS_AIR 10
+
/*
* Basically the heart of the gun, can be upgraded.
*/
@@ -212,3 +222,13 @@
cooling_system_rate = 60
integrity = 500
color = "#6966ff"
+
+
+#undef PHASE_FAILURE_DAMAGED
+#undef PHASE_FAILURE_THROTTLE
+
+#undef PHASE_HEAT_DISSIPATION_BONUS_SPACE
+#undef PHASE_HEAT_DISSIPATION_BONUS_AIR
+
+#undef SHOT_SUCCESS
+#undef SHOT_FAILURE_NO_EMITTER
diff --git a/modular_skyrat/modules/microfusion/code/projectiles.dm b/modular_skyrat/modules/microfusion/code/projectiles.dm
index 53f19941f8d..03849b456a2 100644
--- a/modular_skyrat/modules/microfusion/code/projectiles.dm
+++ b/modular_skyrat/modules/microfusion/code/projectiles.dm
@@ -5,7 +5,7 @@
/obj/item/ammo_casing/energy/laser/microfusion
name = "microfusion energy lens"
projectile_type = /obj/projectile/beam/laser/microfusion
- e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) // 10 shots with a normal cell.
+ e_cost = LASER_SHOTS(12, STANDARD_CELL_CHARGE)
select_name = "laser"
fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg'
fire_sound_volume = 100
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm
index 9d2fae9d311..ef18300ddab 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm
@@ -72,20 +72,17 @@
"cyan" = image(icon = src.icon, icon_state = "mask_cyan_off"))
// Using multitool on pole
-/obj/item/clothing/mask/gas/bdsm_mask/AltClick(mob/user)
+/obj/item/clothing/mask/gas/bdsm_mask/click_alt(mob/user)
if(color_changed == FALSE)
- if(.)
- return
var/choice = show_radial_menu(user, src, mask_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_mask_color = choice
update_icon_state()
update_icon()
update_mob_action_buttonss()
color_changed = TRUE
- return
- . = ..()
+ return CLICK_ACTION_SUCCESS
// To check if we can change mask's model
/obj/item/clothing/mask/gas/bdsm_mask/proc/check_menu(mob/living/user)
@@ -321,6 +318,7 @@
volume = 50
possible_transfer_amounts = list(1, 2, 3, 4, 5, 10, 25, 50)
list_reagents = list(/datum/reagent/drug/aphrodisiac/crocin = 50)
+ interaction_flags_click = NEED_DEXTERITY
// Standard initialize code for filter
/obj/item/reagent_containers/cup/lewd_filter/Initialize(mapload)
@@ -337,11 +335,7 @@
addtimer(CALLBACK(reagents, TYPE_PROC_REF(/datum/reagents, trans_to), user, amount_per_transfer_from_this, TRUE, TRUE, FALSE, user, FALSE, INGEST), 0.5 SECONDS)
// I just wanted to add 2th color variation. Because.
-/obj/item/reagent_containers/cup/lewd_filter/AltClick(mob/user)
- // Catch first AltClick and open reskin menu
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
- return
+/obj/item/reagent_containers/cup/lewd_filter/click_alt(mob/user)
// After reskin all clicks go normal, but we can't change the flow rate if mask on and equipped
var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK)
if(worn_mask)
@@ -350,8 +344,8 @@
if(worn_mask.mask_on == TRUE)
if(istype(src, /obj/item/reagent_containers/cup/lewd_filter))
to_chat(user, span_warning("You can't change the flow rate of the valve while the mask is on!"))
- return
- . = ..()
+ return CLICK_ACTION_BLOCKING
+ return ..()
// Filter click handling
/obj/item/reagent_containers/cup/lewd_filter/attack_hand(mob/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm
index 821e056bb94..f537d9166f8 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm
@@ -17,10 +17,11 @@
/// Has it been laced tightly?
var/laced_tight = FALSE
-/obj/item/clothing/suit/corset/AltClick(mob/user)
+/obj/item/clothing/suit/corset/click_alt(mob/user)
laced_tight = !laced_tight
to_chat(user, span_notice("You [laced_tight ? "tighten" : "loosen"] the corset, making it far [laced_tight ? "harder" : "easier"] to breathe."))
play_lewd_sound(user, laced_tight ? 'sound/items/handling/cloth_pickup.ogg' : 'sound/items/handling/cloth_drop.ogg', 40, TRUE)
+ . = CLICK_ACTION_SUCCESS
if(laced_tight)
slowdown = TIGHT_SLOWDOWN
return
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm
index a6188a546e4..7bcad0d4879 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm
@@ -129,20 +129,18 @@
"tealn" = image(icon = src.icon, icon_state = "dephelmet_tealn"))
// To change model
-/obj/item/clothing/head/deprivation_helmet/AltClick(mob/user)
+/obj/item/clothing/head/deprivation_helmet/click_alt(mob/user)
if(color_changed == FALSE)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, helmet_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_helmet_color = choice
update_icon()
update_mob_action_buttonss()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
else
- return
+ return CLICK_ACTION_BLOCKING
/obj/item/clothing/head/deprivation_helmet/proc/update_mob_action_buttonss()
var/datum/action/item_action/action_button
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm
index 554cfab890c..5150f7a539b 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm
@@ -58,18 +58,16 @@
"teal" = image(icon = src.icon, icon_state = "hypnogoggles_teal"))
//to change model
-/obj/item/clothing/glasses/hypno/AltClick(mob/user)
+/obj/item/clothing/glasses/hypno/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, hypnogoggles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_hypnogoggles_color = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
//to check if we can change kinkphones's model
/obj/item/clothing/glasses/hypno/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm
index aa8ff23f1b6..025d267680e 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm
@@ -35,10 +35,7 @@
body_parts_covered = NECK
slot_flags = ITEM_SLOT_NECK
w_class = WEIGHT_CLASS_SMALL
- /// What the name on the tag is
- var/tagname = null
- /// Item path of on-init creation in the collar's storage
- var/treat_path = /obj/item/food/cookie
+ interaction_flags_click = NEED_DEXTERITY
unique_reskin = list("Cyan" = "collar_cyan",
"Yellow" = "collar_yellow",
"Green" = "collar_green",
@@ -50,6 +47,10 @@
"Black" = "collar_black",
"Black-teal" = "collar_tealblack",
"Spike" = "collar_spike")
+ /// What the name on the tag is
+ var/tagname = null
+ /// Item path of on-init creation in the collar's storage
+ var/treat_path = /obj/item/food/cookie
//spawn thing in collar
@@ -66,13 +67,6 @@
var/obj/item/key/kink_collar/collar_key = key
collar_key.key_id = id
-//reskin code
-
-/obj/item/clothing/neck/kink_collar/AltClick(mob/user)
- . = ..()
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
-
//rename collar code
/obj/item/clothing/neck/kink_collar/attack_self(mob/user)
@@ -90,10 +84,7 @@
worn_icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/mob/lewd_clothing/lewd_neck.dmi'
icon_state = "lock_collar_cyan"
treat_path = /obj/item/key/kink_collar
- /// If the collar is currently locked
- var/locked = FALSE
- /// If the collar has been broken or not
- var/broken = FALSE
+ interaction_flags_click = NEED_DEXTERITY
unique_reskin = list("Cyan" = "lock_collar_cyan",
"Yellow" = "lock_collar_yellow",
"Green" = "lock_collar_green",
@@ -105,6 +96,10 @@
"Black" = "lock_collar_black",
"Black-teal" = "lock_collar_tealblack",
"Spike" = "lock_collar_spike")
+ /// If the collar is currently locked
+ var/locked = FALSE
+ /// If the collar has been broken or not
+ var/broken = FALSE
/obj/item/clothing/neck/kink_collar/locked/Initialize(mapload)
. = ..()
@@ -112,13 +107,6 @@
//spawn thing in collar
-//reskin code
-
-/obj/item/clothing/neck/kink_collar/locked/AltClick(mob/user)
- . = ..()
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
-
//locking or unlocking collar code
/obj/item/clothing/neck/kink_collar/locked/proc/IsLocked(to_lock, mob/user)
@@ -176,6 +164,7 @@
icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_items/lewd_items.dmi'
icon_state = "collar_key_metal"
base_icon_state = "collar_key"
+ interaction_flags_click = NEED_DEXTERITY
/// The name inscribed on the key
var/keyname = null
/// The ID of the key to pair with a collar. Will normally be the ref of the collar
@@ -192,12 +181,6 @@
"Metal" = "collar_key_metal",
"Black-teal" = "collar_key_tealblack")
-//changing color of key in case if we using multiple collars
-/obj/item/key/kink_collar/AltClick(mob/user)
- . = ..()
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
-
//changing name of key in case if we using multiple collars with same color
/obj/item/key/kink_collar/attack_self(mob/user)
keyname = stripped_input(user, "Would you like to change the name on the key?", "Renaming key", "Key", MAX_NAME_LEN)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm
index 40a716f3175..6e1674fc87f 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm
@@ -22,19 +22,16 @@
"teal" = image(icon = src.icon, icon_state = "kblindfold_teal"))
//to change model
-/obj/item/clothing/glasses/blindfold/kinky/AltClick(mob/user)
+/obj/item/clothing/glasses/blindfold/kinky/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, kinkfold_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_kinkfold_color = choice
update_icon()
color_changed = TRUE
-
+ return CLICK_ACTION_SUCCESS
/// to check if we can change kinkphones's model
/obj/item/clothing/glasses/blindfold/kinky/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm
index eb4ed5bf142..8e73ea7d434 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm
@@ -28,18 +28,16 @@
"teal" = image(icon = src.icon, icon_state = "kinkphones_teal_on"))
//to change model
-/obj/item/clothing/ears/kinky_headphones/AltClick(mob/user)
+/obj/item/clothing/ears/kinky_headphones/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, kinkphones_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_kinkphones_color = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/// to check if we can change kinkphones's model
/obj/item/clothing/ears/kinky_headphones/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm
index 2f1588738cb..43e2ea0c904 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm
@@ -48,23 +48,21 @@
"deflated" = image(icon = src.icon, icon_state = "sleepbag_teal_deflated_folded"))
//to change model
-/obj/item/clothing/suit/straight_jacket/kinky_sleepbag/AltClick(mob/user)
+/obj/item/clothing/suit/straight_jacket/kinky_sleepbag/click_alt(mob/user)
var/mob/living/carbon/human/clicking_human = user
if(istype(clicking_human.wear_suit, /obj/item/clothing/suit/straight_jacket/kinky_sleepbag))
to_chat(user, span_warning("Your hands are stuck, you can't do this!"))
- return FALSE
+ return CLICK_ACTION_BLOCKING
switch(color_changed)
if(FALSE)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, bag_colors, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
bag_color = choice
update_icon()
update_icon_state()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
if(TRUE)
if(bag_state == "deflated")
@@ -72,8 +70,10 @@
to_chat(user, span_notice("The sleeping bag now is [bag_fold? "folded." : "unfolded."]"))
update_icon()
update_icon_state()
+ return CLICK_ACTION_SUCCESS
else
to_chat(user, span_notice("You can't fold the bag while it's inflated!"))
+ return CLICK_ACTION_BLOCKING
/obj/item/clothing/suit/straight_jacket/kinky_sleepbag/proc/check_menu(mob/living/user)
if(!istype(user))
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm
index 00caec39977..53b01b6699e 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm
@@ -48,18 +48,16 @@
"yellow" = image (icon = src.icon, icon_state = "lewdapron_yellow"))
//to change model
-/obj/item/clothing/accessory/lewdapron/AltClick(mob/user)
+/obj/item/clothing/accessory/lewdapron/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, apron_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/// to check if we can change kinkphones's model
/obj/item/clothing/accessory/lewdapron/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm
index e062af59494..5201bb02a35 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm
@@ -33,19 +33,17 @@
"metal" = image (icon = src.icon, icon_state = "shackles_metal"))
//to change model
-/obj/item/clothing/suit/straight_jacket/shackles/AltClick(mob/user)
- if(color_changed == FALSE)
- . = ..()
- if(.)
- return
- var/choice = show_radial_menu(user, src, shackles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
- if(!choice)
- return FALSE
- current_color = choice
- update_icon()
- color_changed = TRUE
- else
- return
+/obj/item/clothing/suit/straight_jacket/shackles/click_alt(mob/user)
+ if(color_changed)
+ return CLICK_ACTION_BLOCKING
+
+ var/choice = show_radial_menu(user, src, shackles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
+ if(!choice)
+ return CLICK_ACTION_BLOCKING
+ current_color = choice
+ update_icon()
+ color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
//to check if we can change shackles' model
/obj/item/clothing/suit/straight_jacket/shackles/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm
index b248a0aca88..866526dea48 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm
@@ -60,13 +60,12 @@
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
-/obj/item/clothing/under/shibari/AltClick(mob/user)
- . = ..()
+/obj/item/clothing/under/shibari/click_alt(mob/user)
if(!ishuman(loc))
- return
+ return CLICK_ACTION_BLOCKING
var/mob/living/carbon/human/hooman = loc
if(user == hooman)
- return
+ return CLICK_ACTION_BLOCKING
switch(tightness)
if(SHIBARI_TIGHTNESS_LOW)
tightness = SHIBARI_TIGHTNESS_MED
@@ -74,6 +73,7 @@
tightness = SHIBARI_TIGHTNESS_HIGH
if(SHIBARI_TIGHTNESS_HIGH)
tightness = SHIBARI_TIGHTNESS_LOW
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/under/shibari/process(seconds_per_tick)
if(!ishuman(loc))
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm
index ec2fc7c0d9b..a7e1182d324 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm
@@ -23,19 +23,16 @@
"human" = image (icon = src.icon, icon_state = "strapon_human"))
//to change model
-/obj/item/clothing/strapon/AltClick(mob/user)
- if(type_changed == FALSE)
- . = ..()
- if(.)
- return
- var/choice = show_radial_menu(user, src, strapon_types, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
- if(!choice)
- return FALSE
- strapon_type = choice
- update_icon()
- type_changed = TRUE
- else
- return
+/obj/item/clothing/strapon/click_alt(mob/user)
+ if(type_changed)
+ return CLICK_ACTION_BLOCKING
+ var/choice = show_radial_menu(user, src, strapon_types, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
+ if(!choice)
+ return CLICK_ACTION_BLOCKING
+ strapon_type = choice
+ update_icon()
+ type_changed = TRUE
+ return CLICK_ACTION_SUCCESS
//Check if we can change strapon's model
/obj/item/clothing/strapon/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm
index 545748165c4..f2de5f7f900 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm
@@ -11,6 +11,7 @@
can_adjust = FALSE
icon_state = "stripper_cyan"
inhand_icon_state = "b_suit"
+ interaction_flags_click = NEED_DEXTERITY
unique_reskin = list("Cyan" = "stripper_cyan",
"Yellow" = "stripper_yellow",
"Green" = "stripper_green",
@@ -21,8 +22,3 @@
"Purple" = "stripper_purple",
"Black" = "stripper_black",
"Black-teal" = "stripper_tealblack")
-
-/obj/item/clothing/under/stripper_outfit/AltClick(mob/user)
- . = ..()
- if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY))
- reskin_obj(user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm
index 13423a26016..1db92a08430 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm
@@ -39,11 +39,8 @@
"pink" = image(icon = src.icon, icon_state = "[initial(base_icon_state)]_pink_low[(istype(src, /obj/item/clothing/sextoy/eggvib/signalvib)) ? "_on" : ""]"),
"teal" = image(icon = src.icon, icon_state = "[initial(base_icon_state)]_teal_low[(istype(src, /obj/item/clothing/sextoy/eggvib/signalvib)) ? "_on" : ""]"))
-/obj/item/clothing/sextoy/eggvib/AltClick(mob/user)
+/obj/item/clothing/sextoy/eggvib/click_alt(mob/user)
if(!color_changed)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, vib_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
@@ -63,6 +60,7 @@
to_chat(user, span_notice("You turn off the vibrating egg. Fun time's over."))
update_icon()
update_icon_state()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/eggvib/Initialize(mapload)
. = ..()
@@ -190,18 +188,18 @@
//arousal stuff
-/obj/item/clothing/sextoy/eggvib/signalvib/AltClick(mob/user)
+/obj/item/clothing/sextoy/eggvib/signalvib/click_alt(mob/user)
if(!color_changed)
var/choice = show_radial_menu(user, src, vib_designs, custom_check = CALLBACK(src, /obj/item/clothing/sextoy/proc/check_menu, user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
color_changed = TRUE
else
if(!toy_on)
- to_chat(usr, span_notice("You can't switch modes while the vibrating egg is turned off!"))
- return
+ to_chat(user, span_notice("You can't switch modes while the vibrating egg is turned off!"))
+ return CLICK_ACTION_BLOCKING
toggle_mode()
soundloop1.stop()
soundloop2.stop()
@@ -218,6 +216,7 @@
soundloop3.start()
update_icon()
update_icon_state()
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/eggvib/signalvib/receive_signal(datum/signal/signal)
if(!signal || signal.data["code"] != code)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm
index 7297472b8da..5bcc5129e03 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm
@@ -40,31 +40,27 @@
"medium" = image(icon = src.icon, icon_state = "buttplug_pink_medium"),
"big" = image(icon = src.icon, icon_state = "buttplug_pink_big"))
-/obj/item/clothing/sextoy/buttplug/AltClick(mob/user)
+/obj/item/clothing/sextoy/buttplug/click_alt(mob/user)
if(!color_changed)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, buttplug_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
if(choice == "green")
set_light(0.25)
update_light()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
else
if(form_changed == FALSE)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, buttplug_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_size = choice
update_icon()
form_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/buttplug/Initialize(mapload)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm
index c7256be1610..9feeb963a09 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm
@@ -41,18 +41,16 @@
"human" = image(icon = src.icon, icon_state = "[base_icon_state]_human"),
"tentacle" = image(icon = src.icon, icon_state = "[base_icon_state]_tentacle"))
-/obj/item/clothing/sextoy/dildo/AltClick(mob/user)
+/obj/item/clothing/sextoy/dildo/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, dildo_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_type = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/dildo/Initialize(mapload)
. = ..()
@@ -209,23 +207,22 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors
"medium" = image(icon = src.icon, icon_state = "[base_icon_state]_medium"),
"big" = image(icon = src.icon, icon_state = "[base_icon_state]_big"))
-/obj/item/clothing/sextoy/dildo/custom_dildo/AltClick(mob/living/user)
+/obj/item/clothing/sextoy/dildo/custom_dildo/click_alt(mob/living/user)
if(!size_changed)
var/choice = show_radial_menu(user, src, dildo_sizes, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
poly_size = choice
update_icon()
size_changed = TRUE
-
else
if(color_changed)
- return
+ return CLICK_ACTION_BLOCKING
if(!istype(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
- return
+ return CLICK_ACTION_BLOCKING
customize(user)
color_changed = TRUE
- return TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/dildo/custom_dildo/Initialize(mapload)
. = ..()
@@ -292,8 +289,8 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors
/obj/item/clothing/sextoy/dildo/double_dildo/populate_dildo_designs()
return
-/obj/item/clothing/sextoy/dildo/double_dildo/AltClick(mob/user)
- return
+/obj/item/clothing/sextoy/dildo/double_dildo/click_alt(mob/user)
+ return NONE
/obj/item/clothing/sextoy/dildo/double_dildo/lewd_equipped(mob/living/carbon/human/user, slot, initial)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm
index 3099ce8c3d2..02b25ecefd4 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm
@@ -39,18 +39,16 @@
icon_state = "[base_icon_state]_[current_color]"
inhand_icon_state = "[base_icon_state]_[current_color]"
-/obj/item/clothing/sextoy/fleshlight/AltClick(mob/user)
+/obj/item/clothing/sextoy/fleshlight/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, fleshlight_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/fleshlight/attack(mob/living/carbon/human/target, mob/living/carbon/human/user)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm
index 6e67c51fe34..21328dcea3a 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm
@@ -69,8 +69,9 @@
to_chat(user, span_notice("You install a cell in [src]."))
update_appearance()
-/obj/item/kinky_shocker/AltClick(mob/user)
+/obj/item/kinky_shocker/click_alt(mob/user)
tryremovecell(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/kinky_shocker/proc/tryremovecell(mob/user)
if(!(cell && can_remove_cell))
@@ -81,6 +82,7 @@
to_chat(user, span_notice("You remove the cell from [src]."))
shocker_on = FALSE
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/item/kinky_shocker/attack_self(mob/user)
toggle_shocker(user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm
index 83ac7d1ca0b..83beedd5605 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm
@@ -88,32 +88,27 @@
update_overlays()
//to change color
-/obj/item/clothing/mask/leatherwhip/AltClick(mob/user)
+/obj/item/clothing/mask/leatherwhip/click_alt(mob/user)
if(!color_changed)
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, whip_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_whip_color = choice
update_icon()
update_icon_state()
color_changed = TRUE
-
+ return CLICK_ACTION_SUCCESS
else
if(form_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, whip_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_whip_form = choice
update_icon()
update_icon_state()
form_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/// A check to see if the radial menu can be used
/obj/item/clothing/mask/leatherwhip/proc/check_menu(mob/living/user)
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm
index dcab8ba06e4..facf60ea273 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm
@@ -43,19 +43,17 @@
icon_state = "[base_icon_state]_[current_color]"
inhand_icon_state = "[base_icon_state]_[current_color]"
-/obj/item/spanking_pad/AltClick(mob/user)
+/obj/item/spanking_pad/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, spankpad_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon_state()
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/spanking_pad/attack(mob/living/carbon/human/target, mob/living/carbon/human/user)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm
index fe0582abea5..3d24a3b649e 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm
@@ -108,23 +108,24 @@
open_flame()
update_brightness()
-/obj/item/bdsm_candle/AltClick(mob/user)
- . = ..()
+/obj/item/bdsm_candle/click_alt(mob/user)
if(!lit)
if(color_changed)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, candle_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
light_color = candlelights[choice]
update_icon()
update_brightness()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
else
if(!put_out_candle())
- return
+ return CLICK_ACTION_BLOCKING
user.visible_message(span_notice("[user] snuffs [src]."))
+ return CLICK_ACTION_SUCCESS
/*
* WAX DROPPING
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm
index c8174fe64e5..35b8ce8855e 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm
@@ -42,19 +42,17 @@
"yellow" = image(icon = src.icon, icon_state = "vibrator_yellow_low"),
"green" = image(icon = src.icon, icon_state = "vibrator_green_low"))
-/obj/item/clothing/sextoy/vibrator/AltClick(mob/user)
+/obj/item/clothing/sextoy/vibrator/click_alt(mob/user)
if(color_changed)
return
- . = ..()
- if(.)
- return
var/choice = show_radial_menu(user, src, vibrator_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon_state()
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/vibrator/Initialize(mapload)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm
index dd531231d24..03b1ca6ade5 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm
@@ -36,18 +36,16 @@
"pink" = image(icon = src.icon, icon_state = "vibroring_pink_off"),
"teal" = image(icon = src.icon, icon_state = "vibroring_teal_off"))
-/obj/item/clothing/sextoy/vibroring/AltClick(mob/user)
+/obj/item/clothing/sextoy/vibroring/click_alt(mob/user)
if(color_changed)
- return
- . = ..()
- if(.)
- return
+ return CLICK_ACTION_BLOCKING
var/choice = show_radial_menu(user, src, vibroring_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
color_changed = TRUE
+ return CLICK_ACTION_SUCCESS
/obj/item/clothing/sextoy/vibroring/Initialize(mapload)
. = ..()
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm
index 25dba7d3508..3833fdb8edb 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm
@@ -16,7 +16,6 @@
icon_state = "milking_pink_off"
max_buckled_mobs = 1
item_chair = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
max_integrity = 75
var/static/list/milkingmachine_designs
@@ -67,33 +66,6 @@
var/mutable_appearance/organ_overlay
var/organ_overlay_new_icon_state = "" // Organ overlay update optimization
-// Additional examine text
-/obj/structure/chair/milking_machine/examine(mob/user)
- . = ..()
- . += span_notice("What are these metal mounts on the armrests for...?")
-
-/obj/structure/chair/milking_machine/Destroy()
- if(current_mob)
- if(current_mob.handcuffed)
- current_mob.handcuffed.dropped(current_mob)
- current_mob.set_handcuffed(null)
- current_mob.update_abstract_handcuffed()
- current_mob.layer = initial(current_mob.layer)
-
- if(beaker)
- qdel(beaker)
- beaker = null
-
- current_selected_organ = null
- current_mob = null
- current_breasts = null
- current_testicles = null
- current_vagina = null
-
- STOP_PROCESSING(SSobj, src)
- unbuckle_all_mobs()
- return ..()
-
// Object initialization
/obj/structure/chair/milking_machine/Initialize(mapload)
. = ..()
@@ -124,6 +96,37 @@
populate_milkingmachine_designs()
START_PROCESSING(SSobj, src)
+// Additional examine text
+/obj/structure/chair/milking_machine/examine(mob/user)
+ . = ..()
+ . += span_notice("What are these metal mounts on the armrests for...?")
+
+/obj/structure/chair/milking_machine/Destroy()
+ if(current_mob)
+ if(current_mob.handcuffed)
+ current_mob.handcuffed.dropped(current_mob)
+ current_mob.set_handcuffed(null)
+ current_mob.update_abstract_handcuffed()
+ current_mob.layer = initial(current_mob.layer)
+
+ if(beaker)
+ qdel(beaker)
+ beaker = null
+
+ current_selected_organ = null
+ current_mob = null
+ current_breasts = null
+ current_testicles = null
+ current_vagina = null
+
+ STOP_PROCESSING(SSobj, src)
+ unbuckle_all_mobs()
+ return ..()
+
+// previously NO_DECONSTRUCTION
+/obj/structure/chair/milking_machine/wrench_act_secondary(mob/living/user, obj/item/weapon)
+ return NONE
+
/*
* APPEARANCE MANAGEMENT
*/
@@ -307,7 +310,7 @@
return FALSE
replace_beaker(user, used_container)
- updateUsrDialog()
+ SStgui.update_uis(src)
return TRUE
// Beaker change handler
@@ -583,7 +586,7 @@
data["current_vagina"] = current_vagina = null
data["machine_color"] = machine_color
- updateUsrDialog()
+ SStgui.update_uis(src)
return data
// User action handler in the interface
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm
index 9e46e1d018d..b6baa6d42f2 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm
@@ -7,7 +7,6 @@
icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_structures/bdsm_furniture.dmi'
icon_state = "bdsm_bed"
max_integrity = 50
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/obj/item/bdsm_bed_kit
name = "bdsm bed construction kit"
@@ -41,6 +40,10 @@
. = ..()
. += span_purple("[src] can be assembled by using Ctrl+Shift+Click while [src] is on the floor.")
+// previously NO_DECONSTRUCTION
+/obj/structure/bed/bdsm_bed/wrench_act_secondary(mob/living/user, obj/item/weapon)
+ return NONE
+
/obj/structure/bed/bdsm_bed/post_buckle_mob(mob/living/affected_mob)
density = TRUE
//Push them up from the normal lying position
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm
index cc3ed2cdce8..7d35be6c12f 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm
@@ -3,7 +3,7 @@
name = "construction kit"
desc = "Used for constructing various things"
w_class = WEIGHT_CLASS_BULKY
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
+ obj_flags = CAN_BE_HIT
throwforce = 0
///What is the path for the resulting structure generating by using this item?
var/obj/structure/resulting_structure = /obj/structure/chair
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm
index e88b76206b9..6ba55958fe6 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm
@@ -31,7 +31,8 @@
"green" = COLOR_GREEN,
"white" = COLOR_WHITE,
)
-
+ /// Is the pole in use currently?
+ var/pole_in_use
/obj/structure/stripper_pole/examine(mob/user)
. = ..()
@@ -65,13 +66,14 @@
// Alt-click to turn the lights on or off.
-/obj/structure/stripper_pole/AltClick(mob/user)
+/obj/structure/stripper_pole/click_alt(mob/user)
lights_enabled = !lights_enabled
balloon_alert(user, "lights [lights_enabled ? "on" : "off"]")
playsound(user, lights_enabled ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE)
update_icon_state()
update_icon()
update_brightness()
+ return CLICK_ACTION_SUCCESS
/obj/structure/stripper_pole/Initialize(mapload)
@@ -98,17 +100,17 @@
. = ..()
if(.)
return
- if(obj_flags & IN_USE)
+ if(pole_in_use)
balloon_alert(user, "already in use!")
return
- obj_flags |= IN_USE
+ pole_in_use = TRUE
dancer = user
user.setDir(SOUTH)
user.Stun(10 SECONDS)
user.forceMove(loc)
user.visible_message(pick(span_purple("[user] dances on [src]!"), span_purple("[user] flexes their hip-moving skills on [src]!")))
dance_animate(user)
- obj_flags &= ~IN_USE
+ pole_in_use = FALSE
user.pixel_y = 0
user.pixel_z = pseudo_z_axis //incase we are off it when we jump on!
dancer = null
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm
index 0ac4d57fafb..7ee77500f7a 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm
@@ -34,32 +34,28 @@
"square" = image (icon = src.icon, icon_state = "pillow_pink_square"),
"round" = image(icon = src.icon, icon_state = "pillow_pink_round"))
-/obj/item/fancy_pillow/AltClick(mob/user)
- if(color_changed == FALSE)
- . = ..()
- if(.)
- return
+/obj/item/fancy_pillow/click_alt(mob/user)
+ if(!color_changed)
var/choice = show_radial_menu(user, src, pillow_colors, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
if(!choice)
- return FALSE
+ return CLICK_ACTION_BLOCKING
current_color = choice
update_icon()
color_changed = TRUE
update_icon_state()
- if(color_changed == TRUE)
- if(form_changed == FALSE)
- . = ..()
- if(.)
- return
- var/choice = show_radial_menu(user, src, pillow_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
- if(!choice)
- return FALSE
- current_form = choice
- update_icon()
- form_changed = TRUE
- update_icon_state()
+ return CLICK_ACTION_SUCCESS
else
- return
+ if(form_changed)
+ return CLICK_ACTION_BLOCKING
+ var/choice = show_radial_menu(user, src, pillow_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE)
+ if(!choice)
+ return CLICK_ACTION_BLOCKING
+ current_form = choice
+ update_icon()
+ form_changed = TRUE
+ update_icon_state()
+ return CLICK_ACTION_SUCCESS
+
//to check if we can change pillow's model
/obj/item/fancy_pillow/proc/check_menu(mob/living/user)
@@ -185,7 +181,7 @@
//picking up the pillow
-/obj/structure/bed/pillow_tiny/AltClick(mob/user)
+/obj/structure/bed/pillow_tiny/click_alt(mob/user)
to_chat(user, span_notice("You pick up [src]."))
var/obj/item/fancy_pillow/taken_pillow = new()
user.put_in_hands(taken_pillow)
@@ -198,6 +194,7 @@
taken_pillow.update_icon_state()
taken_pillow.update_icon()
qdel(src)
+ return CLICK_ACTION_SUCCESS
//when we lay on it
@@ -308,7 +305,7 @@
icon_state = "[base_icon_state]_[current_color]"
//Removing pillow from a pile
-/obj/structure/chair/pillow_small/AltClick(mob/user)
+/obj/structure/chair/pillow_small/click_alt(mob/user)
to_chat(user, span_notice("You take [src] from the pile."))
var/obj/item/fancy_pillow/taken_pillow = new()
var/obj/structure/bed/pillow_tiny/pillow_pile = new(get_turf(src))
@@ -330,6 +327,7 @@
pillow_pile.update_icon_state()
pillow_pile.update_icon()
qdel(src)
+ return CLICK_ACTION_SUCCESS
//Upgrading pillow pile to a PILLOW PILE!
/obj/structure/chair/pillow_small/attackby(obj/item/used_item, mob/living/user, params)
@@ -437,7 +435,7 @@
icon_state = "[base_icon_state]_[current_color]"
//Removing pillow from a pile
-/obj/structure/bed/pillow_large/AltClick(mob/user)
+/obj/structure/bed/pillow_large/click_alt(mob/user)
to_chat(user, span_notice("You take [src] from the pile."))
var/obj/item/fancy_pillow/taken_pillow = new()
var/obj/structure/chair/pillow_small/pillow_pile = new(get_turf(src))
@@ -464,3 +462,4 @@
pillow_pile.update_icon_state()
pillow_pile.update_icon()
qdel(src)
+ return CLICK_ACTION_SUCCESS
diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm
index 968b6a34925..9ceeaf04bc6 100644
--- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm
+++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm
@@ -7,7 +7,6 @@
layer = 4
item_chair = null
buildstacktype = null
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
///Overlays for ropes
var/static/mutable_appearance/shibari_rope_overlay
var/static/mutable_appearance/shibari_rope_overlay_behind
@@ -45,6 +44,10 @@
if(!has_buckled_mobs() && can_buckle)
. += span_notice("They need to be wearing full-body shibari, and you need to be holding ropes!")
+// previously NO_DECONSTRUCT
+/obj/structure/chair/shibari_stand/wrench_act_secondary(mob/living/user, obj/item/weapon)
+ return NONE
+
/obj/structure/chair/shibari_stand/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user)
var/mob/living/buckled = buckled_mob
if(buckled)
diff --git a/modular_skyrat/modules/modular_weapons/code/gunsets.dm b/modular_skyrat/modules/modular_weapons/code/gunsets.dm
index 7373e0fa729..09b523f2c86 100644
--- a/modular_skyrat/modules/modular_weapons/code/gunsets.dm
+++ b/modular_skyrat/modules/modular_weapons/code/gunsets.dm
@@ -30,10 +30,10 @@
else
icon_state = initial(icon_state)
-/obj/item/storage/toolbox/guncase/skyrat/AltClick(mob/user)
- . = ..()
+/obj/item/storage/toolbox/guncase/skyrat/click_alt(mob/user)
opened = !opened
update_icon()
+ return CLICK_ACTION_SUCCESS
/obj/item/storage/toolbox/guncase/skyrat/attack_self(mob/user)
. = ..()
diff --git a/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm b/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm
index d631246666c..01eda1e746d 100644
--- a/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm
+++ b/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm
@@ -171,11 +171,9 @@
update_positioning()
-/obj/machinery/mounted_machine_gun/AltClick(mob/user)
- . = ..()
- if(!can_interact(user))
- return
+/obj/machinery/mounted_machine_gun/click_alt(mob/user)
toggle_cover(user)
+ return CLICK_ACTION_SUCCESS
/obj/machinery/mounted_machine_gun/attack_hand_secondary(mob/living/user, list/modifiers)
. = ..()
diff --git a/modular_skyrat/modules/mutants/code/mutant_cure.dm b/modular_skyrat/modules/mutants/code/mutant_cure.dm
index 5bdff67d152..59fdca63325 100644
--- a/modular_skyrat/modules/mutants/code/mutant_cure.dm
+++ b/modular_skyrat/modules/mutants/code/mutant_cure.dm
@@ -219,8 +219,6 @@
if(machine_stat & (NOPOWER|BROKEN|MAINT))
return
- usr.set_machine(src)
-
var/operation = href_list["function"]
var/obj/item/process = locate(href_list["item"]) in src
@@ -230,7 +228,7 @@
else if(operation == "eject")
ejectItem()
else if(operation == "refresh")
- updateUsrDialog()
+ SStgui.update_uis(src)
else
if(status != STATUS_IDLE)
to_chat(usr, span_warning("[src] is currently recombinating!"))
@@ -246,7 +244,7 @@
recombinate_start()
use_energy(3000 JOULES)
- updateUsrDialog()
+ SStgui.update_uis(src)
/obj/machinery/rnd/rna_recombinator/proc/ejectItem()
if(loaded_item)
diff --git a/modular_skyrat/modules/new_cells/code/power_cell.dm b/modular_skyrat/modules/new_cells/code/power_cell.dm
index d9769c479c1..7c604393386 100644
--- a/modular_skyrat/modules/new_cells/code/power_cell.dm
+++ b/modular_skyrat/modules/new_cells/code/power_cell.dm
@@ -4,11 +4,11 @@
icon = 'modular_skyrat/modules/new_cells/icons/power.dmi'
icon_state = "crankcell"
/// how much each crank will give the cell charge
- var/crank_amount = 100
+ var/crank_amount = STANDARD_CELL_CHARGE * 0.1
/// how fast it takes to crank to get the crank_amount
var/crank_speed = 1 SECONDS
/// how much gets discharged every process
- var/discharge_amount = 10
+ var/discharge_amount = STANDARD_CELL_CHARGE * 0.01
charge_light_type = "old"
/obj/item/stock_parts/cell/crank/examine(mob/user)
@@ -38,10 +38,10 @@
desc = "A special cell that will recharge itself over time."
icon = 'modular_skyrat/modules/new_cells/icons/power.dmi'
icon_state = "chargecell"
- maxcharge = 2500
+ maxcharge = STANDARD_CELL_CHARGE * 2.5
charge_light_type = "old"
/// how much is recharged every process
- var/recharge_amount = 200
+ var/recharge_amount = STANDARD_CELL_CHARGE * 0.2
/obj/item/stock_parts/cell/self_charge/Initialize(mapload, override_maxcharge)
. = ..()
diff --git a/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm b/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm
index cfe5386f4a9..bae6bea585a 100644
--- a/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm
+++ b/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm
@@ -36,14 +36,8 @@
return FALSE
return TRUE
-/client/proc/one_click_antag()
- set name = "Create Antagonist"
- set desc = "Auto-create an antagonist of your choice"
- set category = "Admin.Events"
-
- if(holder)
- holder.one_click_antag()
- return
+ADMIN_VERB(one_click_antag, R_ADMIN, "Create Antagonist", "Auto-create an antagonist of your choice", ADMIN_CATEGORY_EVENTS)
+ user.holder?.one_click_antag()
/**
If anyone can figure out how to get Obsessed to work I would be very appreciative.
diff --git a/modular_skyrat/modules/opposing_force/code/admin_procs.dm b/modular_skyrat/modules/opposing_force/code/admin_procs.dm
index 379a1de08cb..9ce7da7c459 100644
--- a/modular_skyrat/modules/opposing_force/code/admin_procs.dm
+++ b/modular_skyrat/modules/opposing_force/code/admin_procs.dm
@@ -1,19 +1,16 @@
-/client/proc/request_more_opfor()
- set category = "Admin.Fun"
- set name = "Request OPFOR"
- set desc = "Request players sign up for opfor if they have antag on."
-
+ADMIN_VERB(request_more_opfor, R_FUN, "Request OPFOR", "Request players sign up for opfor if they have antag on.", ADMIN_CATEGORY_FUN)
var/asked = 0
for(var/mob/living/carbon/human/human in GLOB.alive_player_list)
if(human.client?.prefs?.read_preference(/datum/preference/toggle/be_antag))
to_chat(human, examine_block(span_greentext("The admins are looking for OPFOR players, if you're interested, sign up in the OOC tab!")))
asked++
- message_admins("[ADMIN_LOOKUP(usr)] has requested more OPFOR players! (Asked: [asked] players)")
+ message_admins("[ADMIN_LOOKUP(user)] has requested more OPFOR players! (Asked: [asked] players)")
+ADMIN_VERB(view_opfors, R_ADMIN, "View OPFORs", "View OPFORs.", ADMIN_CATEGORY_GAME)
+ user.mob.client?.view_opfors()
+
/client/proc/view_opfors()
- set name = "View OPFORs"
- set category = "Admin.Game"
if(holder)
var/list/dat = list("")
dat += SSopposing_force.get_check_antag_listing()
diff --git a/modular_skyrat/modules/panicbunker/code/panicbunker.dm b/modular_skyrat/modules/panicbunker/code/panicbunker.dm
index 1054fdfa851..eb9275f8855 100644
--- a/modular_skyrat/modules/panicbunker/code/panicbunker.dm
+++ b/modular_skyrat/modules/panicbunker/code/panicbunker.dm
@@ -1,9 +1,6 @@
GLOBAL_LIST_EMPTY(bunker_passthrough)
-/client/proc/addbunkerbypass(ckeytobypass as text)
- set category = "Admin"
- set name = "Add PB Bypass"
- set desc = "Allows a given ckey to connect despite the panic bunker for a given round."
+ADMIN_VERB(addbunkerbypass, R_ADMIN, "Add PB Bypass", "Allows a given ckey to connect despite the panic bunker for a given round.", ADMIN_CATEGORY_MAIN, ckeytobypass as text|null)
if(!CONFIG_GET(flag/sql_enabled))
to_chat(usr, span_adminnotice("The Database is not enabled!"))
return
@@ -14,11 +11,7 @@ GLOBAL_LIST_EMPTY(bunker_passthrough)
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.")
-/client/proc/revokebunkerbypass(ckeytobypass as text)
- set category = "Admin"
- set name = "Revoke PB Bypass"
- set desc = "Revoke's a ckey's permission to bypass the panic bunker for a given round."
-
+ADMIN_VERB(revokebunkerbypass, R_ADMIN, "Revoke PB Bypass", "Revoke's a ckey's permission to bypass the panic bunker for a given round.", ADMIN_CATEGORY_MAIN, ckeytobypass as text|null)
if(!CONFIG_GET(flag/sql_enabled))
to_chat(usr, span_adminnotice("The Database is not enabled!"))
return
diff --git a/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm b/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm
index 12102f43f39..125a9fb740b 100644
--- a/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm
+++ b/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm
@@ -1,16 +1,12 @@
-/client/proc/spawn_pollution()
- set category = "Admin.Fun"
- set name = "Spawn Pollution"
- set desc = "Spawns an amount of chosen pollutant at your current location."
-
+ADMIN_VERB(spawn_pollution, R_ADMIN, "Spawn Pollution", "Spawns an amount of chosen pollutant at your current location.", ADMIN_CATEGORY_FUN)
var/list/singleton_list = SSpollution.singletons
- var/choice = tgui_input_list(usr, "What type of pollutant would you like to spawn?", "Spawn Pollution", singleton_list)
+ var/choice = tgui_input_list(user, "What type of pollutant would you like to spawn?", "Spawn Pollution", singleton_list)
if(!choice)
return
var/amount_choice = input("Amount of pollution:") as null|num
if(!amount_choice)
return
- var/turf/epicenter = get_turf(mob)
+ var/turf/epicenter = get_turf(user.mob)
epicenter.pollute_turf(choice, amount_choice)
- message_admins("[ADMIN_LOOKUPFLW(usr)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).")
- log_admin("[key_name(usr)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).")
+ message_admins("[ADMIN_LOOKUPFLW(user)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).")
+ log_admin("[key_name(user)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).")
diff --git a/modular_skyrat/modules/pollution/code/perfumes.dm b/modular_skyrat/modules/pollution/code/perfumes.dm
index 2f07404ae76..80ccf1c253e 100644
--- a/modular_skyrat/modules/pollution/code/perfumes.dm
+++ b/modular_skyrat/modules/pollution/code/perfumes.dm
@@ -34,8 +34,9 @@
if(has_cap)
. += span_notice("Alt-click [src] to [ cap ? "take the cap off" : "put the cap on"].")
-/obj/item/perfume/AltClick(mob/user)
+/obj/item/perfume/click_alt(mob/user)
toggle_cap(user)
+ return CLICK_ACTION_SUCCESS
/obj/item/perfume/attack_self(mob/user, modifiers)
toggle_cap(user)
diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm b/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm
index 4860aed6331..282369b1e85 100644
--- a/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm
+++ b/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm
@@ -33,13 +33,14 @@
drop_everything_contained()
return ..()
-/obj/structure/large_mortar/AltClick(mob/user)
+/obj/structure/large_mortar/click_alt(mob/user)
if(!length(contents))
balloon_alert(user, "nothing inside")
- return
+ return CLICK_ACTION_BLOCKING
drop_everything_contained()
balloon_alert(user, "removed all items")
+ return CLICK_ACTION_SUCCESS
/// Drops all contents at the mortar
/obj/structure/large_mortar/proc/drop_everything_contained()
diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm b/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm
index a71e4c7d35a..e677a617817 100644
--- a/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm
+++ b/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm
@@ -57,13 +57,14 @@
drop_everything_contained()
return ..()
-/obj/item/cutting_board/AltClick(mob/user)
+/obj/item/cutting_board/click_alt(mob/user)
if(!length(contents))
balloon_alert(user, "nothing on board")
- return
+ return CLICK_ACTION_BLOCKING
drop_everything_contained()
balloon_alert(user, "cleared board")
+ return CLICK_ACTION_SUCCESS
///Drops all contents at the turf of the item
/obj/item/cutting_board/proc/drop_everything_contained()
diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm b/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm
index 57b5d23e385..76a21851856 100644
--- a/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm
+++ b/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm
@@ -51,13 +51,14 @@
transfer_fingerprints_to(stone)
return ..()
-/obj/structure/millstone/AltClick(mob/user)
+/obj/structure/millstone/click_alt(mob/user)
if(!length(contents))
- balloon_alert(user, "nothing inside")
- return
+ balloon_alert(user, "nothing inside!")
+ return CLICK_ACTION_BLOCKING
drop_everything_contained()
balloon_alert(user, "removed all items")
+ return CLICK_ACTION_SUCCESS
/obj/structure/millstone/CtrlShiftClick(mob/user)
set_anchored(!anchored)
diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm b/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm
index c4c21967a3c..8ccd6e5c668 100644
--- a/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm
+++ b/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm
@@ -6,7 +6,6 @@
icon = 'modular_skyrat/modules/primitive_cooking_additions/icons/stone_kitchen_machines.dmi'
circuit = null
use_power = FALSE
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/// A list of the different oven trays we can spawn with
var/static/list/random_oven_tray_types = list(
@@ -32,6 +31,16 @@
. += span_notice("It can be taken apart with a crowbar.")
+// previously NO_DECONSTRUCTION
+/obj/machinery/oven/stone/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/oven/stone/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
+/obj/machinery/oven/stone/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density)
+ return NONE
+
/obj/machinery/oven/stone/add_tray_to_oven(obj/item/plate/oven_tray, mob/baker)
used_tray = oven_tray
diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm b/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm
index 0057e758571..cdfd64719e3 100644
--- a/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm
+++ b/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm
@@ -10,7 +10,6 @@
use_power = FALSE
circuit = null
resistance_flags = FIRE_PROOF
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/obj/machinery/primitive_stove/Initialize(mapload)
. = ..()
@@ -22,6 +21,13 @@
. += span_notice("It can be taken apart with a crowbar.")
+// previously NO_DECONSTRUCTION
+/obj/machinery/primitive_stove/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
+
+/obj/machinery/primitive_stove/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct)
+ return NONE
+
/obj/machinery/primitive_stove/crowbar_act(mob/living/user, obj/item/tool)
user.balloon_alert_to_viewers("disassembling...")
if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
diff --git a/modular_skyrat/modules/primitive_production/code/glassblowing.dm b/modular_skyrat/modules/primitive_production/code/glassblowing.dm
index ed7b4a31ff8..59198aa1112 100644
--- a/modular_skyrat/modules/primitive_production/code/glassblowing.dm
+++ b/modular_skyrat/modules/primitive_production/code/glassblowing.dm
@@ -227,7 +227,6 @@
if(!Adjacent(usr))
return
add_fingerprint(usr)
- usr.set_machine(src)
var/obj/item/glassblowing/molten_glass/glass = glass_ref?.resolve()
var/actioning_speed = usr.mind.get_skill_modifier(/datum/skill/production, SKILL_SPEED_MODIFIER) * DEFAULT_TIMED
diff --git a/modular_skyrat/modules/primitive_structures/code/fencing.dm b/modular_skyrat/modules/primitive_structures/code/fencing.dm
index 0aeb5a71e20..20816e9ba55 100644
--- a/modular_skyrat/modules/primitive_structures/code/fencing.dm
+++ b/modular_skyrat/modules/primitive_structures/code/fencing.dm
@@ -7,7 +7,7 @@
icon_state = "fence"
layer = BELOW_OBJ_LAYER // I think this is the default but lets be safe?
resistance_flags = FLAMMABLE
- flags_1 = NO_DECONSTRUCTION | ON_BORDER_1
+ flags_1 = ON_BORDER_1
/// If we randomize our icon on spawning
var/random_icons = TRUE
@@ -22,6 +22,10 @@
)
update_appearance()
+// previously NO_DECONSTRUCTION
+/obj/structure/railing/wirecutter_act(mob/living/user, obj/item/I)
+ return NONE
+
// Fence gates for the above mentioned fences
/obj/structure/railing/wooden_fencing/gate
diff --git a/modular_skyrat/modules/primitive_structures/code/storage_structures.dm b/modular_skyrat/modules/primitive_structures/code/storage_structures.dm
index 58c08df7941..d35bd9ce1c6 100644
--- a/modular_skyrat/modules/primitive_structures/code/storage_structures.dm
+++ b/modular_skyrat/modules/primitive_structures/code/storage_structures.dm
@@ -5,7 +5,6 @@
icon_state = "shelf_wood"
icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
resistance_flags = FLAMMABLE
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
/obj/structure/rack/wooden/MouseDrop_T(obj/object, mob/user, params)
. = ..()
@@ -16,6 +15,9 @@
object.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size / 3), world.icon_size / 3)
object.pixel_y = text2num(LAZYACCESS(modifiers, ICON_Y)) > 16 ? 10 : -4
+/obj/structure/rack/wrench_act_secondary(mob/living/user, obj/item/tool)
+ return NONE
+
/obj/structure/rack/wooden/crowbar_act(mob/living/user, obj/item/tool)
user.balloon_alert_to_viewers("disassembling...")
if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
@@ -37,28 +39,18 @@
base_icon_state = "barrel"
icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
resistance_flags = FLAMMABLE
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
+ material_drop = /obj/item/stack/sheet/mineral/wood
+ material_drop_amount = 4
+ cutting_tool = /obj/item/crowbar
-/obj/structure/closet/crate/wooden/storage_barrel/crowbar_act(mob/living/user, obj/item/tool)
- user.balloon_alert_to_viewers("disassembling...")
- if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
- return
- new /obj/item/stack/sheet/mineral/clay(drop_location(), 5)
- deconstruct(TRUE)
- return ITEM_INTERACT_SUCCESS
-
-/obj/structure/closet/crate/wooden/storage_barrel/atom_deconstruct(disassembled = TRUE)
- new /obj/item/stack/sheet/mineral/wood(drop_location(), 4)
- return ..()
-
-/obj/machinery/smartfridge/producebin
- name = "Produce Bin"
- desc = "A wooden hamper, used to hold plant products and try keep them safe from pests."
- icon_state = "producebin"
+/obj/machinery/smartfridge/wooden
+ name = "Debug Wooden Smartfridge"
+ desc = "You shouldn't be seeing this!"
icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
+ icon_state = "producebin"
resistance_flags = FLAMMABLE
- base_build_path = /obj/machinery/smartfridge/producebin
- base_icon_state = "produce"
+ base_build_path = /obj/machinery/smartfridge/wooden
+ base_icon_state = "producebin"
use_power = NO_POWER_USE
light_power = 0
idle_power_usage = 0
@@ -67,14 +59,16 @@
can_atmos_pass = ATMOS_PASS_YES
visible_contents = TRUE
-/obj/machinery/smartfridge/producebin/accept_check(obj/item/weapon)
- return (istype(weapon, /obj/item/food/grown))
+/obj/machinery/smartfridge/wooden/Initialize(mapload)
+ . = ..()
+ if(type == /obj/machinery/smartfridge/wooden) // don't even let these prototypes exist
+ return INITIALIZE_HINT_QDEL
-/obj/machinery/smartfridge/producebin/structure_examine()
- . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.")
+// previously NO_DECONSTRUCTION
+/obj/machinery/smartfridge/wooden/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
+ return NONE
-
-/obj/machinery/smartfridge/producebin/crowbar_act(mob/living/user, obj/item/tool)
+/obj/machinery/smartfridge/wooden/crowbar_act(mob/living/user, obj/item/tool)
user.balloon_alert_to_viewers("disassembling...")
if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
return
@@ -82,92 +76,51 @@
deconstruct(TRUE)
return ITEM_INTERACT_SUCCESS
-/obj/machinery/smartfridge/seedshelf
+/obj/machinery/smartfridge/wooden/structure_examine()
+ . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.")
+
+/obj/machinery/smartfridge/wooden/produce_bin
+ name = "produce bin"
+ desc = "A wooden hamper, used to hold plant products and try to keep them safe from pests."
+ icon_state = "producebin"
+ base_build_path = /obj/machinery/smartfridge/wooden/produce_bin
+ base_icon_state = "producebin"
+
+/obj/machinery/smartfridge/wooden/produce_bin/accept_check(obj/item/item_to_check)
+ var/static/list/accepted_items = list(
+ /obj/item/food/grown,
+ /obj/item/grown,
+ /obj/item/graft,
+ )
+
+ return is_type_in_list(item_to_check, accepted_items)
+
+/obj/machinery/smartfridge/wooden/seed_shelf
name = "Seedshelf"
desc = "A wooden shelf, used to hold seeds preventing them from germinating early."
icon_state = "seedshelf"
- icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
- resistance_flags = FLAMMABLE
- base_build_path = /obj/machinery/smartfridge/seedshelf
+ base_build_path = /obj/machinery/smartfridge/wooden/seed_shelf
base_icon_state = "seed"
- use_power = NO_POWER_USE
- light_power = 0
- idle_power_usage = 0
- circuit = null
- has_emissive = FALSE
- can_atmos_pass = ATMOS_PASS_YES
- visible_contents = TRUE
-/obj/machinery/smartfridge/seedshelf/accept_check(obj/item/weapon)
+/obj/machinery/smartfridge/wooden/seedshelf/wooden/accept_check(obj/item/weapon)
return istype(weapon, /obj/item/seeds)
-/obj/machinery/smartfridge/seedshelf/structure_examine()
- . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.")
-
-/obj/machinery/smartfridge/seedshelf/crowbar_act(mob/living/user, obj/item/tool)
- user.balloon_alert_to_viewers("disassembling...")
- if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
- return
- new /obj/item/stack/sheet/mineral/wood(drop_location(), 10)
- deconstruct(TRUE)
- return ITEM_INTERACT_SUCCESS
-
-/obj/machinery/smartfridge/rationshelf
+/obj/machinery/smartfridge/wooden/ration_shelf
name = "Ration shelf"
desc = "A wooden shelf, used to store food... preferably preserved."
icon_state = "rationshelf"
- icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
- resistance_flags = FLAMMABLE
- base_build_path = /obj/machinery/smartfridge/rationshelf
+ base_build_path = /obj/machinery/smartfridge/wooden/ration_shelf
base_icon_state = "ration"
- use_power = NO_POWER_USE
- light_power = 0
- idle_power_usage = 0
- circuit = null
- has_emissive = FALSE
- can_atmos_pass = ATMOS_PASS_YES
- visible_contents = TRUE
-/obj/machinery/smartfridge/rationshelf/accept_check(obj/item/weapon)
+/obj/machinery/smartfridge/wooden/rationshelf/wooden/accept_check(obj/item/weapon)
return (IS_EDIBLE(weapon) || (istype(weapon,/obj/item/reagent_containers/cup/bowl) && length(weapon.reagents?.reagent_list)))
-/obj/machinery/smartfridge/rationshelf/structure_examine()
- . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.")
-
-/obj/machinery/smartfridge/rationshelf/crowbar_act(mob/living/user, obj/item/tool)
- user.balloon_alert_to_viewers("disassembling...")
- if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
- return
- new /obj/item/stack/sheet/mineral/wood(drop_location(), 10)
- deconstruct(TRUE)
- return ITEM_INTERACT_SUCCESS
-
-/obj/machinery/smartfridge/producedisplay
+/obj/machinery/smartfridge/wooden/produce_display
name = "Produce display"
desc = "A wooden table with awning, used to display produce items."
icon_state = "producedisplay"
- icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi'
- resistance_flags = FLAMMABLE
- base_build_path = /obj/machinery/smartfridge/producedisplay
+ base_build_path = /obj/machinery/smartfridge/wooden/produce_display
base_icon_state = "nonfood"
- use_power = NO_POWER_USE
- light_power = 0
- idle_power_usage = 0
- circuit = null
- has_emissive = FALSE
- can_atmos_pass = ATMOS_PASS_YES
- visible_contents = TRUE
-/obj/machinery/smartfridge/producedisplay/accept_check(obj/item/weapon)
+/obj/machinery/smartfridge/wooden/producedisplay/accept_check(obj/item/weapon)
return (istype(weapon, /obj/item/grown) || istype(weapon, /obj/item/bouquet) || istype(weapon, /obj/item/clothing/head/costume/garland))
-
-/obj/machinery/smartfridge/producedisplay/structure_examine()
- . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.")
-
-/obj/machinery/smartfridge/producedisplay/crowbar_act(mob/living/user, obj/item/tool)
- user.balloon_alert_to_viewers("disassembling...")
- if(!tool.use_tool(src, user, 2 SECONDS, volume = 100))
- return
- new /obj/item/stack/sheet/mineral/wood(drop_location(), 10)
- deconstruct(TRUE)
- return ITEM_INTERACT_SUCCESS
diff --git a/modular_skyrat/modules/primitive_structures/code/windows.dm b/modular_skyrat/modules/primitive_structures/code/windows.dm
index ec861bb2d12..c2c27c62306 100644
--- a/modular_skyrat/modules/primitive_structures/code/windows.dm
+++ b/modular_skyrat/modules/primitive_structures/code/windows.dm
@@ -4,7 +4,7 @@
icon = 'modular_skyrat/modules/primitive_structures/icons/windows.dmi'
icon_state = "green_glass"
flags_1 = NONE
- obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
+ obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION
can_be_unanchored = FALSE
fulltile = TRUE
flags_1 = PREVENT_CLICK_UNDER_1
diff --git a/modular_skyrat/modules/salon/code/hair_tie.dm b/modular_skyrat/modules/salon/code/hair_tie.dm
index 2b490ec749b..73b1a28d93b 100644
--- a/modular_skyrat/modules/salon/code/hair_tie.dm
+++ b/modular_skyrat/modules/salon/code/hair_tie.dm
@@ -86,16 +86,16 @@
user.set_hairstyle(actual_hairstyle, update = TRUE)
actual_hairstyle = null
-/obj/item/clothing/head/hair_tie/AltClick(mob/living/user)
- . = ..()
+/obj/item/clothing/head/hair_tie/click_alt(mob/living/user)
if(!(user.get_slot_by_item(src) == ITEM_SLOT_HANDS))
balloon_alert(user, "hold in-hand!")
- return
+ return CLICK_ACTION_BLOCKING
user.visible_message(
span_danger("[user.name] puts [src] around [user.p_their()] fingers, beginning to flick it!"),
span_notice("You try to flick [src]!"),
)
flick_hair_tie(user)
+ return CLICK_ACTION_SUCCESS
///This proc flicks the hair tie out of the player's hand, tripping the target hit for 1 second
/obj/item/clothing/head/hair_tie/proc/flick_hair_tie(mob/living/user)
@@ -143,7 +143,7 @@
)
build_path = /obj/item/clothing/head/hair_tie/plastic_beads
category = list(
- RND_CATEGORY_INITIAL,
+ RND_CATEGORY_INITIAL,
RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SERVICE,
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE
diff --git a/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm b/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm
index e3b61e0f3e2..fb54222abdb 100644
--- a/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm
+++ b/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm
@@ -80,15 +80,15 @@
. = ..()
. += span_notice("ALT-Click to turn ON when closed.")
-/obj/machinery/self_actualization_device/AltClick(mob/user)
- . = ..()
+/obj/machinery/self_actualization_device/click_alt(mob/user)
if(!powered() || !occupant || state_open)
- return FALSE
+ return CLICK_ACTION_BLOCKING
to_chat(user, "You power on [src].")
addtimer(CALLBACK(src, PROC_REF(eject_new_you)), processing_time, TIMER_OVERRIDE|TIMER_UNIQUE)
processing = TRUE
update_appearance()
+ return CLICK_ACTION_SUCCESS
/obj/machinery/self_actualization_device/container_resist_act(mob/living/user)
if(state_open)
diff --git a/modular_skyrat/modules/server_overflow/code/chat_link.dm b/modular_skyrat/modules/server_overflow/code/chat_link.dm
index 843ec276ac5..85489d1dbe1 100644
--- a/modular_skyrat/modules/server_overflow/code/chat_link.dm
+++ b/modular_skyrat/modules/server_overflow/code/chat_link.dm
@@ -60,19 +60,15 @@
html = msg,
confidential = TRUE)
-/client/proc/request_help()
- set category = "Admin"
- set name = "Cross-server Help Request"
- set desc = "Sends a loud message to all other servers that we are crosslinked to!"
-
- var/help_request_message = tgui_input_text(src, "Input help message!", "Help message", "Send help!", 150, FALSE)
+ADMIN_VERB(request_help, R_ADMIN, "Cross-server Help Request", "Sends a loud message to all other servers that we are crosslinked to!", ADMIN_CATEGORY_MAIN)
+ var/help_request_message = tgui_input_text(user, "Input help message!", "Help message", "Send help!", 150, FALSE)
if(!help_request_message)
return
- send2adminchat(ckey, "CROSSLINK HELP REQUEST([CONFIG_GET(string/cross_server_name) ? CONFIG_GET(string/cross_server_name) : station_name()]): [help_request_message]")
- send_help_request_to_other_server(ckey, help_request_message)
+ send2adminchat(user.ckey, "CROSSLINK HELP REQUEST([CONFIG_GET(string/cross_server_name) ? CONFIG_GET(string/cross_server_name) : station_name()]): [help_request_message]")
+ send_help_request_to_other_server(user.ckey, help_request_message)
- message_admins("[ADMIN_LOOKUPFLW(usr)] sent out a cross-server help request with the message: [help_request_message].")
- log_admin("[key_name(usr)] sent cross-server help request [help_request_message].")
+ message_admins("[ADMIN_LOOKUPFLW(user)] sent out a cross-server help request with the message: [help_request_message].")
+ log_admin("[key_name(user)] sent cross-server help request [help_request_message].")
// Oh no, they need help!
/proc/send_help_request_to_other_server(exp_name, message)
diff --git a/modular_skyrat/modules/specialist_armor/code/sacrificial.dm b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm
index 45643140f83..71bbf99db4d 100644
--- a/modular_skyrat/modules/specialist_armor/code/sacrificial.dm
+++ b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm
@@ -79,8 +79,9 @@
QDEL_NULL(face_shield)
return ..()
-/obj/item/clothing/head/helmet/sf_sacrificial/AltClick(mob/user)
+/obj/item/clothing/head/helmet/sf_sacrificial/click_alt(mob/user)
remove_face_shield(user)
+ return CLICK_ACTION_SUCCESS
/// Attached the passed face shield to the helmet.
/obj/item/clothing/head/helmet/sf_sacrificial/proc/add_face_shield(mob/living/carbon/human/user, obj/shield_in_question)
diff --git a/modular_skyrat/modules/stasisrework/code/stasissleeper.dm b/modular_skyrat/modules/stasisrework/code/stasissleeper.dm
index be21887eed6..abb7437d6f6 100644
--- a/modular_skyrat/modules/stasisrework/code/stasissleeper.dm
+++ b/modular_skyrat/modules/stasisrework/code/stasissleeper.dm
@@ -13,6 +13,7 @@
var/last_stasis_sound = FALSE
fair_market_price = 10
payment_department = ACCOUNT_MED
+ interaction_flags_click = ALLOW_SILICON_REACH
/obj/machinery/stasissleeper/Destroy()
. = ..()
@@ -53,9 +54,7 @@
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, frequency = sound_freq)
last_stasis_sound = _running
-/obj/machinery/stasissleeper/AltClick(mob/user)
- if(!user.can_perform_action(src, ALLOW_SILICON_REACH))
- return
+/obj/machinery/stasissleeper/click_alt(mob/user)
if(!panel_open)
user.visible_message(span_notice("\The [src] [state_open ? "hisses as it seals shut." : "hisses as it swings open."]."), \
span_notice("You [state_open ? "close" : "open"] \the [src]."), \
@@ -65,6 +64,8 @@
else
open_machine()
+ return CLICK_ACTION_SUCCESS
+
/obj/machinery/stasissleeper/Exited(atom/movable/AM, atom/newloc)
if(!state_open && AM == occupant)
container_resist_act(AM)
@@ -141,7 +142,7 @@
/obj/machinery/stasissleeper/default_pry_open(obj/item/used_item)
if(occupant)
thaw_them(occupant)
- . = !(state_open || panel_open || (obj_flags & NO_DECONSTRUCTION)) && used_item.tool_behaviour == TOOL_CROWBAR
+ . = !(state_open || panel_open) && used_item.tool_behaviour == TOOL_CROWBAR
if(.)
used_item.play_tool_sound(src, 50)
visible_message(span_notice("[usr] pries open [src]."), span_notice("You pry open [src]."))
diff --git a/modular_skyrat/modules/stone/code/stone.dm b/modular_skyrat/modules/stone/code/stone.dm
index 0ae23c39c45..ac36480ac79 100644
--- a/modular_skyrat/modules/stone/code/stone.dm
+++ b/modular_skyrat/modules/stone/code/stone.dm
@@ -11,7 +11,6 @@
resistance_flags = FIRE_PROOF
merge_type = /obj/item/stack/sheet/mineral/stone
grind_results = null
- point_value = 0
material_type = /datum/material/stone
matter_amount = 0
source = null
diff --git a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm
index 80ba4fa5223..5d14829cc92 100644
--- a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm
+++ b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm
@@ -56,11 +56,13 @@
UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT)
///Handles charging the synth from borg chargers
-/obj/item/organ/internal/stomach/synth/proc/on_borg_charge(datum/source, amount)
+/obj/item/organ/internal/stomach/synth/proc/on_borg_charge(datum/source, datum/callback/charge_cell, seconds_per_tick)
SIGNAL_HANDLER
if(owner.nutrition >= NUTRITION_LEVEL_ALMOST_FULL)
return
- amount /= 50 // Lowers the charging amount so it isn't instant
- owner.nutrition = min((owner.nutrition + amount), NUTRITION_LEVEL_ALMOST_FULL) // Makes sure we don't make the synth too full, which would apply the overweight slowdown
+ // I am NOT rewriting this to fit with TG's standard. I have like 70 bugfixes waiting. Feel free to give synths actual cells if I don't i the future
+ // ~Waterpig
+
+ owner.nutrition = min(owner.nutrition + (40 / seconds_per_tick), NUTRITION_LEVEL_ALMOST_FULL) // Makes sure we don't make the synth too full, which would apply the overweight slowdown
diff --git a/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm b/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm
index f72fc0a99d3..cf7c4bd7005 100644
--- a/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm
+++ b/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm
@@ -123,6 +123,6 @@
name = "paper - 'Command Safe Note'"
default_raw_text = "Heh... I couldn't handle letting those older papers go, something about them reminded me about why I jumped on this job. The \"Safety of the future\" spiels... Now? Any dingbat can buy their own little constructor in a box... Fancy that we got one ourself, Thing has some handy designs..
Well- That asside, we did get some new updated circuit boards. Industry standard gave us two sets of research constructor boards for redundancy, So we set the spare set in the special safe within the comms room."
-/obj/item/areaeditor/blueprints/tarkon
+/obj/item/blueprints/tarkon
desc = "Blueprints of the Tarkon surface breaching drill and several Tarkon base designs. Red, stamped text reads \"Confidential\" on the backside of it."
name = "Tarkon Design Prints"
diff --git a/modular_skyrat/modules/time_clock/code/console.dm b/modular_skyrat/modules/time_clock/code/console.dm
index 2d4891366a1..8b399d94dec 100644
--- a/modular_skyrat/modules/time_clock/code/console.dm
+++ b/modular_skyrat/modules/time_clock/code/console.dm
@@ -77,14 +77,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/time_clock, 28)
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
return TRUE
-/obj/machinery/time_clock/AltClick(mob/user)
- . = ..()
- if(!Adjacent(user))
- to_chat(user, span_warning("You are out of range of the [src]!"))
- return FALSE
-
+/obj/machinery/time_clock/click_alt(mob/user)
if(!eject_inserted_id(user))
- return FALSE
+ return CLICK_ACTION_BLOCKING
+
+ return CLICK_ACTION_SUCCESS
///Ejects the ID stored inside of the parent machine, if there is one.
/obj/machinery/time_clock/proc/eject_inserted_id(mob/recepient)
diff --git a/modular_skyrat/modules/time_clock/code/console_tgui.dm b/modular_skyrat/modules/time_clock/code/console_tgui.dm
index 64b576828d0..4101ea05932 100644
--- a/modular_skyrat/modules/time_clock/code/console_tgui.dm
+++ b/modular_skyrat/modules/time_clock/code/console_tgui.dm
@@ -20,7 +20,7 @@
/obj/item/circuitboard/machine/techfab/department/medical, \
/obj/item/circuitboard/machine/techfab/department/cargo, \
/obj/item/circuitboard/machine/techfab/department/science, \
- /obj/item/areaeditor/blueprints, \
+ /obj/item/blueprints, \
/obj/item/pipe_dispenser/bluespace, \
/obj/item/mod/control/pre_equipped/advanced, \
/obj/item/clothing/shoes/magboots/advance, \
diff --git a/modular_skyrat/modules/title_screen/code/title_screen_controls.dm b/modular_skyrat/modules/title_screen/code/title_screen_controls.dm
index 3f241af0f23..f3f550e3ffc 100644
--- a/modular_skyrat/modules/title_screen/code/title_screen_controls.dm
+++ b/modular_skyrat/modules/title_screen/code/title_screen_controls.dm
@@ -2,19 +2,13 @@
/**
* Enables an admin to upload a new titlescreen image.
*/
-/client/proc/admin_change_title_screen()
- set category = "Admin.Fun"
- set name = "Title Screen: Change"
-
- if(!check_rights(R_FUN))
- return
-
- log_admin("[key_name(usr)] is changing the title screen.")
- message_admins("[key_name_admin(usr)] is changing the title screen.")
+ADMIN_VERB(admin_change_title_screen, R_FUN, "Title Screen: Change", "Upload a new titlescreen image.", ADMIN_CATEGORY_FUN)
+ log_admin("[key_name(user)] is changing the title screen.")
+ message_admins("[key_name_admin(user)] is changing the title screen.")
switch(alert(usr, "Please select a new title screen.", "Title Screen", "Change", "Reset", "Cancel"))
if("Change")
- var/file = input(usr) as icon|null
+ var/file = input(user) as icon|null
if(!file)
return
SStitle.change_title_screen(file)
@@ -26,13 +20,7 @@
/**
* Sets a titlescreen notice, a big red text on the main screen.
*/
-/client/proc/change_title_screen_notice()
- set category = "Admin.Fun"
- set name = "Title Screen: Set Notice"
-
- if(!check_rights(R_FUN))
- return
-
+ADMIN_VERB(change_title_screen_notice, R_FUN, "Title Screen: Set Notice", "Sets a titlescreen notice, a big red text on the main screen.", ADMIN_CATEGORY_FUN)
log_admin("[key_name(usr)] is setting the title screen notice.")
message_admins("[key_name_admin(usr)] is setting the title screen notice.")
@@ -62,15 +50,9 @@
/**
* An admin debug command that enables you to change the HTML on the go.
*/
-/client/proc/change_title_screen_html()
- set category = "Admin.Fun"
- set name = "Title Screen: Set HTML"
-
- if(!check_rights(R_DEBUG))
- return
-
- log_admin("[key_name(usr)] is setting the title screen HTML.")
- message_admins("[key_name_admin(usr)] is setting the title screen HTML.")
+ADMIN_VERB(change_title_screen_html, R_DEBUG, "Title Screen: Set HTML", "Change lobby screen HTML on the go.", ADMIN_CATEGORY_FUN)
+ log_admin("[key_name(user)] is setting the title screen HTML.")
+ message_admins("[key_name_admin(user)] is setting the title screen HTML.")
var/new_html = input(usr, "Please enter your desired HTML(WARNING: YOU WILL BREAK SHIT)", "DANGER: TITLE HTML EDIT") as message|null
@@ -80,4 +62,4 @@
SStitle.title_html = new_html
SStitle.show_title_screen()
- message_admins("[key_name_admin(usr)] has changed the title screen HTML.")
+ message_admins("[key_name_admin(user)] has changed the title screen HTML.")
diff --git a/modular_skyrat/modules/turretid/code/turret_id_system.dm b/modular_skyrat/modules/turretid/code/turret_id_system.dm
index bae950e5b08..4b7c5ffd170 100644
--- a/modular_skyrat/modules/turretid/code/turret_id_system.dm
+++ b/modular_skyrat/modules/turretid/code/turret_id_system.dm
@@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(turret_id_refs)
/obj/machinery/turretid
var/system_id //The ID system for turrets, will get any turrets with the same ID and put them in controlled turrets
-/obj/machinery/turretid/LateInitialize()
+/obj/machinery/turretid/post_machine_initialize()
. = ..()
if(system_id && GLOB.turret_id_refs[system_id])
for(var/i in GLOB.turret_id_refs[system_id])
diff --git a/modular_skyrat/modules/wargame_projectors/code/projectors.dm b/modular_skyrat/modules/wargame_projectors/code/projectors.dm
index 49c3d46847a..fe34b3a68af 100644
--- a/modular_skyrat/modules/wargame_projectors/code/projectors.dm
+++ b/modular_skyrat/modules/wargame_projectors/code/projectors.dm
@@ -86,7 +86,7 @@
/obj/item/wargame_projector/attack_self(mob/user)
select_hologram(user)
-/obj/item/wargame_projector/AltClick(mob/user)
+/obj/item/wargame_projector/click_alt(mob/user)
var/selected_color = tgui_input_list(user, "Select a color", "Color Selection", color_options)
if(isnull(selected_color))
balloon_alert(user, "no color change")
@@ -95,6 +95,7 @@
holosign_color = color_to_set_to
balloon_alert(user, "color changed")
set_greyscale(holosign_color)
+ return CLICK_ACTION_SUCCESS
/obj/item/wargame_projector/CtrlClick(mob/user)
if(tgui_alert(usr,"Clear all currently active holograms?", "Hologram Removal", list("Yes", "No")) == "Yes")
diff --git a/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm b/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm
index d865fc0653f..384921be62a 100644
--- a/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm
+++ b/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm
@@ -121,8 +121,6 @@
///Implements behaviour that makes it possible to unanchor the railing.
/obj/structure/wrestling_corner/wrench_act(mob/living/user, obj/item/tool)
. = ..()
- if(obj_flags & NO_DECONSTRUCTION)
- return
to_chat(user, span_notice("You begin to [anchored ? "unfasten the turnbuckle from":"fasten the turnbuckle to"] the floor..."))
if(tool.use_tool(src, user, volume = 75, extra_checks = CALLBACK(src, PROC_REF(check_anchored), anchored)))
set_anchored(!anchored)
diff --git a/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm b/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm
index 899297d7447..a655eb44f90 100644
--- a/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm
+++ b/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm
@@ -169,7 +169,7 @@
return FALSE
//Remove the rod.
-/obj/machinery/power/rbmk2/AltClick(mob/living/user)
+/obj/machinery/power/rbmk2/click_alt(mob/living/user)
if(!active && stored_rod)
src.add_fingerprint(user)
stored_rod.add_fingerprint(user)
diff --git a/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm b/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm
index 4aacd9cbb99..02dfbd73f41 100644
--- a/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm
+++ b/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm
@@ -24,7 +24,7 @@
/// The resolved bank account
var/datum/bank_account/synced_bank_account = null
-/obj/machinery/computer/order_console/cook/interdyne/LateInitialize()
+/obj/machinery/computer/order_console/cook/interdyne/post_machine_initialize()
. = ..()
synced_bank_account = SSeconomy.get_dep_account(credits_account == "" ? ACCOUNT_CAR : credits_account)
diff --git a/modular_zubbers/code/game/machinery/department_balance.dm b/modular_zubbers/code/game/machinery/department_balance.dm
index 4bd5cafcf01..76e37cbb7fe 100644
--- a/modular_zubbers/code/game/machinery/department_balance.dm
+++ b/modular_zubbers/code/game/machinery/department_balance.dm
@@ -11,7 +11,7 @@
/// The resolved bank account
var/datum/bank_account/synced_bank_account = null
-/obj/machinery/status_display/department_balance/LateInitialize()
+/obj/machinery/status_display/department_balance/post_machine_initialize()
. = ..()
start_process()
diff --git a/modular_zubbers/code/game/machinery/syndiepad.dm b/modular_zubbers/code/game/machinery/syndiepad.dm
index 8f9bc91d0dd..f1d8cf3be7b 100644
--- a/modular_zubbers/code/game/machinery/syndiepad.dm
+++ b/modular_zubbers/code/game/machinery/syndiepad.dm
@@ -69,7 +69,7 @@
/// The resolved bank account
var/datum/bank_account/synced_bank_account = null
-/obj/machinery/computer/piratepad_control/syndiepad/LateInitialize()
+/obj/machinery/computer/piratepad_control/syndiepad/post_machine_initialize()
. = ..()
synced_bank_account = SSeconomy.get_dep_account(credits_account == "" ? ACCOUNT_CAR : credits_account)
diff --git a/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm b/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm
index 3c9b3767f3c..29ac3ae46e7 100644
--- a/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm
+++ b/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm
@@ -5,7 +5,7 @@
desc = "Releases a harmless blast that confuses most organics. Use in case of hostile blue whales."
var/alarm_phrase = "HARM"
-/obj/item/harmalarm/bubbers/AltClick(mob/living/user)
+/obj/item/harmalarm/bubbers/click_alt(mob/living/user)
var/str = reject_bad_text(tgui_input_text(user, "What would your alarm like to broadcast?", "Alarm Phrase", alarm_phrase, MAX_NAME_LEN)) //Limit of 42 characters.
if(!str)
to_chat(user, span_warning("Invalid text!"))
diff --git a/modular_zubbers/code/game/objects/structures/chalkboard.dm b/modular_zubbers/code/game/objects/structures/chalkboard.dm
index 6466e9779e8..586302b2ec7 100644
--- a/modular_zubbers/code/game/objects/structures/chalkboard.dm
+++ b/modular_zubbers/code/game/objects/structures/chalkboard.dm
@@ -54,7 +54,7 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/structure/chalkboard/wrench_act_secondary(mob/living/user, obj/item/tool)
- if(obj_flags & NO_DECONSTRUCTION)
+ if(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)
return FALSE
to_chat(user, span_notice("You start deconstructing [src]..."))
if(tool.use_tool(src, user, 4 SECONDS, volume=50))
@@ -64,7 +64,7 @@
/obj/structure/chalkboard/handle_deconstruct(disassembled = TRUE)
. = ..()
- if(!(obj_flags & NO_DECONSTRUCTION))
+ if(!(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION))
new /obj/item/stack/sheet/mineral/wood(drop_location(), 10)
qdel(src)
diff --git a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm
index c25b602cdb0..e7b5b5b3cdc 100644
--- a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm
+++ b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm
@@ -302,7 +302,7 @@
return inserted
/// Distance Check (Inside Of)
-/obj/structure/closet/crate/coffin/AltClick(mob/user)
+/obj/structure/closet/crate/coffin/click_alt(mob/user)
. = ..()
if(user in src)
LockMe(user, !locked)
diff --git a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm
index c155f45087b..d3ca07c07e8 100644
--- a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm
+++ b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm
@@ -72,7 +72,7 @@
return FALSE
return TRUE
-/obj/structure/bloodsucker/AltClick(mob/user)
+/obj/structure/bloodsucker/click_alt(mob/user)
. = ..()
if(user == owner && user.Adjacent(src))
balloon_alert(user, "unbolt [src]?")
diff --git a/modular_zubbers/code/modules/debug_tools/physgun.dm b/modular_zubbers/code/modules/debug_tools/physgun.dm
index b9b247e1a87..3c75f9535da 100644
--- a/modular_zubbers/code/modules/debug_tools/physgun.dm
+++ b/modular_zubbers/code/modules/debug_tools/physgun.dm
@@ -77,7 +77,7 @@
if(handlet_atom)
release_atom()
-/obj/item/physic_manipulation_tool/AltClick(mob/user)
+/obj/item/physic_manipulation_tool/click_alt(mob/user)
. = ..()
var/choised_color = input(usr, "Pick new effects color", "Physgun color") as color|null
effects_color = choised_color
diff --git a/modular_zubbers/code/modules/debug_tools/phystool.dm b/modular_zubbers/code/modules/debug_tools/phystool.dm
index d491c66de99..0867947ef96 100644
--- a/modular_zubbers/code/modules/debug_tools/phystool.dm
+++ b/modular_zubbers/code/modules/debug_tools/phystool.dm
@@ -39,7 +39,7 @@
return
. += span_notice(selected_mode.desc)
-/obj/item/phystool/AltClick(mob/user)
+/obj/item/phystool/click_alt(mob/user)
. = ..()
if(selected_mode)
qdel(selected_mode)
diff --git a/modular_zubbers/code/modules/hydroponics/gene_modder.dm b/modular_zubbers/code/modules/hydroponics/gene_modder.dm
index 27bec35eb8d..ae2c60fabd6 100644
--- a/modular_zubbers/code/modules/hydroponics/gene_modder.dm
+++ b/modular_zubbers/code/modules/hydroponics/gene_modder.dm
@@ -260,7 +260,7 @@
/obj/machinery/plantgenes/Topic(href, list/href_list)
if(..())
return
- usr.set_machine(src)
+// usr.set_machine(src)
if(href_list["eject_seed"] && !operation)
var/obj/item/I = usr.get_active_held_item()
diff --git a/modular_zubbers/maps/biodome/pride_flags.dm b/modular_zubbers/maps/biodome/pride_flags.dm
index 419bea39bf4..d4b118235c2 100644
--- a/modular_zubbers/maps/biodome/pride_flags.dm
+++ b/modular_zubbers/maps/biodome/pride_flags.dm
@@ -17,7 +17,7 @@
icon_state = "flag_pride"
item_flag = /obj/item/sign/flag/pride/gay
-/obj/structure/sign/flag/pride/gay/AltClick(mob/user)
+/obj/structure/sign/flag/pride/gay/click_alt(mob/user)
icon_state = "flag_pride_vertical"
.=..()
@@ -27,7 +27,7 @@
icon_state = "flag_ace"
item_flag = /obj/item/sign/flag/pride/ace
-/obj/structure/sign/flag/pride/ace/AltClick(mob/user)
+/obj/structure/sign/flag/pride/ace/click_alt(mob/user)
icon_state = "flag_ace_vertical"
.=..()
@@ -37,7 +37,7 @@
icon_state = "flag_bi"
item_flag = /obj/item/sign/flag/pride/bi
-/obj/structure/sign/flag/pride/bi/AltClick(mob/user)
+/obj/structure/sign/flag/pride/bi/click_alt(mob/user)
icon_state = "flag_bi_vertical"
.=..()
@@ -47,7 +47,7 @@
icon_state = "flag_lesbian"
item_flag = /obj/item/sign/flag/pride/lesbian
-/obj/structure/sign/flag/pride/lesbian/AltClick(mob/user)
+/obj/structure/sign/flag/pride/lesbian/click_alt(mob/user)
icon_state = "flag_lesbian_vertical"
.=..()
@@ -57,7 +57,7 @@
icon_state = "flag_pan"
item_flag = /obj/item/sign/flag/pride/pan
-/obj/structure/sign/flag/pride/pan/AltClick(mob/user)
+/obj/structure/sign/flag/pride/pan/click_alt(mob/user)
icon_state = "flag_pan_vertical"
.=..()
@@ -67,7 +67,7 @@
icon_state = "flag_trans"
item_flag = /obj/item/sign/flag/pride/trans
-/obj/structure/sign/flag/pride/trans/AltClick(mob/user)
+/obj/structure/sign/flag/pride/trans/click_alt(mob/user)
icon_state = "flag_trans_vertical"
.=..()
@@ -112,4 +112,4 @@
name = "folded trans pride flag"
desc = "The folded flag of trans pride."
icon_state = "folded_pride_trans"
- sign_path = /obj/structure/sign/flag/pride/trans
\ No newline at end of file
+ sign_path = /obj/structure/sign/flag/pride/trans
diff --git a/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm b/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm
index a3b5c92f3a5..7e15bf44cc1 100644
--- a/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm
+++ b/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm
@@ -4,4 +4,5 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
GLOB.arcade_prize_pool_mechanical = 1000,
GLOB.arcade_prize_pool_special = 250,
GLOB.arcade_prize_pool_oh_god = 1
-))
\ No newline at end of file
+))
+ // UNTICKED, COME BACK LATER AND OVERRIDE
diff --git a/modular_zubbers/modules/blooper/bark.dm b/modular_zubbers/modules/blooper/bark.dm
index 737b114f0cf..37e1425d4fa 100644
--- a/modular_zubbers/modules/blooper/bark.dm
+++ b/modular_zubbers/modules/blooper/bark.dm
@@ -36,9 +36,9 @@ GLOBAL_VAR_INIT(blooper_allowed, TRUE) // For administrators
message_admins("[key_name_admin(usr)] toggled Voice Barks.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Voice Bark", "[GLOB.blooper_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
-/world/AVerbsAdmin()
+/* /world/AVerbsAdmin()
. = ..()
- return . + /datum/admins/proc/toggleblooper
+ return . + /datum/admins/proc/toggleblooper */
/proc/toggle_blooper(toggle = null)
if(toggle != null)
diff --git a/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm b/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm
index ca001ff0b5b..ec570dc317f 100644
--- a/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm
+++ b/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm
@@ -22,7 +22,7 @@
name = "moon rover controller"
desc = "Unlike the iconic moon rover of yesteryears, our tram is here to remind you that even in space, mediocrity finds a way."
configured_transport_id = MOONSTATION_LINE_1
- obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION
+ obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION
/obj/machinery/transport/destination_sign/moonstation
icon = 'modular_zubbers/modules/bubber_tram/icons/tram_display.dmi'
diff --git a/modular_zubbers/modules/shelves/shelf.dm b/modular_zubbers/modules/shelves/shelf.dm
index be027cca9eb..7e0016e442f 100644
--- a/modular_zubbers/modules/shelves/shelf.dm
+++ b/modular_zubbers/modules/shelves/shelf.dm
@@ -48,7 +48,7 @@
. += " [icon2html(crate, user)] [crate]"
/obj/structure/cargo_shelf/attackby(obj/item/item, mob/living/user, params)
- if (item.tool_behaviour == TOOL_WRENCH && !(flags_1 & NO_DECONSTRUCTION))
+ if (item.tool_behaviour == TOOL_WRENCH && !(flags_1 & NO_DEBRIS_AFTER_DECONSTRUCTION))
item.play_tool_sound(src)
if(do_after(user, 3 SECONDS, target = src))
deconstruct(TRUE)
@@ -133,7 +133,7 @@
crate.visible_message(span_warning("[crate] falls apart!"))
crate.deconstruct()
shelf_contents[shelf_contents.Find(crate)] = null
- if(!(flags_1 & NO_DECONSTRUCTION))
+ if(!(flags_1 & NO_DEBRIS_AFTER_DECONSTRUCTION))
density = FALSE
var/obj/item/rack_parts/cargo_shelf/newparts = new(loc)
transfer_fingerprints_to(newparts)
diff --git a/sound/attributions.txt b/sound/attributions.txt
index c81aa3e664b..be8df17c535 100644
--- a/sound/attributions.txt
+++ b/sound/attributions.txt
@@ -140,3 +140,10 @@ https://freesound.org/people/steaq/sounds/560124/
refinery.ogg, smelter.ogg, and wooping_teleport.ogg are all original works by ArcaneMusic,
with smelter.ogg using samples from rock_break alongside original sound effects from a warrior electric drill,
where refinery and wooping_teleport are modifications of that same electric drill recording.
+
+paper_flip.ogg is made by gynation from Freesound.org, CC0
+https://freesound.org/people/gynation/sounds/82378/
+
+nightmare_poof.ogg and nightmare_reappear.ogg are comprised of breath_01.wav by Nightflame (CC0) and slide-click.wav by Qat (CC0)
+https://freesound.org/people/Qat/sounds/108332/
+https://freesound.org/people/Nightflame/sounds/368615/
diff --git a/sound/effects/nightmare_poof.ogg b/sound/effects/nightmare_poof.ogg
new file mode 100644
index 00000000000..e8b44685ba4
Binary files /dev/null and b/sound/effects/nightmare_poof.ogg differ
diff --git a/sound/effects/nightmare_reappear.ogg b/sound/effects/nightmare_reappear.ogg
new file mode 100644
index 00000000000..3dec2006460
Binary files /dev/null and b/sound/effects/nightmare_reappear.ogg differ
diff --git a/sound/items/paper_flip.ogg b/sound/items/paper_flip.ogg
new file mode 100644
index 00000000000..9e6aca59675
Binary files /dev/null and b/sound/items/paper_flip.ogg differ
diff --git a/sound/weapons/zipline_fire.ogg b/sound/weapons/zipline_fire.ogg
new file mode 100644
index 00000000000..4ac133897b5
Binary files /dev/null and b/sound/weapons/zipline_fire.ogg differ
diff --git a/sound/weapons/zipline_hit.ogg b/sound/weapons/zipline_hit.ogg
new file mode 100644
index 00000000000..cf17cbc84d1
Binary files /dev/null and b/sound/weapons/zipline_hit.ogg differ
diff --git a/sound/weapons/zipline_mid.ogg b/sound/weapons/zipline_mid.ogg
new file mode 100644
index 00000000000..22148f1c594
Binary files /dev/null and b/sound/weapons/zipline_mid.ogg differ
diff --git a/strings/antagonist_flavor/spy_objective.json b/strings/antagonist_flavor/spy_objective.json
index aa696baad6f..908a8da2b82 100644
--- a/strings/antagonist_flavor/spy_objective.json
+++ b/strings/antagonist_flavor/spy_objective.json
@@ -8,73 +8,190 @@
"Ensure @pick(location) is @pick(affected) by the end of the shift.",
"Ensure no heads of staff @pick(escape) the station.",
"Ensure no members of @pick(department) @pick(escape) the station.",
- "Ensure no rival @pick(rivals) @pick(escape) the station.",
+ "Ensure no @pick(rivals) @pick(escape) the station.",
+ "Ensure no @pick(rivals) succeed in their objectives.",
+ "Ensure all @pick(rivals) @pick(escape) the station.",
+ "Ensure all @pick(rivals) succeed in their objectives.",
+ "Ensure at least some @pick(rivals) leave the shift @pick(affected).",
+ "Ensure at least some @pick(rivals) do not leave the shift @pick(affected).",
+ "Ensure at least some @pick(rivals) @pick(escape) the station @pick(affected).",
+ "Ensure no @pick(rivals) @pick(escape) the station @pick(affected).",
+ "Ensure the station's @pick(happenings) turn out @pick(affected).",
"Frame a crewmember for a crime.",
"Free the station's AI from its laws.",
"Halt the station's @pick(happenings).",
+ "Help the station succeed in its @pick(happenings).",
"Invoke a mutiny against the heads of staff.",
- "Make it difficult, but not impossible to @pick(escape) the station.",
+ "Invoke a mutiny in @pick(department).",
+ "Keep everyone out of @pick(location).",
+ "Make it difficult but not impossible to @pick(escape) the station.",
+ "Protect the station's @pick(happenings).",
"Sabotage the station's power grid or engine.",
+ "Steal all the @pick(stealables) from @pick(department).",
+ "Steal all the @pick(stealables) from @pick(location).",
"Steal as many @pick(stealables) as you can.",
"Take control of the station as the new Captain.",
- "Take hostages of high value crewmembers and demand a ransom."
+ "Take hostages of high value crewmembers and demand a ransom.",
+ "Terrorize @pick(department) enough to be attacked on sight.",
+ "Terrorize @pick(rivals) enough to be branded a hero."
],
"department": [
- "Security",
+ "Command",
"Engineering",
"Medical",
"Science",
+ "Security",
+ "Service",
"Supply"
],
"location": [
+ "atmospherics",
+ "departures",
"engineering",
"genetics",
"hydroponics",
"medbay",
+ "the armory",
"the bar",
"the bridge",
"the brig",
"the cargo bay",
+ "the Central Primary hallway",
+ "the courtroom",
"the chapel",
+ "the garden",
+ "the holodeck",
"the kitchen",
"the library",
+ "the mining outpost",
+ "the vault",
+ "virology",
"xenobiology"
],
"happenings": [
- "research",
+ "breakfasts",
"cargo operations",
"communications",
+ "efforts to figure something out",
+ "efforts to make an important decision",
+ "efforts to solve a crime",
+ "efforts to solve a murder",
+ "efforts to start a project",
+ "efforts to stop a disaster",
+ "lunches",
+ "dinners",
"genetic research",
- "mining operation"
+ "mech constructions",
+ "mining operations",
+ "optional surgeries",
+ "public gatherings",
+ "public services",
+ "research efforts",
+ "social events",
+ "xenobiological experiments"
],
"affected": [
+ "a disaster",
"ablaze",
+ "alive",
+ "a failure",
+ "a success",
+ "better than expected",
+ "blasted",
+ "bored",
+ "boring",
"burning",
+ "busy",
+ "clean",
+ "confused",
+ "confusing",
"covered in blood",
+ "cursed",
+ "dead",
+ "dirty",
+ "disrupted",
+ "disabled",
"demolished",
"destroyed",
+ "devastated",
"engulfed in flames",
+ "exploded",
+ "exploding",
+ "free",
+ "frustrated",
+ "functional",
+ "hazardous",
+ "horrified",
+ "horrifying",
+ "in chaos",
+ "inspired",
+ "inspiring",
+ "intact",
+ "locked down",
+ "non-functional",
"obliterated",
+ "offended",
"on fire",
+ "optimized",
+ "peaceful",
+ "powerful",
+ "quiet",
"ruined",
"sabotaged",
+ "safe",
+ "scary",
+ "scandalized",
+ "serene",
+ "shattered",
+ "terrible",
+ "tranquil",
+ "unrecognizable",
+ "vandalized",
"wrecked"
],
"rivals": [
"agents",
+ "aliens",
+ "cowards",
+ "criminals",
+ "entertainers",
+ "extradimensional horrors",
+ "fanatics",
+ "foreigners",
+ "hooligans",
+ "litterers",
+ "magic-users",
"moles",
"operatives",
+ "rude people",
+ "sentient non-humanoids",
"spies",
- "traitors"
+ "subversives",
+ "thieves",
+ "traitors",
+ "tyrants"
],
"stealables": [
+ "appliances",
+ "cargo orders",
+ "critical pieces of infrastructure",
+ "decorations",
+ "floor tiles",
+ "foods",
"items",
+ "materials",
+ "medicines",
"objects",
+ "pets",
+ "public supplies",
+ "quiet moments",
"things",
"tools",
+ "vending machines",
"weapons"
],
"escape": [
+ "abscond from",
"depart",
"escape",
"evacuate",
diff --git a/strings/arcade.json b/strings/arcade.json
index 584cbc6decd..a97a3d75549 100644
--- a/strings/arcade.json
+++ b/strings/arcade.json
@@ -79,64 +79,6 @@
"Yuletide"
],
- "rpg_action": [
- "Annihilate",
- "Ban",
- "Defeat",
- "Destroy",
- "Mutilate",
- "Nuke",
- "Own",
- "Perma",
- "Pwn",
- "Pulverize",
- "Robust",
- "Save",
- "Stop",
- "Strike",
- "Valid",
- "Yeet"
- ],
-
- "rpg_action_valentines": [
- "Bewitch",
- "Crush",
- "Cuddle",
- "Divorce",
- "ERP",
- "Romance",
- "Seduce",
- "Smooch",
- "Titillate"
- ],
-
- "rpg_action_halloween": [
- "Amputate",
- "Behead",
- "Beware",
- "Butcher",
- "Dismember",
- "Exorcise",
- "Frighten",
- "Horrify",
- "Scare",
- "Scythe",
- "Slay",
- "Spook",
- "Vanquish"
- ],
-
- "rpg_action_xmas": [
- "Freeze",
- "Jingle",
- "Nutcrack",
- "Re-gift",
- "Snowplow",
- "Stuff",
- "Unwrap",
- "Wassail"
- ],
-
"rpg_enemy": [
"Administrator",
"Bloopers",
@@ -217,66 +159,6 @@
"Stalking Stocking",
"Yeti",
"Yuki-Onna"
- ],
-
- "rpg_weapon": [
- "baseball bat",
- "bike horn",
- "broken bottle",
- "chef's knife",
- "circular saw",
- "claymore",
- "cleaver",
- "crowbar",
- "curator's whip",
- "fire axe",
- "fire extinguisher",
- "full oxygen tank",
- "glass shard",
- "liz o' nine tails",
- "null rod",
- "potted plant",
- "rolling pin",
- "scalpel",
- "screwdriver",
- "stunprod",
- "toolbox",
- "welder"
- ],
-
- "rpg_weapon_valentines": [
- "bouquet of deathnettles",
- "candy-heart shotgun",
- "cupid's arrow",
- "declaration of anguished feelings",
- "razor-sharp breakup letter",
- "still-beating heart",
- "thorny rose",
- "toolbox of chocolates"
- ],
-
- "rpg_weapon_halloween": [
- "chainsaw",
- "heavy gravestone",
- "lit jack-o-lantern",
- "machete",
- "silver dagger",
- "skeleton femur",
- "spectral blade",
- "wooden stake"
- ],
-
- "rpg_weapon_xmas": [
- "bike horn playing carols",
- "blunt fruitcake",
- "box cutter",
- "Christmas-light garrotte",
- "festivus polearm",
- "rejected present",
- "sharpened icicle",
- "sprig of mistletoe",
- "thrown snowball",
- "whole Christmas tree"
]
}
diff --git a/tgstation.dme b/tgstation.dme
index 463762e4954..00794ab14bd 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -31,6 +31,7 @@
#include "code\__DEFINES\actions.dm"
#include "code\__DEFINES\actionspeed_modification.dm"
#include "code\__DEFINES\admin.dm"
+#include "code\__DEFINES\admin_verb.dm"
#include "code\__DEFINES\adventure.dm"
#include "code\__DEFINES\airlock.dm"
#include "code\__DEFINES\alarm.dm"
@@ -40,7 +41,7 @@
#include "code\__DEFINES\antagonists.dm"
#include "code\__DEFINES\apc_defines.dm"
#include "code\__DEFINES\appearance.dm"
-#include "code\__DEFINES\area_editor.dm"
+#include "code\__DEFINES\arcades.dm"
#include "code\__DEFINES\art.dm"
#include "code\__DEFINES\assemblies.dm"
#include "code\__DEFINES\assert.dm"
@@ -60,6 +61,7 @@
#include "code\__DEFINES\chat.dm"
#include "code\__DEFINES\chat_filter.dm"
#include "code\__DEFINES\cleaning.dm"
+#include "code\__DEFINES\click.dm"
#include "code\__DEFINES\client.dm"
#include "code\__DEFINES\clothing.dm"
#include "code\__DEFINES\colors.dm"
@@ -614,6 +616,7 @@
#include "code\__HELPERS\~skyrat_helpers\unsorted.dm"
#include "code\_globalvars\_regexes.dm"
#include "code\_globalvars\admin.dm"
+#include "code\_globalvars\arcade.dm"
#include "code\_globalvars\bitfields.dm"
#include "code\_globalvars\colorvars.dm"
#include "code\_globalvars\configuration.dm"
@@ -660,6 +663,7 @@
#include "code\_onclick\adjacent.dm"
#include "code\_onclick\ai.dm"
#include "code\_onclick\click.dm"
+#include "code\_onclick\click_alt.dm"
#include "code\_onclick\cyborg.dm"
#include "code\_onclick\drag_drop.dm"
#include "code\_onclick\item_attack.dm"
@@ -721,6 +725,7 @@
#include "code\controllers\configuration\entries\resources.dm"
#include "code\controllers\subsystem\achievements.dm"
#include "code\controllers\subsystem\addiction.dm"
+#include "code\controllers\subsystem\admin_verbs.dm"
#include "code\controllers\subsystem\ai_controllers.dm"
#include "code\controllers\subsystem\air.dm"
#include "code\controllers\subsystem\ambience.dm"
@@ -856,7 +861,6 @@
#include "code\controllers\subsystem\processing\greyscale.dm"
#include "code\controllers\subsystem\processing\instruments.dm"
#include "code\controllers\subsystem\processing\obj.dm"
-#include "code\controllers\subsystem\processing\obj_tab_items.dm"
#include "code\controllers\subsystem\processing\plumbing.dm"
#include "code\controllers\subsystem\processing\processing.dm"
#include "code\controllers\subsystem\processing\projectiles.dm"
@@ -1230,6 +1234,7 @@
#include "code\datums\components\manual_breathing.dm"
#include "code\datums\components\manual_heart.dm"
#include "code\datums\components\marionette.dm"
+#include "code\datums\components\martial_art_giver.dm"
#include "code\datums\components\mind_linker.dm"
#include "code\datums\components\mirv.dm"
#include "code\datums\components\mob_chain.dm"
@@ -1471,6 +1476,7 @@
#include "code\datums\elements\atmos_requirements.dm"
#include "code\datums\elements\atmos_sensitive.dm"
#include "code\datums\elements\attack_equip.dm"
+#include "code\datums\elements\attack_zone_randomiser.dm"
#include "code\datums\elements\backblast.dm"
#include "code\datums\elements\bane.dm"
#include "code\datums\elements\basic_eating.dm"
@@ -1552,6 +1558,7 @@
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\light_eaten.dm"
#include "code\datums\elements\light_eater.dm"
+#include "code\datums\elements\living_limb_initialiser.dm"
#include "code\datums\elements\loomable.dm"
#include "code\datums\elements\mirage_border.dm"
#include "code\datums\elements\mob_access.dm"
@@ -1571,6 +1578,7 @@
#include "code\datums\elements\pet_bonus.dm"
#include "code\datums\elements\plant_backfire.dm"
#include "code\datums\elements\point_of_interest.dm"
+#include "code\datums\elements\poster_tearer.dm"
#include "code\datums\elements\prevent_attacking_of_types.dm"
#include "code\datums\elements\projectile_drop.dm"
#include "code\datums\elements\projectile_shield.dm"
@@ -1598,6 +1606,7 @@
#include "code\datums\elements\tenacious.dm"
#include "code\datums\elements\tiny_mob_hunter.dm"
#include "code\datums\elements\tool_flash.dm"
+#include "code\datums\elements\tool_renaming.dm"
#include "code\datums\elements\toy_talk.dm"
#include "code\datums\elements\turf_transparency.dm"
#include "code\datums\elements\undertile.dm"
@@ -1612,6 +1621,7 @@
#include "code\datums\elements\wall_smasher.dm"
#include "code\datums\elements\wall_tearer.dm"
#include "code\datums\elements\wall_walker.dm"
+#include "code\datums\elements\watery_tile.dm"
#include "code\datums\elements\weapon_description.dm"
#include "code\datums\elements\weather_listener.dm"
#include "code\datums\elements\web_walker.dm"
@@ -1758,6 +1768,7 @@
#include "code\datums\quirks\negative_quirks\addict.dm"
#include "code\datums\quirks\negative_quirks\all_nighter.dm"
#include "code\datums\quirks\negative_quirks\allergic.dm"
+#include "code\datums\quirks\negative_quirks\anosmia.dm"
#include "code\datums\quirks\negative_quirks\bad_back.dm"
#include "code\datums\quirks\negative_quirks\bad_touch.dm"
#include "code\datums\quirks\negative_quirks\big_hands.dm"
@@ -1839,6 +1850,7 @@
#include "code\datums\quirks\positive_quirks\skittish.dm"
#include "code\datums\quirks\positive_quirks\spacer.dm"
#include "code\datums\quirks\positive_quirks\spiritual.dm"
+#include "code\datums\quirks\positive_quirks\strong_stomach.dm"
#include "code\datums\quirks\positive_quirks\tagger.dm"
#include "code\datums\quirks\positive_quirks\throwing_arm.dm"
#include "code\datums\quirks\positive_quirks\voracious.dm"
@@ -2148,7 +2160,10 @@
#include "code\game\machinery\computer\telescreen.dm"
#include "code\game\machinery\computer\terminal.dm"
#include "code\game\machinery\computer\warrant.dm"
-#include "code\game\machinery\computer\arcade\arcade.dm"
+#include "code\game\machinery\computer\arcade\_arcade.dm"
+#include "code\game\machinery\computer\arcade\amputation.dm"
+#include "code\game\machinery\computer\arcade\battle.dm"
+#include "code\game\machinery\computer\arcade\battle_gear.dm"
#include "code\game\machinery\computer\arcade\orion.dm"
#include "code\game\machinery\computer\arcade\orion_event.dm"
#include "code\game\machinery\computer\atmos_computers\__identifiers.dm"
@@ -2231,6 +2246,7 @@
#include "code\game\objects\buckling.dm"
#include "code\game\objects\empulse.dm"
#include "code\game\objects\items.dm"
+#include "code\game\objects\items_reskin.dm"
#include "code\game\objects\obj_defense.dm"
#include "code\game\objects\objs.dm"
#include "code\game\objects\structures.dm"
@@ -2805,6 +2821,7 @@
#include "code\game\objects\structures\gym\weight_machine_action.dm"
#include "code\game\objects\structures\icemoon\cave_entrance.dm"
#include "code\game\objects\structures\lavaland\geyser.dm"
+#include "code\game\objects\structures\lavaland\gulag_vent.dm"
#include "code\game\objects\structures\lavaland\necropolis_tendril.dm"
#include "code\game\objects\structures\lavaland\ore_vent.dm"
#include "code\game\objects\structures\plaques\_plaques.dm"
@@ -2877,7 +2894,6 @@
#include "code\modules\admin\admin_pda_message.dm"
#include "code\modules\admin\admin_ranks.dm"
#include "code\modules\admin\admin_verbs.dm"
-#include "code\modules\admin\adminmenu.dm"
#include "code\modules\admin\antag_panel.dm"
#include "code\modules\admin\chat_commands.dm"
#include "code\modules\admin\check_antagonists.dm"
@@ -2937,6 +2953,8 @@
#include "code\modules\admin\smites\smite.dm"
#include "code\modules\admin\smites\supply_pod.dm"
#include "code\modules\admin\smites\supply_pod_quick.dm"
+#include "code\modules\admin\verb_datums\_admin_verb_datum.dm"
+#include "code\modules\admin\verb_datums\_admin_verb_holder.dm"
#include "code\modules\admin\verbs\admin.dm"
#include "code\modules\admin\verbs\admin_newscaster.dm"
#include "code\modules\admin\verbs\adminevents.dm"
@@ -2991,6 +3009,7 @@
#include "code\modules\admin\verbs\server.dm"
#include "code\modules\admin\verbs\shuttlepanel.dm"
#include "code\modules\admin\verbs\spawnobjasmob.dm"
+#include "code\modules\admin\verbs\special_verbs.dm"
#include "code\modules\admin\verbs\lua\_hooks.dm"
#include "code\modules\admin\verbs\lua\_wrappers.dm"
#include "code\modules\admin\verbs\lua\helpers.dm"
@@ -3405,6 +3424,7 @@
#include "code\modules\asset_cache\assets\fontawesome.dm"
#include "code\modules\asset_cache\assets\genetics.dm"
#include "code\modules\asset_cache\assets\headers.dm"
+#include "code\modules\asset_cache\assets\icon_ref_map.dm"
#include "code\modules\asset_cache\assets\inventory.dm"
#include "code\modules\asset_cache\assets\irv.dm"
#include "code\modules\asset_cache\assets\jquery.dm"
@@ -4459,6 +4479,7 @@
#include "code\modules\library\skill_learning\skillchip.dm"
#include "code\modules\library\skill_learning\job_skillchips\_job.dm"
#include "code\modules\library\skill_learning\job_skillchips\chef.dm"
+#include "code\modules\library\skill_learning\job_skillchips\clown.dm"
#include "code\modules\library\skill_learning\job_skillchips\janitor.dm"
#include "code\modules\library\skill_learning\job_skillchips\miner.dm"
#include "code\modules\library\skill_learning\job_skillchips\psychologist.dm"
@@ -4487,6 +4508,13 @@
#include "code\modules\logging\categories\log_category_silo.dm"
#include "code\modules\logging\categories\log_category_target_zone_switch.dm"
#include "code\modules\logging\categories\log_category_uplink.dm"
+#include "code\modules\lootpanel\_lootpanel.dm"
+#include "code\modules\lootpanel\contents.dm"
+#include "code\modules\lootpanel\handlers.dm"
+#include "code\modules\lootpanel\misc.dm"
+#include "code\modules\lootpanel\search_object.dm"
+#include "code\modules\lootpanel\ss_looting.dm"
+#include "code\modules\lootpanel\ui.dm"
#include "code\modules\mafia\_defines.dm"
#include "code\modules\mafia\controller.dm"
#include "code\modules\mafia\controller_ui.dm"
@@ -4613,6 +4641,7 @@
#include "code\modules\mining\boulder_processing\brm.dm"
#include "code\modules\mining\boulder_processing\refinery.dm"
#include "code\modules\mining\equipment\explorer_gear.dm"
+#include "code\modules\mining\equipment\grapple_gun.dm"
#include "code\modules\mining\equipment\kheiral_cuffs.dm"
#include "code\modules\mining\equipment\kinetic_crusher.dm"
#include "code\modules\mining\equipment\lazarus_injector.dm"
@@ -8712,7 +8741,6 @@
#include "modular_zubbers\modules\arcades\code\loot\arcade_weights_oh_god.dm"
#include "modular_zubbers\modules\arcades\code\loot\arcade_weights_special.dm"
#include "modular_zubbers\modules\arcades\code\loot\arcade_weights_toy.dm"
-#include "modular_zubbers\modules\arcades\code\loot\~arcade_weights_final.dm"
#include "modular_zubbers\modules\arcades\code\minesweeper\minesweeper.dm"
#include "modular_zubbers\modules\arcades\code\overrides\spawners.dm"
#include "modular_zubbers\modules\ashwalkers\code\effects\ash_rituals.dm"
diff --git a/tgui/packages/common/collections.ts b/tgui/packages/common/collections.ts
index 5bfcee85884..9aed42557dc 100644
--- a/tgui/packages/common/collections.ts
+++ b/tgui/packages/common/collections.ts
@@ -12,33 +12,36 @@
* If collection is 'null' or 'undefined', it will be returned "as is"
* without emitting any errors (which can be useful in some cases).
*/
-export const filter =
- (iterateeFn: (input: T, index: number, collection: T[]) => boolean) =>
- (collection: T[]): T[] => {
- if (collection === null || collection === undefined) {
- return collection;
- }
- if (Array.isArray(collection)) {
- const result: T[] = [];
- for (let i = 0; i < collection.length; i++) {
- const item = collection[i];
- if (iterateeFn(item, i, collection)) {
- result.push(item);
- }
+export const filter = (
+ collection: T[],
+ iterateeFn: (input: T, index: number, collection: T[]) => boolean,
+): T[] => {
+ if (collection === null || collection === undefined) {
+ return collection;
+ }
+ if (Array.isArray(collection)) {
+ const result: T[] = [];
+ for (let i = 0; i < collection.length; i++) {
+ const item = collection[i];
+ if (iterateeFn(item, i, collection)) {
+ result.push(item);
}
- return result;
}
- throw new Error(`filter() can't iterate on type ${typeof collection}`);
- };
+ return result;
+ }
+ throw new Error(`filter() can't iterate on type ${typeof collection}`);
+};
type MapFunction = {
(
+ collection: T[],
iterateeFn: (value: T, index: number, collection: T[]) => U,
- ): (collection: T[]) => U[];
+ ): U[];
(
+ collection: Record,
iterateeFn: (value: T, index: K, collection: Record) => U,
- ): (collection: Record) => U[];
+ ): U[];
};
/**
@@ -49,44 +52,30 @@ type MapFunction = {
* If collection is 'null' or 'undefined', it will be returned "as is"
* without emitting any errors (which can be useful in some cases).
*/
-export const map: MapFunction =
- (iterateeFn) =>
- (collection: T[]): U[] => {
- if (collection === null || collection === undefined) {
- return collection;
- }
-
- if (Array.isArray(collection)) {
- return collection.map(iterateeFn);
- }
-
- if (typeof collection === 'object') {
- return Object.entries(collection).map(([key, value]) => {
- return iterateeFn(value, key, collection);
- });
- }
-
- throw new Error(`map() can't iterate on type ${typeof collection}`);
- };
-
-/**
- * Given a collection, will run each element through an iteratee function.
- * Will then filter out undefined values.
- */
-export const filterMap = (
- collection: T[],
- iterateeFn: (value: T) => U | undefined,
-): U[] => {
- const finalCollection: U[] = [];
-
- for (const value of collection) {
- const output = iterateeFn(value);
- if (output !== undefined) {
- finalCollection.push(output);
- }
+export const map: MapFunction = (collection, iterateeFn) => {
+ if (collection === null || collection === undefined) {
+ return collection;
}
- return finalCollection;
+ if (Array.isArray(collection)) {
+ const result: unknown[] = [];
+ for (let i = 0; i < collection.length; i++) {
+ result.push(iterateeFn(collection[i], i, collection));
+ }
+ return result;
+ }
+
+ if (typeof collection === 'object') {
+ const result: unknown[] = [];
+ for (let i in collection) {
+ if (Object.prototype.hasOwnProperty.call(collection, i)) {
+ result.push(iterateeFn(collection[i], i, collection));
+ }
+ }
+ return result;
+ }
+
+ throw new Error(`map() can't iterate on type ${typeof collection}`);
};
const COMPARATOR = (objA, objB) => {
@@ -112,39 +101,38 @@ const COMPARATOR = (objA, objB) => {
*
* Iteratees are called with one argument (value).
*/
-export const sortBy =
- (...iterateeFns: ((input: T) => unknown)[]) =>
- (array: T[]): T[] => {
- if (!Array.isArray(array)) {
- return array;
- }
- let length = array.length;
- // Iterate over the array to collect criteria to sort it by
- let mappedArray: {
- criteria: unknown[];
- value: T;
- }[] = [];
- for (let i = 0; i < length; i++) {
- const value = array[i];
- mappedArray.push({
- criteria: iterateeFns.map((fn) => fn(value)),
- value,
- });
- }
- // Sort criteria using the base comparator
- mappedArray.sort(COMPARATOR);
+export const sortBy = (
+ array: T[],
+ ...iterateeFns: ((input: T) => unknown)[]
+): T[] => {
+ if (!Array.isArray(array)) {
+ return array;
+ }
+ let length = array.length;
+ // Iterate over the array to collect criteria to sort it by
+ let mappedArray: {
+ criteria: unknown[];
+ value: T;
+ }[] = [];
+ for (let i = 0; i < length; i++) {
+ const value = array[i];
+ mappedArray.push({
+ criteria: iterateeFns.map((fn) => fn(value)),
+ value,
+ });
+ }
+ // Sort criteria using the base comparator
+ mappedArray.sort(COMPARATOR);
- // Unwrap values
- const values: T[] = [];
- while (length--) {
- values[length] = mappedArray[length].value;
- }
- return values;
- };
+ // Unwrap values
+ const values: T[] = [];
+ while (length--) {
+ values[length] = mappedArray[length].value;
+ }
+ return values;
+};
-export const sort = sortBy();
-
-export const sortStrings = sortBy();
+export const sort = (array: T[]): T[] => sortBy(array);
/**
* Returns a range of numbers from start to end, exclusively.
@@ -153,12 +141,34 @@ export const sortStrings = sortBy();
export const range = (start: number, end: number): number[] =>
new Array(end - start).fill(null).map((_, index) => index + start);
+type ReduceFunction = {
+ (
+ array: T[],
+ reducerFn: (
+ accumulator: U,
+ currentValue: T,
+ currentIndex: number,
+ array: T[],
+ ) => U,
+ initialValue: U,
+ ): U;
+ (
+ array: T[],
+ reducerFn: (
+ accumulator: T,
+ currentValue: T,
+ currentIndex: number,
+ array: T[],
+ ) => T,
+ ): T;
+};
+
/**
* A fast implementation of reduce.
*/
-export const reduce = (reducerFn, initialValue) => (array) => {
+export const reduce: ReduceFunction = (array, reducerFn, initialValue?) => {
const length = array.length;
- let i;
+ let i: number;
let result;
if (initialValue === undefined) {
i = 1;
@@ -184,15 +194,16 @@ export const reduce = (reducerFn, initialValue) => (array) => {
* is determined by the order they occur in the array. The iteratee is
* invoked with one argument: value.
*/
-export const uniqBy =
- (iterateeFn?: (value: T) => unknown) =>
- (array: T[]): T[] => {
- const { length } = array;
- const result: T[] = [];
- const seen: unknown[] = iterateeFn ? [] : result;
- let index = -1;
- // prettier-ignore
- outer:
+export const uniqBy = (
+ array: T[],
+ iterateeFn?: (value: T) => unknown,
+): T[] => {
+ const { length } = array;
+ const result: T[] = [];
+ const seen: unknown[] = iterateeFn ? [] : result;
+ let index = -1;
+ // prettier-ignore
+ outer:
while (++index < length) {
let value: T | 0 = array[index];
const computed = iterateeFn ? iterateeFn(value) : value;
@@ -214,10 +225,10 @@ export const uniqBy =
result.push(value);
}
}
- return result;
- };
+ return result;
+};
-export const uniq = uniqBy();
+export const uniq = (array: T[]): T[] => uniqBy(array);
type Zip = {
[I in keyof T]: T[I] extends (infer U)[] ? U : never;
@@ -247,17 +258,6 @@ export const zip = (...arrays: T): Zip => {
return result;
};
-/**
- * This method is like "zip" except that it accepts iteratee to
- * specify how grouped values should be combined. The iteratee is
- * invoked with the elements of each group.
- */
-export const zipWith =
- (iterateeFn: (...values: T[]) => U) =>
- (...arrays: T[][]): U[] => {
- return map((values: T[]) => iterateeFn(...values))(zip(...arrays));
- };
-
const binarySearch = (
getKey: (value: T) => U,
collection: readonly T[],
@@ -293,13 +293,15 @@ const binarySearch = (
return compare > insertingKey ? middle : middle + 1;
};
-export const binaryInsertWith =
- (getKey: (value: T) => U) =>
- (collection: readonly T[], value: T) => {
- const copy = [...collection];
- copy.splice(binarySearch(getKey, collection, value), 0, value);
- return copy;
- };
+export const binaryInsertWith = (
+ collection: readonly T[],
+ value: T,
+ getKey: (value: T) => U,
+): T[] => {
+ const copy = [...collection];
+ copy.splice(binarySearch(getKey, collection, value), 0, value);
+ return copy;
+};
/**
* This method takes a collection of items and a number, returning a collection
@@ -325,7 +327,8 @@ export const paginate = (collection: T[], maxPerPage: number): T[][] => {
return pages;
};
-const isObject = (obj: unknown) => typeof obj === 'object' && obj !== null;
+const isObject = (obj: unknown): obj is object =>
+ typeof obj === 'object' && obj !== null;
// Does a deep merge of two objects. DO NOT FEED CIRCULAR OBJECTS!!
export const deepMerge = (...objects: any[]): any => {
diff --git a/tgui/packages/common/fp.js b/tgui/packages/common/fp.js
index ba7df09d407..675e98d807e 100644
--- a/tgui/packages/common/fp.js
+++ b/tgui/packages/common/fp.js
@@ -23,27 +23,3 @@ export const flow = (...funcs) => (input, ...rest) => {
}
return output;
};
-
-/**
- * Composes single-argument functions from right to left.
- *
- * All functions might accept a context in form of additional arguments.
- * If the resulting function is called with more than 1 argument, rest of
- * the arguments are passed to all functions unchanged.
- *
- * @param {...Function} funcs The functions to compose
- * @returns {Function} A function obtained by composing the argument functions
- * from right to left. For example, compose(f, g, h) is identical to doing
- * (input, ...rest) => f(g(h(input, ...rest), ...rest), ...rest)
- */
-export const compose = (...funcs) => {
- if (funcs.length === 0) {
- return (arg) => arg;
- }
- if (funcs.length === 1) {
- return funcs[0];
- }
- // prettier-ignore
- return funcs.reduce((a, b) => (value, ...rest) =>
- a(b(value, ...rest), ...rest));
-};
diff --git a/tgui/packages/common/vector.js b/tgui/packages/common/vector.js
deleted file mode 100644
index b1f85f7429d..00000000000
--- a/tgui/packages/common/vector.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * N-dimensional vector manipulation functions.
- *
- * Vectors are plain number arrays, i.e. [x, y, z].
- *
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-import { map, reduce, zipWith } from './collections';
-
-const ADD = (a, b) => a + b;
-const SUB = (a, b) => a - b;
-const MUL = (a, b) => a * b;
-const DIV = (a, b) => a / b;
-
-export const vecAdd = (...vecs) => {
- return reduce((a, b) => zipWith(ADD)(a, b))(vecs);
-};
-
-export const vecSubtract = (...vecs) => {
- return reduce((a, b) => zipWith(SUB)(a, b))(vecs);
-};
-
-export const vecMultiply = (...vecs) => {
- return reduce((a, b) => zipWith(MUL)(a, b))(vecs);
-};
-
-export const vecDivide = (...vecs) => {
- return reduce((a, b) => zipWith(DIV)(a, b))(vecs);
-};
-
-export const vecScale = (vec, n) => {
- return map((x) => x * n)(vec);
-};
-
-export const vecInverse = (vec) => {
- return map((x) => -x)(vec);
-};
-
-export const vecLength = (vec) => {
- return Math.sqrt(reduce(ADD)(zipWith(MUL)(vec, vec)));
-};
-
-export const vecNormalize = (vec) => {
- return vecDivide(vec, vecLength(vec));
-};
diff --git a/tgui/packages/common/vector.ts b/tgui/packages/common/vector.ts
new file mode 100644
index 00000000000..c91715a8f99
--- /dev/null
+++ b/tgui/packages/common/vector.ts
@@ -0,0 +1,51 @@
+/**
+ * N-dimensional vector manipulation functions.
+ *
+ * Vectors are plain number arrays, i.e. [x, y, z].
+ *
+ * @file
+ * @copyright 2020 Aleksej Komarov
+ * @license MIT
+ */
+
+import { map, reduce, zip } from './collections';
+
+const ADD = (a: number, b: number): number => a + b;
+const SUB = (a: number, b: number): number => a - b;
+const MUL = (a: number, b: number): number => a * b;
+const DIV = (a: number, b: number): number => a / b;
+
+export type Vector = number[];
+
+export const vecAdd = (...vecs: Vector[]): Vector => {
+ return map(zip(...vecs), (x) => reduce(x, ADD));
+};
+
+export const vecSubtract = (...vecs: Vector[]): Vector => {
+ return map(zip(...vecs), (x) => reduce(x, SUB));
+};
+
+export const vecMultiply = (...vecs: Vector[]): Vector => {
+ return map(zip(...vecs), (x) => reduce(x, MUL));
+};
+
+export const vecDivide = (...vecs: Vector[]): Vector => {
+ return map(zip(...vecs), (x) => reduce(x, DIV));
+};
+
+export const vecScale = (vec: Vector, n: number): Vector => {
+ return map(vec, (x) => x * n);
+};
+
+export const vecInverse = (vec: Vector): Vector => {
+ return map(vec, (x) => -x);
+};
+
+export const vecLength = (vec: Vector): number => {
+ return Math.sqrt(reduce(vecMultiply(vec, vec), ADD));
+};
+
+export const vecNormalize = (vec: Vector): Vector => {
+ const length = vecLength(vec);
+ return map(vec, (c) => c / length);
+};
diff --git a/tgui/packages/tgui-panel/chat/selectors.ts b/tgui/packages/tgui-panel/chat/selectors.ts
index 2908f661264..3c1e0b4f429 100644
--- a/tgui/packages/tgui-panel/chat/selectors.ts
+++ b/tgui/packages/tgui-panel/chat/selectors.ts
@@ -9,7 +9,7 @@ import { map } from 'common/collections';
export const selectChat = (state) => state.chat;
export const selectChatPages = (state) =>
- map((id: string) => state.chat.pageById[id])(state.chat.pages);
+ map(state.chat.pages, (id: string) => state.chat.pageById[id]);
export const selectCurrentChatPage = (state) =>
state.chat.pageById[state.chat.currentPageId];
diff --git a/tgui/packages/tgui/backend.ts b/tgui/packages/tgui/backend.ts
index c85d5153210..9190d74dbe2 100644
--- a/tgui/packages/tgui/backend.ts
+++ b/tgui/packages/tgui/backend.ts
@@ -274,10 +274,6 @@ type BackendState = {
shared: Record;
suspending: boolean;
suspended: boolean;
- debug?: {
- debugLayout: boolean;
- kitchenSink: boolean;
- };
};
/**
diff --git a/tgui/packages/tgui/components/Autofocus.tsx b/tgui/packages/tgui/components/Autofocus.tsx
index a0b3f6f7659..403dbe2e965 100644
--- a/tgui/packages/tgui/components/Autofocus.tsx
+++ b/tgui/packages/tgui/components/Autofocus.tsx
@@ -1,17 +1,23 @@
-import { createRef, PropsWithChildren, useEffect } from 'react';
+import { PropsWithChildren, useEffect, useRef } from 'react';
-export const Autofocus = (props: PropsWithChildren) => {
- const ref = createRef();
+/** Used to force the window to steal focus on load. Children optional */
+export function Autofocus(props: PropsWithChildren) {
+ const { children } = props;
+ const ref = useRef(null);
useEffect(() => {
- setTimeout(() => {
+ const timer = setTimeout(() => {
ref.current?.focus();
}, 1);
+
+ return () => {
+ clearTimeout(timer);
+ };
}, []);
return (