diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 49eda07616c2..5eb8f0219e73 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -10,6 +10,12 @@ body:
placeholder: "#1, #2, #3, etc"
validations:
required: true
+ - type: input
+ id: round-id
+ attributes:
+ label: Round ID
+ description: If known, what was the Round ID this bug was found on? Can be left blank if unknown or occured across multiple rounds.
+ placeholder: "12345"
- type: textarea
id: what-happened
attributes:
diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml
index 683f3909b447..0488055312f7 100644
--- a/.github/workflows/ci_suite.yml
+++ b/.github/workflows/ci_suite.yml
@@ -60,6 +60,34 @@ jobs:
with:
outputFile: output-annotations.txt
+
+ odlint:
+ name: Lint with OpenDream
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v3
+ - name: Get OpenDream Version
+ run: |
+ source dependencies.sh
+ echo "OPENDREAM_VERSION=$OPENDREAM_VERSION" >> $GITHUB_ENV
+ - name: Restore OpenDream cache
+ uses: actions/cache@v3
+ id: cache-od
+ with:
+ path: ~/OpenDream
+ key: ${{ runner.os }}-opendream-${{ env.OPENDREAM_VERSION }}
+ - name: Download OpenDream
+ if: steps.cache-od.outputs.cache-hit != 'true'
+ run: |
+ bash tools/ci/download_od.sh
+ - name: Setup OpenDream
+ if: steps.cache-od.outputs.cache-hit != 'true'
+ run: |
+ bash tools/ci/setup_od.sh
+ - name: Run OpenDream
+ run: |
+ bash tools/ci/run_od.sh
+
compile_all_maps:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Compile Maps
diff --git a/.gitignore b/.gitignore
index 210efc84d75b..4d2b7e810de8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,6 @@ test_environment.txt
# byond-tracy backend, not shipped with the codebase so it shouldn't be maintained
prof.dll
libprof.so
+
+# OpenDream compatibility stuff
+colonialmarines.json
diff --git a/code/__DEFINES/__game.dm b/code/__DEFINES/__game.dm
index 113b78dbada1..f1424f5560ec 100644
--- a/code/__DEFINES/__game.dm
+++ b/code/__DEFINES/__game.dm
@@ -283,7 +283,6 @@ block( \
/// Only use the CEILING_PROTECTION_TIER_X defines for `protection_level`
#define CEILING_IS_PROTECTED(ceiling, protection_level) (ceiling >= protection_level)
-
// Default font settings
#define FONT_SIZE "5pt"
#define DEFAULT_FONT_COLOR "#09f"
@@ -493,6 +492,18 @@ block( \
#define TURF_PROTECTION_CAS 2
#define TURF_PROTECTION_OB 3
+/// Convert a turf protection level to a ceiling protection level
+/proc/get_ceiling_protection_level(turf_protection_level)
+ switch(turf_protection_level)
+ if(TURF_PROTECTION_OB)
+ return CEILING_PROTECTION_TIER_4
+ if(TURF_PROTECTION_CAS)
+ return CEILING_PROTECTION_TIER_3
+ if(TURF_PROTECTION_MORTAR)
+ return CEILING_PROTECTION_TIER_2
+ else
+ return CEILING_NO_PROTECTION
+
// Anything above the deck boundary is the upper deck, anything below is the lower deck
// This is exclusive, so anything ON the boundary is an edge case that's neither on the upper nor the lower deck
#define ALMAYER_DECK_BOUNDARY 101
diff --git a/code/__DEFINES/bullet_traits.dm b/code/__DEFINES/bullet_traits.dm
index 0ca3bce2e602..40e250cd0dd2 100644
--- a/code/__DEFINES/bullet_traits.dm
+++ b/code/__DEFINES/bullet_traits.dm
@@ -3,7 +3,7 @@
// list of args if there are any args
/// An entry to a list for giving projectiles bullet traits
/// Must be placed inside of a list
-#define BULLET_TRAIT_ENTRY(trait, args...) trait = #args ? list(##args) : null
+#define BULLET_TRAIT_ENTRY(trait, args...) trait = list(##args)
/// An entry to a list for giving projectiles bullet traits with a unique ID
/// Must be placed inside of a list
#define BULLET_TRAIT_ENTRY_ID(id, trait, args...) id = list(trait, ##args)
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 1bd030313a43..072738184807 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -417,3 +417,4 @@ var/list/default_xeno_onmob_icons = list(
#define HANDLING_LIMBS list("l_arm","l_hand", "r_arm", "r_hand")
#define EXTREMITY_LIMBS list("l_leg","l_foot","r_leg","r_foot","l_arm","l_hand","r_arm","r_hand")
#define CORE_LIMBS list("chest","head","groin")
+
diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm
index 6187a67825a4..d468d6044196 100644
--- a/code/__DEFINES/tgs.dm
+++ b/code/__DEFINES/tgs.dm
@@ -1,6 +1,6 @@
// tgstation-server DMAPI
-#define TGS_DMAPI_VERSION "6.5.3"
+#define TGS_DMAPI_VERSION "6.6.1"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
@@ -129,6 +129,13 @@
/// DreamDaemon Ultrasafe security level.
#define TGS_SECURITY_ULTRASAFE 2
+/// DreamDaemon public visibility level.
+#define TGS_VISIBILITY_PUBLIC 0
+/// DreamDaemon private visibility level.
+#define TGS_VISIBILITY_PRIVATE 1
+/// DreamDaemon invisible visibility level.
+#define TGS_VISIBILITY_INVISIBLE 2
+
//REQUIRED HOOKS
/**
@@ -458,6 +465,10 @@
/world/proc/TgsSecurityLevel()
return
+/// Returns the current BYOND visibility level as a TGS_VISIBILITY_ define if TGS is present, null otherwise. Requires TGS to be using interop API version 5 or higher otherwise the string "___unimplemented" wil be returned. This function may sleep if the call to [/world/proc/TgsNew] is sleeping!
+/world/proc/TgsVisibility()
+ return
+
/// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise. This function may sleep if the call to [/world/proc/TgsNew] is sleeping!
/world/proc/TgsTestMerges()
return
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index edc711d25bc1..1116f1acb2a8 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -732,11 +732,12 @@ world
if (isnull(dir))
dir = thing.dir
- if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+ // Commented out because this is seemingly our source of bad icon operations
+ /* if (ishuman(thing)) // Shitty workaround for a BYOND issue.
var/icon/temp = icon2collapse
icon2collapse = icon()
icon2collapse.Insert(temp, dir = SOUTH)
- dir = SOUTH
+ dir = SOUTH*/
else
if (isnull(dir))
dir = SOUTH
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 4e4a1b3ff31c..5d0d113b0c55 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -21,7 +21,7 @@
var/char = copytext(hex, i, i + 1)
switch(char)
if("0")
- //Apparently, switch works with empty statements, yay! If that doesn't work, blame me, though. -- Urist
+ pass()
if("9", "8", "7", "6", "5", "4", "3", "2", "1")
num += text2num(char) * 16 ** power
if("a", "A")
@@ -77,7 +77,6 @@
hex += "E"
if(15.0)
hex += "F"
- else
power--
while(length(hex) < placeholder)
hex = text("0[]", hex)
@@ -165,8 +164,6 @@
return 6
if("SOUTHWEST")
return 10
- else
- return
//Converts an angle (degrees) into an ss13 direction
/proc/angle2dir(degree)
diff --git a/code/__odlint.dm b/code/__odlint.dm
new file mode 100644
index 000000000000..f42517133746
--- /dev/null
+++ b/code/__odlint.dm
@@ -0,0 +1,11 @@
+// This file is included right at the start of the DME.
+// Its purpose is to enable multiple lints (pragmas) that are supported by OpenDream to better validate the codebase
+// These are essentially nitpicks the DM compiler should pick up on but doesnt
+
+#ifndef SPACEMAN_DMM
+#ifdef OPENDREAM
+// These are in their own file as you need to do it with an include as a hack to avoid
+// SpacemanDMM evaluating the #pragma lines, even if its outside a block it cares about
+#include "__pragmas.dm"
+#endif
+#endif
diff --git a/code/__pragmas.dm b/code/__pragmas.dm
new file mode 100644
index 000000000000..39c14e1bbc95
--- /dev/null
+++ b/code/__pragmas.dm
@@ -0,0 +1,27 @@
+//1000-1999
+#pragma FileAlreadyIncluded error
+#pragma MissingIncludedFile error
+#pragma MisplacedDirective error
+#pragma UndefineMissingDirective error
+#pragma DefinedMissingParen error
+#pragma ErrorDirective error
+#pragma WarningDirective error
+#pragma MiscapitalizedDirective error
+
+//2000-2999
+#pragma SoftReservedKeyword error
+#pragma DuplicateVariable error
+#pragma DuplicateProcDefinition error
+#pragma TooManyArguments error
+#pragma PointlessParentCall error
+#pragma PointlessBuiltinCall error
+#pragma SuspiciousMatrixCall error
+#pragma MalformedRange error
+#pragma InvalidRange error
+#pragma InvalidSetStatement error
+#pragma InvalidOverride error
+#pragma DanglingVarType error
+#pragma MissingInterpolatedExpression error
+
+//3000-3999
+#pragma EmptyBlock error
diff --git a/code/_byond_version_compat.dm b/code/_byond_version_compat.dm
index fb71f15d7f9f..7c146fd9b896 100644
--- a/code/_byond_version_compat.dm
+++ b/code/_byond_version_compat.dm
@@ -3,7 +3,7 @@
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 515
#define MIN_COMPILER_BUILD 1609
-#if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM)
+#if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM) && !defined(OPENDREAM)
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to https://www.byond.com/download and update.
#error You need version 515.1609 or higher
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 0f81b0173ac1..20aa2081318c 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -30,7 +30,7 @@
#define CBT
#endif
-#if !defined(CBT) && !defined(SPACEMAN_DMM)
+#if !defined(CBT) && !defined(SPACEMAN_DMM) && !defined(OPENDREAM)
#warn Building with Dream Maker is no longer supported and will result in errors.
#warn In order to build, run BUILD.bat in the bin directory.
#warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build.
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index 23da8cc8c9eb..3d544dca1390 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -131,7 +131,7 @@ SUBSYSTEM_DEF(atoms)
switch(result)
if (INITIALIZE_HINT_NORMAL)
- // pass
+ pass()
if(INITIALIZE_HINT_LATELOAD)
if(arguments[1]) //mapload
late_loaders += A
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index afecabd74be0..be69bdad1b7e 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -29,9 +29,7 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/proc/HACK_LoadMapConfig()
if(!configs)
configs = load_map_configs(ALL_MAPTYPES, error_if_missing = FALSE)
- for(var/i in GLOB.clients)
- var/client/C = i
- winset(C, null, "mainwindow.title='[CONFIG_GET(string/title)] - [SSmapping.configs[SHIP_MAP].map_name]'")
+ world.name = "[CONFIG_GET(string/title)] - [SSmapping.configs[SHIP_MAP].map_name]"
/datum/controller/subsystem/mapping/Initialize(timeofday)
HACK_LoadMapConfig()
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 3882228a5ab1..a56e10636a1e 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -273,7 +273,7 @@ SUBSYSTEM_DEF(vote)
question = "Gamemode vote"
randomize_entries = TRUE
for(var/mode_type in config.gamemode_cache)
- var/datum/game_mode/M = initial(mode_type)
+ var/datum/game_mode/M = mode_type
if(initial(M.config_tag))
var/vote_cycle_met = !initial(M.vote_cycle) || (text2num(SSperf_logging?.round?.id) % initial(M.vote_cycle) == 0)
if(initial(M.votable) && vote_cycle_met)
diff --git a/code/datums/_ndatabase/code/brsql_adapter.dm b/code/datums/_ndatabase/code/brsql_adapter.dm
index 345ddfe005f3..251267a04fdb 100644
--- a/code/datums/_ndatabase/code/brsql_adapter.dm
+++ b/code/datums/_ndatabase/code/brsql_adapter.dm
@@ -101,8 +101,8 @@
SSdatabase.create_parametric_query(query_updatetable, qpars, CB)
/datum/db/adapter/brsql_adapter/insert_table(table_name, list/values, datum/callback/CB, sync = FALSE)
- if(!sync)
- set waitfor = 0
+ set waitfor = FALSE
+
var/length = values.len
var/list/qpars = list()
var/query_inserttable = getquery_insert_table(table_name, values, qpars)
@@ -530,7 +530,7 @@
if(first && !is_id)
if(!items_first)
update_items+=","
- update_items+="`[table_name]`.[esfield]=`__prep_update`.[esfield]"
+ update_items+="`[table_name]`.[esfield]=`subquery`.[esfield]"
items_first = FALSE
local_first = FALSE
calltext += "SELECT [local_text]"
@@ -539,9 +539,7 @@
issue_log += "No ID passed to update query."
return "" // AAAAAAAAAAAAAH FUCK DON'T JUST KILL THE ENTIRE FUCKING TABLE BRUH
return {"
- WITH __prep_update as (
- [calltext]
- ) UPDATE `[connection.database]`.`[table_name]` INNER JOIN `__prep_update` ON `[table_name]`.id = `__prep_update`.id SET [update_items]
+ UPDATE `[connection.database]`.`[table_name]` JOIN (WITH `__prep_update` AS ( [calltext] ) SELECT * FROM `__prep_update`) subquery ON `[table_name]`.id = subquery.id SET [update_items]
"}
/datum/db/adapter/brsql_adapter/proc/getquery_delete_table(table_name, list/ids)
diff --git a/code/datums/_ndatabase/code/native_adapter.dm b/code/datums/_ndatabase/code/native_adapter.dm
index a5e4d41fb6a0..1c23a6ceab8f 100644
--- a/code/datums/_ndatabase/code/native_adapter.dm
+++ b/code/datums/_ndatabase/code/native_adapter.dm
@@ -83,8 +83,7 @@
SSdatabase.create_query(query_gettable, CB)
/datum/db/adapter/native_adapter/update_table(table_name, list/values, datum/callback/CB, sync = FALSE)
- if(!sync)
- set waitfor = 0
+ set waitfor = FALSE
for(var/list/vals in values)
var/list/qpars = list()
diff --git a/code/datums/ammo/ammo.dm b/code/datums/ammo/ammo.dm
index c536ac83484c..a858c6b1f5a7 100644
--- a/code/datums/ammo/ammo.dm
+++ b/code/datums/ammo/ammo.dm
@@ -171,6 +171,15 @@
else
living_mob.apply_stamina_damage(fired_projectile.ammo.damage, fired_projectile.def_zone, ARMOR_BULLET)
+/datum/ammo/proc/slowdown(mob/living/living_mob, obj/projectile/fired_projectile)
+ if(iscarbonsizexeno(living_mob))
+ var/mob/living/carbon/xenomorph/target = living_mob
+ target.apply_effect(1, SUPERSLOW)
+ target.apply_effect(2, SLOW)
+ to_chat(target, SPAN_XENODANGER("You are slowed by the sudden impact!"))
+ else
+ living_mob.apply_stamina_damage(fired_projectile.ammo.damage, fired_projectile.def_zone, ARMOR_BULLET)
+
/datum/ammo/proc/pushback(mob/target_mob, obj/projectile/fired_projectile, max_range = 2)
if(!target_mob || target_mob == fired_projectile.firer || fired_projectile.distance_travelled > max_range || target_mob.lying)
return
diff --git a/code/datums/ammo/bullet/revolver.dm b/code/datums/ammo/bullet/revolver.dm
index 339609f57be7..633bf3e2f7ff 100644
--- a/code/datums/ammo/bullet/revolver.dm
+++ b/code/datums/ammo/bullet/revolver.dm
@@ -27,8 +27,9 @@
penetration = ARMOR_PENETRATION_TIER_4
accuracy = HIT_ACCURACY_TIER_3
-/datum/ammo/bullet/revolver/heavy/on_hit_mob(mob/M, obj/projectile/P)
- knockback(M, P, 4)
+/datum/ammo/bullet/revolver/heavy/on_hit_mob(mob/entity, obj/projectile/bullet)
+ slowdown(entity, bullet)
+ pushback(entity, bullet, 4)
/datum/ammo/bullet/revolver/incendiary
name = "incendiary revolver bullet"
diff --git a/code/datums/emergency_calls/cryo_marines.dm b/code/datums/emergency_calls/cryo_marines.dm
index 7ed61852e9bf..19f73a9843ce 100644
--- a/code/datums/emergency_calls/cryo_marines.dm
+++ b/code/datums/emergency_calls/cryo_marines.dm
@@ -13,7 +13,7 @@
var/leaders = 0
spawn_max_amount = TRUE
-/datum/emergency_call/cryo_squad/spawn_candidates(announce, override_spawn_loc, announce_dispatch_message)
+/datum/emergency_call/cryo_squad/spawn_candidates(quiet_launch, announce_incoming, override_spawn_loc)
var/datum/squad/marine/cryo/cryo_squad = RoleAuthority.squads_by_type[/datum/squad/marine/cryo]
leaders = cryo_squad.num_leaders
. = ..()
diff --git a/code/datums/emergency_calls/cryo_marines_heavy.dm b/code/datums/emergency_calls/cryo_marines_heavy.dm
index 70ce52443573..f4fe3c9f2a57 100644
--- a/code/datums/emergency_calls/cryo_marines_heavy.dm
+++ b/code/datums/emergency_calls/cryo_marines_heavy.dm
@@ -16,7 +16,7 @@
var/leaders = 0
-/datum/emergency_call/cryo_squad_equipped/spawn_candidates(announce, override_spawn_loc, announce_dispatch_message)
+/datum/emergency_call/cryo_squad_equipped/spawn_candidates(quiet_launch, announce_incoming, override_spawn_loc)
var/datum/squad/marine/cryo/cryo_squad = RoleAuthority.squads_by_type[/datum/squad/marine/cryo]
leaders = cryo_squad.num_leaders
. = ..()
diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm
index 79ba9fff9747..4c3dfbbfac2b 100644
--- a/code/datums/emergency_calls/emergency_call.dm
+++ b/code/datums/emergency_calls/emergency_call.dm
@@ -91,12 +91,12 @@
else
return chosen_call
-/datum/game_mode/proc/get_specific_call(call_name, quiet_launch = FALSE, announce = TRUE, is_emergency = TRUE, info = "", announce_dispatch_message = TRUE)
+/datum/game_mode/proc/get_specific_call(call_name, quiet_launch = FALSE, announce_incoming = TRUE, info = "")
for(var/datum/emergency_call/E in all_calls) //Loop through all potential candidates
if(E.name == call_name)
var/datum/emergency_call/em_call = new E.type()
em_call.objective_info = info
- em_call.activate(quiet_launch, announce, is_emergency, announce_dispatch_message)
+ em_call.activate(quiet_launch, announce_incoming)
return
error("get_specific_call could not find emergency call '[call_name]'")
return
@@ -192,7 +192,7 @@
else
to_chat(src, SPAN_WARNING("You did not get enlisted in the response team. Better luck next time!"))
-/datum/emergency_call/proc/activate(quiet_launch = FALSE, announce = TRUE, turf/override_spawn_loc, announce_dispatch_message = TRUE)
+/datum/emergency_call/proc/activate(quiet_launch = FALSE, announce_incoming = TRUE, turf/override_spawn_loc)
set waitfor = 0
if(!SSticker.mode) //Something horribly wrong with the gamemode ticker
return
@@ -205,9 +205,9 @@
if(!quiet_launch)
marine_announcement("A distress beacon has been launched from the [MAIN_SHIP_NAME].", "Priority Alert", 'sound/AI/distressbeacon.ogg', logging = ARES_LOG_SECURITY)
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/emergency_call, spawn_candidates), quiet_launch, announce, override_spawn_loc, announce_dispatch_message), 30 SECONDS)
+ addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/emergency_call, spawn_candidates), quiet_launch, announce_incoming, override_spawn_loc), 30 SECONDS)
-/datum/emergency_call/proc/spawn_candidates(quiet_launch = FALSE, announce = TRUE, override_spawn_loc, announce_dispatch_message = TRUE)
+/datum/emergency_call/proc/spawn_candidates(quiet_launch = FALSE, announce_incoming = TRUE, override_spawn_loc)
if(SSticker.mode)
SSticker.mode.picked_calls -= src
@@ -248,7 +248,7 @@
if(I.current)
to_chat(I.current, SPAN_WARNING("You didn't get selected to join the distress team. Better luck next time!"))
- if(announce)
+ if(announce_incoming)
marine_announcement(dispatch_message, "Distress Beacon", 'sound/AI/distressreceived.ogg', logging = ARES_LOG_SECURITY) //Announcement that the Distress Beacon has been answered, does not hint towards the chosen ERT
message_admins("Distress beacon: [src.name] finalized, setting up candidates.")
@@ -304,7 +304,7 @@
create_member(null, override_spawn_loc)
candidates = list()
- if(arrival_message && announce)
+ if(arrival_message && announce_incoming)
marine_announcement(arrival_message, "Intercepted Tranmission:")
/datum/emergency_call/proc/add_candidate(mob/M)
diff --git a/code/datums/keybinding/client.dm b/code/datums/keybinding/client.dm
index a5baf09a1360..752287882277 100644
--- a/code/datums/keybinding/client.dm
+++ b/code/datums/keybinding/client.dm
@@ -4,8 +4,8 @@
/datum/keybinding/client/admin_help
- hotkey_keys = list("F1")
- classic_keys = list("F1")
+ hotkey_keys = list("Unbound")
+ classic_keys = list("Unbound")
name = "admin_help"
full_name = "Admin Help"
description = "Ask an admin for help."
diff --git a/code/datums/langchat/langchat.dm b/code/datums/langchat/langchat.dm
index af51a7196020..83b9be0ac053 100644
--- a/code/datums/langchat/langchat.dm
+++ b/code/datums/langchat/langchat.dm
@@ -47,6 +47,13 @@
M.client.images -= langchat_image
langchat_listeners = null
+/atom/proc/langchat_set_x_offset()
+ langchat_image.maptext_x = world.icon_size / 2 - langchat_image.maptext_width / 2
+/atom/movable/langchat_set_x_offset()
+ langchat_image.maptext_x = bound_width / 2 - langchat_image.maptext_width / 2
+/mob/langchat_set_x_offset()
+ langchat_image.maptext_x = icon_size / 2 - langchat_image.maptext_width / 2
+
///Creates the image if one does not exist, resets settings that are modified by speech procs.
/atom/proc/langchat_make_image(override_color = null)
if(!langchat_image)
@@ -56,8 +63,8 @@
langchat_image.appearance_flags = NO_CLIENT_COLOR|KEEP_APART|RESET_COLOR|RESET_TRANSFORM
langchat_image.maptext_y = langchat_height
langchat_image.maptext_height = 64
- langchat_image.maptext_x = - world.icon_size - get_pixel_position_x(src, TRUE)
langchat_image.maptext_y -= LANGCHAT_MESSAGE_POP_Y_SINK
+ langchat_set_x_offset()
langchat_image.pixel_y = 0
langchat_image.alpha = 0
@@ -102,6 +109,7 @@
langchat_image.maptext = text_to_display
langchat_image.maptext_width = LANGCHAT_WIDTH
+ langchat_set_x_offset()
langchat_listeners = listeners
for(var/mob/M in langchat_listeners)
@@ -148,7 +156,7 @@
langchat_image.maptext = text_to_display
langchat_image.maptext_width = LANGCHAT_WIDTH * 2
- langchat_image.maptext_x -= LANGCHAT_WIDTH / 2
+ langchat_set_x_offset()
langchat_listeners = listeners
for(var/mob/M in langchat_listeners)
diff --git a/code/datums/statistics/entities/death_stats.dm b/code/datums/statistics/entities/death_stats.dm
index 4a01e4e9d72b..cb3053a33442 100644
--- a/code/datums/statistics/entities/death_stats.dm
+++ b/code/datums/statistics/entities/death_stats.dm
@@ -84,6 +84,10 @@
if(!mind || statistic_exempt)
return
+ var/area/area = get_area(death_loc)
+ handle_observer_message(cause_data, cause_mob, death_loc, area)
+
+ // Perform logging above before get_player_from_key to avoid delays
var/datum/entity/statistic/death/new_death = DB_ENTITY(/datum/entity/statistic/death)
var/datum/entity/player/player_entity = get_player_from_key(mind.ckey)
if(player_entity)
@@ -95,11 +99,8 @@
new_death.role_name = get_role_name()
new_death.mob_name = real_name
new_death.faction_name = faction
-
new_death.is_xeno = FALSE
-
- var/area/A = get_area(death_loc)
- new_death.area_name = A.name
+ new_death.area_name = area.name
new_death.cause_name = cause_data?.cause_name
var/datum/entity/player/cause_player = get_player_from_key(cause_data?.ckey)
@@ -132,8 +133,6 @@
new_death.total_damage_taken = life_damage_taken_total
new_death.total_revives_done = life_revives_total
- handle_observer_message(cause_data, cause_mob, death_loc, A)
-
if(round_statistics)
round_statistics.track_death(new_death)
diff --git a/code/game/gamemodes/colonialmarines/colonialmarines.dm b/code/game/gamemodes/colonialmarines/colonialmarines.dm
index 258a1a962713..df04873ac140 100644
--- a/code/game/gamemodes/colonialmarines/colonialmarines.dm
+++ b/code/game/gamemodes/colonialmarines/colonialmarines.dm
@@ -265,7 +265,7 @@
continue
if(groundside_humans > (groundside_xenos * GROUNDSIDE_XENO_MULTIPLIER))
- SSticker.mode.get_specific_call("Xenomorphs Groundside (Forsaken)", TRUE, FALSE, FALSE, announce_dispatch_message = FALSE)
+ SSticker.mode.get_specific_call("Xenomorphs Groundside (Forsaken)", TRUE, FALSE)
TIMER_COOLDOWN_START(src, COOLDOWN_HIJACK_GROUND_CHECK, 1 MINUTES)
diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
index 3d856f35ce77..e7d7b7a67edf 100644
--- a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
+++ b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
@@ -193,7 +193,7 @@
announce_xeno_wave(wave)
if(xeno_wave == 7)
//Wave when Marines get reinforcements!
- get_specific_call("Marine Reinforcements (Squad)", FALSE, TRUE, FALSE)
+ get_specific_call("Marine Reinforcements (Squad)", FALSE, TRUE)
xeno_wave = min(xeno_wave + 1, WO_MAX_WAVE)
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 3c4104b6c283..c9092a750f73 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -59,8 +59,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/structure/machinery/optable/get_examine_text(mob/user)
. = ..()
diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm
index 16512a944be1..e6fc0c8de76e 100644
--- a/code/game/machinery/air_alarm.dm
+++ b/code/game/machinery/air_alarm.dm
@@ -431,8 +431,6 @@
var/wireIndex = AAlarmWireColorToIndex[wireColor] //not used in this function
AAlarmwires |= wireFlag
switch(wireIndex)
- if(AALARM_WIRE_IDSCAN)
-
if(AALARM_WIRE_POWER)
shorted = 0
shock(usr, 50)
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index b70829c708ed..d82591994e7b 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -551,7 +551,7 @@
var/speed = ((wires & WIRE_MOTOR1) ? 1:0) + ((wires & WIRE_MOTOR2) ? 2:0)
switch(speed)
if(0)
- // do nothing
+ pass()
if(1)
process_bot()
spawn(2)
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index adce72f7d8b6..304b24a14f04 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -53,8 +53,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/structure/machinery/computer/bullet_act(obj/projectile/Proj)
if(exproof)
diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm
index 60bf17388db8..6218bf0cdedb 100644
--- a/code/game/machinery/computer/dropship_weapons.dm
+++ b/code/game/machinery/computer/dropship_weapons.dm
@@ -594,14 +594,21 @@
return
var/targ_id = text2num(href_list["cas_camera"])
+
+ var/datum/cas_signal/new_signal
for(var/datum/cas_signal/LT as anything in cas_group.cas_signals)
if(LT.target_id == targ_id && LT.valid_signal())
- selected_cas_signal = LT
+ new_signal = LT
break
- if(!selected_cas_signal)
+ if(!new_signal)
to_chat(usr, SPAN_WARNING("Target lost or obstructed."))
return
+
+ if(usr in selected_cas_signal?.linked_cam?.viewing_users) // Reset previous cam
+ remove_from_view(usr)
+
+ selected_cas_signal = new_signal
if(selected_cas_signal && selected_cas_signal.linked_cam)
selected_cas_signal.linked_cam.view_directly(usr)
else
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index b68ca41d6f09..fe85599018ae 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -123,7 +123,6 @@
else
dat += "
[bdat]"
- else
else
dat += text("{Log In}", src)
show_browser(user, dat, "Medical Records", "med_rec")
@@ -365,8 +364,6 @@
for(var/datum/data/record/E in GLOB.data_core.medical)
if ((E.fields["ref"] == R.fields["ref"] || E.fields["id"] == R.fields["id"]))
M = E
- else
- //Foreach continue //goto(2540)
src.active1 = R
src.active2 = M
src.screen = 4
@@ -417,16 +414,12 @@
for(var/datum/data/record/R as anything in GLOB.data_core.medical)
if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"])))
src.active2 = R
- else
- //Foreach continue //goto(3229)
if (!active2)
temp = "Could not locate record [t1]."
else
for(var/datum/data/record/E in GLOB.data_core.general)
if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"]))
src.active1 = E
- else
- //Foreach continue //goto(3334)
src.screen = 4
if (href_list["print_p"])
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index 3858230a089c..f6adaa8edd4e 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -20,7 +20,6 @@
for(var/obj/structure/machinery/mass_driver/M in machines)
if(M.id == id)
connected = M
- else
return
return
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 12f4faedc979..c5a13e2c3e74 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -55,8 +55,7 @@
dat += " Locked Down |"
else
dat += " Operating Normally |"
- if (!R.canmove)
- else if(R.cell)
+ if(R.canmove && R.cell)
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
else
dat += " No Cell Installed |"
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index f891d46bc36b..a20d344b53a9 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -43,16 +43,16 @@
var/dat
if (temp)
- dat = text("[]
Clear Screen", temp, src)
+ dat = "[temp]
Clear Screen"
else
- dat = text("Confirm Identity: []
", src, (scan ? text("[]", scan.name) : "----------"))
+ dat = "Confirm Identity: [scan ? scan.name : "----------"]
"
if (authenticated)
switch(screen)
if(1.0)
dat += {"
"}
- dat += text("Search Records
", src)
- dat += text("New Record
", src)
+ dat += "Search Records
"
+ dat += "New Record
"
dat += {"
@@ -70,20 +70,19 @@
if(!isnull(GLOB.data_core.general))
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order))
for(var/datum/data/record/E in GLOB.data_core.security)
- var/background
- dat += text("[] | ", background, src, R, R.fields["name"])
- dat += text("[] | ", R.fields["id"])
- dat += text("[] | ", R.fields["rank"])
+ dat += "
[R.fields["name"]] | "
+ dat += "[R.fields["id"]] | "
+ dat += "[R.fields["rank"]] | "
dat += "
"
- dat += text("Record Maintenance
", src)
- dat += text("{Log Out}",src)
+ dat += "Record Maintenance
"
+ dat += "{Log Out}"
if(2.0)
dat += "Records Maintenance
"
dat += "
Delete All Records
Back"
if(3.0)
dat += "Employment Record
"
if ((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))
- dat += text(" \
+ dat += "")
+ |
"
else
dat += "General Record Lost!
"
- dat += text("\nDelete Record (ALL)
\nPrint Record
\nBack
", src, src, src)
+ dat += "\nDelete Record (ALL)
\nPrint Record
\nBack
"
if(4.0)
if(!Perp.len)
- dat += text("ERROR. String could not be located.
Back", src)
+ dat += "ERROR. String could not be located.
Back"
else
dat += {"
"}
- dat += text("Search Results for '[]': | ", tempname)
+ dat += "Search Results for '[tempname]': | "
dat += {"
@@ -121,17 +120,14 @@
if(istype(Perp[i+1],/datum/data/record/))
var/datum/data/record/E = Perp[i+1]
crimstat = E.fields["criminal"]
- var/background
- background = "'background-color:#00FF7F;'"
- dat += text("[] | ", background, src, R, R.fields["name"])
- dat += text("[] | ", R.fields["id"])
- dat += text("[] | ", R.fields["rank"])
- dat += text("[] |
", crimstat)
+ dat += "[R.fields["name"]] | "
+ dat += "[R.fields["id"]] | "
+ dat += "[R.fields["rank"]] | "
+ dat += "[crimstat] |
"
dat += "
"
- dat += text("
Return to index.", src)
- else
+ dat += "
Return to index."
else
- dat += text("{Log In}", src)
+ dat += "{Log In}"
show_browser(user, dat, "Employment Records", "secure_rec", "size=600x400")
onclose(user, "secure_rec")
return
@@ -342,7 +338,6 @@ What a mess.*/
if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
GLOB.data_core.medical -= R
qdel(R)
- else
QDEL_NULL(active1)
else
temp = "This function does not appear to be working at the moment. Our apologies."
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index e6df92d258c0..99996bea8978 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -54,7 +54,6 @@
src.health -= W.force * 0.75
if("brute")
src.health -= W.force * 0.5
- else
if (src.health <= 0)
src.explode()
..()
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index f52350aa8db3..903cd06c3119 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -23,7 +23,7 @@
var/icon_on = "smartfridge"
var/icon_off = "smartfridge-off"
var/icon_panel = "smartfridge-panel"
- var/item_quants = list()
+ var/list/item_quants = list() //! Assoc list of names -> list(items)
var/ispowered = TRUE //starts powered
var/is_secure_fridge = FALSE
var/shoot_inventory = FALSE
@@ -40,6 +40,24 @@
GLOB.vending_products[/obj/item/reagent_container/glass/bottle] = 1
GLOB.vending_products[/obj/item/storage/pill_bottle] = 1
+/obj/structure/machinery/smartfridge/Destroy(force)
+ if(is_in_network()) // Delete all contents from networked storage index
+ for(var/atom/movable/item as anything in contents)
+ delete_contents(item)
+ item_quants.Cut()
+ return ..() // parent will delete contents if we're not networked
+
+/// Deletes given object in contents of the smartfridge
+/obj/structure/machinery/smartfridge/proc/delete_contents(obj/item/item)
+ if(item.loc != src)
+ return
+ contents -= item
+ if(item_quants[item.name])
+ item_quants[item.name] -= item
+ if(is_in_network() && chemical_data.shared_item_storage[item.name])
+ chemical_data.shared_item_storage[item.name] -= item
+ qdel(item)
+
/obj/structure/machinery/smartfridge/proc/accept_check(obj/item/O as obj)
if(istype(O,/obj/item/reagent_container/food/snacks/grown/) || istype(O,/obj/item/seeds/))
return 1
diff --git a/code/game/machinery/medical_pod/bodyscanner.dm b/code/game/machinery/medical_pod/bodyscanner.dm
index 4756121e50ae..fdcd0ceb62e6 100644
--- a/code/game/machinery/medical_pod/bodyscanner.dm
+++ b/code/game/machinery/medical_pod/bodyscanner.dm
@@ -62,8 +62,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
#ifdef OBJECTS_PROXY_SPEECH
// Transfers speech to occupant
@@ -124,8 +122,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/structure/machinery/body_scanconsole/power_change()
..()
diff --git a/code/game/machinery/medical_pod/sleeper.dm b/code/game/machinery/medical_pod/sleeper.dm
index 805fedb29257..35d9a44863d2 100644
--- a/code/game/machinery/medical_pod/sleeper.dm
+++ b/code/game/machinery/medical_pod/sleeper.dm
@@ -385,7 +385,6 @@
t1 = "Unconscious"
if(2)
t1 = "*dead*"
- else
to_chat(user, "[]\t Health %: [] ([])", (occupant.health > 50 ? SPAN_NOTICE("") : SPAN_DANGER("")), occupant.health, t1)
to_chat(user, "[]\t -Core Temperature: []°C ([]°F)
", (occupant.bodytemperature > 50 ? "" : ""), occupant.bodytemperature-T0C, occupant.bodytemperature*1.8-459.67)
to_chat(user, "[]\t -Brute Damage %: []", (occupant.getBruteLoss() < 60 ? SPAN_NOTICE("") : SPAN_DANGER("")), occupant.getBruteLoss())
diff --git a/code/game/machinery/vending/cm_vending.dm b/code/game/machinery/vending/cm_vending.dm
index bf7c4fffee65..861f5b37ebca 100644
--- a/code/game/machinery/vending/cm_vending.dm
+++ b/code/game/machinery/vending/cm_vending.dm
@@ -774,8 +774,8 @@ GLOBAL_LIST_EMPTY(vending_products)
desc = "An automated closet hooked up to a colossal storage of standard-issue uniform and armor."
icon_state = "clothing"
use_points = TRUE
+ show_points = TRUE
vendor_theme = VENDOR_THEME_USCM
- show_points = FALSE
vend_flags = VEND_CLUTTER_PROTECTION | VEND_UNIFORM_RANKS | VEND_UNIFORM_AUTOEQUIP | VEND_CATEGORY_CHECK
/obj/structure/machinery/cm_vending/clothing/ui_static_data(mob/user)
diff --git a/code/game/machinery/vending/vending.dm b/code/game/machinery/vending/vending.dm
index a74dd923cbe7..414ab4a562e1 100644
--- a/code/game/machinery/vending/vending.dm
+++ b/code/game/machinery/vending/vending.dm
@@ -398,28 +398,25 @@ GLOBAL_LIST_EMPTY_TYPED(total_vending_machines, /obj/structure/machinery/vending
/obj/structure/machinery/vending/proc/GetProductIndex(datum/data/vending_product/product)
var/list/plist
- switch(product.category)
- if(CAT_NORMAL)
- plist=product_records
- if(CAT_HIDDEN)
- plist=hidden_records
- if(CAT_COIN)
- plist=coin_records
- else
- warning("UNKNOWN CATEGORY [product.category] IN TYPE [product.product_path] INSIDE [type]!")
+ if(product.category == CAT_NORMAL)
+ plist = product_records
+ else if(product.category == CAT_HIDDEN)
+ plist = hidden_records
+ else if(product.category == CAT_COIN)
+ plist = coin_records
+ else
+ warning("UNKNOWN CATEGORY [product.category] IN TYPE [product.product_path] INSIDE [type]!")
return plist.Find(product)
/obj/structure/machinery/vending/proc/GetProductByID(pid, category)
- switch(category)
- if(CAT_NORMAL)
- return product_records[pid]
- if(CAT_HIDDEN)
- return hidden_records[pid]
- if(CAT_COIN)
- return coin_records[pid]
- else
- warning("UNKNOWN PRODUCT: PID: [pid], CAT: [category] INSIDE [type]!")
- return null
+ if(category == CAT_NORMAL)
+ return product_records[pid]
+ else if(category == CAT_HIDDEN)
+ return hidden_records[pid]
+ else if(category == CAT_COIN)
+ return coin_records[pid]
+ else
+ warning("UNKNOWN PRODUCT: PID: [pid], CAT: [category] INSIDE [type]!")
/obj/structure/machinery/vending/attack_hand(mob/user)
if(is_tipped_over)
diff --git a/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm b/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm
index 830511ad4b19..d7d49a8ae044 100644
--- a/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm
+++ b/code/game/machinery/vending/vendor_types/crew/commanding_officer.dm
@@ -1,9 +1,9 @@
//------------GEAR VENDOR---------------
GLOBAL_LIST_INIT(cm_vending_gear_commanding_officer, list(
- list("COMMANDING OFFICER'S PRIMARY (CHOOSE 1)", 0, null, null, null),
- list("M46C pulse rifle", 0, /obj/effect/essentials_set/co/riflepreset, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY),
- list("M56C Smartgun", 0, /obj/item/storage/box/m56c_system, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY),
+ list("COMMANDER'S PRIMARY (CHOOSE 1)", 0, null, null, null),
+ list("M46C Pulse Rifle", 0, /obj/effect/essentials_set/co/riflepreset, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_MANDATORY),
+ list("M56C Smartgun", 0, /obj/item/storage/box/m56c_system, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_MANDATORY),
list("PRIMARY AMMUNITION", 0, null, null, null),
list("M41A MK1 Magazine", 30, /obj/item/ammo_magazine/rifle/m41aMK1, null, VENDOR_ITEM_RECOMMENDED),
@@ -28,11 +28,19 @@ GLOBAL_LIST_INIT(cm_vending_gear_commanding_officer, list(
list("M41A Rubber Shot Magazine", 10, /obj/item/ammo_magazine/rifle/rubber, null, VENDOR_ITEM_REGULAR),
list("Beanbag Slugs", 10, /obj/item/ammo_magazine/shotgun/beanbag, null, VENDOR_ITEM_REGULAR),
+ list("EXPLOSIVES", 0, null, null, null),
+ list("HEDP Grenade Pack", 15, /obj/item/storage/box/packet/high_explosive, null, VENDOR_ITEM_REGULAR),
+ list("HEFA Grenade Pack", 15, /obj/item/storage/box/packet/hefa, null, VENDOR_ITEM_REGULAR),
+ list("WP Grenade Pack", 15, /obj/item/storage/box/packet/phosphorus, null, VENDOR_ITEM_REGULAR),
+
list("RAIL ATTACHMENTS", 0, null, null, null),
list("Red-Dot Sight", 15, /obj/item/attachable/reddot, null, VENDOR_ITEM_REGULAR),
list("Reflex Sight", 15, /obj/item/attachable/reflex, null, VENDOR_ITEM_REGULAR),
list("S4 2x Telescopic Mini-Scope", 15, /obj/item/attachable/scope/mini, null, VENDOR_ITEM_REGULAR),
+ list("Helmet Visors", 0, null, null, null),
+ list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_RECOMMENDED),
+
list("UNDERBARREL ATTACHMENTS", 0, null, null, null),
list("Laser Sight", 15, /obj/item/attachable/lasersight, null, VENDOR_ITEM_REGULAR),
list("Angled Grip", 15, /obj/item/attachable/angledgrip, null, VENDOR_ITEM_REGULAR),
@@ -40,12 +48,13 @@ GLOBAL_LIST_INIT(cm_vending_gear_commanding_officer, list(
list("Underbarrel Shotgun", 15, /obj/item/attachable/attached_gun/shotgun, null, VENDOR_ITEM_REGULAR),
list("Underbarrel Extinguisher", 15, /obj/item/attachable/attached_gun/extinguisher, null, VENDOR_ITEM_REGULAR),
list("Underbarrel Flamethrower", 15, /obj/item/attachable/attached_gun/flamer, null, VENDOR_ITEM_REGULAR),
+ list("Underbarrel Grenade Launcher", 5, /obj/item/attachable/attached_gun/grenade, null, VENDOR_ITEM_REGULAR),
list("BARREL ATTACHMENTS", 0, null, null, null),
- list("Suppressor", 15, /obj/item/attachable/suppressor, null, VENDOR_ITEM_REGULAR),
list("Extended Barrel", 15, /obj/item/attachable/extended_barrel, null, VENDOR_ITEM_REGULAR),
list("Recoil Compensator", 15, /obj/item/attachable/compensator, null, VENDOR_ITEM_REGULAR),
- ))
+ list("Suppressor", 15, /obj/item/attachable/suppressor, null, VENDOR_ITEM_REGULAR),
+ ))
/obj/structure/machinery/cm_vending/gear/commanding_officer
name = "\improper ColMarTech Commanding Officer Weapon Rack"
@@ -63,9 +72,15 @@ GLOBAL_LIST_INIT(cm_vending_gear_commanding_officer, list(
GLOBAL_LIST_INIT(cm_vending_clothing_commanding_officer, list(
list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null),
list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom/cdrcom, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
- list("Satchel", 0, /obj/item/storage/backpack/satchel/lockable, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
+ list("COMMANDING OFFICER ESSENTIALS KIT (TAKE ALL)", 0, null, null, null),
+ list("Commanding Officer Essentials Kit", 0, /obj/effect/essentials_set/commanding_officer, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY),
+
+ list("BAGS (CHOOSE 1)", 0, null, null, null),
+ list("Commanding Officer Backpack", 0, /obj/item/storage/backpack/mcommander, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY),
+ list("Secure Satchel", 0, /obj/item/storage/backpack/satchel/lockable, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY),
+
list("COMBAT EQUIPMENT (TAKE ALL)", 0, null, null, null),
list("Commanding Officer's M3 Armor", 0, /obj/item/clothing/suit/storage/marine/MP/CO, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY),
list("Commanding Officer's M10 Helmet", 0, /obj/item/clothing/head/helmet/marine/CO, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
@@ -84,8 +99,13 @@ GLOBAL_LIST_INIT(cm_vending_clothing_commanding_officer, list(
list("Medical HUD Glasses", 0, /obj/item/clothing/glasses/hud/health, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_RECOMMENDED),
list("Security HUD Glasses", 0, /obj/item/clothing/glasses/sunglasses/sechud, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR),
- list("BELTS (TAKE ALL)", 0, null, null, null),
+ list("BELTS (CHOOSE 1)", 0, null, null, null),
list("G8-A General Utility Pouch", 0, /obj/item/storage/backpack/general_belt, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("Military Police Belt", 0, /obj/item/storage/belt/security/MP/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Medical Storage Rig", 0, /obj/item/storage/belt/medical/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Ammo Load Rig", 0, /obj/item/storage/belt/marine, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Holster Toolrig", 0, /obj/item/storage/belt/gun/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 M82F Holster Rig", 0, /obj/item/storage/belt/gun/flaregun, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
list("POUCHES (CHOOSE 2)", 0, null, null, null),
list("First-Aid Pouch (Refillable Injectors)", 0, /obj/item/storage/pouch/firstaid/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
@@ -110,6 +130,15 @@ GLOBAL_LIST_INIT(cm_vending_clothing_commanding_officer, list(
/obj/structure/machinery/cm_vending/clothing/commanding_officer/get_listed_products(mob/user)
return GLOB.cm_vending_clothing_commanding_officer
+/obj/effect/essentials_set/commanding_officer
+ spawned_gear_list = list(
+ /obj/item/device/binoculars/range/designator,
+ /obj/item/map/current_map,
+ /obj/item/device/whistle,
+ /obj/item/weapon/gun/energy/taser,
+ /obj/item/device/megaphone,
+ )
+
// This gets around the COs' weapon not spawning without incendiary mag.
/obj/effect/essentials_set/co/riflepreset
spawned_gear_list = list(
diff --git a/code/game/machinery/vending/vendor_types/crew/staff_officer.dm b/code/game/machinery/vending/vendor_types/crew/staff_officer.dm
index 85a8a58d162e..50b83ccdc54f 100644
--- a/code/game/machinery/vending/vendor_types/crew/staff_officer.dm
+++ b/code/game/machinery/vending/vendor_types/crew/staff_officer.dm
@@ -13,13 +13,13 @@ GLOBAL_LIST_INIT(cm_vending_clothing_staff_officer, list(
list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null),
list("Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY),
list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
- list("Helmet", 0, /obj/item/clothing/head/helmet/marine/MP/SO, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null),
list("Service Uniform", 0, /obj/item/clothing/under/marine/officer/bridge, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_REGULAR),
list("Operations Uniform", 0, /obj/item/clothing/under/marine/officer/boiler, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_RECOMMENDED),
+ list("Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_REGULAR),
list("JACKET (CHOOSE 1)", 0, null, null, null),
list("Service Jacket", 0, /obj/item/clothing/suit/storage/jacket/marine/service, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_RECOMMENDED),
@@ -33,66 +33,21 @@ GLOBAL_LIST_INIT(cm_vending_clothing_staff_officer, list(
list("PERSONAL SIDEARM (CHOOSE 1)", 0, null, null, null),
- list("M44 Revolver", 0, /obj/item/storage/belt/gun/m44/mp, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
- list("M4A3 Pistol", 0, /obj/item/storage/belt/gun/m4a3/commander, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
- list("VP78 Pistol", 0, /obj/item/storage/belt/gun/m4a3/vp78, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M44 Revolver", 0, /obj/item/storage/belt/gun/m44/mp, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_RECOMMENDED),
+ list("M4A3 Pistol", 0, /obj/item/storage/belt/gun/m4a3/commander, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_RECOMMENDED),
+ list("VP78 Pistol", 0, /obj/item/storage/belt/gun/m4a3/vp78, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_RECOMMENDED),
list("BACKPACK (CHOOSE 1)", 0, null, null, null),
list("Backpack", 0, /obj/item/storage/backpack/marine, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
list("Satchel", 0, /obj/item/storage/backpack/marine/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR),
- list("Radio Telephone Pack", 0, /obj/item/storage/backpack/marine/satchel/rto, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_RECOMMENDED),
- list("BELT (CHOOSE 1)", 0, null, null, null),
- list("G8-A General Utility Pouch", 0, /obj/item/storage/backpack/general_belt, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
- list("M276 Ammo Load Rig", 0, /obj/item/storage/belt/marine, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
- list("M276 Lifesaver Bag (Full)", 0, /obj/item/storage/belt/medical/lifesaver/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
- list("M276 Medical Storage Rig (Full)", 0, /obj/item/storage/belt/medical/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
- list("M276 M39 Holster Rig", 0, /obj/item/storage/belt/gun/m39, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
- list("M276 M82F Holster Rig", 0, /obj/item/storage/belt/gun/flaregun, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
- list("M276 Shotgun Shell Loading Rig", 0, /obj/item/storage/belt/shotgun, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
- list("M276 M40 Grenade Rig", 0, /obj/item/storage/belt/grenade, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
-
- list("POUCHES (CHOOSE 2)", 0, null, null, null),
- list("Autoinjector Pouch", 0, /obj/item/storage/pouch/autoinjector, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Construction Pouch", 0, /obj/item/storage/pouch/construction, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Document Pouch", 0, /obj/item/storage/pouch/document, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Electronics Pouch (Full)", 0, /obj/item/storage/pouch/electronics/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("First-Aid Pouch (Refillable Injectors)", 0, /obj/item/storage/pouch/firstaid/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("First-Aid Pouch (Splints, Gauze, Ointment)", 0, /obj/item/storage/pouch/firstaid/full/alternate, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("First-Aid Pouch (Pill Packets)", 0, /obj/item/storage/pouch/firstaid/full/pills, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("First Responder Pouch", 0, /obj/item/storage/pouch/first_responder, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Flare Pouch (Full)", 0, /obj/item/storage/pouch/flare/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Fuel Tank Strap Pouch", 0, /obj/item/storage/pouch/flamertank, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Large General Pouch", 0, /obj/item/storage/pouch/general/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_RECOMMENDED),
- list("Large Magazine Pouch", 0, /obj/item/storage/pouch/magazine/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Large Shotgun Shell Pouch", 0, /obj/item/storage/pouch/shotgun/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Large Pistol Magazine Pouch", 0, /obj/item/storage/pouch/magazine/pistol/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Medical Pouch", 0, /obj/item/storage/pouch/medical, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Medical Kit Pouch", 0, /obj/item/storage/pouch/medkit, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Pistol Pouch", 0, /obj/item/storage/pouch/pistol, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Sling Pouch", 0, /obj/item/storage/pouch/sling, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
- list("Tools Pouch (Full)", 0, /obj/item/storage/pouch/tools/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
-
- list("ACCESSORIES (CHOOSE 1)", 0, null, null, null),
- list("Black Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
- list("Brown Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest/brown_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_RECOMMENDED),
- list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
- list("Webbing", 0, /obj/item/clothing/accessory/storage/webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
- list("Shoulder Holster", 0, /obj/item/clothing/accessory/storage/holster, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
-
- list("MASK (CHOOSE 1)", 0, null, null, null),
- list("Gas Mask", 0, /obj/item/clothing/mask/gas, MARINE_CAN_BUY_MASK, VENDOR_ITEM_REGULAR),
- list("Heat Absorbent Coif", 0, /obj/item/clothing/mask/rebreather/scarf, MARINE_CAN_BUY_MASK, VENDOR_ITEM_REGULAR),
list("OTHER SUPPLIES", 0, null, null, null),
list("Binoculars", 5,/obj/item/device/binoculars, null, VENDOR_ITEM_REGULAR),
list("Rangefinder", 8, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR),
list("Laser Designator", 12, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_RECOMMENDED),
- list("Data Detector", 5, /obj/item/device/motiondetector/intel, null, VENDOR_ITEM_REGULAR),
list("Flashlight", 1, /obj/item/device/flashlight, null, VENDOR_ITEM_RECOMMENDED),
- list("Fulton Recovery Device", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
- list("Motion Detector", 5, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR),
+ list("Motion Detector", 5, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED),
list("Space Cleaner", 2, /obj/item/reagent_container/spray/cleaner, null, VENDOR_ITEM_REGULAR),
list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR),
- list("Machete Scabbard (Full)", 2, /obj/item/storage/large_holster/machete/full, null, VENDOR_ITEM_REGULAR)
))
diff --git a/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm b/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm
new file mode 100644
index 000000000000..ac7b22b4e0a0
--- /dev/null
+++ b/code/game/machinery/vending/vendor_types/crew/staff_officer_armory.dm
@@ -0,0 +1,83 @@
+/obj/structure/machinery/cm_vending/clothing/staff_officer_armory
+ name = "\improper ColMarTech Staff Officer Armory Equipment Rack"
+ desc = "An automated combat equipment vendor for Staff Officers."
+ req_access = list(ACCESS_MARINE_COMMAND)
+ icon_state = "mar_rack"
+ vendor_role = list(JOB_SO)
+
+/obj/structure/machinery/cm_vending/clothing/staff_officer_armory/get_listed_products(mob/user)
+ return GLOB.cm_vending_clothing_staff_officer_armory
+
+//------------GEAR---------------
+
+GLOBAL_LIST_INIT(cm_vending_clothing_staff_officer_armory, list(
+ list("COMBAT EQUIPMENT (TAKE ALL)", 0, null, null, null),
+ list("Officer M3 Armor", 0, /obj/item/clothing/suit/storage/marine/MP/SO, MARINE_CAN_BUY_COMBAT_ARMOR, VENDOR_ITEM_MANDATORY),
+ list("Officer M10 Helmet", 0, /obj/item/clothing/head/helmet/marine/MP/SO, MARINE_CAN_BUY_COMBAT_HELMET, VENDOR_ITEM_MANDATORY),
+ list("Marine Combat Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY),
+ list("Marine Combat Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
+ list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
+ list("Aviator Shades", 0, /obj/item/clothing/glasses/sunglasses/aviator, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR),
+
+ list("SPECIALISATION KIT (CHOOSE 1)", 0, null, null, null),
+ list("Essential Engineer Set", 0, /obj/effect/essentials_set/engi, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_RECOMMENDED),
+ list("Essential Medical Set", 0, /obj/effect/essentials_set/medic, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_RECOMMENDED),
+
+ list("BELT (CHOOSE 1)", 0, null, null, null),
+ list("G8-A General Utility Pouch", 0, /obj/item/storage/backpack/general_belt, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Ammo Load Rig", 0, /obj/item/storage/belt/marine, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Toolbelt Rig (Full)", 0, /obj/item/storage/belt/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED),
+ list("M276 Lifesaver Bag (Full)", 0, /obj/item/storage/belt/medical/lifesaver/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+ list("M276 Medical Storage Rig (Full)", 0, /obj/item/storage/belt/medical/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+ list("M276 M39 Holster Rig", 0, /obj/item/storage/belt/gun/m39, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+ list("M276 M82F Holster Rig", 0, /obj/item/storage/belt/gun/flaregun, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+ list("M276 Shotgun Shell Loading Rig", 0, /obj/item/storage/belt/shotgun, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+ list("M276 M40 Grenade Rig", 0, /obj/item/storage/belt/grenade, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR),
+
+ list("POUCHES (CHOOSE 2)", 0, null, null, null),
+ list("Autoinjector Pouch", 0, /obj/item/storage/pouch/autoinjector, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Construction Pouch", 0, /obj/item/storage/pouch/construction, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Document Pouch", 0, /obj/item/storage/pouch/document, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Electronics Pouch (Full)", 0, /obj/item/storage/pouch/electronics/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("First-Aid Pouch (Refillable Injectors)", 0, /obj/item/storage/pouch/firstaid/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("First-Aid Pouch (Splints, Gauze, Ointment)", 0, /obj/item/storage/pouch/firstaid/full/alternate, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("First-Aid Pouch (Pill Packets)", 0, /obj/item/storage/pouch/firstaid/full/pills, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("First Responder Pouch", 0, /obj/item/storage/pouch/first_responder, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Flare Pouch (Full)", 0, /obj/item/storage/pouch/flare/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Fuel Tank Strap Pouch", 0, /obj/item/storage/pouch/flamertank, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Large General Pouch", 0, /obj/item/storage/pouch/general/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_RECOMMENDED),
+ list("Large Magazine Pouch", 0, /obj/item/storage/pouch/magazine/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Large Shotgun Shell Pouch", 0, /obj/item/storage/pouch/shotgun/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Large Pistol Magazine Pouch", 0, /obj/item/storage/pouch/magazine/pistol/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Medical Pouch", 0, /obj/item/storage/pouch/medical, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Medical Kit Pouch", 0, /obj/item/storage/pouch/medkit, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Pistol Pouch", 0, /obj/item/storage/pouch/pistol, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Sling Pouch", 0, /obj/item/storage/pouch/sling, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+ list("Tools Pouch (Full)", 0, /obj/item/storage/pouch/tools/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR),
+
+ list("ACCESSORIES (CHOOSE 1)", 0, null, null, null),
+ list("Black Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
+ list("Brown Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest/brown_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_RECOMMENDED),
+ list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
+ list("Webbing", 0, /obj/item/clothing/accessory/storage/webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
+ list("Shoulder Holster", 0, /obj/item/clothing/accessory/storage/holster, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR),
+
+ list("MASK (CHOOSE 1)", 0, null, null, null),
+ list("Gas Mask", 0, /obj/item/clothing/mask/gas, MARINE_CAN_BUY_MASK, VENDOR_ITEM_REGULAR),
+ list("Heat Absorbent Coif", 0, /obj/item/clothing/mask/rebreather/scarf, MARINE_CAN_BUY_MASK, VENDOR_ITEM_REGULAR),
+
+ list("OTHER SUPPLIES", 0, null, null, null),
+ list("Medical Helmet Optic", 5, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
+ list("Magnetic Harness", 12, /obj/item/attachable/magnetic_harness, null, VENDOR_ITEM_REGULAR),
+ list("Radio Telephone Pack", 15, /obj/item/storage/backpack/marine/satchel/rto, null, VENDOR_ITEM_RECOMMENDED),
+ list("Binoculars", 5,/obj/item/device/binoculars, null, VENDOR_ITEM_REGULAR),
+ list("Rangefinder", 8, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR),
+ list("Laser Designator", 12, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_RECOMMENDED),
+ list("Data Detector", 5, /obj/item/device/motiondetector/intel, null, VENDOR_ITEM_REGULAR),
+ list("Flashlight", 1, /obj/item/device/flashlight, null, VENDOR_ITEM_RECOMMENDED),
+ list("Fulton Recovery Device", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
+ list("Motion Detector", 5, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR),
+ list("Space Cleaner", 2, /obj/item/reagent_container/spray/cleaner, null, VENDOR_ITEM_REGULAR),
+ list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR),
+ list("Machete Scabbard (Full)", 5, /obj/item/storage/large_holster/machete/full, null, VENDOR_ITEM_REGULAR)
+ ))
diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm
index 07284e7f8e71..8558019839f7 100644
--- a/code/game/machinery/vending/vendor_types/requisitions.dm
+++ b/code/game/machinery/vending/vendor_types/requisitions.dm
@@ -192,7 +192,7 @@
turf_to_vent_to = H.loc
return turf_to_vent_to
-/obj/structure/machinery/cm_vending/sorted/cargo_guns/blend
+/obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/blend
icon_state = "req_guns_wall"
tiles_with = list(
/obj/structure/window/framed/almayer,
@@ -296,7 +296,7 @@
updateUsrDialog()
return //We found our item, no reason to go on.
-/obj/structure/machinery/cm_vending/sorted/cargo_ammo/blend
+/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/blend
icon_state = "req_ammo_wall"
tiles_with = list(
/obj/structure/window/framed/almayer,
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm
index 49d758b52b19..867c6924b39d 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/effects/aliens.dm
@@ -287,19 +287,23 @@
opacity = FALSE
anchored = TRUE
unacidable = TRUE
+ /// Target the acid is melting
var/atom/acid_t
- var/ticks = 0
- var/acid_strength = 1 //100% speed, normal
- var/barricade_damage = 40
+ /// Duration left to next acid stage
+ var/remaining = 0
+ /// Acid stages left to complete melting
+ var/ticks_left = 3
+ /// Factor of duration between acid progression
+ var/acid_delay = 1
/// How much fuel the acid drains from the flare every acid tick
var/flare_damage = 500
- var/barricade_damage_ticks = 10 // tick is once per 5 seconds. This tells us how many times it will try damaging barricades
+ var/barricade_damage = 40
var/in_weather = FALSE
//Sentinel weakest acid
/obj/effect/xenomorph/acid/weak
name = "weak acid"
- acid_strength = 2.5 //250% normal speed
+ acid_delay = 2.5 //250% delay (40% speed)
barricade_damage = 20
flare_damage = 150
icon_state = "acid_weak"
@@ -307,24 +311,32 @@
//Superacid
/obj/effect/xenomorph/acid/strong
name = "strong acid"
- acid_strength = 0.4 //40% normal speed
+ acid_delay = 0.4 //40% delay (250% speed)
barricade_damage = 100
flare_damage = 1875
icon_state = "acid_strong"
-/obj/effect/xenomorph/acid/New(loc, target)
- ..(loc)
+/obj/effect/xenomorph/acid/Initialize(mapload, atom/target)
+ . = ..()
acid_t = target
- var/strength_t = isturf(acid_t) ? 8:4 // Turf take twice as long to take down.
+ if(isturf(acid_t))
+ ticks_left = 7 // Turf take twice as long to take down.
+ else if(istype(acid_t, /obj/structure/barricade))
+ ticks_left = 9
handle_weather()
- tick(strength_t)
-
RegisterSignal(SSdcs, COMSIG_GLOB_WEATHER_CHANGE, PROC_REF(handle_weather))
+ RegisterSignal(acid_t, COMSIG_PARENT_QDELETING, PROC_REF(cleanup))
+ START_PROCESSING(SSeffects, src)
/obj/effect/xenomorph/acid/Destroy()
acid_t = null
+ STOP_PROCESSING(SSeffects, src)
. = ..()
+/obj/effect/xenomorph/acid/proc/cleanup()
+ SIGNAL_HANDLER
+ qdel(src)
+
/obj/effect/xenomorph/acid/proc/handle_weather()
SIGNAL_HANDLER
@@ -333,76 +345,85 @@
return
if(SSweather.is_weather_event && locate(acids_area) in SSweather.weather_areas)
- acid_strength = acid_strength + (SSweather.weather_event_instance.fire_smothering_strength * 0.33) //smothering_strength is 1-10, acid strength is a multiplier
+ acid_delay = acid_delay + (SSweather.weather_event_instance.fire_smothering_strength * 0.33) //smothering_strength is 1-10, acid strength is a multiplier
in_weather = SSweather.weather_event_instance.fire_smothering_strength
else
- acid_strength = initial(acid_strength)
+ acid_delay = initial(acid_delay)
in_weather = FALSE
/obj/effect/xenomorph/acid/proc/handle_barricade()
+ if(prob(in_weather))
+ visible_message(SPAN_XENOWARNING("Acid on \The [acid_t] subsides!"))
+ return NONE
var/obj/structure/barricade/cade = acid_t
- if(istype(cade))
- cade.take_acid_damage(barricade_damage)
-
-/obj/effect/xenomorph/acid/proc/tick(strength_t)
- set waitfor = 0
- if(!acid_t || !acid_t.loc)
- qdel(src)
+ cade.take_acid_damage(barricade_damage)
+ return (5 SECONDS)
+
+/obj/effect/xenomorph/acid/proc/handle_flashlight()
+ var/obj/item/device/flashlight/flare/flare = acid_t
+ if(flare.fuel <= 0)
+ return NONE
+ flare.fuel -= flare_damage
+ return (rand(15, 25) SECONDS) * acid_delay
+
+/obj/effect/xenomorph/acid/process(delta_time)
+ remaining -= delta_time * (1 SECONDS)
+ if(remaining > 0)
return
+ ticks_left -= 1
- if(istype(acid_t,/obj/structure/barricade))
- if(++ticks >= barricade_damage_ticks || prob(in_weather))
- visible_message(SPAN_XENOWARNING("Acid on \The [acid_t] subsides!"))
- qdel(src)
- return
- handle_barricade()
- sleep(50)
- .()
- return
- if(istype(acid_t, /obj/item/device/flashlight/flare))
- var/obj/item/device/flashlight/flare/flare = acid_t
- if(flare.fuel > 0) //Flares that have fuel in them lose fuel instead of melting
- flare.fuel -= flare_damage
- sleep(rand(150,250) * (acid_strength))
- return .()
-
- if(++ticks >= strength_t)
- visible_message(SPAN_XENODANGER("[acid_t] collapses under its own weight into a puddle of goop and undigested debris!"))
- playsound(src, "acid_hit", 25, TRUE)
-
- if(istype(acid_t, /turf))
- if(istype(acid_t, /turf/closed/wall))
- var/turf/closed/wall/W = acid_t
- new /obj/effect/acid_hole (W)
- else
- var/turf/T = acid_t
- T.ScrapeAway()
- else if (istype(acid_t, /obj/structure/girder))
- var/obj/structure/girder/G = acid_t
- G.dismantle()
- else if(istype(acid_t, /obj/structure/window/framed))
- var/obj/structure/window/framed/WF = acid_t
- WF.deconstruct(disassembled = FALSE)
- else if(istype(acid_t,/obj/item/explosive/plastic))
- qdel(acid_t)
+ var/return_delay = NONE
+ if(istype(acid_t, /obj/structure/barricade))
+ return_delay = handle_barricade()
+ else if(istype(acid_t, /obj/item/device/flashlight/flare))
+ return_delay = handle_flashlight()
+ else
+ return_delay = (rand(20, 30) SECONDS) * acid_delay
- else
- if(acid_t.contents.len) //Hopefully won't auto-delete things inside melted stuff..
- for(var/mob/M in acid_t.contents)
- if(acid_t.loc) M.forceMove(acid_t.loc)
- QDEL_NULL(acid_t)
+ if(!ticks_left)
+ finish_melting()
+ return PROCESS_KILL
+ if(!return_delay)
qdel(src)
- return
+ return PROCESS_KILL
- switch(strength_t - ticks)
+ remaining = return_delay
+
+ switch(ticks_left)
if(6) visible_message(SPAN_XENOWARNING("\The [acid_t] is barely holding up against the acid!"))
if(4) visible_message(SPAN_XENOWARNING("\The [acid_t]\s structure is being melted by the acid!"))
if(2) visible_message(SPAN_XENOWARNING("\The [acid_t] is struggling to withstand the acid!"))
if(0 to 1) visible_message(SPAN_XENOWARNING("\The [acid_t] begins to crumble under the acid!"))
- sleep(rand(200,300) * (acid_strength))
- .()
+/obj/effect/xenomorph/acid/proc/finish_melting()
+ visible_message(SPAN_XENODANGER("[acid_t] collapses under its own weight into a puddle of goop and undigested debris!"))
+ playsound(src, "acid_hit", 25, TRUE)
+
+ if(istype(acid_t, /turf))
+ if(istype(acid_t, /turf/closed/wall))
+ var/turf/closed/wall/wall = acid_t
+ new /obj/effect/acid_hole(wall)
+ else
+ var/turf/turf = acid_t
+ turf.ScrapeAway()
+
+ else if (istype(acid_t, /obj/structure/girder))
+ var/obj/structure/girder/girder = acid_t
+ girder.dismantle()
+
+ else if(istype(acid_t, /obj/structure/window/framed))
+ var/obj/structure/window/framed/window = acid_t
+ window.deconstruct(disassembled = FALSE)
+
+ else if(istype(acid_t, /obj/structure/barricade))
+ pass() // Don't delete it, just damaj
+
+ else
+ for(var/mob/mob in acid_t)
+ mob.forceMove(loc)
+ qdel(acid_t)
+ qdel(src)
/obj/effect/xenomorph/boiler_bombard
name = "???"
diff --git a/code/game/objects/effects/decals/cleanable/blood/tracks.dm b/code/game/objects/effects/decals/cleanable/blood/tracks.dm
index 32593f6f30fa..c764259a6252 100644
--- a/code/game/objects/effects/decals/cleanable/blood/tracks.dm
+++ b/code/game/objects/effects/decals/cleanable/blood/tracks.dm
@@ -14,6 +14,9 @@
var/list/overlay_images = list()
+ /// Amount of pixels to shift either way in an attempt to make the tracks more organic
+ var/transverse_amplitude = 3
+
/obj/effect/decal/cleanable/blood/tracks/Crossed()
return
@@ -21,19 +24,27 @@
return FALSE
/obj/effect/decal/cleanable/blood/tracks/proc/add_tracks(direction, tcolor, out)
- var/image/I = image(icon = icon, icon_state = out ? going_state : coming_state, dir = direction)
- var/mutable_appearance/MA = new(I)
+ var/image/image = image(icon = icon, icon_state = out ? going_state : coming_state, dir = direction)
+
+ var/mutable_appearance/MA = new(image)
MA.color = tcolor
MA.layer = layer
MA.appearance_flags |= RESET_COLOR
- I.appearance = MA
+ image.appearance = MA
+
+ switch(direction)
+ if(NORTH, SOUTH)
+ image.pixel_x += rand(-transverse_amplitude, transverse_amplitude)
+ if(EAST, WEST)
+ image.pixel_y += rand(-transverse_amplitude, transverse_amplitude)
+
if(out)
- LAZYSET(steps_out, "[direction]", I)
+ LAZYSET(steps_out, "[direction]", image)
else
- LAZYSET(steps_in, "[direction]", I)
+ LAZYSET(steps_in, "[direction]", image)
- overlay_images += I
- cleanable_turf.overlays += I
+ overlay_images += image
+ cleanable_turf.overlays += image
/obj/effect/decal/cleanable/blood/tracks/clear_overlay()
if(length(overlay_images))
diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm
index bebe0ec8b27f..56c6ae45cda7 100644
--- a/code/game/objects/effects/glowshroom.dm
+++ b/code/game/objects/effects/glowshroom.dm
@@ -95,8 +95,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/effect/glowshroom/fire_act(exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm
index 1f52901c21a6..82566c80302f 100644
--- a/code/game/objects/explosion_recursive.dm
+++ b/code/game/objects/explosion_recursive.dm
@@ -149,7 +149,7 @@ explosion resistance exactly as much as their health
switch(angle) //this reduces power when the explosion is going around corners
if (0)
- //no change
+ pass()
if (45)
if(spread_power >= 0)
spread_power *= 0.75
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2d142789fdaf..bf24b0758262 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -156,6 +156,11 @@
var/list/inherent_traits
+ /// How much to offset the item randomly either way alongside X visually
+ var/ground_offset_x = 0
+ /// How much to offset the item randomly either way alongside Y visually
+ var/ground_offset_y = 0
+
/obj/item/Initialize(mapload, ...)
. = ..()
@@ -175,6 +180,8 @@
if(flags_item & MOB_LOCK_ON_EQUIP)
AddComponent(/datum/component/id_lock)
+ scatter_item()
+
/obj/item/Destroy()
flags_item &= ~DELONDROP //to avoid infinite loop of unequip, delete, unequip, delete.
flags_item &= ~NODROP //so the item is properly unequipped if on a mob.
@@ -268,7 +275,6 @@ cases. Override_icon_state should be a list.*/
size = "huge"
if(SIZE_MASSIVE)
size = "massive"
- else
. += "This is a [blood_color ? blood_color != "#030303" ? "bloody " : "oil-stained " : ""][icon2html(src, user)][src.name]. It is a [size] item."
if(desc)
. += desc
@@ -459,6 +465,11 @@ cases. Override_icon_state should be a list.*/
/obj/item/proc/item_action_slot_check(mob/user, slot)
return TRUE
+/obj/item/proc/scatter_item()
+ if(!pixel_x && !pixel_y)
+ pixel_x = rand(-ground_offset_x, ground_offset_x)
+ pixel_y = rand(-ground_offset_y, ground_offset_y)
+
// The mob M is attempting to equip this item into the slot passed through as 'slot'. return TRUE if it can do this and 0 if it can't.
// If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
// Set disable_warning to TRUE if you wish it to not give you outputs.
diff --git a/code/game/objects/items/devices/coins.dm b/code/game/objects/items/devices/coins.dm
index 6ab79e3216d4..7343d14ad199 100644
--- a/code/game/objects/items/devices/coins.dm
+++ b/code/game/objects/items/devices/coins.dm
@@ -11,11 +11,8 @@
black_market_value = 10
var/string_attached
var/sides = 2
-
-/obj/item/coin/Initialize()
- . = ..()
- pixel_x = rand(0,16)-8
- pixel_y = rand(0,8)-8
+ ground_offset_x = 8
+ ground_offset_y = 4
/obj/item/coin/gold
name = "gold coin"
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index e795f4e28de4..114964464a25 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -12,6 +12,8 @@
light_range = 5
light_power = 1
+ ground_offset_x = 2
+ ground_offset_y = 6
actions_types = list(/datum/action/item_action)
var/on = FALSE
@@ -33,6 +35,11 @@
else
icon_state = initial(icon_state)
+/obj/item/device/flashlight/animation_spin(speed = 5, loop_amount = -1, clockwise = TRUE, sections = 3, angular_offset = 0, pixel_fuzz = 0)
+ clockwise = pick(TRUE, FALSE)
+ angular_offset = rand(360)
+ return ..()
+
/obj/item/device/flashlight/proc/update_brightness(mob/user = null)
if(on)
set_light_range(light_range)
@@ -296,8 +303,6 @@
// Causes flares to stop with a rotation offset for visual purposes
/obj/item/device/flashlight/flare/animation_spin(speed = 5, loop_amount = -1, clockwise = TRUE, sections = 3, angular_offset = 0, pixel_fuzz = 0)
- clockwise = pick(TRUE, FALSE)
- angular_offset = rand(360)
pixel_fuzz = 16
return ..()
/obj/item/device/flashlight/flare/pickup()
diff --git a/code/game/objects/items/explosives/grenades/grenade.dm b/code/game/objects/items/explosives/grenades/grenade.dm
index 7e98e9819931..6b793233678d 100644
--- a/code/game/objects/items/explosives/grenades/grenade.dm
+++ b/code/game/objects/items/explosives/grenades/grenade.dm
@@ -20,12 +20,12 @@
var/hand_throwable = TRUE
harmful = TRUE //Is it harmful? Are they banned for synths?
antigrief_protection = TRUE //Should it be checked by antigrief?
+ ground_offset_x = 7
+ ground_offset_y = 6
/obj/item/explosive/grenade/Initialize()
. = ..()
det_time = max(0, rand(det_time - 5, det_time + 5))
- pixel_y = rand(-6, 6)
- pixel_x = rand(-7, 7)
/obj/item/explosive/grenade/proc/can_use_grenade(mob/living/carbon/human/user)
if(!hand_throwable)
diff --git a/code/game/objects/items/explosives/warhead.dm b/code/game/objects/items/explosives/warhead.dm
index 5dfdf2a41eac..9825d7483193 100644
--- a/code/game/objects/items/explosives/warhead.dm
+++ b/code/game/objects/items/explosives/warhead.dm
@@ -2,11 +2,8 @@
icon = 'icons/obj/items/weapons/grenade.dmi'
customizable = TRUE
allowed_sensors = list() //We only need a detonator
-
-/obj/item/explosive/warhead/Initialize(mapload, ...)
- . = ..()
- pixel_y = rand(-6, 6)
- pixel_x = rand(-7, 7)
+ ground_offset_x = 7
+ ground_offset_y = 6
/obj/item/explosive/warhead/rocket
name = "84mm rocket warhead"
diff --git a/code/game/objects/items/reagent_containers/food/snacks.dm b/code/game/objects/items/reagent_containers/food/snacks.dm
index 06a4d785e677..2892eb1113e7 100644
--- a/code/game/objects/items/reagent_containers/food/snacks.dm
+++ b/code/game/objects/items/reagent_containers/food/snacks.dm
@@ -182,10 +182,9 @@
return 0
var/inaccurate = 0
- if(W.sharp == IS_SHARP_ITEM_ACCURATE)
- else if(W.sharp == IS_SHARP_ITEM_BIG)
+ if(W.sharp == IS_SHARP_ITEM_BIG)
inaccurate = 1
- else
+ else if(W.sharp != IS_SHARP_ITEM_ACCURATE)
return 1
if ( !istype(loc, /obj/structure/surface/table) && \
(!isturf(src.loc) || \
@@ -206,7 +205,7 @@
SPAN_NOTICE("[user] crudely slices \the [src] with [W]!"), \
SPAN_NOTICE("You crudely slice \the [src] with your [W]!") \
)
- slices_lost = rand(1,min(1,round(slices_num/2)))
+ slices_lost = rand(1,max(1,round(slices_num/2)))
var/reagents_per_slice = reagents.total_volume/slices_num
for(var/i=1 to (slices_num-slices_lost))
var/obj/slice = new slice_path (src.loc)
diff --git a/code/game/objects/items/reagent_containers/glass.dm b/code/game/objects/items/reagent_containers/glass.dm
index 240809b7851f..df344506c72c 100644
--- a/code/game/objects/items/reagent_containers/glass.dm
+++ b/code/game/objects/items/reagent_containers/glass.dm
@@ -363,11 +363,8 @@
matter = list()
possible_transfer_amounts = list(5,10,15,25,30)
flags_atom = FPRINT|OPENCONTAINER
-
-/obj/item/reagent_container/glass/beaker/vial/Initialize()
- . = ..()
- pixel_y = rand(-8, 8)
- pixel_x = rand(-9, 9)
+ ground_offset_x = 9
+ ground_offset_y = 8
/obj/item/reagent_container/glass/beaker/vial/tricordrazine
name = "tricordrazine vial"
diff --git a/code/game/objects/items/reagent_containers/pill.dm b/code/game/objects/items/reagent_containers/pill.dm
index de86ad07f53a..6c71d8be3c0c 100644
--- a/code/game/objects/items/reagent_containers/pill.dm
+++ b/code/game/objects/items/reagent_containers/pill.dm
@@ -23,6 +23,8 @@
w_class = SIZE_TINY
volume = 60
reagent_desc_override = TRUE //it has a special examining mechanic
+ ground_offset_x = 7
+ ground_offset_y = 7
var/identificable = TRUE //can medically trained people tell what's in it?
var/pill_desc = "An unknown pill." // The real description of the pill, shown when examined by a medically trained person
var/pill_icon_class = "random" // Pills with the same icon class share icons
diff --git a/code/game/objects/items/reagent_containers/reagent_container.dm b/code/game/objects/items/reagent_containers/reagent_container.dm
index eddbf5197a9e..e0561d5a7e3d 100644
--- a/code/game/objects/items/reagent_containers/reagent_container.dm
+++ b/code/game/objects/items/reagent_containers/reagent_container.dm
@@ -14,6 +14,8 @@
var/transparent = FALSE //can we see what's in it?
var/reagent_desc_override = FALSE //does it have a special examining mechanic that should override the normal /reagent_containers examine proc?
actions_types = list(/datum/action/item_action/reagent_container/set_transfer_amount)
+ ground_offset_x = 7
+ ground_offset_y = 7
/obj/item/reagent_container/Initialize()
if(!possible_transfer_amounts)
diff --git a/code/game/objects/items/stacks/cable_coil.dm b/code/game/objects/items/stacks/cable_coil.dm
index 9135c793cd00..e846979c00b4 100644
--- a/code/game/objects/items/stacks/cable_coil.dm
+++ b/code/game/objects/items/stacks/cable_coil.dm
@@ -20,14 +20,14 @@
attack_verb = list("whipped", "lashed", "disciplined", "flogged")
stack_id = "cable coil"
attack_speed = 3
+ ground_offset_x = 2
+ ground_offset_y = 2
/obj/item/stack/cable_coil/Initialize(mapload, length = MAXCOIL, param_color = null)
. = ..()
src.amount = length
if (param_color) // It should be red by default, so only recolor it if parameter was specified.
color = param_color
- pixel_x = rand(-2,2)
- pixel_y = rand(-2,2)
updateicon()
update_wclass()
@@ -276,8 +276,6 @@
/obj/item/stack/cable_coil/cut/Initialize()
. = ..()
src.amount = rand(1,2)
- pixel_x = rand(-2,2)
- pixel_y = rand(-2,2)
updateicon()
update_wclass()
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 32e9a030462e..754a36c6012a 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -40,7 +40,7 @@
H.pain.recalculate_pain()
H.updatehealth()
use(1)
- var/others_msg = "\The [user] applies some nanite paste at[user != M ? " \the [M]'s" : " \the"] [S.display_name] with \the [src]." // Needs to create vars for these messages because macro doesn't work otherwise
+ var/others_msg = "\The [user] applies some nanite paste at[user != M ? " \the [M]'s" : " the"] [S.display_name] with \the [src]." // Needs to create vars for these messages because macro doesn't work otherwise
var/user_msg = "You apply some nanite paste at [user == M ? "your" : "[M]'s"] [S.display_name]."
user.visible_message(SPAN_NOTICE("[others_msg]"),\
SPAN_NOTICE("[user_msg]"))
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index f6a8d02c3e9d..07345dcdc09f 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -69,6 +69,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
sheettype = "metal"
stack_id = "metal"
+
/obj/item/stack/sheet/metal/small_stack
amount = STACK_10
@@ -114,6 +115,8 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list ( \
amount_sprites = TRUE
sheettype = "plasteel"
stack_id = "plasteel"
+ ground_offset_x = 4
+ ground_offset_y = 5
/obj/item/stack/sheet/plasteel/New(loc, amount=null)
recipes = plasteel_recipes
diff --git a/code/game/objects/items/storage/large_holster.dm b/code/game/objects/items/storage/large_holster.dm
index ef2bcfb7216a..b4a6c3a8c1af 100644
--- a/code/game/objects/items/storage/large_holster.dm
+++ b/code/game/objects/items/storage/large_holster.dm
@@ -326,7 +326,7 @@
/obj/item/storage/large_holster/fuelpack/get_examine_text(mob/user)
. = ..()
if(contents.len)
- . += "It is storing \a M240-T incinerator unit."
+ . += "It is storing a M240-T incinerator unit."
if (get_dist(user, src) <= 1)
if(fuel)
. += "The [fuel.caliber] currently contains: [round(fuel.get_ammo_percent())]% fuel."
diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm
index f24c0c3f3131..48eb322f2093 100644
--- a/code/game/objects/items/storage/pouch.dm
+++ b/code/game/objects/items/storage/pouch.dm
@@ -168,7 +168,7 @@
name = "synth survival pouch"
desc = "An emergency pouch given to synthetics in the event of an emergency."
icon_state = "tools"
- storage_slots = 7
+ storage_slots = 6
max_w_class = SIZE_MEDIUM
can_hold = list(
/obj/item/device/flashlight,
@@ -181,7 +181,6 @@
)
/obj/item/storage/pouch/survival/synth/full/fill_preset_inventory()
- new /obj/item/device/flashlight(src)
new /obj/item/tool/crowbar/red(src)
new /obj/item/tool/weldingtool(src)
new /obj/item/stack/cable_coil(src)
diff --git a/code/game/objects/structures/barricade/barricade.dm b/code/game/objects/structures/barricade/barricade.dm
index 0ca2ccb1ddbc..5a72ec33ea2a 100644
--- a/code/game/objects/structures/barricade/barricade.dm
+++ b/code/game/objects/structures/barricade/barricade.dm
@@ -78,7 +78,7 @@
switch(dir)
if(SOUTH)
layer = ABOVE_MOB_LAYER
- else if(NORTH)
+ if(NORTH)
layer = initial(layer) - 0.01
else
layer = initial(layer)
diff --git a/code/game/objects/structures/barricade/handrail.dm b/code/game/objects/structures/barricade/handrail.dm
index ea10dc7256de..ae166dbbf985 100644
--- a/code/game/objects/structures/barricade/handrail.dm
+++ b/code/game/objects/structures/barricade/handrail.dm
@@ -24,7 +24,7 @@
switch(dir)
if(SOUTH)
layer = ABOVE_MOB_LAYER
- else if(NORTH)
+ if(NORTH)
layer = initial(layer) - 0.01
else
layer = initial(layer)
diff --git a/code/game/objects/structures/bookcase.dm b/code/game/objects/structures/bookcase.dm
index c71b2853ea07..becb0906e3c6 100644
--- a/code/game/objects/structures/bookcase.dm
+++ b/code/game/objects/structures/bookcase.dm
@@ -58,8 +58,6 @@
contents_explosion(severity)
deconstruct(FALSE)
return
- else
- return
/obj/structure/bookcase/update_icon()
if(contents.len < 5)
diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
index 7848aaba4897..b000fd5733a2 100644
--- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm
@@ -51,8 +51,6 @@
new /obj/item/clothing/mask/gas(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/storage/firstaid/o2(src)
- if ("nothing")
- // doot
// teehee - Ah, tg coders...
if ("delete")
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 7c9faaf1a027..9f0417ccb372 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -130,8 +130,6 @@
contents_explosion(severity)
deconstruct(FALSE)
return
- else
- return
/obj/structure/closet/crate/alpha
name = "alpha squad crate"
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index 38201e052c50..d2b3d36b5920 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -43,8 +43,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/structure/lattice/attackby(obj/item/C as obj, mob/user as mob)
diff --git a/code/game/objects/structures/reagent_dispensers.dm b/code/game/objects/structures/reagent_dispensers.dm
index 7dc6d883a2d5..6471dfa21520 100644
--- a/code/game/objects/structures/reagent_dispensers.dm
+++ b/code/game/objects/structures/reagent_dispensers.dm
@@ -119,8 +119,6 @@
if(EXPLOSION_THRESHOLD_MEDIUM to INFINITY)
deconstruct(FALSE)
return
- else
- return
/obj/structure/reagent_dispensers/attack_hand()
if(!reagents || reagents.locked)
diff --git a/code/game/objects/structures/surface.dm b/code/game/objects/structures/surface.dm
index 3a2dbd3e8d5c..efc69002424f 100644
--- a/code/game/objects/structures/surface.dm
+++ b/code/game/objects/structures/surface.dm
@@ -61,8 +61,7 @@
draw_item_overlays()
/obj/structure/surface/proc/detach_item(obj/item/O)
- O.pixel_x = initial(O.pixel_x)
- O.pixel_y = initial(O.pixel_y)
+ O.scatter_item()
UnregisterSignal(O, COMSIG_ATOM_DECORATED)
draw_item_overlays()
return
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index 53ce9ef177fa..e8f40c1d52b3 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -1251,7 +1251,7 @@ var/datum/controller/supply/supply_controller = new()
/datum/controller/supply/proc/black_market_investigation()
black_market_heat = -1
- SSticker.mode.get_specific_call("Inspection - Colonial Marshal Ledger Investigation Team", TRUE, TRUE, FALSE)
+ SSticker.mode.get_specific_call("Inspection - Colonial Marshal Ledger Investigation Team", TRUE, TRUE)
log_game("Black Market Inspection auto-triggered.")
/obj/structure/machinery/computer/supplycomp/proc/is_buyable(datum/supply_packs/supply_pack)
diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm
index 22979858ce62..1b4091eb2aab 100644
--- a/code/game/turfs/walls/wall_types.dm
+++ b/code/game/turfs/walls/wall_types.dm
@@ -24,8 +24,8 @@
/obj/structure/girder,
/obj/structure/machinery/door,
/obj/structure/machinery/cm_vending/sorted/attachments/blend,
- /obj/structure/machinery/cm_vending/sorted/cargo_ammo/blend,
- /obj/structure/machinery/cm_vending/sorted/cargo_guns/blend,
+ /obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/blend,
+ /obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/blend,
)
/turf/closed/wall/almayer/update_icon()
diff --git a/code/game/verbs/records.dm b/code/game/verbs/records.dm
index f09de72da2e6..18ed35ee6321 100644
--- a/code/game/verbs/records.dm
+++ b/code/game/verbs/records.dm
@@ -143,7 +143,7 @@
dat += ""
var/color = "#008800"
- var/add_dat = "Add Admin Note
Add Confidential Admin Note
"
+ var/add_dat = "Add Admin Note
Add Confidential Admin Note
"
switch(note_category)
if(NOTE_MERIT)
color = "#9e3dff"
diff --git a/code/modules/admin/tabs/event_tab.dm b/code/modules/admin/tabs/event_tab.dm
index 2bd20b14ab56..8bcd15cb04a9 100644
--- a/code/modules/admin/tabs/event_tab.dm
+++ b/code/modules/admin/tabs/event_tab.dm
@@ -218,14 +218,17 @@
if(!istype(chosen_ert))
return
- var/quiet_launch = tgui_alert(usr, "Would you like to announce the distress beacon to the server population? This will reveal the distress beacon to all players.", "Announce distress beacon?", list("Yes", "No"), 20 SECONDS)
- if(!quiet_launch)
- qdel(chosen_ert)
- return
- if(quiet_launch == "No")
- quiet_launch = TRUE
- if (quiet_launch == "Yes")
- quiet_launch = FALSE
+ var/launch_broadcast = tgui_alert(usr, "Would you like to broadcast the beacon launch? This will reveal the distress beacon to all players.", "Announce distress beacon?", list("Yes", "No"), 20 SECONDS)
+ if(launch_broadcast == "Yes")
+ launch_broadcast = TRUE
+ else
+ launch_broadcast = FALSE
+
+ var/announce_receipt = tgui_alert(usr, "Would you like to announce the beacon received message? This will reveal the distress beacon to all players.", "Announce beacon received?", list("Yes", "No"), 20 SECONDS)
+ if(announce_receipt == "Yes")
+ announce_receipt = TRUE
+ else
+ announce_receipt = FALSE
var/turf/override_spawn_loc
var/prompt = tgui_alert(usr, "Spawn at their assigned spawn, or at your location?", "Spawnpoint Selection", list("Spawn", "Current Location"), 0)
@@ -235,7 +238,7 @@
if(prompt == "Current Location")
override_spawn_loc = get_turf(usr)
- chosen_ert.activate(quiet_launch = quiet_launch, announce = !quiet_launch, override_spawn_loc = override_spawn_loc)
+ chosen_ert.activate(quiet_launch = launch_broadcast, announce_incoming = announce_receipt, override_spawn_loc = override_spawn_loc)
message_admins("[key_name_admin(usr)] admin-called a [choice == "Randomize" ? "randomized ":""]distress beacon: [chosen_ert.name]")
@@ -931,13 +934,8 @@
message_admins("[key_name(usr)] has fired \an [warhead.name] at ([target.x],[target.y],[target.z]).")
warhead.warhead_impact(target)
- if(istype(warhead, /obj/structure/ob_ammo/warhead/cluster))
- // so the user's screen can shake for the duration of the cluster, otherwise we get a runtime.
- QDEL_IN(warhead, OB_CLUSTER_DURATION)
- else
- QDEL_IN(warhead, OB_CRASHING_DOWN)
else
- warhead.loc = target
+ warhead.forceMove(target)
/client/proc/change_taskbar_icon()
set name = "Set Taskbar Icon"
diff --git a/code/modules/admin/topic/topic.dm b/code/modules/admin/topic/topic.dm
index 8bbc99925239..f78b6a844d4b 100644
--- a/code/modules/admin/topic/topic.dm
+++ b/code/modules/admin/topic/topic.dm
@@ -336,86 +336,6 @@
/////////////////////////////////////new ban stuff
- else if(href_list["jobban2"])
-// if(!check_rights(R_BAN)) return
- /*
- var/mob/M = locate(href_list["jobban2"])
- if(!ismob(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- if(!M.ckey) //sanity
- to_chat(usr, "This mob has no ckey")
- return
- if(!RoleAuthority)
- to_chat(usr, "The Role Authority is not set up!")
- return
-
- var/datum/entity/player/P = get_player_from_key(M.ckey)
-
- var/dat = ""
- var/body
- var/jobs = ""
-
- /***********************************WARNING!************************************
- The jobban stuff looks mangled and disgusting
- But it looks beautiful in-game
- -Nodrak
- ************************************WARNING!***********************************/
-//Regular jobs
- //Command (Blue)
- jobs += generate_job_ban_list(M, ROLES_CIC, "CIC", "ddddff")
- jobs += "
"
- // SUPPORT
- jobs += generate_job_ban_list(M, ROLES_AUXIL_SUPPORT, "Support", "ccccff")
- jobs += "
"
- // MPs
- jobs += generate_job_ban_list(M, ROLES_POLICE, "Police", "ffdddd")
- jobs += "
"
- //Engineering (Yellow)
- jobs += generate_job_ban_list(M, ROLES_ENGINEERING, "Engineering", "fff5cc")
- jobs += "
"
- //Cargo (Yellow) //Copy paste, yada, yada. Hopefully Snail can rework this in the future.
- jobs += generate_job_ban_list(M, ROLES_REQUISITION, "Requisition", "fff5cc")
- jobs += "
"
- //Medical (White)
- jobs += generate_job_ban_list(M, ROLES_MEDICAL, "Medical", "ffeef0")
- jobs += "
"
- //Marines
- jobs += generate_job_ban_list(M, ROLES_MARINES, "Marines", "ffeeee")
- jobs += "
"
- // MISC
- jobs += generate_job_ban_list(M, ROLES_MISC, "Misc", "aaee55")
- jobs += "
"
- // Xenos (Orange)
- jobs += generate_job_ban_list(M, ROLES_XENO, "Xenos", "a268b1")
- jobs += "
"
- //Extra (Orange)
- var/isbanned_dept = jobban_isbanned(M, "Syndicate", P)
- jobs += ""
- jobs += "Extras |
---|
"
-
- //ERT
- if(jobban_isbanned(M, "Emergency Response Team", P) || isbanned_dept)
- jobs += "Emergency Response Team | "
- else
- jobs += "Emergency Response Team | "
-
- //Survivor
- if(jobban_isbanned(M, "Survivor", P) || isbanned_dept)
- jobs += "Survivor | "
- else
- jobs += "Survivor | "
-
- if(jobban_isbanned(M, "Agent", P) || isbanned_dept)
- jobs += "Agent | "
- else
- jobs += "Agent | "
-
- body = "[jobs]"
- dat = "[body]"
- show_browser(usr, dat, "Job-Ban Panel: [M.name]", "jobban2", "size=800x490")
- return*/ // DEPRECATED
//JOBBAN'S INNARDS
else if(href_list["jobban3"])
if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return
@@ -697,7 +617,6 @@
to_world(SPAN_NOTICE("The mode is now: [GLOB.master_mode]!"))
Game() // updates the main game menu
SSticker.save_mode(GLOB.master_mode)
- .(href, list("c_mode"=1))
else if(href_list["f_secret2"])
@@ -2098,7 +2017,7 @@
if(distress_cancel)
return
distress_cancel = TRUE
- SSticker.mode.get_specific_call("[ert_called]", TRUE, FALSE, FALSE)
+ SSticker.mode.get_specific_call("[ert_called]", TRUE, FALSE)
log_game("[key_name_admin(approver)] has sent [ert_called], requested by [key_name_admin(ref_person)]")
message_admins("[key_name_admin(approver)] has sent [ert_called], requested by [key_name_admin(ref_person)]")
diff --git a/code/modules/admin/topic/topic_events.dm b/code/modules/admin/topic/topic_events.dm
index 45d826668d4b..c38f715d93bf 100644
--- a/code/modules/admin/topic/topic_events.dm
+++ b/code/modules/admin/topic/topic_events.dm
@@ -206,7 +206,19 @@
em_call.players_to_offer = humans
em_call.owner = owner
- em_call.activate(announce = FALSE)
+ var/launch_broadcast = tgui_alert(usr, "Would you like to broadcast the beacon launch? This will reveal the distress beacon to all players.", "Announce distress beacon?", list("Yes", "No"), 20 SECONDS)
+ if(launch_broadcast == "Yes")
+ launch_broadcast = TRUE
+ else
+ launch_broadcast = FALSE
+
+ var/announce_receipt = tgui_alert(usr, "Would you like to announce the beacon received message? This will reveal the distress beacon to all players.", "Announce beacon received?", list("Yes", "No"), 20 SECONDS)
+ if(announce_receipt == "Yes")
+ announce_receipt = TRUE
+ else
+ announce_receipt = FALSE
+
+ em_call.activate(launch_broadcast, announce_receipt)
message_admins("[key_name_admin(usr)] created [humans_to_spawn] humans as [job_name] at [get_area(initial_spot)]")
@@ -284,7 +296,19 @@
em_call.players_to_offer = xenos
em_call.owner = owner
- em_call.activate(announce = FALSE)
+ var/launch_broadcast = tgui_alert(usr, "Would you like to broadcast the beacon launch? This will reveal the distress beacon to all players.", "Announce distress beacon?", list("Yes", "No"), 20 SECONDS)
+ if(launch_broadcast == "Yes")
+ launch_broadcast = TRUE
+ else
+ launch_broadcast = FALSE
+
+ var/announce_receipt = tgui_alert(usr, "Would you like to announce the beacon received message? This will reveal the distress beacon to all players.", "Announce beacon received?", list("Yes", "No"), 20 SECONDS)
+ if(announce_receipt == "Yes")
+ announce_receipt = TRUE
+ else
+ announce_receipt = FALSE
+
+ em_call.activate(launch_broadcast, announce_receipt)
message_admins("[key_name_admin(usr)] created [xenos_to_spawn] xenos as [xeno_caste] at [get_area(initial_spot)]")
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index d5d44a047947..d1e7f83dacb1 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -321,7 +321,7 @@
I = icon(icon_file, icon_state, SOUTH)
var/c = initial(item.color)
if (!isnull(c) && c != "#FFFFFF")
- I.Blend(initial(c), ICON_MULTIPLY)
+ I.Blend(c, ICON_MULTIPLY)
else
if (ispath(k, /obj/effect/essentials_set))
var/obj/effect/essentials_set/es_set = new k()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 1da30d6e47e3..04b82628e3c6 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1414,11 +1414,8 @@ var/const/MAX_SAVE_SLOTS = 10
var/all_ok = TRUE
for(var/i=1, i<=length(new_xeno_prefix), i++)
var/ascii_char = text2ascii(new_xeno_prefix,i)
- switch(ascii_char)
- // A .. Z
- if(65 to 90) //Uppercase Letters will work
- else
- all_ok = FALSE //everything else - won't
+ if(ascii_char < 65 || ascii_char > 90)
+ all_ok = FALSE //everything else - won't
if(all_ok)
xeno_prefix = new_xeno_prefix
owner.load_xeno_name()
diff --git a/code/modules/clothing/glasses/night.dm b/code/modules/clothing/glasses/night.dm
index afb711c3ca15..2a3780832e2a 100644
--- a/code/modules/clothing/glasses/night.dm
+++ b/code/modules/clothing/glasses/night.dm
@@ -187,7 +187,7 @@
if(target)
var/obj/item/clothing/glasses/night/m56_goggles/G = target
G.set_far_sight(owner, !G.far_sight)
- to_chat(owner, SPAN_NOTICE("You [G.far_sight ? "enable" : "disable"] \the [src]'s far sight system."))
+ to_chat(owner, SPAN_NOTICE("You [G.far_sight ? "enable" : "disable"] \the [G]'s far sight system."))
/datum/action/item_action/m56_goggles/far_sight/update_button_icon()
if(!target)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index d969587e32e5..cc7fee7724f4 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -423,7 +423,7 @@
return
var/obj/item/weapon/gun/W = usr.get_active_hand()
if (W.w_class > SIZE_MEDIUM)
- to_chat(usr, SPAN_DANGER("This gun won't fit in \the belt!"))
+ to_chat(usr, SPAN_DANGER("This gun won't fit in the belt!"))
return
holstered = usr.get_active_hand()
usr.drop_held_item()
diff --git a/code/modules/clothing/suits/marine_armor.dm b/code/modules/clothing/suits/marine_armor.dm
index e375502f5435..94361c420d2b 100644
--- a/code/modules/clothing/suits/marine_armor.dm
+++ b/code/modules/clothing/suits/marine_armor.dm
@@ -1635,47 +1635,47 @@
//=======================================================================\\
/obj/item/clothing/suit/storage/marine/MP/provost
- name = "\improper M3 pattern Provost armor"
- desc = "A lighter Provost M3 Pattern Chestplate. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
- icon_state = "pvlight"
- item_state_slots = list(WEAR_JACKET = "pvlight")
- slowdown = SLOWDOWN_ARMOR_VERY_LIGHT
- flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE
- w_class = SIZE_MEDIUM
-
-/obj/item/clothing/suit/storage/marine/MP/provost/enforcer
name = "\improper M3 pattern Provost armor"
desc = "A standard Provost M3 Pattern Chestplate. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
icon_state = "pvmedium"
item_state_slots = list(WEAR_JACKET = "pvmedium")
- slowdown = SLOWDOWN_ARMOR_MEDIUM
- armor_melee = CLOTHING_ARMOR_MEDIUM
+ slowdown = SLOWDOWN_ARMOR_LIGHT
armor_bullet = CLOTHING_ARMOR_MEDIUM
armor_laser = CLOTHING_ARMOR_MEDIUMLOW
- armor_bomb = CLOTHING_ARMOR_MEDIUMLOW
- armor_bio = CLOTHING_ARMOR_MEDIUM
+ armor_bomb = CLOTHING_ARMOR_MEDIUMHIGH
+ armor_bio = CLOTHING_ARMOR_MEDIUMHIGH
armor_internaldamage = CLOTHING_ARMOR_MEDIUM
+ flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE
+ storage_slots = 3
/obj/item/clothing/suit/storage/marine/MP/provost/tml
name = "\improper M3 pattern Senior Provost armor"
+ desc = "A more refined Provost M3 Pattern Chestplate for senior officers. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
icon_state = "pvleader"
item_state_slots = list(WEAR_JACKET = "pvleader")
- desc = "A more refined Provost M3 Pattern Chestplate for senior officers. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
-
- slowdown = SLOWDOWN_ARMOR_MEDIUM
- armor_bullet = CLOTHING_ARMOR_MEDIUM
- armor_laser = CLOTHING_ARMOR_MEDIUMLOW
- armor_bio = CLOTHING_ARMOR_MEDIUMHIGH
- armor_internaldamage = CLOTHING_ARMOR_MEDIUMHIGH
/obj/item/clothing/suit/storage/marine/MP/provost/marshal
+ name = "\improper M5 pattern Provost Marshal armor"
+ desc = "A custom fit luxury armor suit for Provost Marshals. Useful for letting your men know who is in charge when taking to the field."
icon_state = "pvmarshal"
item_state_slots = list(WEAR_JACKET = "pvmarshal")
- name = "\improper M3 pattern Provost Marshal armor"
- desc = "A custom fit luxury armor suit for Provost Marshals. Useful for letting your men know who is in charge when taking to the field."
+ w_class = SIZE_MEDIUM
+ storage_slots = 4
+
+/obj/item/clothing/suit/storage/marine/MP/provost/light
+ name = "\improper M3 pattern Provost light armor"
+ desc = "A lighter Provost M3 Pattern Chestplate. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
+ icon_state = "pvlight"
+ item_state_slots = list(WEAR_JACKET = "pvlight")
+ slowdown = SLOWDOWN_ARMOR_VERY_LIGHT
-/obj/item/clothing/suit/storage/marine/MP/provost/marshal/chief
- name = "\improper M3 pattern Provost Chief Marshal armor"
+/obj/item/clothing/suit/storage/marine/MP/provost/light/flexi
+ name = "\improper M3 pattern Provost flexi-armor"
+ desc = "A flexible and easy to store M3 Pattern Chestplate. Protects the chest from ballistic rounds, bladed objects and accidents. It has a small leather pouch strapped to it for limited storage."
+ w_class = SIZE_MEDIUM
+ icon_state = "pvlight_2"
+ item_state_slots = list(WEAR_JACKET = "pvlight_2")
+ storage_slots = 2
//================//UNITED AMERICAS ALLIED COMMAND\\=====================\\
//=======================================================================\\
diff --git a/code/modules/clothing/suits/marine_coat.dm b/code/modules/clothing/suits/marine_coat.dm
index d6781147a092..73d7e0981859 100644
--- a/code/modules/clothing/suits/marine_coat.dm
+++ b/code/modules/clothing/suits/marine_coat.dm
@@ -235,31 +235,23 @@
//=========================//PROVOST\\================================\\
//=======================================================================\\
+
/obj/item/clothing/suit/storage/jacket/marine/provost
- name = "\improper Provost Coat"
- desc = "The crisp coat of a Provost Officer."
+ name = "\improper Provost Jacket"
+ desc = "A crisp jacket with the Provost sigil."
+ icon_state = "provost_jacket"
flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE
- icon_state = "provost_coat"
valid_accessory_slots = list(ACCESSORY_SLOT_ARMBAND, ACCESSORY_SLOT_RANK, ACCESSORY_SLOT_DECOR)
-/obj/item/clothing/suit/storage/jacket/marine/provost/advisor
- name = "\improper Provost Advisor Jacket"
- desc = "The crisp jacket of a Provost Advisor."
- icon_state = "provost_jacket"
-
-/obj/item/clothing/suit/storage/jacket/marine/provost/inspector
- name = "\improper Provost Inspector Jacket"
- desc = "The crisp jacket of a Provost Inspector."
- icon_state = "provost_jacket"
+/obj/item/clothing/suit/storage/jacket/marine/provost/coat
+ name = "\improper Provost Coat"
+ desc = "The crisp coat of a Provost Officer."
+ icon_state = "provost_coat"
-/obj/item/clothing/suit/storage/jacket/marine/provost/marshal
- name = "\improper Provost Marshal Jacket"
- desc = "The crisp jacket of a Provost Marshal."
- icon_state = "provost_jacket"
+/obj/item/clothing/suit/storage/jacket/marine/provost/coat/marshal
+ name = "\improper Provost Marshal Coat"
+ icon_state = "provost_coat_marshal"
-/obj/item/clothing/suit/storage/jacket/marine/provost/marshal/chief
- name = "\improper Provost Chief Marshal Jacket"
- desc = "The crisp jacket of the Provost Chief Marshal."
//=========================//DRESS BLUES\\================================\\
//=======================================================================\\
diff --git a/code/modules/clothing/under/marine_uniform.dm b/code/modules/clothing/under/marine_uniform.dm
index d9d8d7da45b7..59cc02b12577 100644
--- a/code/modules/clothing/under/marine_uniform.dm
+++ b/code/modules/clothing/under/marine_uniform.dm
@@ -374,41 +374,17 @@
min_cold_protection_temperature = ICE_PLANET_MIN_COLD_PROT
-/obj/item/clothing/under/marine/mp/provost/enforcer
- name = "\improper Provost Enforcer Uniform"
- desc = "The crisp uniform of a Provost Enforcer."
-
-/obj/item/clothing/under/marine/mp/provost/tml
- name = "\improper Provost Team Leader Uniform"
- desc = "The crisp uniform of a Provost Team Leader."
- icon_state = "warden_jumpsuit"
- worn_state = "warden_jumpsuit"
-
-/obj/item/clothing/under/marine/mp/provost/advisor
- name = "\improper Provost Advisor Uniform"
- desc = "The crisp uniform of a Provost Advisor."
- icon_state = "warden_jumpsuit"
- worn_state = "warden_jumpsuit"
-
-/obj/item/clothing/under/marine/mp/provost/inspector
- name = "\improper Provost Inspector Uniform"
- desc = "The crisp uniform of a Provost Inspector."
- icon_state = "warden_jumpsuit"
- worn_state = "warden_jumpsuit"
+/obj/item/clothing/under/marine/mp/provost/senior
+ name = "\improper Provost Senior Uniform"
+ desc = "The crisp uniform of a senior member of the Provost Office."
+ icon_state = "provost_tml"
+ worn_state = "provost_tml"
/obj/item/clothing/under/marine/mp/provost/marshal
name = "\improper Provost Marshal Uniform"
desc = "The crisp uniform of a Provost Marshal."
- icon_state = "WO_jumpsuit"
- worn_state = "WO_jumpsuit"
-
-/obj/item/clothing/under/marine/mp/provost/marshal/sector
- name = "\improper Provost Sector Marshal Uniform"
- desc = "The crisp uniform of a Provost Sector Marshal."
-
-/obj/item/clothing/under/marine/mp/provost/marshal/chief
- name = "\improper Provost Chief Marshal Uniform"
- desc = "The crisp uniform of the Provost Chief Marshal."
+ icon_state = "provost_marshal"
+ worn_state = "provost_marshal"
//==================//UNITED AMERICAS ALLIED COMMAND\\===================\\
//=======================================================================\\
diff --git a/code/modules/cm_marines/Donator_Items.dm b/code/modules/cm_marines/Donator_Items.dm
index 1c7281114c01..bcebad4661b0 100644
--- a/code/modules/cm_marines/Donator_Items.dm
+++ b/code/modules/cm_marines/Donator_Items.dm
@@ -126,6 +126,9 @@
/obj/item/storage/backpack/marine/fluff
xeno_types = null
+/obj/item/storage/backpack/marine/satchel/fluff
+ xeno_types = null
+
/obj/item/clothing/gloves/marine/fluff //MARINE GLOVES TEMPLATE
name = "ITEM NAME"
desc = "ITEM DESCRIPTION. DONOR ITEM" //Add UNIQUE if Unique
@@ -211,10 +214,10 @@
item_state = "armor_reflec"
/obj/item/clothing/suit/storage/marine/fluff/sas_juggernaut //CKEY=sasoperative (UNIQUE)
- name = "Juggernaut Armor"
+ name = "juggernaut armor"
desc = "Some fancy looking armor. DONOR ITEM"
- icon_state = "rig-syndi"
- item_state = "syndie_hardsuit"
+ icon_state = "skinnerarmor"
+ item_state = "skinnerarmor"
/obj/item/clothing/suit/storage/marine/fluff/penguin //CKEY=tophatpenguin
name = "Trenchcoat"
@@ -589,8 +592,8 @@
flags_inv_hide = HIDEEARS|HIDEALLHAIR
/obj/item/clothing/head/helmet/marine/fluff/sas_juggernaut //CKEY=sasoperative (UNIQUE)
- name = "Juggernaut Helmet"
- icon_state = "rig0-syndi"
+ name = "juggernaut helmet"
+ icon_state = "skinnerhelmet"
desc = "A red helmet, for pairing with JuggerNaut Armor. DONOR ITEM"
/obj/item/clothing/head/helmet/marine/fluff/tristan //CKEY=tristan63
@@ -613,13 +616,6 @@
flags_inventory = BLOCKSHARPOBJ
flags_inv_hide = HIDEEARS|HIDEMASK|HIDEEYES|HIDEALLHAIR
-/obj/item/clothing/head/helmet/marine/fluff/sas_juggernaut_alt //CKEY=sasoperative (UNIQUE)
- name = "Juggernaut Helmet"
- icon_state = "ncrhelmet"
- desc = "A red helmet, for pairing with JuggerNaut Armor. DONOR ITEM"
- flags_inventory = BLOCKSHARPOBJ
- flags_inv_hide = HIDEEARS|HIDEMASK|HIDEEYES|HIDEALLHAIR
-
/obj/item/clothing/head/helmet/marine/fluff/sadokist //CKEY=sadokist
name = "Tanya's Beret"
desc = "A bright red beret, owned by Tanya Edenia."
@@ -1366,6 +1362,12 @@
icon_state = "securitypack"
item_state = "securitypack"
+/obj/item/storage/backpack/marine/satchel/fluff/sas_juggernaut //CKEY=sasoperative (UNIQUE)
+ name = "tactical radiopack"
+ desc = "A Radio backpack for use with the Juggernaut armor. DONOR ITEM"
+ icon_state = "skinnerpack"
+ item_state = "skinnerpack"
+
/obj/item/clothing/glasses/fluff/alexwarhammer
name = "Black Jack's Dank Shades"
desc = "+20 Badass points. Donor item"
diff --git a/code/modules/cm_marines/Donator_Kits.dm b/code/modules/cm_marines/Donator_Kits.dm
index 6c8347f3280e..01acf638c2cd 100644
--- a/code/modules/cm_marines/Donator_Kits.dm
+++ b/code/modules/cm_marines/Donator_Kits.dm
@@ -427,7 +427,7 @@
donor_key = "sasoperative"
kit_variant = "Juggernaut"
donor_gear = list(
- /obj/item/clothing/head/helmet/marine/fluff/sas_juggernaut_alt,
+ /obj/item/storage/backpack/marine/satchel/fluff/sas_juggernaut,
/obj/item/clothing/head/helmet/marine/fluff/sas_juggernaut,
/obj/item/clothing/suit/storage/marine/fluff/sas_juggernaut,
)
diff --git a/code/modules/cm_marines/equipment/guncases.dm b/code/modules/cm_marines/equipment/guncases.dm
index 507d6140666d..ddf010547ba4 100644
--- a/code/modules/cm_marines/equipment/guncases.dm
+++ b/code/modules/cm_marines/equipment/guncases.dm
@@ -9,6 +9,7 @@
can_hold = list()//define on a per case basis for the original firearm.
foldable = TRUE
foldable = /obj/item/stack/sheet/mineral/plastic//it makes sense
+ ground_offset_y = 5
/obj/item/storage/box/guncase/update_icon()
if(LAZYLEN(contents))
diff --git a/code/modules/cm_marines/equipment/kit_boxes.dm b/code/modules/cm_marines/equipment/kit_boxes.dm
index 43cf733adb75..4a7864dbe0f5 100644
--- a/code/modules/cm_marines/equipment/kit_boxes.dm
+++ b/code/modules/cm_marines/equipment/kit_boxes.dm
@@ -274,12 +274,12 @@
slowdown = 1
can_hold = list() //Nada. Once you take the stuff out it doesn't fit back in.
foldable = TRUE
+ ground_offset_x = 5
+ ground_offset_y = 5
var/pro_case_overlay
/obj/item/storage/box/kit/Initialize()
. = ..()
- pixel_x = rand(-5, 5)
- pixel_y = rand(-5, 5)
if(pro_case_overlay)
overlays += image('icons/obj/items/storage.dmi', "+[pro_case_overlay]")
diff --git a/code/modules/cm_marines/equipment/mortar/mortar_shells.dm b/code/modules/cm_marines/equipment/mortar/mortar_shells.dm
index 7fd05322f1c7..45b3a6859d4a 100644
--- a/code/modules/cm_marines/equipment/mortar/mortar_shells.dm
+++ b/code/modules/cm_marines/equipment/mortar/mortar_shells.dm
@@ -6,11 +6,9 @@
w_class = SIZE_HUGE
flags_atom = FPRINT|CONDUCT
var/datum/cause_data/cause_data
+ ground_offset_x = 7
+ ground_offset_y = 6
-/obj/item/mortar_shell/Initialize(mapload, ...)
- . = ..()
- pixel_y = rand(-6, 6)
- pixel_x = rand(-7, 7)
/obj/item/mortar_shell/Destroy()
. = ..()
diff --git a/code/modules/cm_marines/orbital_cannon.dm b/code/modules/cm_marines/orbital_cannon.dm
index 8d80f80860f3..1d49c42f5e0d 100644
--- a/code/modules/cm_marines/orbital_cannon.dm
+++ b/code/modules/cm_marines/orbital_cannon.dm
@@ -217,15 +217,16 @@ var/list/ob_type_fuel_requirements
if(user)
tray.warhead.source_mob = user
- tray.warhead.warhead_impact(target)
+ var/obj/structure/ob_ammo/warhead/warhead = tray.warhead
+ tray.warhead = null
+ warhead.moveToNullspace()
+ warhead.warhead_impact(target)
sleep(OB_CRASHING_DOWN)
ob_cannon_busy = FALSE
-
chambered_tray = FALSE
tray.fuel_amt = 0
- QDEL_NULL(tray.warhead)
tray.update_icon()
update_icon()
@@ -357,6 +358,9 @@ var/list/ob_type_fuel_requirements
var/max_shake_factor
var/max_knockdown_time
+ // Note that the warhead should be cleared of location by the firing proc,
+ // then auto-delete at the end of the warhead_impact implementation
+
/obj/structure/ob_ammo/warhead/proc/warhead_impact(turf/target)
// make damn sure everyone hears it
playsound(target, 'sound/weapons/gun_orbital_travel.ogg', 100, 1, 75)
@@ -366,7 +370,7 @@ var/list/ob_type_fuel_requirements
message_admins(FONT_SIZE_XL("CLICK TO CANCEL THIS OB"))
var/relative_dir
- for(var/mob/M in range(30, target))
+ for(var/mob/M in urange(30, target))
if(get_turf(M) == target)
relative_dir = 0
else
@@ -377,7 +381,7 @@ var/list/ob_type_fuel_requirements
)
sleep(OB_TRAVEL_TIMING/3)
- for(var/mob/M in range(25, target))
+ for(var/mob/M in urange(25, target))
if(get_turf(M) == target)
relative_dir = 0
else
@@ -388,7 +392,7 @@ var/list/ob_type_fuel_requirements
)
sleep(OB_TRAVEL_TIMING/3)
- for(var/mob/M in range(15, target))
+ for(var/mob/M in urange(15, target))
M.show_message( \
SPAN_HIGHDANGER("OH GOD THE SKY WILL EXPLODE!!!"), SHOW_MESSAGE_VISIBLE, \
SPAN_HIGHDANGER("YOU SHOULDN'T BE HERE!"), SHOW_MESSAGE_AUDIBLE \
@@ -455,6 +459,7 @@ var/list/ob_type_fuel_requirements
handle_ob_shake(target)
sleep(double_explosion_delay)
cell_explosion(target, standard_power, standard_falloff, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data)
+ qdel(src)
return
// Checks turf around the target
@@ -464,8 +469,11 @@ var/list/ob_type_fuel_requirements
handle_ob_shake(target)
sleep(double_explosion_delay)
cell_explosion(target, standard_power, standard_falloff, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data)
+ qdel(src)
return
+ qdel(src)
+
/obj/structure/ob_ammo/warhead/incendiary
name = "\improper Incendiary orbital warhead"
warhead_kind = "incendiary"
@@ -497,6 +505,7 @@ var/list/ob_type_fuel_requirements
sleep(clear_delay)
fire_spread(target, cause_data, distance, fire_level, burn_level, fire_color, fire_type, TURF_PROTECTION_OB)
+ qdel(src)
/obj/structure/ob_ammo/warhead/cluster
name = "\improper Cluster orbital warhead"
@@ -529,12 +538,16 @@ var/list/ob_type_fuel_requirements
for(var/i = 1 to total_amount)
for(var/k = 1 to instant_amount)
- var/turf/U = pick(turf_list)
- if(protected_by_pylon(TURF_PROTECTION_OB, U)) //If the turf somehow gained OB protection while the cluster was firing
+ var/turf/selected_turf = pick(turf_list)
+ if(protected_by_pylon(TURF_PROTECTION_OB, selected_turf))
continue
- fire_in_a_hole(U)
+ var/area/selected_area = get_area(selected_turf)
+ if(CEILING_IS_PROTECTED(selected_area?.ceiling, CEILING_PROTECTION_TIER_4))
+ continue
+ fire_in_a_hole(selected_turf)
sleep(delay_between_clusters)
+ QDEL_IN(src, 5 SECONDS) // Leave time for last handle_ob_shake below
/obj/structure/ob_ammo/warhead/cluster/proc/fire_in_a_hole(turf/loc)
new /obj/effect/overlay/temp/blinking_laser (loc)
@@ -546,8 +559,8 @@ var/list/ob_type_fuel_requirements
icon_state = "ob_fuel"
is_solid_fuel = 1
-/obj/structure/ob_ammo/ob_fuel/New()
- ..()
+/obj/structure/ob_ammo/ob_fuel/Initialize()
+ . = ..()
pixel_x = rand(-5,5)
pixel_y = rand(-5,5)
diff --git a/code/modules/cm_tech/techs/marine/tier3/cryo_spec.dm b/code/modules/cm_tech/techs/marine/tier3/cryo_spec.dm
index d6c849e883af..16f0f26576a3 100644
--- a/code/modules/cm_tech/techs/marine/tier3/cryo_spec.dm
+++ b/code/modules/cm_tech/techs/marine/tier3/cryo_spec.dm
@@ -21,4 +21,4 @@
/datum/tech/cryomarine/on_unlock()
. = ..()
- SSticker.mode.get_specific_call("Marine Cryo Reinforcement (Spec)", TRUE, FALSE, FALSE, announce_dispatch_message = FALSE)
+ SSticker.mode.get_specific_call("Marine Cryo Reinforcement (Spec)", TRUE, FALSE)
diff --git a/code/modules/cm_tech/techs/marine/tier3/cryorine.dm b/code/modules/cm_tech/techs/marine/tier3/cryorine.dm
index 575ffe67b85b..49b4eea8f525 100644
--- a/code/modules/cm_tech/techs/marine/tier3/cryorine.dm
+++ b/code/modules/cm_tech/techs/marine/tier3/cryorine.dm
@@ -23,4 +23,4 @@
/datum/tech/repeatable/cryomarine/on_unlock()
. = ..()
- SSticker.mode.get_specific_call("Marine Cryo Reinforcements (Tech)", TRUE, FALSE, FALSE, announce_dispatch_message = FALSE)
+ SSticker.mode.get_specific_call("Marine Cryo Reinforcements (Tech)", TRUE, FALSE)
diff --git a/code/modules/desert_dam/filtration/consoles.dm b/code/modules/desert_dam/filtration/consoles.dm
index 038b96eb4713..8c2814fafde7 100644
--- a/code/modules/desert_dam/filtration/consoles.dm
+++ b/code/modules/desert_dam/filtration/consoles.dm
@@ -35,8 +35,6 @@ var/global/river_activated = FALSE
if (prob(10))
get_broken()
return
- else
- return
/obj/structure/machinery/filtration/console/proc/get_broken()
if(damaged)
diff --git a/code/modules/flufftext/Chinese.dm b/code/modules/flufftext/Chinese.dm
index 36da1d307a5b..6b19dd61fcf5 100644
--- a/code/modules/flufftext/Chinese.dm
+++ b/code/modules/flufftext/Chinese.dm
@@ -62,12 +62,12 @@
//remove complex/simple -u- glide final_syllables
if(initial.initial_sound_flags & SIMPLE_U_ONLY)
for(var/datum/chinese_sound/final_syllable/final_syllable as anything in possible_final_syllables)
- if(initial(initial(final_syllable.vowel_class)) == VOWEL_CLASS_BACK_CLOSE)
+ if(initial(final_syllable.vowel_class) == VOWEL_CLASS_BACK_CLOSE)
possible_final_syllables -= final_syllable
possible_final_syllables += /datum/chinese_sound/final_syllable/u
else if(initial.initial_sound_flags & HALF_U)
for(var/datum/chinese_sound/final_syllable/final_syllable as anything in possible_final_syllables)
- if(initial(initial(final_syllable.vowel_class)) == VOWEL_CLASS_BACK_CLOSE && initial(final_syllable.final_syllable_sound_flags) & U_GROUP_FULL)
+ if(initial(final_syllable.vowel_class) == VOWEL_CLASS_BACK_CLOSE && initial(final_syllable.final_syllable_sound_flags) & U_GROUP_FULL)
possible_final_syllables -= final_syllable
//check for if the sound is alveolo-palatal or sibilant/retroflex - then remove or keep front close vowels accordingly
diff --git a/code/modules/gear_presets/uscm_event.dm b/code/modules/gear_presets/uscm_event.dm
index 8bd2468c78dc..5f7c40c016e0 100644
--- a/code/modules/gear_presets/uscm_event.dm
+++ b/code/modules/gear_presets/uscm_event.dm
@@ -206,11 +206,11 @@
back_item = /obj/item/storage/backpack/security
new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/provost(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/enforcer(new_human), WEAR_BODY)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost(new_human), WEAR_BODY)
new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
new_human.equip_to_slot_or_del(new /obj/item/storage/belt/security/MP/full(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost/enforcer(new_human), WEAR_JACKET)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost(new_human), WEAR_JACKET)
if(new_human.disabilities & NEARSIGHTED)
new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
else
@@ -248,7 +248,7 @@
back_item = /obj/item/storage/backpack/security
new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/provost(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/tml(new_human), WEAR_BODY)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/senior(new_human), WEAR_BODY)
new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/m4a3/vp78(new_human), WEAR_WAIST)
@@ -275,44 +275,8 @@
new_human.equip_to_slot_or_del(new /obj/item/handcuffs(new_human), WEAR_IN_JACKET)
new_human.equip_to_slot_or_del(new /obj/item/weapon/gun/shotgun/combat(new_human), WEAR_J_STORE)
-
-/datum/equipment_preset/uscm_event/provost/advisor
- name = "Provost Advisor (ME6)"
- skills = /datum/skills/CMP
-
- assignment = JOB_PROVOST_ADVISOR
- rank = "Provost Advisor"
- paygrade = "ME6"
- role_comm_title = "PvA"
- flags = EQUIPMENT_PRESET_EXTRA
-
-/datum/equipment_preset/uscm_event/provost/advisor/load_gear(mob/living/carbon/human/new_human)
- var/back_item = /obj/item/storage/backpack/satchel/sec
- if (new_human.client && new_human.client.prefs && (new_human.client.prefs.backbag == 1))
- back_item = /obj/item/storage/backpack/security
-
- new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/provost(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/advisor(new_human), WEAR_BODY)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
- new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/m4a3/mod88(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/advisor(new_human), WEAR_JACKET)
- if(new_human.disabilities & NEARSIGHTED)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
- else
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(new_human), WEAR_EYES)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/head/beret/marine/mp/provost/senior(new_human), WEAR_HEAD)
- new_human.equip_to_slot_or_del(new back_item(new_human), WEAR_BACK)
- new_human.equip_to_slot_or_del(new /obj/item/device/taperecorder(new_human), WEAR_L_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large(new_human), WEAR_R_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost(new_human.back), WEAR_IN_BACK)
-
- new_human.equip_to_slot_or_del(new /obj/item/device/flash(new_human), WEAR_IN_JACKET)
- new_human.equip_to_slot_or_del(new /obj/item/handcuffs(new_human), WEAR_IN_JACKET)
-
/datum/equipment_preset/uscm_event/provost/inspector
name = "Provost Inspector (PvI)"
- skills = /datum/skills/CMP
assignment = JOB_PROVOST_INSPECTOR
rank = "Provost Inspector"
@@ -326,11 +290,11 @@
back_item = /obj/item/storage/backpack/security
new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/provost(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/inspector(new_human), WEAR_BODY)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/senior(new_human), WEAR_BODY)
new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/m4a3/mod88(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/inspector(new_human), WEAR_JACKET)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost(new_human), WEAR_JACKET)
if(new_human.disabilities & NEARSIGHTED)
new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
else
@@ -339,11 +303,19 @@
new_human.equip_to_slot_or_del(new back_item(new_human), WEAR_BACK)
new_human.equip_to_slot_or_del(new /obj/item/device/taperecorder(new_human), WEAR_L_STORE)
new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large(new_human), WEAR_R_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost(new_human.back), WEAR_IN_BACK)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost/light/flexi(new_human.back), WEAR_IN_BACK)
new_human.equip_to_slot_or_del(new /obj/item/device/flash(new_human), WEAR_IN_JACKET)
new_human.equip_to_slot_or_del(new /obj/item/handcuffs(new_human), WEAR_IN_JACKET)
+/datum/equipment_preset/uscm_event/provost/inspector/advisor
+ name = "Provost Advisor (ME6)"
+
+ assignment = JOB_PROVOST_ADVISOR
+ rank = "Provost Advisor"
+ paygrade = "ME6"
+ role_comm_title = "PvA"
+ flags = EQUIPMENT_PRESET_EXTRA
/datum/equipment_preset/uscm_event/provost/marshal
name = "Provost Marshal (MO6)"
@@ -366,7 +338,7 @@
new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/mateba/general/impact(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/marshal(new_human), WEAR_JACKET)
+ new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/coat/marshal(new_human), WEAR_JACKET)
if(new_human.disabilities & NEARSIGHTED)
new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
else
@@ -377,70 +349,24 @@
new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/magazine/pistol/pmc_mateba(new_human), WEAR_R_STORE)
new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost/marshal(new_human.back), WEAR_IN_BACK)
-
/datum/equipment_preset/uscm_event/provost/marshal/sector
name = "Provost Sector Marshal (MO7)"
minimum_age = 50
- skills = /datum/skills/general
assignment = JOB_PROVOST_SMARSHAL
rank = "Provost Sector Marshal"
paygrade = "MO7"
role_comm_title = "PvSM"
-/datum/equipment_preset/uscm_event/provost/marshal/sector/load_gear(mob/living/carbon/human/new_human)
- var/back_item = /obj/item/storage/backpack/satchel/sec
- if (new_human.client && new_human.client.prefs && (new_human.client.prefs.backbag == 1))
- back_item = /obj/item/storage/backpack/security
-
- new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/highcom(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/marshal(new_human), WEAR_BODY)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
- new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/mateba/general/impact(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/marshal(new_human), WEAR_JACKET)
- if(new_human.disabilities & NEARSIGHTED)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
- else
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(new_human), WEAR_EYES)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/marine/mp/provost/marshal(new_human), WEAR_HEAD)
- new_human.equip_to_slot_or_del(new back_item(new_human), WEAR_BACK)
- new_human.equip_to_slot_or_del(new /obj/item/device/taperecorder(new_human), WEAR_L_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/magazine/pistol/pmc_mateba(new_human), WEAR_R_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost/marshal(new_human.back), WEAR_IN_BACK)
-
-
/datum/equipment_preset/uscm_event/provost/marshal/chief
name = "Provost Chief Marshal (PvCM)"
minimum_age = 60
- skills = /datum/skills/general
assignment = JOB_PROVOST_CMARSHAL
rank = "Provost Chief Marshal"
paygrade = "PvCM"
role_comm_title = "PvCM"
-/datum/equipment_preset/uscm_event/provost/marshal/chief/load_gear(mob/living/carbon/human/new_human)
- var/back_item = /obj/item/storage/backpack/satchel/sec
- if (new_human.client && new_human.client.prefs && (new_human.client.prefs.backbag == 1))
- back_item = /obj/item/storage/backpack/security
-
- new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/highcom(new_human), WEAR_L_EAR)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/mp/provost/marshal/chief(new_human), WEAR_BODY)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS)
- new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/mateba/general/impact(new_human), WEAR_WAIST)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/jacket/marine/provost/marshal/chief(new_human), WEAR_JACKET)
- if(new_human.disabilities & NEARSIGHTED)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud/prescription(new_human), WEAR_EYES)
- else
- new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(new_human), WEAR_EYES)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/marine/mp/provost/marshal(new_human), WEAR_HEAD)
- new_human.equip_to_slot_or_del(new back_item(new_human), WEAR_BACK)
- new_human.equip_to_slot_or_del(new /obj/item/device/taperecorder(new_human), WEAR_L_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/magazine/pistol/pmc_mateba(new_human), WEAR_R_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/MP/provost/marshal/chief(new_human.back), WEAR_IN_BACK)
-
/*****************************************************************************************************/
/datum/equipment_preset/uscm_event/uaac/tis
diff --git a/code/modules/gear_presets/uscm_ship.dm b/code/modules/gear_presets/uscm_ship.dm
index 4c383cfed6d9..d34137a1c36b 100644
--- a/code/modules/gear_presets/uscm_ship.dm
+++ b/code/modules/gear_presets/uscm_ship.dm
@@ -458,7 +458,6 @@
new_human.equip_to_slot_or_del(new back_item(new_human), WEAR_BACK)
new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/general/large(new_human), WEAR_R_STORE)
new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/pistol/command(new_human), WEAR_L_STORE)
- new_human.equip_to_slot_or_del(new /obj/item/device/binoculars/range/designator(new_human), WEAR_L_HAND)
if(kit)
new_human.equip_to_slot_or_del(new kit(new_human), WEAR_IN_BACK)
diff --git a/code/modules/hydroponics/botany_disks.dm b/code/modules/hydroponics/botany_disks.dm
index fda43b6f164e..602003b19ccc 100644
--- a/code/modules/hydroponics/botany_disks.dm
+++ b/code/modules/hydroponics/botany_disks.dm
@@ -4,14 +4,12 @@
icon = 'icons/obj/items/disk.dmi'
icon_state = "botanydisk"
w_class = SIZE_TINY
+ ground_offset_x = 5
+ ground_offset_y = 5
var/list/genes = list()
var/genesource = "unknown"
-/obj/item/disk/botany/Initialize()
- . = ..()
- pixel_x = rand(-5,5)
- pixel_y = rand(-5,5)
/obj/item/disk/botany/attack_self(mob/user)
..()
diff --git a/code/modules/mentor/mentorhelp.dm b/code/modules/mentor/mentorhelp.dm
index 7746e90d960d..695ec604631e 100644
--- a/code/modules/mentor/mentorhelp.dm
+++ b/code/modules/mentor/mentorhelp.dm
@@ -169,10 +169,7 @@
if(sender == author)
message_title = "MentorHelp"
// If there's a mentor, let them mark it. If not, let them unmark it
- if(mentor)
- message_sender_options = " (Unmark"
- else
- message_sender_options = " (Mark"
+ message_sender_options = " (Mark/Unmark"
message_sender_options += " | Close | AutoResponse)"
var/message_header = SPAN_MENTORHELP("[message_title] from [message_sender_key]: [message_sender_options]
")
@@ -274,9 +271,10 @@
if("autorespond")
autoresponse(C)
if("mark")
- mark(C)
- if("unmark")
- unmark(C)
+ if(!mentor)
+ mark(C)
+ else
+ unmark(C)
if("close")
if(C == author || C == mentor || CLIENT_IS_STAFF(C))
close(C)
@@ -327,7 +325,7 @@
var/msg = SPAN_MENTORSAY("Autoresponse: [choice]")
switch(choice)
if("L: Discord")
- msg += "You can join our Discord server by using this link!"
+ msg += "You can join our Discord server by using this link!"
if("L: Xeno Quickstart Guide")
msg += "Your answer can be found on the Xeno Quickstart Guide on our wiki. Check it out here."
if("L: Marine Quickstart Guide")
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index 4b86c827a069..28e45dcb2f5e 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -132,7 +132,6 @@
for(var/message_mode in parsed["modes"])
var/list/obj/item/used_radios = list()
switch(message_mode)
- if(MESSAGE_MODE_LOCAL)
if(RADIO_MODE_WHISPER)
whisper_say(message, speaking, alt_name)
return
@@ -142,9 +141,10 @@
used_radios += I
break // remove this if we EVER have two different intercomms with DIFFERENT frequencies IN ONE ROOM
else
- var/earpiece = get_type_in_ears(/obj/item/device/radio)
- if(earpiece)
- used_radios += earpiece
+ if(message_mode != MESSAGE_MODE_LOCAL)
+ var/earpiece = get_type_in_ears(/obj/item/device/radio)
+ if(earpiece)
+ used_radios += earpiece
var/sound/speech_sound
var/sound_vol
diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm
index fa9036bd8305..3fd8e53024d5 100644
--- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm
+++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm
@@ -357,8 +357,8 @@
/mob/living/carbon/xenomorph/proc/pounced_turf(turf/T)
if(!T.density)
- for(var/mob/M in T)
- pounced_mob(M)
+ for(var/mob/living/mob in T)
+ pounced_mob(mob)
break
else
turf_launch_collision(T)
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm b/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm
index af8f33cf1c76..705837699275 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm
@@ -135,7 +135,7 @@
if(istype(O, /obj/vehicle/multitile))
var/obj/vehicle/multitile/R = O
- R.take_damage_type((1 / A.acid_strength) * 40, "acid", src)
+ R.take_damage_type(40 / A.acid_delay, "acid", src)
visible_message(SPAN_XENOWARNING("[src] vomits globs of vile stuff at \the [O]. It sizzles under the bubbling mess of acid!"), \
SPAN_XENOWARNING("You vomit globs of vile stuff at [O]. It sizzles under the bubbling mess of acid!"), null, 5)
playsound(loc, "sound/bullets/acid_impact1.ogg", 25)
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm
index 3975a229bbc1..e926349af60d 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm
@@ -1,74 +1,76 @@
-/datum/action/xeno_action/activable/pierce/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/X = owner
+/datum/action/xeno_action/activable/pierce/use_ability(atom/targetted_atom)
+ var/mob/living/carbon/xenomorph/source_xeno = owner
if (!action_cooldown_check())
return
- if (!X.check_state())
+ if (!source_xeno.check_state())
return
- if(!A || A.layer >= FLY_LAYER || !isturf(X.loc))
+ if(!targetted_atom || targetted_atom.layer >= FLY_LAYER || !isturf(source_xeno.loc))
return
if (!check_and_use_plasma_owner())
return
+ //X = xeno user, A = target atom
+ var/list/turf/target_turfs = getline2(source_xeno, targetted_atom, include_from_atom = FALSE)
+ var/length_of_line = LAZYLEN(target_turfs)
+ if(length_of_line > 3)
+ target_turfs = target_turfs.Copy(1, 4)
+
// Get list of target mobs
var/list/target_mobs = list()
+ var/blocked = FALSE
-
- var/list/target_turfs = list()
- var/facing = Get_Compass_Dir(X, A)
- var/turf/T = X.loc
- var/turf/temp = X.loc
-
- for(var/x in 0 to 2)
- temp = get_step(T, facing)
- if(!temp || temp.density || temp.opacity)
- break
-
- var/blocked = FALSE
- for(var/obj/structure/S in temp)
- if(istype(S, /obj/structure/window/framed))
- var/obj/structure/window/framed/W = S
- if(!W.unslashable)
- W.deconstruct(disassembled = FALSE)
-
- if(S.opacity)
- blocked = TRUE
- break
+ for(var/turf/path_turf as anything in target_turfs)
if(blocked)
break
+ //Check for walls etc and stop if we encounter one
+ if(path_turf.density)
+ break
- T = temp
- target_turfs += T
-
- for(var/turf/target_turf in target_turfs)
- for(var/mob/living/carbon/H in target_turf)
- if (!isxeno_human(H) || X.can_not_harm(H))
- continue
-
- if(!(H in target_mobs))
- target_mobs += H
-
- X.visible_message(SPAN_XENODANGER("[X] slashes its claws through the area in front of it!"), SPAN_XENODANGER("You slash your claws through the area in front of you!"))
- X.animation_attack_on(A, 15)
-
- X.emote("roar")
-
- // Loop through our turfs, finding any humans there and dealing damage to them
- for (var/mob/living/carbon/H in target_mobs)
- if (!isxeno_human(H) || X.can_not_harm(H))
+ //Check for structures such as doors
+ for(var/atom/path_content as anything in path_turf.contents)
+ if(isobj(path_content))
+ var/obj/object = path_content
+ //If we shouldn't be able to pass through it then stop at this turf
+ if(object.density && !object.throwpass)
+ blocked = TRUE
+ break
+
+ if(istype(object, /obj/structure/window/framed))
+ var/obj/structure/window/framed/framed_window = object
+ if(!framed_window.unslashable)
+ framed_window.deconstruct(disassembled = FALSE)
+
+ //Check for mobs and add them to our target list for damage
+ if(iscarbon(path_content))
+ var/mob/living/carbon/mob_to_act = path_content
+ if(!isxeno_human(mob_to_act) || source_xeno.can_not_harm(mob_to_act))
+ continue
+
+ if(!(mob_to_act in target_mobs))
+ target_mobs += mob_to_act
+
+ source_xeno.visible_message(SPAN_XENODANGER("[source_xeno] slashes its tail through the area in front of it!"), SPAN_XENODANGER("You slash your tail through the area in front of you!"))
+ source_xeno.animation_attack_on(targetted_atom, 15)
+
+ source_xeno.emote("roar")
+
+ // Loop through our mob list, finding any humans there and dealing damage to them
+ for (var/mob/living/carbon/current_mob in target_mobs)
+ if (!isxeno_human(current_mob) || source_xeno.can_not_harm(current_mob))
continue
- if (H.stat == DEAD)
+ if (current_mob.stat == DEAD)
continue
- X.flick_attack_overlay(H, "slash")
- H.apply_armoured_damage(get_xeno_damage_slash(H, damage), ARMOR_MELEE, BRUTE, null, 20)
+ current_mob.flick_attack_overlay(current_mob, "slash")
+ current_mob.apply_armoured_damage(get_xeno_damage_slash(current_mob, damage), ARMOR_MELEE, BRUTE, null, 20)
if (target_mobs.len >= shield_regen_threshold)
- if (X.mutation_type == PRAETORIAN_VANGUARD)
- var/datum/behavior_delegate/praetorian_vanguard/BD = X.behavior_delegate
+ if (source_xeno.mutation_type == PRAETORIAN_VANGUARD)
+ var/datum/behavior_delegate/praetorian_vanguard/BD = source_xeno.behavior_delegate
if (istype(BD))
BD.regen_shield()
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm
index 708334d31a96..9a29e2cb6da0 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm
@@ -130,7 +130,7 @@
if(istype(O, /obj/vehicle/multitile))
var/obj/vehicle/multitile/R = O
- R.take_damage_type((1 / A.acid_strength) * 20, "acid", src)
+ R.take_damage_type(20 / A.acid_delay, "acid", src)
visible_message(SPAN_XENOWARNING("[src] vomits globs of vile stuff at \the [O]. It sizzles under the bubbling mess of acid!"), \
SPAN_XENOWARNING("You vomit globs of vile stuff at [O]. It sizzles under the bubbling mess of acid!"), null, 5)
playsound(loc, "sound/bullets/acid_impact1.ogg", 25)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 3d74673c5308..56951097a12c 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -28,7 +28,7 @@
//TODO: Integrate defence zones and targeting body parts with the actual organ system, move these into organ definitions.
-//The base miss chance for the different defence zones
+/// The base miss chance for the different defence zones
var/list/global/base_miss_chance = list(
"head" = 10,
"chest" = 0,
diff --git a/code/modules/mob/new_player/sprite_accessories/hair.dm b/code/modules/mob/new_player/sprite_accessories/hair.dm
index 3f624b8d3b15..3dfe8bebd5af 100644
--- a/code/modules/mob/new_player/sprite_accessories/hair.dm
+++ b/code/modules/mob/new_player/sprite_accessories/hair.dm
@@ -738,3 +738,20 @@
/datum/sprite_accessory/hair/aviator
name = "Aviator"
icon_state = "hair_aviator"
+
+/datum/sprite_accessory/hair/gantleponytail
+ name = "Gentle Ponytail"
+ icon_state = "hair_gantleponytail"
+ gender = FEMALE
+
+/datum/sprite_accessory/hair/edgar
+ name = "Edgar"
+ icon_state = "hair_edgar"
+
+/datum/sprite_accessory/hair/emobun
+ name = "Emo Little Bun"
+ icon_state = "hair_emobun"
+
+/datum/sprite_accessory/hair/taper
+ name = "Taper"
+ icon_state = "hair_taper"
diff --git a/code/modules/objectives/data_retrieval.dm b/code/modules/objectives/data_retrieval.dm
index 955d2cc8e63e..01689a18d081 100644
--- a/code/modules/objectives/data_retrieval.dm
+++ b/code/modules/objectives/data_retrieval.dm
@@ -177,6 +177,8 @@
var/datum/cm_objective/retrieve_item/document/retrieve_objective
var/display_color = "white"
var/disk_color = "White"
+ ground_offset_x = 9
+ ground_offset_y = 8
/obj/item/disk/objective/Initialize(mapload, ...)
. = ..()
@@ -210,8 +212,6 @@
name = "[disk_color] computer disk [label]"
objective = new /datum/cm_objective/retrieve_data/disk(src)
retrieve_objective = new /datum/cm_objective/retrieve_item/document(src)
- pixel_y = rand(-8, 8)
- pixel_x = rand(-9, 9)
w_class = SIZE_TINY
/obj/item/disk/objective/Destroy()
diff --git a/code/modules/objectives/documents.dm b/code/modules/objectives/documents.dm
index 14bef02245f0..5c6041a406c2 100644
--- a/code/modules/objectives/documents.dm
+++ b/code/modules/objectives/documents.dm
@@ -122,6 +122,8 @@
unacidable = TRUE
indestructible = 1
is_objective = TRUE
+ ground_offset_x = 9
+ ground_offset_y = 8
var/label // label on the document
var/renamed = FALSE //Once someone reads a document the item gets renamed based on the objective they are linked to)
@@ -131,8 +133,6 @@
objective = new objective_type(src)
retrieve_objective = new /datum/cm_objective/retrieve_item/document(src)
LAZYADD(objective.enables_objectives, retrieve_objective)
- pixel_y = rand(-8, 8)
- pixel_x = rand(-9, 9)
/obj/item/document_objective/Destroy()
qdel(objective)
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 71d1090b20e0..e18c1ce3c2e7 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -19,6 +19,8 @@
flags_equip_slot = SLOT_HEAD
flags_armor_protection = BODY_FLAG_HEAD
attack_verb = list("bapped")
+ ground_offset_x = 9
+ ground_offset_y = 8
var/info //What's actually written on the paper.
var/info_links //A different version of the paper which includes html links at fields and EOF
@@ -42,8 +44,6 @@
/obj/item/paper/Initialize(mapload, photo_list)
. = ..()
- pixel_y = rand(-8, 8)
- pixel_x = rand(-9, 9)
stamps = ""
src.photo_list = photo_list
@@ -382,9 +382,6 @@
/obj/item/paper/attackby(obj/item/P, mob/user)
..()
- var/clown = 0
- if(user.mind && (user.job == "Clown"))
- clown = 1
if(istype(P, /obj/item/paper) || istype(P, /obj/item/photo))
if (istype(P, /obj/item/paper/carbon))
@@ -424,6 +421,7 @@
return
stamps += (stamps=="" ? "
" : "
") + "This paper has been stamped with the [P.name]."
+ playsound(src, 'sound/effects/alien_footstep_medium3.ogg', 20, TRUE, 6)
var/image/stampoverlay = image('icons/obj/items/paper.dmi')
var/x
@@ -439,11 +437,6 @@
stampoverlay.pixel_x = x
stampoverlay.pixel_y = y
- if(istype(P, /obj/item/tool/stamp/clown))
- if(!clown)
- to_chat(user, SPAN_NOTICE("You are totally unable to use the stamp. HONK!"))
- return
-
if(!ico)
ico = new
ico += "paper_[P.icon_state]"
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 70d6bf3898a6..b47f630974e6 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -82,8 +82,6 @@
p.update_icon()
p.icon_state = "paper_words"
p.name = bundle.name
- p.pixel_y = rand(-8, 8)
- p.pixel_x = rand(-9, 9)
sleep(15*j)
updateUsrDialog()
else if(href_list["remove"])
diff --git a/code/modules/projectiles/ammo_boxes/ammo_boxes.dm b/code/modules/projectiles/ammo_boxes/ammo_boxes.dm
index 831923415453..df8a7d7bdd76 100644
--- a/code/modules/projectiles/ammo_boxes/ammo_boxes.dm
+++ b/code/modules/projectiles/ammo_boxes/ammo_boxes.dm
@@ -85,6 +85,8 @@
var/handful = "shells" //used for 'magazine' boxes that give handfuls to determine what kind for the sprite
can_explode = TRUE
limit_per_tile = 2
+ ground_offset_x = 5
+ ground_offset_y = 5
/obj/item/ammo_box/magazine/empty
empty = TRUE
@@ -102,8 +104,6 @@
while(i < num_of_magazines)
contents += new magazine_type(src)
i++
- pixel_x = rand(-5, 5)
- pixel_y = rand(-5, 5)
update_icon()
/obj/item/ammo_box/magazine/update_icon()
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index d747525f3feb..594ad6b69dce 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -18,6 +18,8 @@ They're all essentially identical when it comes to getting the job done.
w_class = SIZE_SMALL
throw_speed = SPEED_SLOW
throw_range = 6
+ ground_offset_x = 7
+ ground_offset_y = 6
var/default_ammo = /datum/ammo/bullet
var/caliber = null // This is used for matching handfuls to each other or whatever the mag is. Examples are" "12g" ".44" ".357" etc.
var/current_rounds = -1 //Set this to something else for it not to start with different initial counts.
@@ -50,8 +52,7 @@ They're all essentially identical when it comes to getting the job done.
if(0)
icon_state += "_e" //In case it spawns empty instead.
item_state += "_e"
- pixel_y = rand(-6, 6)
- pixel_x = rand(-7, 7)
+
if(ammo_band_color && ammo_band_icon)
update_ammo_band()
diff --git a/code/modules/projectiles/guns/flamer/flamer.dm b/code/modules/projectiles/guns/flamer/flamer.dm
index 13ccd03c3e82..323e994529ae 100644
--- a/code/modules/projectiles/guns/flamer/flamer.dm
+++ b/code/modules/projectiles/guns/flamer/flamer.dm
@@ -719,12 +719,12 @@ GLOBAL_LIST_EMPTY(flamer_particles)
var/direction_angle = dir2angle(direction)
var/obj/flamer_fire/foundflame = locate() in target
if(!foundflame)
- var/datum/reagent/R = new()
- R.intensityfire = burn_lvl
- R.durationfire = fire_lvl
- R.burn_sprite = burn_sprite
- R.burncolor = f_color
- new/obj/flamer_fire(target, cause_data, R)
+ var/datum/reagent/fire_reag = new()
+ fire_reag.intensityfire = burn_lvl
+ fire_reag.durationfire = fire_lvl
+ fire_reag.burn_sprite = burn_sprite
+ fire_reag.burncolor = f_color
+ new/obj/flamer_fire(target, cause_data, fire_reag)
if(target.density)
return
@@ -737,11 +737,9 @@ GLOBAL_LIST_EMPTY(flamer_particles)
var/angle = 180 - abs( abs( direction_angle - spread_direction_angle ) - 180 ) // the angle difference between the spread direction and initial direction
switch(angle) //this reduces power when the explosion is going around corners
- if (0)
- //no change
if (45)
spread_power *= 0.75
- else //turns out angles greater than 90 degrees almost never happen. This bit also prevents trying to spread backwards
+ if (90 to 180) //turns out angles greater than 90 degrees almost never happen. This bit also prevents trying to spread backwards
continue
switch(spread_direction)
@@ -753,25 +751,29 @@ GLOBAL_LIST_EMPTY(flamer_particles)
if (spread_power < 1)
continue
- var/turf/T = get_step(target, spread_direction)
+ var/turf/picked_turf = get_step(target, spread_direction)
- if(!T) //prevents trying to spread into "null" (edge of the map?)
+ if(!picked_turf) //prevents trying to spread into "null" (edge of the map?)
continue
- if(aerial_flame_level && (T.get_pylon_protection_level() >= aerial_flame_level))
- break
+ if(aerial_flame_level)
+ if(picked_turf.get_pylon_protection_level() >= aerial_flame_level)
+ break
+ var/area/picked_area = get_area(picked_turf)
+ if(CEILING_IS_PROTECTED(picked_area?.ceiling, get_ceiling_protection_level(aerial_flame_level)))
+ break
spawn(0)
- fire_spread_recur(T, cause_data, spread_power, spread_direction, fire_lvl, burn_lvl, f_color, burn_sprite, aerial_flame_level)
+ fire_spread_recur(picked_turf, cause_data, spread_power, spread_direction, fire_lvl, burn_lvl, f_color, burn_sprite, aerial_flame_level)
/proc/fire_spread(turf/target, datum/cause_data/cause_data, range, fire_lvl, burn_lvl, f_color, burn_sprite = "dynamic", aerial_flame_level = TURF_PROTECTION_NONE)
- var/datum/reagent/R = new()
- R.intensityfire = burn_lvl
- R.durationfire = fire_lvl
- R.burn_sprite = burn_sprite
- R.burncolor = f_color
+ var/datum/reagent/fire_reag = new()
+ fire_reag.intensityfire = burn_lvl
+ fire_reag.durationfire = fire_lvl
+ fire_reag.burn_sprite = burn_sprite
+ fire_reag.burncolor = f_color
- new/obj/flamer_fire(target, cause_data, R)
+ new/obj/flamer_fire(target, cause_data, fire_reag)
for(var/direction in alldirs)
var/spread_power = range
switch(direction)
@@ -779,7 +781,11 @@ GLOBAL_LIST_EMPTY(flamer_particles)
spread_power--
else
spread_power -= 1.414 //diagonal spreading
- var/turf/T = get_step(target, direction)
- if(aerial_flame_level && (T.get_pylon_protection_level() >= aerial_flame_level))
- continue
- fire_spread_recur(T, cause_data, spread_power, direction, fire_lvl, burn_lvl, f_color, burn_sprite, aerial_flame_level)
+ var/turf/picked_turf = get_step(target, direction)
+ if(aerial_flame_level)
+ if(picked_turf.get_pylon_protection_level() >= aerial_flame_level)
+ continue
+ var/area/picked_area = get_area(picked_turf)
+ if(CEILING_IS_PROTECTED(picked_area?.ceiling, get_ceiling_protection_level(aerial_flame_level)))
+ continue
+ fire_spread_recur(picked_turf, cause_data, spread_power, direction, fire_lvl, burn_lvl, f_color, burn_sprite, aerial_flame_level)
diff --git a/code/modules/projectiles/guns/smgs.dm b/code/modules/projectiles/guns/smgs.dm
index 89e6594c64e7..24eddf31597d 100644
--- a/code/modules/projectiles/guns/smgs.dm
+++ b/code/modules/projectiles/guns/smgs.dm
@@ -11,7 +11,7 @@
aim_slowdown = SLOWDOWN_ADS_QUICK
wield_delay = WIELD_DELAY_VERY_FAST
attachable_allowed = list(
- /obj/item/attachable/suppressor,
+ /obj/item/attachable/suppressor,
/obj/item/attachable/reddot,
/obj/item/attachable/reflex,
/obj/item/attachable/flashlight,
@@ -50,7 +50,8 @@
/obj/item/attachable/suppressor,
/obj/item/attachable/reddot,
/obj/item/attachable/reflex,
- /obj/item/attachable/angledgrip,
+ /obj/item/attachable/angledgrip,
+ /obj/item/attachable/verticalgrip,
/obj/item/attachable/flashlight/grip,
/obj/item/attachable/stock/smg,
/obj/item/attachable/stock/smg/collapsible,
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index b01203d0f4d8..adb97e3a1c43 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -455,12 +455,31 @@
if(hit_chance) // Calculated from combination of both ammo accuracy and gun accuracy
var/hit_roll = rand(1,100)
+ var/direct_hit = FALSE
- if(original != L || hit_roll > hit_chance-base_miss_chance[def_zone]-20) // If hit roll is high or the firer wasn't aiming at this mob, we still hit but now we might hit the wrong body part
+ // Wasn't the clicked target
+ if(original != L)
def_zone = rand_zone()
+
+ // Xenos get a RNG limb miss chance regardless of being clicked target or not, see below
+ else if(isxeno(L) && hit_roll > hit_chance - 20)
+ def_zone = rand_zone()
+
+ // Other targets do the same roll with penalty - a near hit will hit but redirected to another limb
+ else if(!isxeno(L) && hit_roll > hit_chance - 20 - base_miss_chance[def_zone])
+ def_zone = rand_zone()
+
else
+ direct_hit = TRUE
SEND_SIGNAL(firer, COMSIG_BULLET_DIRECT_HIT, L)
- hit_chance -= base_miss_chance[def_zone] // Reduce accuracy based on spot.
+
+ // At present, Xenos have no inherent effects or localized damage stemming from limb targeting
+ // Therefore we exempt the shooter from direct hit accuracy penalties as well,
+ // simply to avoid them from resetting target to chest every time they want to shoot a xeno
+
+ if(!direct_hit || !isxeno(L)) // For normal people or direct hits we apply the limb accuracy penalty
+ hit_chance -= base_miss_chance[def_zone]
+ // else for direct hits on xenos, we skip it, pretending it's a chest shot with zero penalty
#if DEBUG_HIT_CHANCE
to_world(SPAN_DEBUG("([L]) Hit chance: [hit_chance] | Roll: [hit_roll]"))
diff --git a/code/modules/reagents/chemistry_machinery/autodispenser.dm b/code/modules/reagents/chemistry_machinery/autodispenser.dm
index a06042aac7a8..eed96564da71 100644
--- a/code/modules/reagents/chemistry_machinery/autodispenser.dm
+++ b/code/modules/reagents/chemistry_machinery/autodispenser.dm
@@ -346,8 +346,7 @@
C.reagents.trans_to(container, amount)
//We don't care about keeping empty bottles stored
if(C.reagents.total_volume <= 0 && istypestrict(C,/obj/item/reagent_container/glass/bottle))
- linked_storage.item_quants[C.name]--
- qdel(C) //Might want to connect it to a disposal system later instead
+ linked_storage.delete_contents(C)
if(stage_missing)
amount = stage_missing
diff --git a/code/modules/reagents/chemistry_machinery/chem_master.dm b/code/modules/reagents/chemistry_machinery/chem_master.dm
index 9d2d1ff10a0c..1e7e3bb08384 100644
--- a/code/modules/reagents/chemistry_machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry_machinery/chem_master.dm
@@ -237,8 +237,6 @@
while (count--)
var/obj/item/reagent_container/pill/P = new/obj/item/reagent_container/pill(loc)
P.pill_desc = "A custom pill."
- P.pixel_x = rand(-7, 7) //random position
- P.pixel_y = rand(-7, 7)
P.icon_state = "pill"+pillsprite
reagents.trans_to(P,amount_per_pill)
if(loaded_pill_bottle)
@@ -271,8 +269,6 @@
P.name = "[name] vial"
reagents.trans_to(P, 30)
- P.pixel_x = rand(-7, 7) //random position
- P.pixel_y = rand(-7, 7)
P.update_icon()
if(href_list["store"])
diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm
index 7f476cecf2c5..971051e9bf88 100644
--- a/code/modules/reagents/chemistry_properties/prop_positive.dm
+++ b/code/modules/reagents/chemistry_properties/prop_positive.dm
@@ -548,7 +548,7 @@
rarity = PROPERTY_RARE
category = PROPERTY_TYPE_REACTANT
value = 3
- max_level = 1
+ COOLDOWN_DECLARE(ghost_notif)
/datum/chem_property/positive/defibrillating/on_delete(mob/living/M)
..()
@@ -574,19 +574,33 @@
/datum/chem_property/positive/defibrillating/process_dead(mob/living/M, potency = 1, delta_time)
if(!ishuman(M))
return
- var/mob/living/carbon/human/H = M
- H.apply_damage(-H.getOxyLoss(), OXY)
- if(H.check_tod() && H.is_revivable() && H.health > HEALTH_THRESHOLD_DEAD)
- to_chat(H, SPAN_NOTICE("You feel your heart struggling as you suddenly feel a spark, making it desperately try to continue pumping."))
- playsound_client(H.client, 'sound/effects/Heart Beat Short.ogg', 35)
- addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/carbon/human, handle_revive)), 50, TIMER_UNIQUE)
- else if (potency > POTENCY_MAX_TIER_1 && H.check_tod() && H.is_revivable() && H.health < HEALTH_THRESHOLD_DEAD) //Will heal if level is 7 or greater
- to_chat(H, SPAN_NOTICE("You feel a faint spark in your chest."))
- H.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, BRUTE)
- H.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, BURN)
- H.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, TOX)
- H.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, CLONE)
- H.apply_damage(-H.getOxyLoss(), OXY)
+ var/mob/living/carbon/human/dead = M
+ var/revivable = dead.check_tod() && dead.is_revivable()
+ if(revivable && (dead.health > HEALTH_THRESHOLD_DEAD))
+ addtimer(CALLBACK(dead, TYPE_PROC_REF(/mob/living/carbon/human, handle_revive)), 5 SECONDS)
+ to_chat(dead, SPAN_NOTICE("You feel your heart struggling as you suddenly feel a spark, making it desperately try to continue pumping."))
+ playsound_client(dead.client, 'sound/effects/heart_beat_short.ogg', 35)
+ else if ((potency >= 1) && revivable && dead.health <= HEALTH_THRESHOLD_DEAD) //heals on all level above 1. This is however, minimal.
+ to_chat(dead, SPAN_NOTICE("You feel a faint spark in your chest."))
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_VLOW, BRUTE)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_VLOW, BURN)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_VLOW, TOX)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_VLOW, CLONE)
+ dead.apply_damage(-dead.getOxyLoss(), OXY)
+ if(potency > CREATE_MAX_TIER_1) //heal more if higher levels
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, BRUTE)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, BURN)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, TOX)
+ dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, CLONE)
+ if(dead.health < HEALTH_THRESHOLD_DEAD)
+ return
+ if(!COOLDOWN_FINISHED(src, ghost_notif))
+ return
+ var/mob/dead/observer/ghost = dead.get_ghost()
+ if(ghost?.client)
+ COOLDOWN_START(src, ghost_notif, 30 SECONDS)
+ playsound_client(ghost.client, 'sound/effects/adminhelp_new.ogg')
+ to_chat(ghost, SPAN_BOLDNOTICE("Your heart is struggling to pump! There is a chance you might get up!(Verbs -> Ghost -> Re-enter corpse, or click here!)"))
return TRUE
/datum/chem_property/positive/hyperdensificating
diff --git a/code/modules/reagents/chemistry_properties/prop_special.dm b/code/modules/reagents/chemistry_properties/prop_special.dm
index 640e18426311..cec04ca66616 100644
--- a/code/modules/reagents/chemistry_properties/prop_special.dm
+++ b/code/modules/reagents/chemistry_properties/prop_special.dm
@@ -96,7 +96,7 @@
H.contract_disease(new /datum/disease/xeno_transformation(0),1) //This is the real reason PMCs are being sent to retrieve it.
/datum/chem_property/special/DNA_Disintegrating/trigger()
- SSticker.mode.get_specific_call("Weyland-Yutani Goon (Chemical Investigation Squad)", TRUE, FALSE, FALSE, holder.name, TRUE)
+ SSticker.mode.get_specific_call("Weyland-Yutani Goon (Chemical Investigation Squad)", TRUE, FALSE, holder.name)
chemical_data.update_credits(10)
message_admins("The research department has discovered DNA_Disintegrating in [holder.name] adding 10 bonus tech points.")
var/datum/techtree/tree = GET_TREE(TREE_MARINE)
diff --git a/code/modules/reagents/chemistry_reagents/drink.dm b/code/modules/reagents/chemistry_reagents/drink.dm
index 468243a0cc8d..3bd7336c32b6 100644
--- a/code/modules/reagents/chemistry_reagents/drink.dm
+++ b/code/modules/reagents/chemistry_reagents/drink.dm
@@ -85,13 +85,13 @@
/datum/reagent/drink/carrotjuice/on_mob_life(mob/living/M)
. = ..()
- if(!.) return
+ if(!.)
+ return
M.ReduceEyeBlur(1)
M.ReduceEyeBlind(1)
- if(!data) data = 1
+ if(!data)
+ data = 1
switch(data)
- if(1 to 20)
- //nothing
if(21 to INFINITY)
if(prob(data-10))
M.disabilities &= ~NEARSIGHTED
diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm
index 41a047339452..b9a9f27a28ae 100644
--- a/code/modules/tgs/core/core.dm
+++ b/code/modules/tgs/core/core.dm
@@ -153,4 +153,9 @@
/world/TgsSecurityLevel()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
- api.SecurityLevel()
+ return api.SecurityLevel()
+
+/world/TgsVisibility()
+ var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
+ if(api)
+ return api.Visibility()
diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm
index 68b0330fe860..de420a2a325a 100644
--- a/code/modules/tgs/core/datum.dm
+++ b/code/modules/tgs/core/datum.dm
@@ -11,6 +11,10 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
src.event_handler = event_handler
src.version = version
+/datum/tgs_api/proc/TerminateWorld()
+ del(world)
+ sleep(1) // https://www.byond.com/forum/post/2894866
+
/datum/tgs_api/latest
parent_type = /datum/tgs_api/v5
@@ -57,3 +61,6 @@ TGS_PROTECT_DATUM(/datum/tgs_api)
/datum/tgs_api/proc/SecurityLevel()
return TGS_UNIMPLEMENTED
+
+/datum/tgs_api/proc/Visibility()
+ return TGS_UNIMPLEMENTED
diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm
index b9a75c4abb48..945e2e411767 100644
--- a/code/modules/tgs/v4/api.dm
+++ b/code/modules/tgs/v4/api.dm
@@ -73,7 +73,7 @@
if(cached_json["apiValidateOnly"])
TGS_INFO_LOG("Validating API and exiting...")
Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]"))
- del(world)
+ TerminateWorld()
security_level = cached_json["securityLevel"]
chat_channels_json_path = cached_json["chatChannelsJson"]
@@ -188,7 +188,7 @@
requesting_new_port = TRUE
if(!world.OpenPort(0)) //open any port
TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
//request a new port
export_lock = FALSE
@@ -196,16 +196,16 @@
if(!new_port_json)
TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
var/new_port = new_port_json[TGS4_PARAMETER_DATA]
if(!isnum(new_port) || new_port <= 0)
TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
if(new_port != world.port && !world.OpenPort(new_port))
TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
requesting_new_port = FALSE
while(export_lock)
diff --git a/code/modules/tgs/v5/__interop_version.dm b/code/modules/tgs/v5/__interop_version.dm
index 5d3d491a7362..1b52b31d6a73 100644
--- a/code/modules/tgs/v5/__interop_version.dm
+++ b/code/modules/tgs/v5/__interop_version.dm
@@ -1 +1 @@
-"5.6.1"
+"5.6.2"
diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm
index f973338daa03..bdcd4e4dd58e 100644
--- a/code/modules/tgs/v5/_defines.dm
+++ b/code/modules/tgs/v5/_defines.dm
@@ -48,6 +48,7 @@
#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision"
#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges"
#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel"
+#define DMAPI5_RUNTIME_INFORMATION_VISIBILITY "visibility"
#define DMAPI5_CHAT_UPDATE_CHANNELS "channels"
diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm
index 34cc43f8762f..7226f29bba60 100644
--- a/code/modules/tgs/v5/api.dm
+++ b/code/modules/tgs/v5/api.dm
@@ -4,6 +4,7 @@
var/instance_name
var/security_level
+ var/visibility
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
@@ -50,10 +51,11 @@
if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY])
TGS_INFO_LOG("DMAPI validation, exiting...")
- del(world)
+ TerminateWorld()
version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION])
security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL]
+ visibility = runtime_information[DMAPI5_RUNTIME_INFORMATION_VISIBILITY]
instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME]
var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION]
@@ -252,3 +254,7 @@
/datum/tgs_api/v5/SecurityLevel()
RequireInitialBridgeResponse()
return security_level
+
+/datum/tgs_api/v5/Visibility()
+ RequireInitialBridgeResponse()
+ return visibility
diff --git a/code/modules/tgs/v5/undefs.dm b/code/modules/tgs/v5/undefs.dm
index c679737dfc49..f163adaaafe3 100644
--- a/code/modules/tgs/v5/undefs.dm
+++ b/code/modules/tgs/v5/undefs.dm
@@ -48,6 +48,7 @@
#undef DMAPI5_RUNTIME_INFORMATION_REVISION
#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES
#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL
+#undef DMAPI5_RUNTIME_INFORMATION_VISIBILITY
#undef DMAPI5_CHAT_UPDATE_CHANNELS
diff --git a/colonialmarines.dme b/colonialmarines.dme
index b6967c2df59b..fe2fadba5c0e 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -1,4 +1,4 @@
-s// DM Environment file for colonialmarines.dme.
+// DM Environment file for colonialmarines.dme.
// All manual changes should be made outside the BEGIN_ and END_ blocks.
// New source code should be placed in .dm files: choose File/New --> Code File.
// BEGIN_INTERNALS
@@ -11,6 +11,7 @@ s// DM Environment file for colonialmarines.dme.
#define DEBUG
// END_PREFERENCES
// BEGIN_INCLUDE
+#include "code\__odlint.dm"
#include "code\_byond_version_compat.dm"
#include "code\_compile_options.dm"
#include "code\_experiments.dm"
@@ -938,6 +939,7 @@ s// DM Environment file for colonialmarines.dme.
#include "code\game\machinery\vending\vendor_types\crew\sea.dm"
#include "code\game\machinery\vending\vendor_types\crew\senior_officers.dm"
#include "code\game\machinery\vending\vendor_types\crew\staff_officer.dm"
+#include "code\game\machinery\vending\vendor_types\crew\staff_officer_armory.dm"
#include "code\game\machinery\vending\vendor_types\crew\synthetic.dm"
#include "code\game\machinery\vending\vendor_types\crew\vehicle_crew.dm"
#include "code\game\machinery\vending\vendor_types\squad_prep\squad_engineer.dm"
diff --git a/dependencies.sh b/dependencies.sh
index c099cb413c97..21af234d1bea 100644
--- a/dependencies.sh
+++ b/dependencies.sh
@@ -19,3 +19,5 @@ export SPACEMAN_DMM_VERSION=suite-1.8
# Python version for mapmerge and other tools
export PYTHON_VERSION=3.7.9
+
+export OPENDREAM_VERSION=0.2.0
diff --git a/html/changelogs/AutoChangeLog-pr-4733.yml b/html/changelogs/AutoChangeLog-pr-4733.yml
deleted file mode 100644
index 43d1d2b92e0a..000000000000
--- a/html/changelogs/AutoChangeLog-pr-4733.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "realforest2001"
-delete-after: True
-changes:
- - rscadd: "Added Discretionary Arrest to JAS."
- - rscadd: "Added a new category to JAS, Precautionary Charges. Moves Insanity and POW to this category."
\ No newline at end of file
diff --git a/html/changelogs/archive/2023-10.yml b/html/changelogs/archive/2023-10.yml
index 94c952734866..a7002c5825b1 100644
--- a/html/changelogs/archive/2023-10.yml
+++ b/html/changelogs/archive/2023-10.yml
@@ -315,3 +315,108 @@
- rscadd: Added splints to the survival pouch
- rscadd: Increased survival pouch storage space by 1
- spellcheck: Updates the survival pouch's description
+2023-10-22:
+ Drathek:
+ - bugfix: Fix incend and cluster OBs not respecting ceiling OB protections.
+ - bugfix: Disabled code in icon2html that is causing bad icon operations
+ Morrow:
+ - server: the rustg mysql driver is now properly compatible with mariadb
+ Zonespace27:
+ - rscadd: Mentors can now unmark mhelps
+ fira:
+ - bugfix: Removed redundant double binding for F1 to AdminHelp from default keybinds.
+ This does not affect existing users or their settings.
+ - rscadd: Stamping papers now makes a noise.
+ - bugfix: Fixed incorrect Reqs vendors visuals on the Almayer. They now blend in
+ with the walls again.
+ - bugfix: Re-fixed Megaphone above-head-chat drifting to the left.
+ harryob:
+ - admin: no more href token errors when changing the game mode via game panel
+ - bugfix: mentorhelp response no longer gives a dead discord link
+ - admin: view-target-records now allows you to note people properly
+ kiVts:
+ - rscadd: Ghosts get notified when they are being revived by DFB property
+ - balance: DFB property healing threshold lowered, You can create DFB property higher
+ than one.
+ realforest2001:
+ - rscadd: Added Discretionary Arrest to JAS.
+ - rscadd: Added a new category to JAS, Precautionary Charges. Moves Insanity and
+ POW to this category.
+2023-10-23:
+ QuickLode:
+ - balance: Nerfs synth surv pouch by removing 1 storage slot.
+ SpypigDev:
+ - rscadd: CIC Armory SO vendor
+ - balance: Moved most combat-themed gear from SO spawn vendors, to CIC Armory vendor
+ - balance: Made RTO pack a point-buy item in CIC Armory vendor for SOs
+ Steelpoint:
+ - balance: Revolver Heavy ammo no longer stuns targets it strikes, it will instead
+ knock them back and slow them down for a short time.
+ harryob:
+ - server: the server now respects /string/title for late joiners
+ stalkerino:
+ - balance: m39 is able to use vertigrip
+2023-10-24:
+ Segrain:
+ - bugfix: Slicing food once again works as intended.
+2023-10-25:
+ fira:
+ - bugfix: Fixed Ghosts and Queen Eye occasionally "eating" pounces in place of a
+ mob on the same turf.
+ - bugfix: Re-Re-Fixed Xeno Above Head Chat offsets, for real this time
+ - bugfix: Fixed people talking in radios all the time. Finally some quiet.
+ - bugfix: deadchat death messages should now display immediately rather than being
+ delayed a couple seconds.
+2023-10-26:
+ 4hands44:
+ - rscadd: Added more attachments, and belts to the CO arsenal.
+ - rscadd: CO now has an Essentials Kit like other roles, containing his Designator,
+ and other useful tools.
+ - rscadd: Re-Adds Bridgecoat to some Officer Dress vendors. (Limited to CO(+) and
+ XO currently.)
+ - rscdel: Removed Laser Designator from CO spawn Preset.
+ - balance: CO can now vend welding Helmet visors.
+ - balance: Adds grenade packets to CO Vendor.
+ XDinka:
+ - rscadd: 'Added four new haircuts: gentle ponytail, edgar haircut, emo bun, taper
+ haircut.'
+2023-10-27:
+ Backsea:
+ - bugfix: Fixed the incorrectly placed shutters at req and that one light near CIC
+ Birdtalon:
+ - refactor: Refactored praetorian pierce ability
+ - bugfix: Praetorian vanguard can no longer pierce through windowed doors
+ SASoperative:
+ - rscadd: Added donator item and sprites
+ Zonespace27:
+ - rscdel: Re-removed CO/XO bridge coat
+ fira:
+ - rscadd: Added about 50 new tips.
+ - rscadd: Bloody footprints are now slightly offset to break long visual straight
+ lines.
+ - bugfix: Items do not align back to the center of turfs anymore when picked from
+ a surface (table or rack)
+ - rscadd: Some more items now have offsets on the map display, and they all can
+ be slightly offset.
+ - code_imp: Rewrote Xeno Acid ticking code.
+ - bugfix: Weather updates won't cause turfs to acid melt more rapidly anymore
+ - bugfix: Fixed various issues in the Networking between Turing machine and Smartfridges.
+ realforest2001:
+ - bugfix: Fixes custom ERT calling broadcasting when it should not.
+ - code_imp: Removes unused vars from ERT procs.
+ - code_imp: Renames the announce var in ERT procs to be more indicative of what
+ it does.
+ - rscadd: Added a setting on custom ERTs for announcing beacon was received.
+2023-10-29:
+ Segrain:
+ - bugfix: Incendiary OB once again spreads to intended size.
+ fira:
+ - bugfix: Sprite-click shots onto Xenos are no longer affected by limb-targeting
+ penalty, because it was an accuracy debuff when there is no inherent benefit
+ to targeting Xeno limbs.
+ realforest2001:
+ - imageadd: Added sprites for provost senior and marshal uniforms.
+ - spellcheck: Gave unique names to the provost armour subtypes.
+ - balance: Prevented most provost armour from being able to fit inside bags.
+ - balance: Returned provost armour to the same slowdowns as MP armour.
+ - code_imp: Removed a lot of duplicate code in Provost presets and uniform/suits.
diff --git a/icons/mob/humans/human_hair.dmi b/icons/mob/humans/human_hair.dmi
index ca4a20bcafbd..9634a2543aa4 100644
Binary files a/icons/mob/humans/human_hair.dmi and b/icons/mob/humans/human_hair.dmi differ
diff --git a/icons/mob/humans/onmob/back.dmi b/icons/mob/humans/onmob/back.dmi
index 8a51050c03c3..a6e9ef72c010 100644
Binary files a/icons/mob/humans/onmob/back.dmi and b/icons/mob/humans/onmob/back.dmi differ
diff --git a/icons/mob/humans/onmob/head_0.dmi b/icons/mob/humans/onmob/head_0.dmi
index ce576bdd9cc5..51cad85586e7 100644
Binary files a/icons/mob/humans/onmob/head_0.dmi and b/icons/mob/humans/onmob/head_0.dmi differ
diff --git a/icons/mob/humans/onmob/suit_0.dmi b/icons/mob/humans/onmob/suit_0.dmi
index d7dfd5394f0d..52f2c7f0a9cb 100644
Binary files a/icons/mob/humans/onmob/suit_0.dmi and b/icons/mob/humans/onmob/suit_0.dmi differ
diff --git a/icons/mob/humans/onmob/suit_1.dmi b/icons/mob/humans/onmob/suit_1.dmi
index 624d8792cf2d..a911171f8521 100644
Binary files a/icons/mob/humans/onmob/suit_1.dmi and b/icons/mob/humans/onmob/suit_1.dmi differ
diff --git a/icons/mob/humans/onmob/uniform_0.dmi b/icons/mob/humans/onmob/uniform_0.dmi
index 873c325a560e..7a2dcce20c5d 100644
Binary files a/icons/mob/humans/onmob/uniform_0.dmi and b/icons/mob/humans/onmob/uniform_0.dmi differ
diff --git a/icons/obj/items/clothing/backpacks.dmi b/icons/obj/items/clothing/backpacks.dmi
index f9c06fca4437..4119b32a09cf 100644
Binary files a/icons/obj/items/clothing/backpacks.dmi and b/icons/obj/items/clothing/backpacks.dmi differ
diff --git a/icons/obj/items/clothing/cm_suits.dmi b/icons/obj/items/clothing/cm_suits.dmi
index d05d7ffdf77e..fb655de1eafa 100644
Binary files a/icons/obj/items/clothing/cm_suits.dmi and b/icons/obj/items/clothing/cm_suits.dmi differ
diff --git a/icons/obj/items/clothing/hats.dmi b/icons/obj/items/clothing/hats.dmi
index 7d2c45103ba6..a6a0e6fb9099 100644
Binary files a/icons/obj/items/clothing/hats.dmi and b/icons/obj/items/clothing/hats.dmi differ
diff --git a/icons/obj/items/clothing/suits.dmi b/icons/obj/items/clothing/suits.dmi
index d158d9f6bd1f..10fbfff30d7c 100644
Binary files a/icons/obj/items/clothing/suits.dmi and b/icons/obj/items/clothing/suits.dmi differ
diff --git a/icons/obj/items/clothing/uniforms.dmi b/icons/obj/items/clothing/uniforms.dmi
index 4266db88afe8..765f9deae113 100644
Binary files a/icons/obj/items/clothing/uniforms.dmi and b/icons/obj/items/clothing/uniforms.dmi differ
diff --git a/interface/interface.dm b/interface/interface.dm
index a37ab648b7f5..c9112160d94f 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -55,7 +55,7 @@
if(tgui_alert(src, "This will open the discord in your browser. Are you sure?", "Confirm", list("Yes", "No")) != "Yes")
return
- src << link("https://discord.gg/cmss13")
+ src << link("[CONFIG_GET(string/discordurl)]")
return
/client/verb/submitbug()
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 5d06bb40e858..e31c42938cd9 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -164,7 +164,6 @@ window "mainwindow"
anchor2 = -1,-1
is-default = true
saved-params = "pos;size;is-minimized;is-maximized"
- title = "CM-SS13 - USS Almayer"
is-maximized = true
statusbar = false
icon = 'icons\\taskbar\\gml_distress.png'
diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm
index 3740158c7e0f..523f461ee94d 100644
--- a/maps/map_files/USS_Almayer/USS_Almayer.dmm
+++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm
@@ -530,14 +530,12 @@
},
/area/almayer/hallways/aft_hallway)
"abQ" = (
-/obj/structure/surface/rack,
-/obj/item/clothing/suit/storage/marine/light/vest,
-/obj/item/clothing/suit/storage/marine/light/vest,
/obj/item/device/radio/intercom{
freerange = 1;
name = "General Listening Channel";
pixel_y = 28
},
+/obj/structure/machinery/cm_vending/clothing/staff_officer_armory,
/turf/open/floor/almayer{
icon_state = "redfull"
},
@@ -20263,6 +20261,9 @@
/area/almayer/squads/req)
"bGz" = (
/obj/structure/window/framed/almayer,
+/obj/structure/machinery/door/firedoor/border_only/almayer{
+ dir = 1
+ },
/turf/open/floor/almayer{
dir = 9;
icon_state = "green"
@@ -22749,9 +22750,7 @@
/turf/closed/wall/almayer,
/area/almayer/squads/req)
"bQS" = (
-/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo{
- icon_state = "req_ammo_wall"
- },
+/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/blend,
/turf/open/floor/almayer{
icon_state = "green"
},
@@ -24366,9 +24365,7 @@
/turf/open/floor/almayer,
/area/almayer/hallways/vehiclehangar)
"bYa" = (
-/obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo{
- icon_state = "req_guns_wall"
- },
+/obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/blend,
/turf/open/floor/almayer{
dir = 10;
icon_state = "green"
@@ -39686,7 +39683,6 @@
/obj/structure/machinery/door/airlock/multi_tile/almayer/generic2{
access_modified = 1;
name = "\improper Flight Crew Quarters";
- req_access_txt = null;
req_one_access_txt = "19;22"
},
/turf/open/floor/almayer{
@@ -48201,7 +48197,6 @@
access_modified = 1;
dir = 1;
name = "\improper Flight Crew Quarters";
- req_access_txt = null;
req_one_access_txt = "19;22"
},
/turf/open/floor/almayer{
@@ -51463,15 +51458,6 @@
icon_state = "silver"
},
/area/almayer/living/briefing)
-"moU" = (
-/obj/structure/machinery/door/firedoor/border_only/almayer{
- dir = 1
- },
-/turf/open/floor/almayer{
- dir = 4;
- icon_state = "plating_striped"
- },
-/area/almayer/squads/req)
"moY" = (
/obj/structure/disposalpipe/segment,
/turf/closed/wall/almayer,
@@ -56357,6 +56343,9 @@
id = "req_belt"
},
/obj/structure/plasticflaps,
+/obj/structure/machinery/door/firedoor/border_only/almayer{
+ dir = 1
+ },
/turf/open/floor/almayer,
/area/almayer/squads/req)
"oqZ" = (
@@ -57242,18 +57231,6 @@
},
/turf/open/floor/plating/plating_catwalk,
/area/almayer/hull/upper_hull/u_a_p)
-"oLg" = (
-/obj/structure/machinery/conveyor{
- id = "req_belt"
- },
-/obj/structure/machinery/door/firedoor/border_only/almayer{
- dir = 1
- },
-/turf/open/floor/almayer{
- dir = 5;
- icon_state = "plating"
- },
-/area/almayer/squads/req)
"oLi" = (
/obj/effect/landmark/start/marine/medic/bravo,
/obj/effect/landmark/late_join/bravo,
@@ -63678,9 +63655,7 @@
},
/area/almayer/lifeboat_pumps/north1)
"ryR" = (
-/obj/structure/machinery/cm_vending/sorted/uniform_supply/squad_prep{
- req_access = list(1)
- },
+/obj/structure/machinery/cm_vending/clothing/staff_officer_armory,
/turf/open/floor/almayer{
icon_state = "redfull"
},
@@ -72176,6 +72151,9 @@
/area/almayer/squads/bravo)
"vbR" = (
/obj/structure/window/framed/almayer,
+/obj/structure/machinery/door/firedoor/border_only/almayer{
+ dir = 1
+ },
/turf/open/floor/almayer{
dir = 5;
icon_state = "green"
@@ -76471,11 +76449,12 @@
/turf/open/floor/plating/plating_catwalk,
/area/almayer/squads/delta)
"wGI" = (
+/obj/effect/decal/cleanable/dirt,
/obj/structure/machinery/light{
- dir = 4
+ dir = 8
},
-/turf/closed/wall/almayer/reinforced,
-/area/almayer/shipboard/port_missiles)
+/turf/open/floor/almayer,
+/area/almayer/hull/upper_hull/u_f_p)
"wGX" = (
/obj/structure/pipes/standard/manifold/hidden/supply{
dir = 1
@@ -79238,15 +79217,6 @@
"xMs" = (
/turf/closed/wall/almayer/white,
/area/almayer/medical/operating_room_two)
-"xMt" = (
-/obj/structure/machinery/door/firedoor/border_only/almayer{
- dir = 1
- },
-/turf/open/floor/almayer{
- dir = 8;
- icon_state = "plating_striped"
- },
-/area/almayer/squads/req)
"xMA" = (
/obj/structure/machinery/computer/med_data,
/obj/structure/sign/safety/terminal{
@@ -97657,7 +97627,7 @@ vcK
mBA
kCi
kCi
-wGI
+kCi
kCi
vmW
nIE
@@ -97860,7 +97830,7 @@ ukU
bfP
fvv
vcK
-vcK
+wGI
tuA
tuA
tuA
@@ -122715,7 +122685,7 @@ bxg
bZr
bNQ
bNQ
-xMt
+bNQ
bGz
hMs
cbw
@@ -122918,7 +122888,7 @@ bxh
bZr
krN
krN
-oLg
+krN
oqY
can
buH
@@ -123121,7 +123091,7 @@ bxg
bZr
ibc
uly
-moU
+bNN
vbR
pky
cbv
diff --git a/sound/effects/Heart Beat Short.ogg b/sound/effects/heart_beat_short.ogg
similarity index 100%
rename from sound/effects/Heart Beat Short.ogg
rename to sound/effects/heart_beat_short.ogg
diff --git a/strings/marinetips.txt b/strings/marinetips.txt
index cf808884f1e5..416c9ef0a4dd 100644
--- a/strings/marinetips.txt
+++ b/strings/marinetips.txt
@@ -53,35 +53,51 @@ A misloaded OB can deviate severely from the intended target area - ensure you l
The XO and CO are trained in Power Loader use and engineering, and can load the OB.
You can change what your SL tracker beacon is tracking by right clicking on your headset and clicking "Switch Tracker Target".
Boilers emit light - not every glow from around the corner is friendly!
+The amount of items in Requisitions and Squad Preparations depend on how many players readied up at the start of the round.
You can carry a variety of items inside your helmet - from gauze and cigarettes to flares and screwdrivers.
CIC staff can track every USCM-aligned person via the suit sensors console and overwatch console - useful for finding escaped prisoners or dead marines.
When the M7 RPG is fired, it creates a substantial shockwave behind it that can stun and harm marines standing too close. Watch your backblast!
Remember that you need to put a defibrillator's paddles away in order to store it.
-W-Y PMCs do not have marine IFF. Don't fire Smartguns through them!
-To talk on multiple radio channels at once, put a COMMA [,] before your message and add up to four prefixes. E.g, ,abcd talks on all squad channels at once.
+W-Y PMCs do not have marine IFF. Don't fire Smartguns at them!
+To talk on multiple radio channels at once, put a COMMA [,] before your message and add up to four prefixes. E.g, ,abcd talks on the main four squad channels at once.
Put .w or :w before your message to whisper. Another way to whisper is to use the verb "whisper" in the IC tab or command bar.
For Vehicle Crewmen : it is often safer to repair the parts of your APC or tank inside the vehicle than outside it.
It is almost always faster to do surgery manually than in the autodoc.
To check your skills, go to the IC tab and click "view skills".
+Minirockets pack the most punch per cost as far as CAS weaponry is concerned.
The U7 underbarrel shotgun can instantly break down both resin doors and mechanical airlocks, and it's not bad at breaking walls down either.
You can find breaching charges in Requisitions or the Squad Engineer vendor. They function like C4, but can be deployed and explode much quicker, and release powerful shrapnel on the opposite side. They require minor engineering knowledge, which can be obtained from pamphlets.
Armor piercing ammunition does less damage to unarmored targets.
+Requisitions may not grant you service if you are a 'pajamarine' : a marine in cryosleep attire. Be sure to dress up!
You can insert empty pill bottles into ChemMasters before creating pills to have them automatically inserted.
Nurses can practice a full range of surgeries on Professor DUMMY. Ask the gods to give you one if you see (or are) a nurse practicing.
Drinks from the hot drinks machine warm you up.
Be careful! Barricades block grenades, and indeed all thrown items, from the front if they're barbed up.
+CAS Fire Missions doubles the accuracy of fired weapons, which can be substantial.
Painkillers do not stack. Only the strongest has any effect.
+Don't underestimate the mortar: with ammo and proper communication it can hit surprisingly hard.
+You can shoot through tents, but they won't protect you much in return.
+Reqs doesn't have an infinite budget.
+Good Reqs can land supplies anywhere outside - given coords - and sometimes in a minimal amount of time.
+A ‘point blank’ or ‘PB’ is a type of attack with a firearm where you click directly on a mob next to you. These attacks are not effected by accuracy allowing you to quickly fire with weapons like a shotgun to great effect.
Intel Officers can be put in a squad by going to CIC and requesting it.
Any marine can perform CPR. On dead marines, this will increase the time they have until they become unrevivable.
If you've been pounced on and your squad is unloading into the target, you can hit the 'rest' button to stay down so you don't get filled with lead after getting up.
You can check the landing zone as a marine in the status panel.
+The Colonial Marshals may come to crack down on too heavy of a Black Market usage.
Functioning night vision goggles can be recharged with batteries. Broken night vision goggles can be repaired by an Engineer with a screwdriver. Not the loadout ones though, those cannot be fixed.
You can put a pistol belt on your suit slot. (Just grab a rifle instead.)
Alt-clicking the Squad Leader tracker lets you track your fireteam leader instead.
Armor has a randomized reduction in effectiveness, and does not protect the digits. Take the wiki damage values as a best-case scenario.
You can click on your Security Access Tuner (multitool) in your hand to locate the area's APC if there is one.
+Need help learning the game and these tips aren't enough? Use MentorHelp or try to get ahold of your ship's Senior Enlisted Advisor.
Clicking on your sprite with help intent will let you check your body, seeing where your fractures and other wounds are.
Armor has insulative properties - taking it off will help you cool off and take less damage faster if you've been set on fire.
Both foldable cades & plasteel cades if loosened and folded down can be transported in crates! In this way, you can use the crate as a portable breach-repair kit, or dragged (or carried via Power Loader) to an unsecure area for quick defensive set up.
The fuel tank pouch doesn't just carry fuel for an incinerator- they can also carry full-size extinguishers. Toolbelts & tool pouches also may hold miniature extinguishers.
The M2C heavy machine gunner belt rig can also carry C4, breaching charges, and most tools.
+You can always multitask as Medic, such as by using pills or healing kits at the same time as defibrillator.
+The nuclear ordnance requires BOTH communication towers to be actively held to decrypt the nuclear codes.
+ARES will periodically report the amount of available tech points on Command Channel.
+The quick wield keys generally prioritize wieldable gear going from left to right on your inventory bar.
+Orbital Bombardment warheads respect roofing and hive core protection. They won't hit inside of protected areas.
diff --git a/strings/memetips.txt b/strings/memetips.txt
index e05ac2f66bdb..abfe0872180c 100644
--- a/strings/memetips.txt
+++ b/strings/memetips.txt
@@ -12,17 +12,39 @@ Contrary to popular belief, turning off IFF as a Smartgunner does not actually i
When playing as a Xenomorph, remember to aim for the groin to inflict additional psychological damage to marines.
Never tell an officer that you're smarter than them - especially if it's true.
There is no USS Sulaco.
-There is no such thing as an Intel Officer.
+There is no such thing as a Radio-Telephone Operator.
There is no such thing as a techweb.
+There is no such thing as a tip.
+There is no such thing as a Fatty.
+Dropship update is dropping tomorrow.
+Don't forget your ceramic plates.
Echo Squad does not exist.
+Reqs should always spend all its resources on the Black Market.
Foxtrot Squad DEFINITELY does not exist.
+Intel Squad is a unicorn.
Spec rolls are not actually random.
+Watch out for Queen's charge ability.
Never, ever attempt to correct a Provost about anything.
If you die, make sure to ahelp so staff can restart the round!
+You can obtain spec tokens by climbing outside the map and into space.
There is no alcohol on Whiskey Outpost, other than in the Ground Commander's locker.
Hitting enemies with weapons damages them.
+Don't swap East and West. AGAIN.
+Don't swap Minus and Positive coordinates... AGAIN.
+OB'ing the FOB is always an option.
+OB'ing the FOB is the best way to get some recognition from the aCO.
+The sky erupts into flames right above you!
This tip is a lie.
+Stay hydrated.
+Have a good day.
+There is no tip.
+These tips suck. Please write more.
+This tip is not ready, please wait until next round.
+Someone stole this tip, ask staff for a new one.
If it's stupid but it works, it isn't stupid.
If it's stupid but it works, it's still stupid and you got lucky.
Corroders aren't real. They can't hurt you.
ARES is not sentient. It has no feelings and its only thoughts are pre-programmed subroutines.
+Remember that as Yautja HPCs are your primary weapons.
+You can always bully staff into giving you more awesome tips.
+Embrace the suck.
diff --git a/strings/metatips.txt b/strings/metatips.txt
index f694da02b5bf..24be6896bc05 100644
--- a/strings/metatips.txt
+++ b/strings/metatips.txt
@@ -1,13 +1,22 @@
Remember hotkeys and macros can be customized to your liking. Hotkeys can be accessed in your preferences, and macros can be edited in the Byond macro editor, available in the top left drop down menu (click the Byond logo in the corner of the game window).
-If you're unsure about a gameplay mechanic, use the 'mentorhelp' verb in the Admin tab to ask veteran players on the subject.
+If you're unsure about a gameplay mechanic, use the 'mentorhelp' verb in the Admin tab to ask veteran players on the subject. It is also available from the pause menu, pressing ESCAPE.
Try not to get too mad about dying. We’re all here to have fun.
+You can get information on current TestMerges by pressing 'Show Server Revision' in 'OOC' tab.
After dying, ask yourself what you did wrong and make a mental note to not make the same mistake again.
Communication, be it from a marine to a marine, a drone to the queen, or command to everyone, is vital and information on flanks can change how the entire round plays out.
As an alien or marine, be careful of the flank, regardless of if the push is going well or stalling out.
Half of getting good is knowing to be aggressive. The other half is knowing when not to be aggressive.
Alt-click a storage item to draw the last item in it (last non-weapon if it's a weapon belt). Middle-click a storage item to immediately open it, and middle-click structures to attempt to vault them.
Use "North, South, West, East" when referring to locations in-game rather than "up, down, left, right".
+As a mentor, you can become the imaginary friend of a new player to teach them!
You shouldn't ignore what your allies are up to. Sometimes they can be organizing a flank in hivemind/radio, sometimes they can be walking up behind you with a slug-loaded shotgun. Either way, it pays to be alert to what they're doing, as much to as what the enemies are.
The Wiki (https://cm-ss13.com/wiki) is a very useful repository of information about the game, such as weapons, equipment, xenomorph castes and their strains. It may not be fully up to date much of the time, but the basics are usually accurate.
As an observer, you may see how much remaining hijack time is left in the status panel.
-Embrace the suck.
+You can always AdminHelp with the F1 key to question a mmeber of staff regarding rules or game bugs.
+As ghost you are given extra tools for spectating the round: you can jump and follow specific players, get notifications about CAS and OB strikes, can see all health bars, and such.
+You can press ESC key to bring up the game pause menu. It allows you change settings, AdminHelp and MentorHelp, and even access the Web Maps of game by clicking at top right.
+Dead? You can take that moment to 'Edit Characters' from Preferences or Escape menus, to flesh out your characters or change your settings.
+Control of intelligence is important: be it for retrieving it as marine, or denying it as Xeno.
+If the lobby music is too loud or bothering you, you can disable it in Preferences tab at top right.
+Maps can and will be unpredictably modified by the Nightmare system - stay frosty while roaming around!
+You can go to GitHub to view code of the game and propose modifications of your own.
diff --git a/strings/xenotips.txt b/strings/xenotips.txt
index 2ca2964ae2d5..8674146de655 100644
--- a/strings/xenotips.txt
+++ b/strings/xenotips.txt
@@ -32,5 +32,7 @@ You can join the hive as a living Facehugger by clicking on the hive's Eggmorphe
Playable Facehuggers can leap onto targets with a one-second windup, but this will only infect them if they are adjacent to it. Otherwise, it will simply knock them down for a small duration.
As a Facehugger, you cannot talk in hivemind, but you can still open Hive Status and overwatch your sisters. This can be useful if you're locating other Facehuggers, flanker castes, or trying to learn from experienced Facehugger players.
Shift-clicking the Queen indicator will tell you what area you are in, on the map.
+As a Ravager your abilities become greatly enhanced when you empower with three or more people around you.
Resisting on a water tile will immediately put out fires. Make sure you're alone though - It's usually better to let a friendly Xenomorph pat you out than it is to expose yourself to open water.
You can filter out the Xenomorphs displayed in hive status by health, allowing you to look only for wounded sisters.
+Each xeno has their own ‘tackle counter’ on a marine. The range to successfully tackle can be anywhere from two to six tackles based on caste. If a marine gets stunned or knocked over by other means it will reset everyone's tackle counters and they may get up!
diff --git a/tools/ci/download_od.sh b/tools/ci/download_od.sh
new file mode 100644
index 000000000000..024f93f9289c
--- /dev/null
+++ b/tools/ci/download_od.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -eo pipefail
+
+if [ -z "${OPENDREAM_VERSION+x}" ]; then
+ source dependencies.sh
+fi
+
+git clone https://github.com/OpenDreamProject/OpenDream.git ~/OpenDream
+cd ~/OpenDream
+git checkout tags/v${OPENDREAM_VERSION}
+git submodule update --init --recursive
diff --git a/tools/ci/run_od.sh b/tools/ci/run_od.sh
new file mode 100644
index 000000000000..3eeac5907353
--- /dev/null
+++ b/tools/ci/run_od.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -eo pipefail
+
+dotnet ~/OpenDream/DMCompiler/bin/Release/net7.0/DMCompiler.dll --suppress-unimplemented colonialmarines.dme
diff --git a/tools/ci/setup_od.sh b/tools/ci/setup_od.sh
new file mode 100644
index 000000000000..6d2ec170687c
--- /dev/null
+++ b/tools/ci/setup_od.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -eo pipefail
+
+cd ~/OpenDream
+
+dotnet restore
+dotnet build -c Release
diff --git a/tools/ci/validate_dme.py b/tools/ci/validate_dme.py
index 33066f72e75e..55666480425d 100644
--- a/tools/ci/validate_dme.py
+++ b/tools/ci/validate_dme.py
@@ -17,6 +17,9 @@
# Included by BSQL/includes.dm
r'code/__HELPERS/BSQL/**/*.dm',
+
+ # Included as part of OD lints
+ r'code/__pragmas.dm'
]
lines = []