diff --git a/Dockerfile b/Dockerfile
index a037093576..ec3694c7e8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM tgstation/byond:512.1484 as base
+FROM tgstation/byond:512.1488 as base
FROM base as build_base
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 554904ada0..e7374c50e6 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -1010,10 +1010,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
-"aez" = (
-/obj/machinery/keycard_auth,
-/turf/closed/wall,
-/area/quartermaster/qm)
"aeB" = (
/obj/machinery/status_display,
/turf/closed/wall,
@@ -9291,7 +9287,6 @@
/obj/machinery/status_display{
pixel_y = 32
},
-/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot,
/obj/machinery/vending/wardrobe/jani_wardrobe,
/obj/effect/turf_decal/tile/neutral{
@@ -9919,7 +9914,6 @@
pixel_x = 32
},
/obj/item/reagent_containers/glass/bucket,
-/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -10581,8 +10575,6 @@
},
/obj/item/storage/box/lights/mixed,
/obj/item/lightreplacer,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -11320,7 +11312,6 @@
/turf/open/floor/plasteel,
/area/janitor)
"aze" = (
-/obj/effect/decal/cleanable/dirt,
/obj/structure/disposalpipe/segment{
dir = 6
},
@@ -12595,7 +12586,6 @@
/turf/open/floor/plasteel,
/area/maintenance/port/fore)
"aBy" = (
-/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
icon_state = "1-8"
},
@@ -12640,7 +12630,6 @@
/turf/open/floor/plasteel,
/area/maintenance/port/fore)
"aBB" = (
-/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
@@ -127439,6 +127428,22 @@
/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/plasteel,
/area/maintenance/port/fore)
+"ost" = (
+/obj/structure/filingcabinet/chestdrawer,
+/obj/effect/turf_decal/tile/brown{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/brown{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/brown{
+ dir = 8
+ },
+/obj/machinery/keycard_auth{
+ pixel_x = -25
+ },
+/turf/open/floor/plasteel,
+/area/quartermaster/qm)
"owr" = (
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -174988,7 +174993,7 @@ aaa
aaa
aad
aQQ
-aez
+aQQ
aUp
aVY
aXE
@@ -175245,7 +175250,7 @@ aaa
aaa
aad
aQR
-aSs
+ost
aUq
aVR
aXF
diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm
index 01d95d7ff9..8d6c0644cf 100644
--- a/code/__DEFINES/obj_flags.dm
+++ b/code/__DEFINES/obj_flags.dm
@@ -10,6 +10,7 @@
#define UNIQUE_RENAME (1<<6) // can you customize the description/name of the thing?
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
#define FROZEN (1<<8)
+#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 3b32745b5c..e2bc2e9565 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"UNIQUE_RENAME" = UNIQUE_RENAME,
"USES_TGUI" = USES_TGUI,
"FROZEN" = FROZEN,
+ "SHOVABLE_ONTO" = SHOVABLE_ONTO
),
"datum_flags" = list(
"DF_USE_TAG" = DF_USE_TAG,
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index 006207c3f3..7f63b74945 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -55,6 +55,17 @@
var/obj/item/W = get_active_held_item()
+ if(!W && A.Adjacent(src) && (isobj(A) || ismob(A)))
+ var/atom/movable/C = A
+ if(C.can_buckle && C.has_buckled_mobs())
+ if(C.buckled_mobs.len > 1)
+ var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs
+ if(C.user_unbuckle_mob(unbuckled,src))
+ return
+ else
+ if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
+ return
+
if(!W && get_dist(src,A) <= interaction_range)
A.attack_robot(src)
return
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 6665e4d59b..7c9dc3f4fe 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -235,6 +235,11 @@
SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone)
. = P.on_hit(src, 0, def_zone)
+//used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it.
+// IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first.
+/atom/proc/shove_act(mob/living/target, mob/living/user)
+ return FALSE
+
/atom/proc/in_contents_of(container)//can take class or object instance as argument
if(ispath(container))
if(istype(src.loc, container))
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index ab4ac4d5c6..e22b785670 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -290,7 +290,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) + world.time
- message_admins("Dynamic Mode initialized with a Threat Level of... [threat_level]!")
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
return TRUE
@@ -420,7 +419,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return FALSE
starting_rule = pickweight(drafted_rules)
- message_admins("Picking a [istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/) ? " delayed " : ""] ruleset [starting_rule.name]")
log_game("DYNAMIC: Picking a [istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/) ? " delayed " : ""] ruleset [starting_rule.name]")
roundstart_rules -= starting_rule
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 76ea855c77..46d124ee49 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -88,17 +88,50 @@
return
close_machine(target)
-/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
- if(!state_open && !occupant)
- if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
- return
+/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
+ . = TRUE
+ if(..())
+ return
+ if(occupant)
+ to_chat(user, "[src] is currently occupied!")
+ return
+ if(state_open)
+ to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!")
+ return
+ if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
+ return
+ return FALSE
+
+/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I)
+ . = ..()
if(default_change_direction_wrench(user, I))
- return
+ return TRUE
+
+/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I)
+ . = ..()
if(default_pry_open(I))
- return
+ return TRUE
if(default_deconstruction_crowbar(I))
+ return TRUE
+
+/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew
+ . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
+ if(.)
+ I.play_tool_sound(src, 50)
+ visible_message("[usr] pries open [src].", "You pry open [src].")
+ open_machine()
+
+/obj/machinery/sleeper/AltClick(mob/user)
+ if(!user.canUseTopic(src, !issilicon(user)))
return
- return ..()
+ if(state_open)
+ close_machine()
+ else
+ open_machine()
+
+/obj/machinery/sleeper/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click [src] to [state_open ? "close" : "open"] it.")
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
@@ -190,7 +223,7 @@
if(inject_chem(chem, usr))
. = TRUE
if(scrambled_chems && prob(5))
- to_chat(usr, "Chem System Re-route detected, results may not be as expected!")
+ to_chat(usr, "Chemical system re-route detected, results may not be as expected!")
/obj/machinery/sleeper/emag_act(mob/user)
. = ..()
diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm
index 7895fb8c9f..c9e1e7195b 100644
--- a/code/game/machinery/dna_scanner.dm
+++ b/code/game/machinery/dna_scanner.dm
@@ -89,11 +89,11 @@
return C
return null
-/obj/machinery/dna_scannernew/close_machine(mob/living/carbon/user)
+/obj/machinery/dna_scannernew/close_machine(atom/movable/target)
if(!state_open)
return FALSE
- ..(user)
+ ..(target)
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
@@ -111,7 +111,7 @@
return TRUE
/obj/machinery/dna_scannernew/open_machine()
- if(state_open)
+ if(state_open || panel_open)
return FALSE
..()
@@ -126,23 +126,48 @@
return
open_machine()
-/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
-
- if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
- update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
+/obj/machinery/dna_scannernew/screwdriver_act(mob/living/user, obj/item/I)
+ . = TRUE
+ if(..())
return
+ if(occupant)
+ to_chat(user, "[src] is currently occupied!")
+ return
+ if(state_open)
+ to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!")
+ return
+ if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) //sent icon_state is irrelevant...
+ update_icon() //..since we're updating the icon here, since the scanner can be unpowered when opened/closed
+ return
+ return FALSE
+/obj/machinery/dna_scannernew/wrench_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(default_change_direction_wrench(user, I))
+ return TRUE
+
+/obj/machinery/dna_scannernew/crowbar_act(mob/living/user, obj/item/I)
+ . = ..()
if(default_pry_open(I))
- return
-
+ return TRUE
if(default_deconstruction_crowbar(I))
- return
+ return TRUE
- return ..()
+/obj/machinery/dna_scannernew/default_pry_open(obj/item/I) //wew
+ . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
+ if(.)
+ I.play_tool_sound(src, 50)
+ visible_message("[usr] pries open [src].", "You pry open [src].")
+ open_machine()
/obj/machinery/dna_scannernew/interact(mob/user)
toggle_open(user)
+/obj/machinery/dna_scannernew/AltClick(mob/user)
+ if(!user.canUseTopic(src, !issilicon(user)))
+ return
+ interact(user)
+
/obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
return
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 1fccadda21..db015eb7c1 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -138,7 +138,7 @@
to_chat(user, "[src] is currently occupied!")
return
if(state_open)
- to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] it's maintenance hatch!")
+ to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!")
return
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
return
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 2e5a13beb2..9f8f3ef742 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -279,12 +279,12 @@
name = "\improper Melon Seed \"Scattershot\""
desc = "A weapon for combat exosuits. Shoots a spread of pellets, shaped as seed."
icon_state = "mecha_scatter"
- equip_cooldown = 30
+ equip_cooldown = 20
projectile = /obj/item/projectile/bullet/seed
- projectiles = 4
- projectile_energy_cost = 55
+ projectiles = 20
+ projectile_energy_cost = 25
projectiles_per_shot = 10
- variance = 20
+ variance = 25
harmful = TRUE
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index cd9b595f0a..b17d585385 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -21,6 +21,7 @@
anchored = TRUE
layer = TABLE_LAYER
climbable = TRUE
+ obj_flags = CAN_BE_HIT|SHOVABLE_ONTO
pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.")
var/frame = /obj/structure/table_frame
var/framestack = /obj/item/stack/rods
@@ -136,6 +137,15 @@
var/mob/living/carbon/human/H = pushed_mob
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table)
+/obj/structure/table/shove_act(mob/living/target, mob/living/user)
+ if(!target.resting)
+ target.Knockdown(SHOVE_KNOCKDOWN_TABLE)
+ user.visible_message("[user.name] shoves [target.name] onto \the [src]!",
+ "You shove [target.name] onto \the [src]!", null, COMBAT_MESSAGE_RANGE)
+ target.forceMove(src.loc)
+ log_combat(user, target, "shoved", "onto [src] (table)")
+ return TRUE
+
/obj/structure/table/attackby(obj/item/I, mob/user, params)
if(!(flags_1 & NODECONSTRUCT_1))
if(istype(I, /obj/item/screwdriver) && deconstruction_ready)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 7110ff4405..181b72e4a2 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -382,6 +382,19 @@
if(ismob(A) || .)
A.ratvar_act()
+//called on /datum/species/proc/altdisarm()
+/turf/shove_act(mob/living/target, mob/living/user, pre_act = FALSE)
+ var/list/possibilities
+ for(var/obj/O in contents)
+ if(CHECK_BITFIELD(O.obj_flags, SHOVABLE_ONTO))
+ LAZYADD(possibilities, O)
+ else if(!O.CanPass(target, src))
+ return FALSE
+ if(possibilities)
+ var/obj/O = pick(possibilities)
+ return O.shove_act(target, user)
+ return FALSE
+
/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = icon
underlay_appearance.icon_state = icon_state
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index f56c6f7fb5..0dd6b08c4d 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -86,7 +86,7 @@
var/static/image/radial_whetstone = image(icon = 'icons/obj/kitchen.dmi', icon_state = "cult_sharpener")
var/static/image/radial_shell = image(icon = 'icons/obj/wizard.dmi', icon_state = "construct-cult")
- var/static/image/radial_unholy_water = image(icon = 'icons/obj/chemical.dmi', icon_state = "holyflask")
+ var/static/image/radial_unholy_water = image(icon = 'icons/obj/drinks.dmi', icon_state = "holyflask")
/obj/structure/destructible/cult/talisman/Initialize()
. = ..()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 35b30107d8..ccd13d8d4a 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -394,6 +394,21 @@
. = TRUE
update_icon()
+/obj/machinery/atmospherics/components/unary/cryo_cell/CtrlClick(mob/user)
+ if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) && !state_open)
+ on = !on
+ update_icon()
+ return ..()
+
+/obj/machinery/atmospherics/components/unary/cryo_cell/AltClick(mob/user)
+ if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ if(state_open)
+ close_machine()
+ else
+ open_machine()
+ update_icon()
+ return ..()
+
/obj/machinery/atmospherics/components/unary/cryo_cell/update_remote_sight(mob/living/user)
return // we don't see the pipe network while inside cryo.
diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm
index f1aea5706a..af5919969c 100644
--- a/code/modules/hydroponics/grown/flowers.dm
+++ b/code/modules/hydroponics/grown/flowers.dm
@@ -37,7 +37,7 @@
species = "lily"
plantname = "Lily Plants"
product = /obj/item/reagent_containers/food/snacks/grown/poppy/lily
- mutatelist = list()
+ mutatelist = list(/obj/item/seeds/bee_balm)
/obj/item/reagent_containers/food/snacks/grown/poppy/lily
seed = /obj/item/seeds/poppy/lily
@@ -221,3 +221,61 @@
if(!user.gloves)
to_chat(user, "The [name] burns your bare hand!")
user.adjustFireLoss(rand(1, 5))
+
+// Beebalm
+/obj/item/seeds/bee_balm
+ name = "pack of Bee Balm seeds"
+ desc = "These seeds grow into Bee Balms."
+ icon_state = "seed-bee_balm"
+ species = "bee_balm"
+ plantname = "Bee Balm Buds"
+ product = /obj/item/reagent_containers/food/snacks/grown/bee_balm
+ endurance = 10
+ maturation = 8
+ yield = 3
+ potency = 30
+ growthstages = 3
+ growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
+ icon_grow = "bee_balm-grow"
+ icon_dead = "bee_balm-dead"
+ mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey) //Lower odds of becoming honey
+ reagents_add = list("spaceacillin" = 0.1, "sterilizine" = 0.05)
+
+/obj/item/reagent_containers/food/snacks/grown/bee_balm
+ seed = /obj/item/seeds/bee_balm
+ name = "bee balm"
+ desc = "A flower used for medical antiseptic in history."
+ icon_state = "bee_balm"
+ filling_color = "#FF6347"
+ bitesize_mod = 8
+ tastes = list("strong antiseptic " = 1)
+ foodtype = GROSS
+
+// Beebalm
+/obj/item/seeds/bee_balm/honey
+ name = "pack of Honey Balm seeds"
+ desc = "These seeds grow into Honey Balms."
+ icon_state = "seed-bee_balmalt"
+ species = "seed-bee_balm_alt"
+ plantname = "Honey Balm Pods"
+ product = /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
+ endurance = 1
+ maturation = 10
+ yield = 1
+ potency = 1
+ growthstages = 3
+ growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
+ icon_grow = "bee_balmalt-grow"
+ icon_dead = "bee_balmalt-dead"
+ reagents_add = list("honey" = 0.1, "lye" = 0.3) //To make wax
+ rarity = 30
+
+/obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
+ seed = /obj/item/seeds/bee_balm/honey
+ name = "honey balm"
+ desc = "A large honey filled pod of a flower."
+ icon_state = "bee_balmalt"
+ filling_color = "#FF6347"
+ bitesize_mod = 8
+ tastes = list("wax" = 1)
+ foodtype = SUGAR
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index d2e8cab240..4ef1aef5ff 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1821,67 +1821,36 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!target.resting)
target.adjustStaminaLoss(5)
+ if(target.is_shove_knockdown_blocked())
+ return
var/turf/target_oldturf = target.loc
var/shove_dir = get_dir(user.loc, target_oldturf)
var/turf/target_shove_turf = get_step(target.loc, shove_dir)
var/mob/living/carbon/human/target_collateral_human
- var/obj/structure/table/target_table
var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied
//Thank you based whoneedsspace
target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents
- if(target_collateral_human)
+ if(target_collateral_human && !target_collateral_human.resting)
shove_blocked = TRUE
else
+ target_collateral_human = null
target.Move(target_shove_turf, shove_dir)
if(get_turf(target) == target_oldturf)
- if(target_shove_turf.density)
- shove_blocked = TRUE
- else
- var/thoushallnotpass = FALSE
- for(var/obj/O in target_shove_turf)
- if(istype(O, /obj/structure/table))
- target_table = O
- else if(!O.CanPass(src, target_shove_turf))
- shove_blocked = TRUE
- thoushallnotpass = TRUE
- if(thoushallnotpass)
- target_table = null
+ shove_blocked = TRUE
- if(target.is_shove_knockdown_blocked())
- return
-
- if(shove_blocked || target_table)
- var/directional_blocked = FALSE
- if(shove_dir in GLOB.cardinals) //Directional checks to make sure that we're not shoving through a windoor or something like that
- var/target_turf = get_turf(target)
- for(var/obj/O in target_turf)
- if(O.flags_1 & ON_BORDER_1 && O.dir == shove_dir && O.density)
- directional_blocked = TRUE
- break
- if(target_turf != target_shove_turf) //Make sure that we don't run the exact same check twice on the same tile
- for(var/obj/O in target_shove_turf)
- if(O.flags_1 & ON_BORDER_1 && O.dir == turn(shove_dir, 180) && O.density)
- directional_blocked = TRUE
- break
+ if(shove_blocked && !target.buckled)
+ var/directional_blocked = !target.Adjacent(target_shove_turf)
var/targetatrest = target.resting
- if(((!target_table && !target_collateral_human) || directional_blocked) && !targetatrest)
+ if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest)
target.Knockdown(SHOVE_KNOCKDOWN_SOLID)
user.visible_message("[user.name] shoves [target.name], knocking them down!",
"You shove [target.name], knocking them down!", null, COMBAT_MESSAGE_RANGE)
log_combat(user, target, "shoved", "knocking them down")
- else if(target_table)
- if(!targetatrest)
- target.Knockdown(SHOVE_KNOCKDOWN_TABLE)
- user.visible_message("[user.name] shoves [target.name] onto \the [target_table]!",
- "You shove [target.name] onto \the [target_table]!", null, COMBAT_MESSAGE_RANGE)
- target.forceMove(target_shove_turf)
- log_combat(user, target, "shoved", "onto [target_table]")
else if(target_collateral_human && !targetatrest)
target.Knockdown(SHOVE_KNOCKDOWN_HUMAN)
- if(!target_collateral_human.resting)
- target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
+ target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
user.visible_message("[user.name] shoves [target.name] into [target_collateral_human.name]!",
"You shove [target.name] into [target_collateral_human.name]!", null, COMBAT_MESSAGE_RANGE)
log_combat(user, target, "shoved", "into [target_collateral_human.name]")
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index c6d4527812..f757203237 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -49,7 +49,7 @@
else
padloc = "(UNKNOWN)"
src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]")
- send_speech(message, 7, T, "robot", language = language)
+ send_speech(message, 7, T, "robot", message_language = language)
to_chat(src, "Holopad transmitted, [real_name] \"[message]\"")
else
to_chat(src, "No holopad connected.")
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 907fccdc5b..ccbcf34d8c 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -67,6 +67,9 @@
/obj/structure/filingcabinet/ui_interact(mob/user)
. = ..()
+ if(isobserver(user))
+ return
+
if(contents.len <= 0)
to_chat(user, "[src] is empty.")
return
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index d837f0d420..5fc29cb813 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -802,8 +802,6 @@
if(!ui)
ui = new(user, src, ui_key, "apc", name, 535, 515, master_ui, state)
ui.open()
- if(ui)
- ui.set_autoupdate(state = (failure_timer ? 1 : 0))
/obj/machinery/power/apc/ui_data(mob/user)
var/list/data = list(
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 5ae6b8f35c..56cb02293e 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -746,11 +746,13 @@
total_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
+ if(R.volume == 0)
+ del_reagent(R.id)
if((R.volume < 0.01) && !fermiIsReacting)
del_reagent(R.id)
else
total_volume += R.volume
- if(total_volume <= 0)
+ if(!reagent_list)
pH = 7
return 0
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 2f7a8652ba..a6bec66cfc 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1665,7 +1665,7 @@
reagent_state = LIQUID
color = "#FFFFD6" // very very light yellow
taste_description = "alkali" //who put ACID for NaOH ????
- pH = 13
+ pH = 11.9
/datum/reagent/drying_agent
name = "Drying agent"
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 082b1a7d11..a4a6a7d473 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -111,14 +111,7 @@
stuff_mob_in(target, user)
/obj/machinery/disposal/proc/stuff_mob_in(mob/living/target, mob/living/user)
- if(!iscarbon(user) && !user.ventcrawler) //only carbon and ventcrawlers can climb into disposal by themselves.
- return
- if(!isturf(user.loc)) //No magically doing it from inside closets
- return
- if(target.buckled || target.has_buckled_mobs())
- return
- if(target.mob_size > MOB_SIZE_HUMAN)
- to_chat(user, "[target] doesn't fit inside [src]!")
+ if(!can_stuff_mob_in(target, user))
return
add_fingerprint(user)
if(user == target)
@@ -137,6 +130,19 @@
target.LAssailant = user
update_icon()
+/obj/machinery/disposal/proc/can_stuff_mob_in(mob/living/target, mob/living/user, pushing = FALSE)
+ if(!pushing && !iscarbon(user) && !user.ventcrawler) //only carbon and ventcrawlers can climb into disposal by themselves.
+ return FALSE
+ if(!isturf(user.loc)) //No magically doing it from inside closets
+ return FALSE
+ if(target.buckled || target.has_buckled_mobs())
+ return FALSE
+ if(target.mob_size > MOB_SIZE_HUMAN)
+ if(!pushing)
+ to_chat(user, "[target] doesn't fit inside [src]!")
+ return FALSE
+ return TRUE
+
/obj/machinery/disposal/relaymove(mob/user)
attempt_escape(user)
@@ -265,6 +271,7 @@
desc = "A pneumatic waste disposal unit."
icon_state = "disposal"
var/datum/oracle_ui/themed/nano/ui
+ obj_flags = CAN_BE_HIT | USES_TGUI | SHOVABLE_ONTO
/obj/machinery/disposal/bin/Initialize(mapload, obj/structure/disposalconstruct/make_from)
. = ..()
@@ -305,7 +312,7 @@
if(Adjacent(user))
return TRUE
return ..()
-
+
/obj/machinery/disposal/bin/oui_data(mob/user)
var/list/data = list()
@@ -360,6 +367,17 @@
else
return ..()
+/obj/machinery/disposal/bin/shove_act(mob/living/target, mob/living/user)
+ if(!can_stuff_mob_in(target, user, TRUE))
+ return FALSE
+ target.Knockdown(SHOVE_KNOCKDOWN_SOLID)
+ target.forceMove(src)
+ user.visible_message("[user.name] shoves [target.name] into \the [src]!",
+ "You shove [target.name] into \the [src]!", null, COMBAT_MESSAGE_RANGE)
+ log_combat(user, target, "shoved", "into [src] (disposal bin)")
+ return TRUE
+
+
/obj/machinery/disposal/bin/flush()
..()
full_pressure = FALSE
diff --git a/html/changelogs/AutoChangeLog-pr-9365.yml b/html/changelogs/AutoChangeLog-pr-9365.yml
new file mode 100644
index 0000000000..1a0543f28e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9365.yml
@@ -0,0 +1,7 @@
+author: "Ghommie (original PR by 81Denton, kriskog and nemvar)"
+delete-after: True
+changes:
+ - spellcheck: "Sleepers now show a message if players try to unscrew the maintenance hatch while they're occupied or open. Fixed typos in sleeper/organ harvester messages."
+ - tweak: "Sleepers and dna scanners can now be pried open with crowbars."
+ - tweak: "You can open and close sleepers and dna scanners by alt-clicking them."
+ - bugfix: "The scanner's hatch now must be closed (on top of being unoccupied), just like sleepers, before being screwdriverable. This fixes a tricky door stuck issue with the machine."
diff --git a/html/changelogs/AutoChangeLog-pr-9373.yml b/html/changelogs/AutoChangeLog-pr-9373.yml
new file mode 100644
index 0000000000..0dc7d7a85f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9373.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Beebal and Honeybalm plants"
diff --git a/html/changelogs/AutoChangeLog-pr-9380.yml b/html/changelogs/AutoChangeLog-pr-9380.yml
new file mode 100644
index 0000000000..0d42ef7276
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9380.yml
@@ -0,0 +1,6 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed people being shovable hrough windows, windoors and the such."
+ - rscadd: "You can now shove people into disposal bins."
+ - refactor: "refactored altdisarm(), ergo the \"shoving people around\" proc."
diff --git a/html/changelogs/AutoChangeLog-pr-9382.yml b/html/changelogs/AutoChangeLog-pr-9382.yml
new file mode 100644
index 0000000000..c82a6a4309
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9382.yml
@@ -0,0 +1,4 @@
+author: "Chayse"
+delete-after: True
+changes:
+ - bugfix: "Borgs now have the necessary dexterity to unbuckle people from themselves and from bucklable objects."
diff --git a/html/changelogs/AutoChangeLog-pr-9385.yml b/html/changelogs/AutoChangeLog-pr-9385.yml
new file mode 100644
index 0000000000..36c0f7c105
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9385.yml
@@ -0,0 +1,4 @@
+author: "Sishen1542"
+delete-after: True
+changes:
+ - bugfix: "removed reflect from divine lightblade"
diff --git a/html/changelogs/AutoChangeLog-pr-9388.yml b/html/changelogs/AutoChangeLog-pr-9388.yml
new file mode 100644
index 0000000000..9c42745219
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9388.yml
@@ -0,0 +1,4 @@
+author: "original by Skoglol, port by sishen1542"
+delete-after: True
+changes:
+ - admin: "Dynamic gamemode now more auto-deadmin friendly."
diff --git a/html/changelogs/AutoChangeLog-pr-9393.yml b/html/changelogs/AutoChangeLog-pr-9393.yml
new file mode 100644
index 0000000000..ef03eb483f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9393.yml
@@ -0,0 +1,4 @@
+author: "Chayse"
+delete-after: True
+changes:
+ - bugfix: "AIs can now once more talk through holopads successfully"
diff --git a/html/changelogs/AutoChangeLog-pr-9394.yml b/html/changelogs/AutoChangeLog-pr-9394.yml
new file mode 100644
index 0000000000..2c1c89877b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9394.yml
@@ -0,0 +1,5 @@
+author: "EmeraldSundisk"
+delete-after: True
+changes:
+ - bugfix: "Readjusts positioning of Delta's QM keycard device"
+ - bugfix: "Cleaned up a few spots I missed in #9356, particularly around the janitor's office"
diff --git a/html/changelogs/AutoChangeLog-pr-9401.yml b/html/changelogs/AutoChangeLog-pr-9401.yml
new file mode 100644
index 0000000000..ba40c9af65
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9401.yml
@@ -0,0 +1,4 @@
+author: "actioninja"
+delete-after: True
+changes:
+ - bugfix: "APC UI autoupdates correctly"
diff --git a/html/changelogs/AutoChangeLog-pr-9405.yml b/html/changelogs/AutoChangeLog-pr-9405.yml
new file mode 100644
index 0000000000..ee4bce83bd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9405.yml
@@ -0,0 +1,5 @@
+author: "Thalpy"
+delete-after: True
+changes:
+ - tweak: "Alkaline buffer recipe so people don't get grumpy and expanded the pH range"
+ - bugfix: "fixes buffers"
diff --git a/html/changelogs/AutoChangeLog-pr-9407.yml b/html/changelogs/AutoChangeLog-pr-9407.yml
new file mode 100644
index 0000000000..dbfadaebb7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9407.yml
@@ -0,0 +1,4 @@
+author: "AdmiralPancakes1"
+delete-after: True
+changes:
+ - rscadd: "Cryo cell shortcuts: alt-click toggles the doors, ctrl-click toggles the power"
diff --git a/icons/mob/custom_w.dmi b/icons/mob/custom_w.dmi
index 1b917d9434..f29231c48d 100644
Binary files a/icons/mob/custom_w.dmi and b/icons/mob/custom_w.dmi differ
diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi
index 601e32fb63..92f7f50279 100644
Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ
diff --git a/icons/obj/hydroponics/growing_flowers.dmi b/icons/obj/hydroponics/growing_flowers.dmi
index 2f541dfc9b..245841a6b4 100644
Binary files a/icons/obj/hydroponics/growing_flowers.dmi and b/icons/obj/hydroponics/growing_flowers.dmi differ
diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi
index 7796e1b199..fa5728f3b4 100644
Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ
diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi
index 96fd5be650..7caf346f91 100644
Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ
diff --git a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
index 4cf1d326a2..e677c1f3ab 100644
--- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
+++ b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
@@ -277,6 +277,9 @@
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
+ return FALSE
+
/obj/item/twohanded/dualsaber/hypereutactic/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
altafterattack(A, user, TRUE, params)
return TRUE
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index cc75e1bff9..136aefb8f5 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -447,4 +447,8 @@ datum/gear/darksabresheath
path = /obj/item/clothing/head/blueberet
ckeywhitelist = list("foxystalin")
-
+/datum/gear/donorgoggles
+ name = "Flight Goggles"
+ category = SLOT_HEAD
+ path = /obj/item/clothing/glasses/flight
+ ckeywhitelist = list("maxlynchy")
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 5d81dbfa49..0cabdca6ee 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -493,3 +493,12 @@
item_state = "blueberet"
icon = 'icons/obj/custom.dmi'
alternate_worn_icon = 'icons/mob/custom_w.dmi'
+
+/obj/item/clothing/glasses/flight
+ name = "flight goggles"
+ desc = "Old style flight goggles with a leather cap attached."
+ icon_state = "flight-g"
+ item_state = "flight-g"
+ icon = 'icons/obj/custom.dmi'
+ alternate_worn_icon = 'icons/mob/custom_w.dmi'
+ actions_types = list(/datum/action/item_action/toggle)
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
index aa64370217..bfd8dbb137 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
@@ -338,7 +338,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume)
return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
- return
+ return ..()
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
@@ -360,7 +360,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume)
return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
- return
+ return ..()
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
index d385f23239..0f148e8614 100644
--- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
@@ -432,8 +432,8 @@
OptimalTempMin = 250
OptimalTempMax = 500
ExplodeTemp = 9999 //check to see overflow doesn't happen!
- OptimalpHMin = 2
- OptimalpHMax = 6
+ OptimalpHMin = 0
+ OptimalpHMax = 14
ReactpHLim = 0
//CatalystFact = 0 //To do 1
CurveSharpT = 4
@@ -454,14 +454,14 @@
name = "Ethyl Ethanoate buffer"
id = "basic_buffer"
results = list("basic_buffer" = 1.5)
- required_reagents = list("acidic_buffer" = 0.5, "ethanol" = 0.5, "water" = 0.5)
+ required_reagents = list("lye" = 0.3, "ethanol" = 0.6, "water" = 0.6)
required_catalysts = list("sacid" = 1) //vagely acetic
//FermiChem vars:x
OptimalTempMin = 250
OptimalTempMax = 500
ExplodeTemp = 9999 //check to see overflow doesn't happen!
- OptimalpHMin = 5
- OptimalpHMax = 12
+ OptimalpHMin = 0
+ OptimalpHMax = 14
ReactpHLim = 0
//CatalystFact = 0 //To do 1
CurveSharpT = 4