diff --git a/.github/workflows/update_tgs_dmapi.yml b/.github/workflows/update_tgs_dmapi.yml
index 8dfdee90e36a0..232c02c0ecbed 100644
--- a/.github/workflows/update_tgs_dmapi.yml
+++ b/.github/workflows/update_tgs_dmapi.yml
@@ -21,6 +21,7 @@ jobs:
- name: Apply DMAPI update
uses: tgstation/tgs-dmapi-updater@v2
+ id: dmapi-update
with:
header-path: 'code/__DEFINES/tgs.dm'
library-path: 'code/modules/tgs'
@@ -41,7 +42,7 @@ jobs:
source_branch: "tgs-dmapi-update"
destination_branch: "master"
pr_title: "Automatic TGS DMAPI Update"
- pr_body: "This pull request updates the TGS DMAPI to the latest version. Please note any changes that may be breaking or unimplemented in your codebase by checking what changes are in the definitions file: code/__DEFINES/tgs.dm before merging."
+ pr_body: "This pull request updates the TGS DMAPI to the latest version. Please note any changes that may be breaking or unimplemented in your codebase by checking what changes are in the definitions file: code/__DEFINES/tgs.dm before merging.\n\n${{ steps.dmapi-update.outputs.release-notes }}"
pr_label: "Tools"
pr_allow_empty: false
github_token: ${{ secrets.COMFY_ORANGE_PAT }}
diff --git a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm
index 21b981191aeb3..abccc6b550eb1 100644
--- a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm
+++ b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm
@@ -562,7 +562,7 @@
/obj/machinery/airalarm/directional/north,
/obj/effect/mapping_helpers/airalarm/all_access,
/obj/machinery/icecream_vat{
- desc = "Waffle co. actually ordered these guys to steal one of these just to be sure."
+ desc = "Waffle Corp. actually ordered these guys to steal one of these just to be sure."
},
/turf/open/floor/plating,
/area/ruin/space/has_grav/infested_frigate)
diff --git a/_maps/safehouses/bathroom.dmm b/_maps/safehouses/bathroom.dmm
index 76712d6193c44..69ad0b25e9520 100644
--- a/_maps/safehouses/bathroom.dmm
+++ b/_maps/safehouses/bathroom.dmm
@@ -27,7 +27,7 @@
dir = 4
},
/obj/machinery/light/small/blacklight/directional/east,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"v" = (
/obj/machinery/light/small/blacklight/directional/east,
@@ -68,7 +68,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"M" = (
/obj/effect/decal/cleanable/dirt,
diff --git a/_maps/safehouses/den.dmm b/_maps/safehouses/den.dmm
index 15debc7e284e6..9b0b37f535150 100644
--- a/_maps/safehouses/den.dmm
+++ b/_maps/safehouses/den.dmm
@@ -18,7 +18,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"e" = (
/obj/structure/table/reinforced/plastitaniumglass,
@@ -59,7 +59,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"z" = (
/obj/effect/turf_decal/trimline/yellow/corner{
diff --git a/_maps/safehouses/dig.dmm b/_maps/safehouses/dig.dmm
index 73f0d247dfbe4..aa26f980d6089 100644
--- a/_maps/safehouses/dig.dmm
+++ b/_maps/safehouses/dig.dmm
@@ -20,7 +20,7 @@
dir = 8
},
/obj/effect/landmark/bitrunning/cache_goal_turf,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"i" = (
/obj/effect/turf_decal/siding/yellow{
@@ -98,7 +98,7 @@
/obj/effect/turf_decal/loading_area,
/obj/effect/turf_decal/box/corners,
/obj/effect/landmark/bitrunning/cache_goal_turf,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"T" = (
/obj/effect/landmark/bitrunning/hololadder_spawn,
diff --git a/_maps/safehouses/ice.dmm b/_maps/safehouses/ice.dmm
index 96d689339ab87..f9716de71032f 100644
--- a/_maps/safehouses/ice.dmm
+++ b/_maps/safehouses/ice.dmm
@@ -60,7 +60,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"p" = (
/obj/structure/railing,
@@ -69,7 +69,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"u" = (
/obj/effect/decal/cleanable/dirt/dust,
diff --git a/_maps/safehouses/lavaland_boss.dmm b/_maps/safehouses/lavaland_boss.dmm
index 7331a5b79d7a0..56141803990a5 100644
--- a/_maps/safehouses/lavaland_boss.dmm
+++ b/_maps/safehouses/lavaland_boss.dmm
@@ -63,7 +63,7 @@
/obj/machinery/light/directional/east,
/obj/structure/railing,
/obj/effect/landmark/bitrunning/cache_goal_turf,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"A" = (
/obj/effect/turf_decal/trimline/brown/filled/line{
diff --git a/_maps/safehouses/mine.dmm b/_maps/safehouses/mine.dmm
index 904c3c5378e8a..4bf99ab14f3ac 100644
--- a/_maps/safehouses/mine.dmm
+++ b/_maps/safehouses/mine.dmm
@@ -26,7 +26,7 @@
},
/obj/machinery/light/directional/east,
/obj/effect/landmark/bitrunning/cache_goal_turf,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"B" = (
/obj/effect/turf_decal/trimline/brown/filled/line{
@@ -52,7 +52,7 @@
},
/obj/structure/railing,
/obj/effect/landmark/bitrunning/cache_goal_turf,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"H" = (
/obj/machinery/door/airlock/external/glass{
diff --git a/_maps/safehouses/shuttle.dmm b/_maps/safehouses/shuttle.dmm
index 75fe975258c51..19f0c4b73aacc 100644
--- a/_maps/safehouses/shuttle.dmm
+++ b/_maps/safehouses/shuttle.dmm
@@ -16,7 +16,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/landmark/bitrunning/cache_goal_turf,
/obj/effect/turf_decal/loading_area,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"i" = (
/obj/effect/turf_decal/stripes/line{
@@ -41,7 +41,7 @@
/obj/machinery/light/small/directional/south,
/obj/effect/landmark/bitrunning/cache_goal_turf,
/obj/effect/turf_decal/loading_area,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"m" = (
/obj/modular_map_connector,
diff --git a/_maps/safehouses/shuttle_space.dmm b/_maps/safehouses/shuttle_space.dmm
index 0029f5b0a6e7d..2f4071a834755 100644
--- a/_maps/safehouses/shuttle_space.dmm
+++ b/_maps/safehouses/shuttle_space.dmm
@@ -67,7 +67,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/landmark/bitrunning/cache_goal_turf,
/obj/effect/turf_decal/loading_area,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"z" = (
/obj/effect/turf_decal/stripes/line{
@@ -98,7 +98,7 @@
/obj/machinery/light/small/directional/south,
/obj/effect/landmark/bitrunning/cache_goal_turf,
/obj/effect/turf_decal/loading_area,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"E" = (
/obj/effect/turf_decal/stripes/line{
diff --git a/_maps/safehouses/wood.dmm b/_maps/safehouses/wood.dmm
index 05fbb97f915fb..5faa33faa4181 100644
--- a/_maps/safehouses/wood.dmm
+++ b/_maps/safehouses/wood.dmm
@@ -19,7 +19,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"v" = (
/obj/machinery/light/small/directional/east,
@@ -50,7 +50,7 @@
/obj/effect/turf_decal/loading_area{
dir = 4
},
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/safehouse)
"T" = (
/obj/effect/landmark/bitrunning/hololadder_spawn,
diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm
index fa04316b9b626..c9010062f54b1 100644
--- a/_maps/virtual_domains/island_brawl.dmm
+++ b/_maps/virtual_domains/island_brawl.dmm
@@ -2540,7 +2540,7 @@
/area/virtual_domain)
"GD" = (
/obj/effect/landmark/bitrunning/permanent_exit,
-/turf/open/floor/bitrunning_transport,
+/turf/open/indestructible/bitrunning_transport,
/area/virtual_domain/protected_space/fullbright)
"GI" = (
/turf/open/floor/iron/dark/textured_large,
diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm
index 345ff07ea18a2..2dcb96b8c42f1 100644
--- a/code/__DEFINES/sound.dm
+++ b/code/__DEFINES/sound.dm
@@ -176,3 +176,5 @@ GLOBAL_LIST_INIT(announcer_keys, list(
#define SFX_PORTAL_CLOSE "portal_closed"
#define SFX_PORTAL_CREATED "portal_created"
#define SFX_SCREECH "screech"
+#define SFX_STONE_DROP "stone_drop"
+#define SFX_STONE_PICKUP "stone_pickup"
diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm
index 17464b44dae81..4766b3dfe661e 100644
--- a/code/__DEFINES/tgs.dm
+++ b/code/__DEFINES/tgs.dm
@@ -1,18 +1,19 @@
// tgstation-server DMAPI
+// The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119.
-#define TGS_DMAPI_VERSION "7.1.3"
+#define TGS_DMAPI_VERSION "7.2.1"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
// CONFIGURATION
-/// Create this define if you want to do TGS configuration outside of this file.
+/// Consumers SHOULD create this define if you want to do TGS configuration outside of this file.
#ifndef TGS_EXTERNAL_CONFIGURATION
-// Comment this out once you've filled in the below.
+// Consumers MUST comment this out once you've filled in the below and are not using [TGS_EXTERNAL_CONFIGURATION].
#error TGS API unconfigured
-// Uncomment this if you wish to allow the game to interact with TGS 3..
+// Consumers MUST uncomment this if you wish to allow the game to interact with TGS version 3.
// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()().
//#define TGS_V3_API
@@ -52,7 +53,7 @@
#ifndef TGS_FILE2TEXT_NATIVE
#ifdef file2text
-#error Your codebase is re-defining the BYOND proc file2text. The DMAPI requires the native version to read the result of world.Export(). You can fix this by adding "#define TGS_FILE2TEXT_NATIVE file2text" before your override of file2text to allow the DMAPI to use the native version. This will only be used for world.Export(), not regular file accesses
+#error Your codebase is re-defining the BYOND proc file2text. The DMAPI requires the native version to read the result of world.Export(). You SHOULD fix this by adding "#define TGS_FILE2TEXT_NATIVE file2text" before your override of file2text to allow the DMAPI to use the native version. This will only be used for world.Export(), not regular file accesses
#endif
#define TGS_FILE2TEXT_NATIVE file2text
#endif
@@ -152,16 +153,17 @@
//REQUIRED HOOKS
/**
- * Call this somewhere in [/world/proc/New] that is always run. This function may sleep!
+ * Consumers MUST call this somewhere in [/world/proc/New] that is always run. This function may sleep!
*
* * event_handler - Optional user defined [/datum/tgs_event_handler].
* * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED].
+ * * http_handler - Optional user defined [/datum/tgs_http_handler].
*/
-/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
+/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE, datum/tgs_http_handler/http_handler)
return
/**
- * Call this when your initializations are complete and your game is ready to play before any player interactions happen.
+ * Consumers MUST call this when world initializations are complete and the game is ready to play before any player interactions happen.
*
* This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running.
* Afterwards, consider explicitly setting it to what you want to avoid this BYOND bug: http://www.byond.com/forum/post/2575184
@@ -170,12 +172,10 @@
/world/proc/TgsInitializationComplete()
return
-/// Put this at the start of [/world/proc/Topic].
+/// Consumers MUST run this macro at the start of [/world/proc/Topic].
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return
-/**
- * Call this as late as possible in [world/proc/Reboot] (BEFORE ..()).
- */
+/// Consumers MUST call this as late as possible in [world/proc/Reboot] (BEFORE ..()).
/world/proc/TgsReboot()
return
@@ -269,7 +269,7 @@
/// The [/datum/tgs_chat_channel] the user was from.
var/datum/tgs_chat_channel/channel
-/// User definable handler for TGS events.
+/// User definable handler for TGS events This abstract version SHOULD be overridden to be used.
/datum/tgs_event_handler
/// If the handler receieves [TGS_EVENT_HEALTH_CHECK] events.
var/receive_health_checks = FALSE
@@ -283,7 +283,41 @@
set waitfor = FALSE
return
-/// User definable chat command.
+/// User definable handler for HTTP calls. This abstract version MUST be overridden to be used.
+/datum/tgs_http_handler
+
+/**
+ * User definable callback for executing HTTP GET requests.
+ * MUST perform BYOND sleeps while the request is in flight.
+ * MUST return a [/datum/tgs_http_result].
+ * SHOULD log its own errors
+ *
+ * url - The full URL to execute the GET request for including query parameters.
+ */
+/datum/tgs_http_handler/proc/PerformGet(url)
+ CRASH("[type]/PerformGet not implemented!")
+
+/// Result of a [/datum/tgs_http_handler] call. MUST NOT be overridden.
+/datum/tgs_http_result
+ /// HTTP response as text
+ var/response_text
+ /// Boolean request success flag. Set for any 2XX response code.
+ var/success
+
+/**
+ * Create a [/datum/tgs_http_result].
+ *
+ * * response_text - HTTP response as text. Must be provided in New().
+ * * success - Boolean request success flag. Set for any 2XX response code. Must be provided in New().
+ */
+/datum/tgs_http_result/New(response_text, success)
+ if(response_text && !istext(response_text))
+ CRASH("response_text was not text!")
+
+ src.response_text = response_text
+ src.success = success
+
+/// User definable chat command. This abstract version MUST be overridden to be used.
/datum/tgs_chat_command
/// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...`.
var/name = ""
@@ -296,21 +330,27 @@
/**
* Process command activation. Should return a [/datum/tgs_message_content] to respond to the issuer with.
+ * MUST be implemented
*
- * sender - The [/datum/tgs_chat_user] who issued the command.
- * params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
+ * * sender - The [/datum/tgs_chat_user] who issued the command.
+ * * params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
*/
/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params)
CRASH("[type] has no implementation for Run()")
-/// User definable chat message.
+/// User definable chat message. MUST NOT be overridden.
/datum/tgs_message_content
- /// The tring content of the message. Must be provided in New().
+ /// The string content of the message. Must be provided in New().
var/text
/// The [/datum/tgs_chat_embed] to embed in the message. Not supported on all chat providers.
var/datum/tgs_chat_embed/structure/embed
+/**
+ * Create a [/datum/tgs_message_content].
+ *
+ * * text - The string content of the message.
+ */
/datum/tgs_message_content/New(text)
..()
if(!istext(text))
@@ -319,7 +359,7 @@
src.text = text
-/// User definable chat embed. Currently mirrors Discord chat embeds. See https://discord.com/developers/docs/resources/channel#embed-object-embed-structure for details.
+/// User definable chat embed. Currently mirrors Discord chat embeds. See https://discord.com/developers/docs/resources/message#embed-object for details.
/datum/tgs_chat_embed/structure
var/title
var/description
@@ -331,13 +371,13 @@
/// Colour must be #AARRGGBB or #RRGGBB hex string.
var/colour
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-image-structure for details.
var/datum/tgs_chat_embed/media/image
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-thumbnail-structure for details.
var/datum/tgs_chat_embed/media/thumbnail
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-video-structure for details.
var/datum/tgs_chat_embed/media/video
var/datum/tgs_chat_embed/footer/footer
@@ -346,7 +386,7 @@
var/list/datum/tgs_chat_embed/field/fields
-/// Common datum for similar discord embed medias.
+/// Common datum for similar Discord embed medias.
/datum/tgs_chat_embed/media
/// Must be set in New().
var/url
@@ -354,6 +394,7 @@
var/height
var/proxy_url
+/// Create a [/datum/tgs_chat_embed].
/datum/tgs_chat_embed/media/New(url)
..()
if(!istext(url))
@@ -361,13 +402,14 @@
src.url = url
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure for details.
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-footer-structure for details.
/datum/tgs_chat_embed/footer
/// Must be set in New().
var/text
var/icon_url
var/proxy_icon_url
+/// Create a [/datum/tgs_chat_embed/footer].
/datum/tgs_chat_embed/footer/New(text)
..()
if(!istext(text))
@@ -375,16 +417,17 @@
src.text = text
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-provider-structure for details.
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-provider-structure for details.
/datum/tgs_chat_embed/provider
var/name
var/url
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure for details. Must have name set in New().
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-author-structure for details. Must have name set in New().
/datum/tgs_chat_embed/provider/author
var/icon_url
var/proxy_icon_url
+/// Create a [/datum/tgs_chat_embed/footer].
/datum/tgs_chat_embed/provider/author/New(name)
..()
if(!istext(name))
@@ -392,12 +435,15 @@
src.name = name
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure for details. Must have name and value set in New().
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-field-structure for details.
/datum/tgs_chat_embed/field
+ /// Must be set in New().
var/name
+ /// Must be set in New().
var/value
var/is_inline
+/// Create a [/datum/tgs_chat_embed/field].
/datum/tgs_chat_embed/field/New(name, value)
..()
if(!istext(name))
diff --git a/code/__HELPERS/_dreamluau.dm b/code/__HELPERS/_dreamluau.dm
index 76d38effd19a2..196774d6a88e8 100644
--- a/code/__HELPERS/_dreamluau.dm
+++ b/code/__HELPERS/_dreamluau.dm
@@ -1,4 +1,6 @@
-#define DREAMLUAU (world.system_type == MS_WINDOWS ? "dreamluau.dll" : "libdreamluau.so")
+/* This comment bypasses grep checks */ /var/__dreamluau
+
+#define DREAMLUAU (world.system_type == MS_WINDOWS ? "dreamluau.dll" : (__dreamluau || (__dreamluau = __detect_auxtools("dreamluau"))))
#define DREAMLUAU_CALL(func) call_ext(DREAMLUAU, "byond:[#func]")
diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm
index 36679fa1d2a02..a8c42631488e5 100644
--- a/code/controllers/subsystem/persistence/_persistence.dm
+++ b/code/controllers/subsystem/persistence/_persistence.dm
@@ -43,8 +43,6 @@ SUBSYSTEM_DEF(persistence)
/// List of persistene ids which piggy banks.
var/list/queued_broken_piggy_ids
- var/list/broken_piggy_banks
-
var/rounds_since_engine_exploded = 0
var/delam_highscore = 0
var/tram_hits_this_round = 0
diff --git a/code/datums/components/gunpoint.dm b/code/datums/components/gunpoint.dm
index ed4142f41ceba..edde591c0c386 100644
--- a/code/datums/components/gunpoint.dm
+++ b/code/datums/components/gunpoint.dm
@@ -48,7 +48,7 @@
RegisterSignals(targ, list(COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_GET_PULLED), PROC_REF(cancel))
RegisterSignals(weapon, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED), PROC_REF(cancel))
- var/distance = min(get_dist(shooter, target), 1) // treat 0 distance as adjacent
+ var/distance = max(get_dist(shooter, target), 1) // treat 0 distance as adjacent
var/distance_description = (distance <= 1 ? "point blank " : "")
shooter.visible_message(span_danger("[shooter] aims [weapon] [distance_description]at [target]!"),
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index d831ba2f0d964..d64022d22b872 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -295,6 +295,8 @@
if (uplink_handler.telecrystals <= 0)
return
var/desired_amount = tgui_input_number(ui.user, "How many raw telecrystals to buy?", "Buy Raw TC", default = uplink_handler.telecrystals, max_value = uplink_handler.telecrystals)
+ if(!desired_amount || desired_amount < 1)
+ return
uplink_handler.purchase_raw_tc(ui.user, desired_amount, parent)
if("lock")
if(!lockable)
diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm
index 9560820f2f048..154027b8b9ae6 100644
--- a/code/datums/diseases/_disease.dm
+++ b/code/datums/diseases/_disease.dm
@@ -146,6 +146,8 @@
cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_HARMFUL)
if(DISEASE_SEVERITY_BIOHAZARD)
cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_BIOHAZARD)
+ else
+ cycles_to_beat = max(DISEASE_RECOVERY_SCALING, DISEASE_CYCLES_NONTHREAT)
peaked_cycles += stage/max_stages //every cycle we spend sick counts towards eventually curing the virus, faster at higher stages
recovery_prob += DISEASE_RECOVERY_CONSTANT + (peaked_cycles / (cycles_to_beat / DISEASE_RECOVERY_SCALING)) //more severe viruses are beaten back more aggressively after the peak
if(stage_peaked)
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 8c8e8e02169b4..82099a7532b52 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -265,7 +265,7 @@
properties["severity"] += round((properties["transmittable"] / 8), 1)
properties["severity"] = round((properties["severity"] / 2), 1)
properties["severity"] *= (symptoms.len / VIRUS_SYMPTOM_LIMIT) //fewer symptoms, less severity
- properties["severity"] = clamp(properties["severity"], 1, 7)
+ properties["severity"] = round(clamp(properties["severity"], 1, 7), 1)
properties["capacity"] = get_symptom_weights()
// Assign the properties that are in the list.
diff --git a/code/datums/elements/pet_collar.dm b/code/datums/elements/pet_collar.dm
new file mode 100644
index 0000000000000..5c49de2eceb5b
--- /dev/null
+++ b/code/datums/elements/pet_collar.dm
@@ -0,0 +1,95 @@
+/datum/element/wears_collar
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ ///our icon's pathfile
+ var/collar_icon
+ ///our collar's icon state
+ var/collar_icon_state
+ ///iconstate of our collar while resting
+ var/collar_resting_icon_state
+
+/datum/element/wears_collar/Attach(datum/target, collar_icon = 'icons/mob/simple/pets.dmi', collar_resting_icon_state = FALSE, collar_icon_state)
+ . = ..()
+
+ if(!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.collar_icon = collar_icon
+ src.collar_icon_state = collar_icon_state
+ src.collar_resting_icon_state = collar_resting_icon_state
+
+ RegisterSignal(target, COMSIG_ATOM_ATTACKBY, PROC_REF(attach_collar))
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_overlays_updated))
+ RegisterSignal(target, COMSIG_ATOM_EXITED, PROC_REF(on_content_exit))
+ RegisterSignal(target, COMSIG_ATOM_ENTERED, PROC_REF(on_content_enter))
+ RegisterSignal(target, COMSIG_LIVING_RESTING, PROC_REF(on_rest))
+ RegisterSignal(target, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change))
+
+/datum/element/wears_collar/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, list(
+ COMSIG_ATOM_ATTACKBY,
+ COMSIG_ATOM_UPDATE_OVERLAYS,
+ COMSIG_ATOM_EXITED,
+ COMSIG_ATOM_ENTERED,
+ COMSIG_LIVING_RESTING,
+ COMSIG_MOB_STATCHANGE,
+ ))
+
+/datum/element/wears_collar/proc/on_stat_change(mob/living/source)
+ SIGNAL_HANDLER
+
+ if(collar_icon_state)
+ source.update_icon(UPDATE_OVERLAYS)
+
+/datum/element/wears_collar/proc/on_content_exit(mob/living/source, atom/moved)
+ SIGNAL_HANDLER
+
+ if(!istype(moved, /obj/item/clothing/neck/petcollar))
+ return
+ source.fully_replace_character_name(null, source::name)
+ if(collar_icon_state)
+ source.update_appearance()
+
+/datum/element/wears_collar/proc/on_content_enter(mob/living/source, obj/item/clothing/neck/petcollar/new_collar)
+ SIGNAL_HANDLER
+
+ if(!istype(new_collar))
+ return
+
+ source.fully_replace_character_name(null, "\proper [new_collar.tagname]")
+ if(collar_icon_state)
+ source.update_appearance()
+
+/datum/element/wears_collar/proc/attach_collar(atom/source, atom/movable/attacking_item, atom/user, params)
+ SIGNAL_HANDLER
+
+ if(!istype(attacking_item, /obj/item/clothing/neck/petcollar))
+ return NONE
+ if(locate(/obj/item/clothing/neck/petcollar) in source)
+ user.balloon_alert(source, "already wearing a collar!")
+ return NONE
+ attacking_item.forceMove(source)
+ return COMPONENT_NO_AFTERATTACK
+
+/datum/element/wears_collar/proc/on_overlays_updated(mob/living/source, list/overlays)
+ SIGNAL_HANDLER
+
+ if(!locate(/obj/item/clothing/neck/petcollar) in source)
+ return
+
+ var/icon_tag = ""
+
+ if(source.stat == DEAD || HAS_TRAIT(source, TRAIT_FAKEDEATH))
+ icon_tag = "_dead"
+ else if(collar_resting_icon_state && source.resting)
+ icon_tag = "_rest"
+
+ overlays += mutable_appearance(collar_icon, "[collar_icon_state][icon_tag]collar")
+ overlays += mutable_appearance(collar_icon, "[collar_icon_state][icon_tag]tag")
+
+
+/datum/element/wears_collar/proc/on_rest(atom/movable/source)
+ SIGNAL_HANDLER
+
+ source.update_icon(UPDATE_OVERLAYS)
diff --git a/code/datums/elements/pet_cult.dm b/code/datums/elements/pet_cult.dm
new file mode 100644
index 0000000000000..36941e7b74299
--- /dev/null
+++ b/code/datums/elements/pet_cult.dm
@@ -0,0 +1,127 @@
+#define PET_CULT_ATTACK_UPPER 15
+#define PET_CULT_HEALTH 50
+
+/datum/element/cultist_pet
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ ///our pet cult icon's pathfile
+ var/pet_cult_icon
+ ///our pet cult icon state
+ var/pet_cult_icon_state
+
+/datum/element/cultist_pet/Attach(datum/target, pet_cult_icon = 'icons/mob/simple/pets.dmi', pet_cult_icon_state)
+ . = ..()
+
+ if(!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.pet_cult_icon = pet_cult_icon
+ src.pet_cult_icon_state = pet_cult_icon_state
+
+ RegisterSignal(target, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(become_cultist))
+ RegisterSignal(target, COMSIG_MOB_CLIENT_LOGIN, PROC_REF(on_login))
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_icon_state_updated))
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_overlays_updated))
+
+/datum/element/cultist_pet/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, list(
+ COMSIG_MOB_LOGIN,
+ COMSIG_LIVING_CULT_SACRIFICED,
+ COMSIG_ATOM_UPDATE_ICON_STATE,
+ COMSIG_ATOM_UPDATE_OVERLAYS,
+ ))
+
+/datum/element/cultist_pet/proc/on_overlays_updated(mob/living/basic/source, list/overlays)
+ SIGNAL_HANDLER
+
+ if(isnull(source.mind) && (FACTION_CULT in source.faction)) //cult indicator we show for non sentient pets
+ var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE)
+ overlays += cult_indicator
+
+/datum/element/cultist_pet/proc/on_icon_state_updated(mob/living/basic/source)
+ SIGNAL_HANDLER
+
+ if(pet_cult_icon_state && (FACTION_CULT in source.faction))
+ source.icon_state = pet_cult_icon_state
+ source.icon_living = pet_cult_icon_state
+
+///turn into terrifying beasts
+/datum/element/cultist_pet/proc/become_cultist(mob/living/basic/source, list/invokers, datum/team)
+ SIGNAL_HANDLER
+
+ if(source.stat == DEAD)
+ return
+
+ if(FACTION_CULT in source.faction)
+ return STOP_SACRIFICE
+
+ source.mind?.add_antag_datum(/datum/antagonist/cult, team)
+ qdel(source.GetComponent(/datum/component/obeys_commands)) //if we obey commands previously, forget about them
+ source.melee_damage_lower = max(PET_CULT_ATTACK_UPPER - 5, source::melee_damage_lower)
+ source.melee_damage_upper = max(PET_CULT_ATTACK_UPPER, source::melee_damage_upper)
+ source.maxHealth = max(PET_CULT_HEALTH, source::maxHealth)
+ source.fully_heal()
+
+ source.faction = list(FACTION_CULT) //we only serve the cult
+
+ if(isnull(pet_cult_icon_state))
+ source.add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
+
+ var/static/list/cult_appetite = list(
+ /obj/item/organ,
+ /obj/effect/decal/cleanable/blood,
+ )
+
+ var/static/list/death_loot = list(
+ /obj/effect/gibspawner/generic,
+ /obj/item/soulstone,
+ )
+
+ source.AddElement(/datum/element/basic_eating, heal_amt = 15, food_types = cult_appetite)
+ source.AddElement(/datum/element/death_drops, death_loot)
+
+ source.basic_mob_flags &= DEL_ON_DEATH
+ qdel(source.ai_controller)
+ source.ai_controller = new /datum/ai_controller/basic_controller/pet_cult(source)
+ var/datum/action/cooldown/spell/conjure/revive_rune/rune_ability = new(source)
+ rune_ability.Grant(source)
+ source.ai_controller.set_blackboard_key(BB_RUNE_ABILITY, rune_ability)
+ source.ai_controller.set_blackboard_key(BB_CULT_TEAM, team)
+
+ var/static/list/new_pet_commands = list(
+ /datum/pet_command/point_targeting/attack,
+ /datum/pet_command/follow,
+ /datum/pet_command/free,
+ /datum/pet_command/idle,
+ /datum/pet_command/untargeted_ability/draw_rune,
+ )
+ source.AddComponent(/datum/component/obeys_commands, new_pet_commands)
+ RegisterSignal(source, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(activate_rune))
+ source.update_appearance()
+ return STOP_SACRIFICE
+
+
+/datum/element/cultist_pet/proc/activate_rune(datum/source, atom/target)
+ SIGNAL_HANDLER
+
+ if(!istype(target, /obj/effect/rune/raise_dead)) //we can only revive people...
+ return NONE
+
+ INVOKE_ASYNC(target, TYPE_PROC_REF(/atom, attack_hand), source)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/datum/element/cultist_pet/proc/on_login(mob/living/source)
+ SIGNAL_HANDLER
+
+ if(!(FACTION_CULT in source.faction))
+ return
+ var/datum/team/cult_team = source.ai_controller.blackboard[BB_CULT_TEAM]
+ if(isnull(cult_team))
+ return
+ source.mind.add_antag_datum(/datum/antagonist/cult, cult_team)
+ source.update_appearance(UPDATE_OVERLAYS)
+
+
+#undef PET_CULT_ATTACK_UPPER
+#undef PET_CULT_HEALTH
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index 32a81d1f75f9c..6565bcae44f5b 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -74,7 +74,7 @@
/obj/item/soap/nanotrasen/cyborg
/obj/item/soap/deluxe
- desc = "A deluxe Waffle Co. brand bar of soap. Smells of high-class luxury."
+ desc = "A deluxe Waffle Corporation brand bar of soap. Smells of high-class luxury."
grind_results = list(/datum/reagent/consumable/aloejuice = 10, /datum/reagent/lye = 10)
icon_state = "soapdeluxe"
inhand_icon_state = "soapdeluxe"
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index 554db2beb5399..4211e2f507990 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -277,7 +277,7 @@
target_felinid.setDir(get_dir(target_felinid, targloc)) // kitty always looks at the light
if(prob(effectchance * diode.rating))
target_felinid.visible_message(span_warning("[target_felinid] makes a grab for the light!"), span_userdanger("LIGHT!"))
- target_felinid.Move(targloc)
+ target_felinid.Move(targloc, get_dir(target_felinid, targloc))
log_combat(user, target_felinid, "moved with a laser pointer", src)
else
target_felinid.visible_message(span_notice("[target_felinid] looks briefly distracted by the light."), span_warning("You're briefly tempted by the shiny light..."))
diff --git a/code/game/objects/items/food/monkeycube.dm b/code/game/objects/items/food/monkeycube.dm
index a364a251a8344..02882bb3776f4 100644
--- a/code/game/objects/items/food/monkeycube.dm
+++ b/code/game/objects/items/food/monkeycube.dm
@@ -82,7 +82,7 @@
/obj/item/food/monkeycube/gorilla
name = "gorilla cube"
- desc = "A Waffle Co. brand gorilla cube. Now with extra molecules!"
+ desc = "A Waffle Corp. brand gorilla cube. Now with extra molecules!"
bite_consumption = 20
food_reagents = list(
/datum/reagent/monkey_powder = 30,
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index cb4f419dbd809..5aadc9fbb3f23 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -501,7 +501,7 @@
/obj/item/grenade/chem_grenade/ez_clean
name = "cleaner grenade"
- desc = "Waffle Co.-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
+ desc = "Waffle Corp. brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
stage = GRENADE_READY
/obj/item/grenade/chem_grenade/ez_clean/Initialize(mapload)
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index dfcd6031d8729..7edc000920454 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -200,6 +200,8 @@
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 1.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.75)
breakouttime = 30 SECONDS
cuffsound = 'sound/weapons/cablecuff.ogg'
+ pickup_sound = null
+ drop_sound = null
restraint_strength = HANDCUFFS_TYPE_WEAK
/obj/item/restraints/handcuffs/cable/Initialize(mapload, new_color)
diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm
index 4e6795c182b24..848058a6a279e 100644
--- a/code/game/objects/items/knives.dm
+++ b/code/game/objects/items/knives.dm
@@ -190,7 +190,6 @@
desc = "A sharpened bone. The bare minimum in survival."
embed_type = /datum/embed_data/combat_knife/weak
obj_flags = parent_type::obj_flags & ~CONDUCTS_ELECTRICITY
- slot_flags = NONE
force = 15
throwforce = 15
custom_materials = null
@@ -202,7 +201,9 @@
name = "cyborg knife"
icon = 'icons/obj/items_cyborg.dmi'
icon_state = "knife_cyborg"
+ worn_icon_state = "knife_cyborg" //error sprite - this shouldn't have been dropped
desc = "A cyborg-mounted plasteel knife. Extremely sharp and durable."
+ slot_flags = NONE //you can't put this in your mouth
/obj/item/knife/shiv
name = "glass shiv"
diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm
index 410724862f3b5..2979541038980 100644
--- a/code/game/objects/items/stacks/bscrystal.dm
+++ b/code/game/objects/items/stacks/bscrystal.dm
@@ -21,6 +21,8 @@
points = 0
refined_type = null
merge_type = /obj/item/stack/ore/bluespace_crystal/refined
+ drop_sound = null //till I make a better one
+ pickup_sound = null
/obj/item/stack/ore/bluespace_crystal/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
. = ..()
@@ -60,6 +62,8 @@
refined_type = null
grind_results = list(/datum/reagent/bluespace = 10, /datum/reagent/silicon = 20)
merge_type = /obj/item/stack/ore/bluespace_crystal/artificial
+ drop_sound = null //till I make a better one
+ pickup_sound = null
//Polycrystals, aka stacks
/obj/item/stack/sheet/bluespace_crystal
@@ -79,6 +83,7 @@
material_type = /datum/material/bluespace
var/crystal_type = /obj/item/stack/ore/bluespace_crystal/refined
+
/obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening
to_chat(user, span_warning("You cannot crush the polycrystal in-hand, try breaking one off."))
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 425a624984550..7443085aa4d5f 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -940,6 +940,8 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/sandblock
material_type = /datum/material/sand
material_modifier = 1
+ drop_sound = SFX_STONE_DROP
+ pickup_sound = SFX_STONE_PICKUP
/obj/item/stack/sheet/sandblock/fifty
amount = 50
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index bd1f52a832349..32b825f803f61 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -532,7 +532,7 @@
/obj/item/storage/belt/military/snack/Initialize(mapload)
. = ..()
- var/sponsor = pick("Donk Co.", "Waffle Co.", "Roffle Co.", "Gorlax Marauders", "Tiger Cooperative")
+ var/sponsor = pick("Donk Co.", "Waffle Corp.", "Roffle Co.", "Gorlex Marauders", "Tiger Cooperative")
desc = "A set of snack-tical webbing worn by athletes of the [sponsor] VR sports division."
atom_storage.max_slots = 6
atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
diff --git a/code/game/objects/items/storage/boxes/science_boxes.dm b/code/game/objects/items/storage/boxes/science_boxes.dm
index f0654cdf024bc..48ab6cd5b7243 100644
--- a/code/game/objects/items/storage/boxes/science_boxes.dm
+++ b/code/game/objects/items/storage/boxes/science_boxes.dm
@@ -50,12 +50,12 @@
new cube_type(src)
/obj/item/storage/box/monkeycubes/syndicate
- desc = "Waffle Co. brand monkey cubes. Just add water and a dash of subterfuge!"
+ desc = "Waffle Corp. brand monkey cubes. Just add water and a dash of subterfuge!"
cube_type = /obj/item/food/monkeycube/syndicate
/obj/item/storage/box/gorillacubes
name = "gorilla cube box"
- desc = "Waffle Co. brand gorilla cubes. Do not taunt."
+ desc = "Waffle Corp. brand gorilla cubes. Do not taunt."
icon_state = "monkeycubebox"
illustration = null
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index c6b0d52cdc1c3..20e3846adefab 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -191,7 +191,7 @@
desc = "A hydraulic prying tool, simple but powerful."
icon = 'icons/obj/items_cyborg.dmi'
icon_state = "toolkit_engiborg_crowbar"
- worn_icon_state = "crowbar"
+ worn_icon_state = "toolkit_engiborg_crowbar" //error sprite - this shouldn't have been dropped
usesound = 'sound/items/jaws_pry.ogg'
force = 10
toolspeed = 0.5
diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm
index e06cd8c6771ef..9420156d91805 100644
--- a/code/game/objects/structures/water_structures/water_source.dm
+++ b/code/game/objects/structures/water_structures/water_source.dm
@@ -165,7 +165,7 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
icon_state = "[base_icon_state]-splash"
balloon_alert(user, "scooping tadpoles...")
- if(do_after(user, src, 5 SECONDS))
+ if(do_after(user, 5 SECONDS, src))
playsound(loc, 'sound/effects/slosh.ogg', 15, TRUE)
balloon_alert(user, "got a tadpole")
var/obj/item/fish/tadpole/tadpole = new(loc)
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 7c9784bcc7f61..49c716d8e0c56 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -472,4 +472,15 @@
'sound/creatures/monkey/monkey_screech_6.ogg',
'sound/creatures/monkey/monkey_screech_7.ogg',
)
+ if(SFX_STONE_DROP)
+ soundin = pick(
+ 'sound/items/stones/stone_drop1.ogg',
+ 'sound/items/stones/stone_drop2.ogg',
+ 'sound/items/stones/stone_drop3.ogg',
+ )
+ if(SFX_STONE_PICKUP)
+ soundin = pick(
+ 'sound/items/stones/stone_pick_up1.ogg',
+ 'sound/items/stones/stone_pick_up2.ogg',
+ )
return soundin
diff --git a/code/modules/admin/verbs/lua/lua_state.dm b/code/modules/admin/verbs/lua/lua_state.dm
index 37a60f1fdb5e1..577b0e365c2d8 100644
--- a/code/modules/admin/verbs/lua/lua_state.dm
+++ b/code/modules/admin/verbs/lua/lua_state.dm
@@ -55,6 +55,8 @@ GLOBAL_PROTECT(lua_state_stack)
var/status = result["status"]
if(!verbose && status != "error" && status != "panic" && status != "runtime" && !(result["name"] == "input" && (status == "finished" || length(result["return_values"]))))
return
+ if(status == "runtime" && supress_runtimes)
+ return
var/append_to_log = TRUE
var/index_of_log
if(log.len)
diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm
index fb7bc16cf24e0..a8389ca0bc155 100644
--- a/code/modules/admin/verbs/server.dm
+++ b/code/modules/admin/verbs/server.dm
@@ -16,10 +16,15 @@ ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibilit
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
+#define REGULAR_RESTART "Regular Restart"
+#define REGULAR_RESTART_DELAYED "Regular Restart (with delay)"
+#define HARD_RESTART "Hard Restart (No Delay/Feedback Reason)"
+#define HARDEST_RESTART "Hardest Restart (No actions, just reboot)"
+#define TGS_RESTART "Server Restart (Kill and restart DD)"
ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.", ADMIN_CATEGORY_SERVER)
- var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
+ var/list/options = list(REGULAR_RESTART, REGULAR_RESTART_DELAYED, HARD_RESTART, HARDEST_RESTART)
if(world.TgsAvailable())
- options += "Server Restart (Kill and restart DD)";
+ options += TGS_RESTART;
if(SSticker.admin_delay_notice)
if(alert(user, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes")
@@ -32,12 +37,12 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
BLACKBOX_LOG_ADMIN_VERB("Reboot World")
var/init_by = "Initiated by [user.holder.fakekey ? "Admin" : user.key]."
switch(result)
- if("Regular Restart")
+ if(REGULAR_RESTART)
if(!user.is_localhost())
if(alert(user, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", 10)
- if("Regular Restart (with delay)")
+ if(REGULAR_RESTART_DELAYED)
var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null
if(!delay)
return FALSE
@@ -45,16 +50,22 @@ ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.",
if(alert(user,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart")
return FALSE
SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", delay * 10)
- if("Hard Restart (No Delay, No Feeback Reason)")
+ if(HARD_RESTART)
to_chat(world, "World reboot - [init_by]")
world.Reboot()
- if("Hardest Restart (No actions, just reboot)")
+ if(HARDEST_RESTART)
to_chat(world, "Hard world reboot - [init_by]")
world.Reboot(fast_track = TRUE)
- if("Server Restart (Kill and restart DD)")
+ if(TGS_RESTART)
to_chat(world, "Server restart - [init_by]")
world.TgsEndProcess()
+#undef REGULAR_RESTART
+#undef REGULAR_RESTART_DELAYED
+#undef HARD_RESTART
+#undef HARDEST_RESTART
+#undef TGS_RESTART
+
ADMIN_VERB(end_round, R_SERVER, "End Round", "Forcibly ends the round and allows the server to restart normally.", ADMIN_CATEGORY_SERVER)
var/confirm = tgui_alert(user, "End the round and restart the game world?", "End Round", list("Yes", "Cancel"))
if(confirm != "Yes")
diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm
index 662af81249a5c..631bf04dcefc6 100644
--- a/code/modules/antagonists/heretic/influences.dm
+++ b/code/modules/antagonists/heretic/influences.dm
@@ -248,7 +248,7 @@
return SECONDARY_ATTACK_CALL_NORMAL
if(being_drained)
- balloon_alert(user, "already being drained!")
+ loc.balloon_alert(user, "already being drained!")
else
INVOKE_ASYNC(src, PROC_REF(drain_influence), user, 1)
@@ -280,15 +280,15 @@
/obj/effect/heretic_influence/proc/drain_influence(mob/living/user, knowledge_to_gain)
being_drained = TRUE
- balloon_alert(user, "draining influence...")
+ loc.balloon_alert(user, "draining influence...")
if(!do_after(user, 10 SECONDS, src, hidden = TRUE))
being_drained = FALSE
- balloon_alert(user, "interrupted!")
+ loc.balloon_alert(user, "interrupted!")
return
// We don't need to set being_drained back since we delete after anyways
- balloon_alert(user, "influence drained")
+ loc.balloon_alert(user, "influence drained")
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user)
heretic_datum.knowledge_points += knowledge_to_gain
diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm
index 4f7b8804f8a8e..bd6dbfacf457a 100644
--- a/code/modules/antagonists/nukeop/outfits.dm
+++ b/code/modules/antagonists/nukeop/outfits.dm
@@ -152,7 +152,7 @@
head = /obj/item/clothing/head/utility/hardhat/orange
shoes = /obj/item/clothing/shoes/workboots
glasses = /obj/item/clothing/glasses/meson
- faction = "the Donk Corporation"
+ faction = "Donk Company"
/datum/outfit/syndicate/reinforcement/waffle
name = "Syndicate Operative - Waffle Reinforcement"
diff --git a/code/modules/bitrunning/turfs.dm b/code/modules/bitrunning/turfs.dm
index 4c35153311e53..763388b6e0850 100644
--- a/code/modules/bitrunning/turfs.dm
+++ b/code/modules/bitrunning/turfs.dm
@@ -1,4 +1,4 @@
-/turf/open/floor/bitrunning_transport
+/turf/open/indestructible/bitrunning_transport
name = "circuit floor"
desc = "Looks complex. You can see the circuits running through the floor."
icon_state = "bitrunning"
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 63a0dd515c3f6..380cd0cf3fb53 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -118,33 +118,45 @@
. = ..()
if(!up)
. += visor_icon
-
-/obj/item/clothing/head/helmet/space/plasmaman/attackby(obj/item/hitting_item, mob/living/user)
- . = ..()
- if(istype(hitting_item, /obj/item/toy/crayon))
- if(smile == FALSE)
- var/obj/item/toy/crayon/CR = hitting_item
- to_chat(user, span_notice("You start drawing a smiley face on the helmet's visor.."))
- if(do_after(user, 2.5 SECONDS, target = src))
- smile = TRUE
- smile_color = CR.paint_color
- to_chat(user, "You draw a smiley on the helmet visor.")
- update_appearance()
- else
- to_chat(user, span_warning("Seems like someone already drew something on this helmet's visor!"))
- return
- if(istype(hitting_item, /obj/item/clothing/head))
- var/obj/item/clothing/hitting_clothing = hitting_item
- if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT)
- to_chat(user, span_notice("You cannot place [hitting_clothing.name] on helmet!"))
- return
- if(attached_hat)
- to_chat(user, span_notice("There's already something placed on helmet!"))
- return
- attached_hat = hitting_clothing
- to_chat(user, span_notice("You placed [hitting_clothing.name] on helmet!"))
- hitting_clothing.forceMove(src)
+ if(smile)
+ var/mutable_appearance/smiley = mutable_appearance(icon, smile_state)
+ smiley.color = smile_color
+ . += smiley
+
+/obj/item/clothing/head/helmet/space/plasmaman/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(istype(tool, /obj/item/toy/crayon))
+ if(smile)
+ to_chat(user, span_warning("Seems like someone already drew something on [src]'s visor!"))
+ return ITEM_INTERACT_BLOCKING
+
+ var/obj/item/toy/crayon/crayon = tool
+ to_chat(user, span_notice("You start drawing a smiley face on [src]'s visor..."))
+ if(!do_after(user, 2.5 SECONDS, target = src))
+ return ITEM_INTERACT_BLOCKING
+
+ smile = TRUE
+ smile_color = crayon.paint_color
+ to_chat(user, "You draw a smiley on [src] visor.")
update_appearance()
+ return ITEM_INTERACT_SUCCESS
+
+ if(!istype(tool, /obj/item/clothing/head))
+ return NONE
+
+ var/obj/item/clothing/hitting_clothing = tool
+ if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT)
+ to_chat(user, span_notice("You cannot place [hitting_clothing.name] on [src]!"))
+ return ITEM_INTERACT_BLOCKING
+
+ if(attached_hat)
+ to_chat(user, span_notice("There's already something placed on [src]!"))
+ return ITEM_INTERACT_BLOCKING
+
+ attached_hat = hitting_clothing
+ to_chat(user, span_notice("You placed [hitting_clothing.name] on [src]!"))
+ hitting_clothing.forceMove(src)
+ update_appearance()
+ return ITEM_INTERACT_SUCCESS
///By the by, helmets have the update_icon_updates_onmob element, so we don't have to call mob.update_worn_head()
/obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(mutable_appearance/standing, isinhands)
diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm
index 6e115af7df217..a8d07dc8d8769 100644
--- a/code/modules/food_and_drinks/machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/machinery/smartfridge.dm
@@ -417,7 +417,8 @@
for(var/obj/item/dispensed_item in src)
if(desired <= 0)
break
- if(params["path"] == "[dispensed_item.type]-[dispensed_item.name]")
+ var/item_name = "[dispensed_item.type]-[replacetext(replacetext(dispensed_item.name, "\proper", ""), "\improper", "")]"
+ if(params["path"] == item_name)
if(dispensed_item in component_parts)
CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.")
//dispense the item
diff --git a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
index ed2851366153c..23fd9616ee3cb 100644
--- a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
+++ b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm
@@ -167,6 +167,7 @@
belt = /obj/item/storage/belt/utility/full
head = /obj/item/clothing/head/utility/hardhat
uniform = /obj/item/clothing/under/color/yellow
+ l_pocket = /obj/item/modular_computer/pda/assistant
outfit_weight = 6
diff --git a/code/modules/loadout/categories/pocket.dm b/code/modules/loadout/categories/pocket.dm
index e1cddde76e5b9..fd3f11e112b27 100644
--- a/code/modules/loadout/categories/pocket.dm
+++ b/code/modules/loadout/categories/pocket.dm
@@ -106,10 +106,6 @@
name = "Plush (Moth)"
item_path = /obj/item/toy/plush/moth
-/datum/loadout_item/pocket_items/plush/narsie
- name = "Plush (Nar'sie)"
- item_path = /obj/item/toy/plush/narplush
-
/datum/loadout_item/pocket_items/plush/nukie
name = "Plush (Nukie)"
item_path = /obj/item/toy/plush/nukeplushie
@@ -122,10 +118,6 @@
name = "Plush (Plasmaman)"
item_path = /obj/item/toy/plush/plasmamanplushie
-/datum/loadout_item/pocket_items/plush/ratvar
- name = "Plush (Ratvar)"
- item_path = /obj/item/toy/plush/ratplush
-
/datum/loadout_item/pocket_items/plush/rouny
name = "Plush (Rouny)"
item_path = /obj/item/toy/plush/rouny
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
index ac026045674e8..77b8aa0bbce28 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
@@ -64,7 +64,7 @@
var/mob/living/carbon/human/human_occupant = occupant
if(!istype(human_occupant))
return
- if(!human_occupant.dropItemToGround(human_occupant.back))
+ if(!isnull(human_occupant.back) && !human_occupant.dropItemToGround(human_occupant.back))
return
if(!human_occupant.equip_to_slot_if_possible(mod_unit, mod_unit.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
return
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index 5d9809a01f798..e9e8b3a7c3daf 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -22,6 +22,9 @@
var/list/stack_overlays
var/scan_state = "" //Used by mineral turfs for their scan overlay.
var/spreadChance = 0 //Also used by mineral turfs for spreading veins
+ drop_sound = SFX_STONE_DROP
+ pickup_sound = SFX_STONE_PICKUP
+ sound_vary = TRUE
/obj/item/stack/ore/update_overlays()
. = ..()
diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm
index 031ec3d45256c..7dcbc4ae325b0 100644
--- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm
+++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm
@@ -41,8 +41,6 @@
/mob/living/basic/mining/lobstrosity/Initialize(mapload)
. = ..()
- var/static/list/food_types = list(/obj/item/fish/lavaloop)
- ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(food_types))
AddComponent(/datum/component/profound_fisher)
AddElement(/datum/element/mob_grabber)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW)
diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm
index 5ca1ca2cfd5b0..32ec66a62cc37 100644
--- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm
+++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm
@@ -34,6 +34,14 @@
/datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing,
/datum/ai_planning_subtree/find_fingers,
)
+
+/datum/ai_controller/basic_controller/lobstrosity/TryPossessPawn(atom/new_pawn)
+ . = ..()
+ if(. & AI_CONTROLLER_INCOMPATIBLE)
+ return
+ var/static/list/food_types = typecacheof(list(/obj/item/fish/lavaloop))
+ set_blackboard_key(BB_BASIC_FOODS, food_types)
+
///Ensure that juveline lobstrosities witll charge at things they can reach.
/datum/ai_controller/basic_controller/lobstrosity/juvenile
blackboard = list(
diff --git a/code/modules/mob/living/basic/pets/cat/cat.dm b/code/modules/mob/living/basic/pets/cat/cat.dm
index 400bd9ac9f173..2bcd715d7f5c8 100644
--- a/code/modules/mob/living/basic/pets/cat/cat.dm
+++ b/code/modules/mob/living/basic/pets/cat/cat.dm
@@ -24,8 +24,6 @@
response_harm_simple = "kick"
mobility_flags = MOBILITY_FLAGS_REST_CAPABLE_DEFAULT
gold_core_spawnable = FRIENDLY_SPAWN
- collar_icon_state = "cat"
- has_collar_resting_icon_state = TRUE
can_be_held = TRUE
ai_controller = /datum/ai_controller/basic_controller/cat
held_state = "cat2"
@@ -33,7 +31,8 @@
attack_verb_simple = "claw"
attack_sound = 'sound/weapons/slash.ogg'
attack_vis_effect = ATTACK_EFFECT_CLAW
- cult_icon_state = "cat_cult"
+ ///icon of the collar we can wear
+ var/collar_icon_state = "cat"
///can this cat breed?
var/can_breed = TRUE
///can hold items?
@@ -50,9 +49,13 @@
var/obj/item/held_food
///mutable appearance for held item
var/mutable_appearance/held_item_overlay
+ ///icon state of our cult icon
+ var/cult_icon_state = "cat_cult"
/mob/living/basic/pet/cat/Initialize(mapload)
. = ..()
+ AddElement(/datum/element/cultist_pet, pet_cult_icon_state = cult_icon_state)
+ AddElement(/datum/element/wears_collar, collar_icon_state = collar_icon_state, collar_resting_icon_state = TRUE)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/pet_bonus, "purrs!")
AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW)
@@ -147,7 +150,6 @@
icon_living = "breadcat"
icon_dead = "breadcat_dead"
ai_controller = /datum/ai_controller/basic_controller/cat/bread
- collar_icon_state = null
held_state = "breadcat"
can_interact_with_stove = TRUE
butcher_results = list(
@@ -156,6 +158,7 @@
/obj/item/organ/external/tail/cat = 1,
/obj/item/food/breadslice/plain = 1
)
+ collar_icon_state = null
/mob/living/basic/pet/cat/breadcat/add_cell_sample()
return
@@ -167,7 +170,6 @@
icon_state = "original"
icon_living = "original"
icon_dead = "original_dead"
- collar_icon_state = null
unique_pet = TRUE
held_state = "original"
@@ -183,10 +185,10 @@
density = FALSE
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
- collar_icon_state = "kitten"
can_breed = FALSE
ai_controller = /datum/ai_controller/basic_controller/cat/kitten
can_hold_item = FALSE
+ collar_icon_state = "kitten"
/mob/living/basic/pet/cat/kitten/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm
index 5cd970575ec6f..b1c2c5e486fc1 100644
--- a/code/modules/mob/living/basic/pets/dog/_dog.dm
+++ b/code/modules/mob/living/basic/pets/dog/_dog.dm
@@ -44,9 +44,15 @@
/datum/pet_command/point_targeting/fetch,
/datum/pet_command/play_dead,
)
+ ///icon state of the collar we can wear
+ var/collar_icon_state
+ ///icon state of our cult icon
+ var/cult_icon_state
/mob/living/basic/pet/dog/Initialize(mapload)
. = ..()
+ AddElement(/datum/element/cultist_pet, pet_cult_icon_state = cult_icon_state)
+ AddElement(/datum/element/wears_collar, collar_icon_state = collar_icon_state)
ADD_TRAIT(src, TRAIT_WOUND_LICKER, INNATE_TRAIT)
AddElement(/datum/element/pet_bonus, "woofs happily!")
AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW)
diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm
index 7e13c792d2830..e1f05b33d81fb 100644
--- a/code/modules/mob/living/basic/pets/dog/corgi.dm
+++ b/code/modules/mob/living/basic/pets/dog/corgi.dm
@@ -544,9 +544,9 @@
pass_flags = PASSMOB
ai_controller = /datum/ai_controller/basic_controller/dog/puppy
mob_size = MOB_SIZE_SMALL
- collar_icon_state = "puppy"
strippable_inventory_slots = list(/datum/strippable_item/pet_collar, /datum/strippable_item/corgi_id) //puppies are too small to handle hats and back slot items
can_breed = FALSE
+ collar_icon_state = "puppy"
//PUPPY IAN! SQUEEEEEEEEE~
/mob/living/basic/pet/dog/corgi/puppy/ian
diff --git a/code/modules/mob/living/basic/pets/dog/strippable_items.dm b/code/modules/mob/living/basic/pets/dog/strippable_items.dm
index 2799ca38b978f..c92948e2b6ffd 100644
--- a/code/modules/mob/living/basic/pets/dog/strippable_items.dm
+++ b/code/modules/mob/living/basic/pets/dog/strippable_items.dm
@@ -38,11 +38,11 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
key = STRIPPABLE_ITEM_PET_COLLAR
/datum/strippable_item/pet_collar/get_item(atom/source)
- var/mob/living/basic/pet/pet_source = source
+ var/mob/living/basic/pet_source = source
if(!istype(pet_source))
return
- return pet_source.collar
+ return (locate(/obj/item/clothing/neck/petcollar) in source)
/datum/strippable_item/pet_collar/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
@@ -56,18 +56,10 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
return TRUE
/datum/strippable_item/pet_collar/finish_equip(atom/source, obj/item/equipping, mob/user)
- var/mob/living/basic/pet/pet_source = source
- if(!istype(pet_source))
- return
-
- pet_source.add_collar(equipping, user)
+ user.transferItemToLoc(equipping, source)
/datum/strippable_item/pet_collar/finish_unequip(atom/source, mob/user)
- var/mob/living/basic/pet/pet_source = source
- if(!istype(pet_source))
- return
-
- var/obj/collar = pet_source.remove_collar(user.drop_location())
+ var/obj/item/clothing/neck/petcollar/collar = locate() in source
user.put_in_hands(collar)
/datum/strippable_item/corgi_back
diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm
index 03ac2be54bedd..e4e978568a0e6 100644
--- a/code/modules/mob/living/basic/pets/fox.dm
+++ b/code/modules/mob/living/basic/pets/fox.dm
@@ -31,6 +31,8 @@
/mob/living/basic/pet/fox/Initialize(mapload)
. = ..()
+ AddElement(/datum/element/cultist_pet)
+ AddElement(/datum/element/wears_collar)
AddElement(/datum/element/pet_bonus, "pants and yaps happily!")
AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW)
AddElement(/datum/element/tiny_mob_hunter, MOB_SIZE_SMALL)
diff --git a/code/modules/mob/living/basic/pets/penguin.dm b/code/modules/mob/living/basic/pets/penguin.dm
index 1bf3adec5574e..a597bd70cbba4 100644
--- a/code/modules/mob/living/basic/pets/penguin.dm
+++ b/code/modules/mob/living/basic/pets/penguin.dm
@@ -20,6 +20,8 @@
/mob/living/basic/pet/penguin/Initialize(mapload)
. = ..()
+ AddElement(/datum/element/cultist_pet)
+ AddElement(/datum/element/wears_collar)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/ai_flee_while_injured)
AddElement(/datum/element/pet_bonus, "honks happily!")
diff --git a/code/modules/mob/living/basic/pets/pet.dm b/code/modules/mob/living/basic/pets/pet.dm
index de5ad59eb1f0c..64896a3f2ab47 100644
--- a/code/modules/mob/living/basic/pets/pet.dm
+++ b/code/modules/mob/living/basic/pets/pet.dm
@@ -3,146 +3,12 @@
mob_size = MOB_SIZE_SMALL
mob_biotypes = MOB_ORGANIC|MOB_BEAST
blood_volume = BLOOD_VOLUME_NORMAL
-
/// if the mob is protected from being renamed by collars.
var/unique_pet = FALSE
- /// If the mob has collar sprites, this is the base of the icon states.
- var/collar_icon_state = null
- /// We have a seperate _rest collar icon state when the pet is resting.
- var/has_collar_resting_icon_state = FALSE
- /// Our collar
- var/obj/item/clothing/neck/petcollar/collar
- ///can we become cultists?
- var/can_cult_convert = TRUE
- ///whether we have a custom icon state when we get culted
- var/cult_icon_state
-
-/mob/living/basic/pet/Initialize(mapload)
- . = ..()
-
- /// Can set the collar var beforehand to start the pet with a collar.
- if(collar)
- collar = new(src)
-
- update_icon(UPDATE_OVERLAYS)
- if(can_cult_convert)
- RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(become_cultist))
-
-/mob/living/basic/pet/Destroy()
- . = ..()
-
- QDEL_NULL(collar)
-
-/mob/living/basic/pet/attackby(obj/item/thing, mob/user, params)
- if(istype(thing, /obj/item/clothing/neck/petcollar) && !collar)
- add_collar(thing, user)
- return TRUE
-
- if(istype(thing, /obj/item/newspaper) && !stat)
- user.visible_message(span_notice("[user] baps [name] on the nose with the rolled up [thing]."))
- dance_rotate(src)
- return TRUE
- return ..()
-
-/mob/living/basic/pet/update_overlays()
- . = ..()
-
- if(isnull(mind) && (FACTION_CULT in faction))
- var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE)
- . += cult_indicator
-
- if(!collar || !collar_icon_state)
- return
-
- // Determine which status tag to add to the middle of the icon state.
- var/dead_tag = (stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH)) ? "_dead" : null
- var/rest_tag = has_collar_resting_icon_state && resting ? "_rest" : null
- var/stat_tag = dead_tag || rest_tag || ""
-
- . += mutable_appearance(icon, "[collar_icon_state][stat_tag]collar")
- . += mutable_appearance(icon, "[collar_icon_state][stat_tag]tag")
-
-/mob/living/basic/pet/update_icon_state()
- if(cult_icon_state && (FACTION_CULT in faction))
- icon_state = cult_icon_state
- icon_living = cult_icon_state
- return ..()
-
-/mob/living/basic/pet/gib()
- remove_collar(drop_location(), update_visuals = FALSE)
- return ..()
-
-/mob/living/basic/pet/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE)
- . = ..()
- if(!.)
- return
-
- update_icon(UPDATE_OVERLAYS)
/mob/living/basic/pet/death(gibbed)
. = ..()
add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it
-/mob/living/basic/pet/Exited(atom/movable/gone, direction)
- . = ..()
- if(gone != collar)
- return
-
- collar = null
-
- if(QDELETED(src))
- return
-
- update_icon(UPDATE_OVERLAYS)
-
-/mob/living/basic/pet/update_stat()
- . = ..()
-
- update_icon(UPDATE_OVERLAYS)
-
-/mob/living/basic/pet/set_resting(new_resting, silent, instant)
- . = ..()
-
- if(!has_collar_resting_icon_state)
- return
-
- update_icon(UPDATE_OVERLAYS)
-
-/**
- * Add a collar to the pet.
- *
- * Arguments:
- * * new_collar - the collar.
- * * user - the user that did it.
- */
-/mob/living/basic/pet/proc/add_collar(obj/item/clothing/neck/petcollar/new_collar, mob/user)
- if(QDELETED(new_collar) || collar)
- return
- if(!user.transferItemToLoc(new_collar, src))
- return
-
- collar = new_collar
- if(collar_icon_state)
- update_icon(UPDATE_OVERLAYS)
-
- to_chat(user, span_notice("You put [new_collar] around [src]'s neck."))
- if(new_collar.tagname && !unique_pet)
- fully_replace_character_name(null, "\proper [new_collar.tagname]")
-
-/**
- * Remove the collar from the pet.
- */
-/mob/living/basic/pet/proc/remove_collar(atom/new_loc, update_visuals = TRUE)
- if(!collar)
- return
-
- var/obj/old_collar = collar
-
- collar.forceMove(new_loc)
- collar = null
-
- if(collar_icon_state && update_visuals)
- update_icon(UPDATE_OVERLAYS)
- return old_collar
diff --git a/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm b/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm
deleted file mode 100644
index 438737a1ad261..0000000000000
--- a/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-#define PET_CULT_ATTACK 10
-#define PET_CULT_HEALTH 50
-
-///turn into terrifying beasts
-/mob/living/basic/pet/proc/become_cultist(datum/source, list/invokers, datum/team)
- SIGNAL_HANDLER
-
- if(stat == DEAD || !can_cult_convert)
- return
-
- if(FACTION_CULT in faction)
- return STOP_SACRIFICE
-
- mind?.add_antag_datum(/datum/antagonist/cult, team)
- qdel(GetComponent(/datum/component/obeys_commands))
- melee_damage_lower = max(PET_CULT_ATTACK, initial(melee_damage_lower))
- melee_damage_upper = max(PET_CULT_ATTACK + 5, initial(melee_damage_upper))
- maxHealth = max(PET_CULT_HEALTH, initial(maxHealth))
- fully_heal()
-
- faction = list(FACTION_CULT) //we only serve the cult
-
- if(isnull(cult_icon_state))
- add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
-
- var/static/list/cult_appetite = list(
- /obj/item/organ,
- /obj/effect/decal/cleanable/blood,
- )
-
- var/static/list/death_loot = list(
- /obj/effect/gibspawner/generic,
- /obj/item/soulstone,
- )
-
- AddElement(/datum/element/basic_eating, heal_amt = 15, food_types = cult_appetite)
- AddElement(/datum/element/death_drops, death_loot)
-
- basic_mob_flags &= DEL_ON_DEATH
- qdel(ai_controller)
- ai_controller = new /datum/ai_controller/basic_controller/pet_cult(src)
- var/datum/action/cooldown/spell/conjure/revive_rune/rune_ability = new(src)
- rune_ability.Grant(src)
- ai_controller.set_blackboard_key(BB_RUNE_ABILITY, rune_ability)
- ai_controller.set_blackboard_key(BB_CULT_TEAM, team)
-
- var/static/list/new_pet_commands = list(
- /datum/pet_command/point_targeting/attack,
- /datum/pet_command/follow,
- /datum/pet_command/free,
- /datum/pet_command/idle,
- /datum/pet_command/untargeted_ability/draw_rune,
- )
- AddComponent(/datum/component/obeys_commands, new_pet_commands)
- RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(activate_rune), override = TRUE)
- update_appearance()
- return STOP_SACRIFICE
-
-
-/mob/living/basic/pet/proc/activate_rune(datum/source, atom/target)
- SIGNAL_HANDLER
-
- if(!istype(target, /obj/effect/rune/raise_dead))
- return NONE
-
- target.attack_hand(src)
-
- return COMPONENT_CANCEL_ATTACK_CHAIN
-
-/mob/living/basic/pet/Login()
- . = ..()
- if(!. || !client)
- return FALSE
-
- if(!(FACTION_CULT in faction))
- return
- var/datum/team/cult_team = locate(/datum/team/cult) in GLOB.antagonist_teams
- if(isnull(cult_team))
- return
- mind.add_antag_datum(/datum/antagonist/cult, cult_team)
- update_appearance(UPDATE_OVERLAYS)
-
-
-#undef PET_CULT_ATTACK
-#undef PET_CULT_HEALTH
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index 3717cfcb89a1a..630171ba2c15d 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -33,7 +33,6 @@ In all, this is a lot like the monkey code. /N
to_chat(user, span_danger("You bite [src]!"))
adjustBruteLoss(1)
log_combat(user, src, "attacked")
- updatehealth()
else
to_chat(user, span_warning("[name] is too injured for that."))
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index 04feb94b524a7..5e1bdf4282686 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -1195,10 +1195,9 @@ GLOBAL_LIST_EMPTY(features_by_species)
// Get the insulation value based on the area's temp
var/thermal_protection = humi.get_insulation_protection(area_temp)
- var/original_bodytemp = humi.bodytemperature
// Changes to the skin temperature based on the area
- var/area_skin_diff = area_temp - original_bodytemp
+ var/area_skin_diff = area_temp - humi.bodytemperature
if(!humi.on_fire || area_skin_diff > 0)
// change rate of 0.05 as area temp has large impact on the surface
var/area_skin_change = get_temp_change_amount(area_skin_diff, 0.05 * seconds_per_tick)
@@ -1218,7 +1217,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
// Core to skin temp transfer, when not on fire
if(!humi.on_fire)
// Get the changes to the skin from the core temp
- var/core_skin_diff = humi.coretemperature - original_bodytemp
+ var/core_skin_diff = humi.coretemperature - humi.bodytemperature
// change rate of 0.045 to reflect temp back to the skin at the slight higher rate then core to skin
var/core_skin_change = (1 + thermal_protection) * get_temp_change_amount(core_skin_diff, 0.045 * seconds_per_tick)
diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm
index 7dea684e56941..0c5eb6ec164b2 100644
--- a/code/modules/mob/living/silicon/ai/ai_defense.dm
+++ b/code/modules/mob/living/silicon/ai/ai_defense.dm
@@ -14,7 +14,6 @@
/mob/living/silicon/ai/blob_act(obj/structure/blob/B)
if (stat != DEAD)
adjustBruteLoss(60)
- updatehealth()
return TRUE
return FALSE
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index b7a669b4a2e62..73d6ac25bdd0f 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -18,7 +18,6 @@
flash_act(affect_silicon = 1)
log_combat(user, src, "attacked")
adjustBruteLoss(damage)
- updatehealth()
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, TRUE, -1)
visible_message(span_danger("[user]'s swipe misses [src]!"), \
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 2fea2871c0388..baaf1b39b3c56 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -27,7 +27,6 @@
playsound(loc, attacked_sound, 25, TRUE, -1)
apply_damage(harm_intent_damage)
log_combat(user, src, "attacked")
- updatehealth()
return TRUE
/mob/living/simple_animal/get_shoving_message(mob/living/shover, obj/item/weapon, shove_flags)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index d51a586224603..cde5ecdbc05a8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -542,9 +542,9 @@
possessor.investigate_log("has died from [src].", INVESTIGATE_DEATHS)
possessor.death(FALSE)
if(holder_animal)
- possessor.forceMove(get_turf(holder_animal))
holder_animal.mind.transfer_to(possessor)
possessor.mind.grab_ghost(force = TRUE)
+ possessor.forceMove(get_turf(holder_animal))
holder_animal.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
holder_animal.gib(DROP_ALL_REMAINS)
return ..()
diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm
index 394ddea0ecdea..230f53e9403be 100644
--- a/code/modules/mod/mod_theme.dm
+++ b/code/modules/mod/mod_theme.dm
@@ -1407,7 +1407,7 @@
/datum/mod_theme/interdyne
name = "interdyne"
desc = "A corpse-snatching and rapid-retrieval modsuit, resulting from a lucrative tech exchange between Interdyne Pharmaceutics and Cybersun Industries."
- extended_desc = "While Waffle Co. and Azik Interstellar provide the means, Donk Co., Tiger Cooperative, Animal Rights Consortium and \
+ extended_desc = "While Waffle Corp. and Azik Interstellar provide the means, Donk Co., Tiger Cooperative, Animal Rights Consortium and \
Gorlex Marauders willing or easily bribable brawn, S.E.L.F. and MI13 information, the clear syndicate tech providers would be Interdyne and Cybersun, \
their combined knowledge in technologies rivaled by only the most enigmatic of aliens, and certainly not by any Nanotrasen scientist. \
This model is one of the rare fruits created by their joint operations, mashing scrapped designs with super soldier enhancements. \
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index 8db88e16ba312..2ab0b0a1fd269 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -54,7 +54,7 @@
/obj/item/mod/module/storage/large_capacity
name = "MOD expanded storage module"
- desc = "Reverse engineered by Nakamura Engineering from Donk Corporation designs, this system of hidden compartments \
+ desc = "Reverse engineered by Nakamura Engineering from Donk Company designs, this system of hidden compartments \
is entirely within the suit, distributing items and weight evenly to ensure a comfortable experience for the user; \
whether smuggling, or simply hauling."
icon_state = "storage_large"
@@ -450,7 +450,7 @@
///Dispenser - Dispenses an item after a time passes.
/obj/item/mod/module/dispenser
name = "MOD burger dispenser module"
- desc = "A rare piece of technology reverse-engineered from a prototype found in a Donk Corporation vessel. \
+ desc = "A rare piece of technology reverse-engineered from a prototype found in a Donk Company vessel. \
This can draw incredible amounts of power from the suit's charge to create edible organic matter in the \
palm of the wearer's glove; however, research seemed to have entirely stopped at burgers. \
Notably, all attempts to get it to dispense Earl Grey tea have failed."
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index f4e6c7122468d..17ecc92708cbd 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -13,6 +13,13 @@
throw_range = 7
slot_flags = ITEM_SLOT_BELT
resistance_flags = FLAMMABLE
+
+ unique_reskin = list(
+ "Brown" = "clipboard",
+ "Black" = "clipboard_black",
+ "White" = "clipboard_white",
+ )
+
/// The stored pen
var/obj/item/pen/pen
/// Is the pen integrated?
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index f7d9ed19cbea5..cd7d75556727b 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -137,7 +137,7 @@
/obj/item/gun/ballistic/revolver/syndicate
name = "\improper Syndicate Revolver"
- desc = "A modernized 7 round revolver manufactured by Waffle Co. Uses .357 ammo."
+ desc = "A modernized 7 round revolver manufactured by Waffle Corp. Uses .357 ammo."
icon_state = "revolversyndie"
/obj/item/gun/ballistic/revolver/syndicate/nuclear
diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
index 336ab2353947a..3a633e5c83679 100644
--- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm
@@ -783,7 +783,10 @@ Basically, we fill the time between now and 2s from now with hands based off the
if(!isnull(speaker) && HAS_TRAIT(speaker, TRAIT_SIGN_LANG))
return
- hearing_args[HEARING_SPANS] |= random_span
+ var/list/spans = hearing_args[HEARING_SPANS]
+ var/list/copied_spans = spans.Copy()
+ copied_spans |= random_span
+ hearing_args[HEARING_SPANS] = copied_spans
/datum/reagent/inverse/sal_acid
name = "Benzoic Acid"
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 1ecc9ca9b5db5..18d02ba2e31fc 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1349,7 +1349,7 @@
/datum/reagent/space_cleaner/ez_clean
name = "EZ Clean"
- description = "A powerful, acidic cleaner sold by Waffle Co. Affects organic matter while leaving other objects unaffected."
+ description = "A powerful, acidic cleaner sold by Waffle Corp. Affects organic matter while leaving other objects unaffected."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
taste_description = "acid"
penetrates_skin = VAPOR
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index d9feba5179e08..9aaa047d3a1c3 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -473,7 +473,7 @@
/datum/design/plasticducky
name = "Rubber Ducky"
- desc = "The classic Nanotrasen design for competitively priced bath based duck toys. No need for fancy Waffle co. rubber, buy Plastic Ducks today!"
+ desc = "The classic Nanotrasen design for competitively priced bath based duck toys. No need for fancy Waffle Corp. rubber, buy Plastic Ducks today!"
id = "plasticducky"
build_type = PROTOLATHE | AWAY_LATHE
materials = list(/datum/material/plastic =HALF_SHEET_MATERIAL_AMOUNT)
diff --git a/code/modules/surgery/revival.dm b/code/modules/surgery/revival.dm
index bda1aaaafef7f..e0111feb52231 100644
--- a/code/modules/surgery/revival.dm
+++ b/code/modules/surgery/revival.dm
@@ -104,8 +104,7 @@
span_notice("[user] send a powerful shock to [target]'s brain with [tool]..."),
)
target.grab_ghost()
- target.adjustOxyLoss(-50, 0)
- target.updatehealth()
+ target.adjustOxyLoss(-50)
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
carbon_target.set_heartattack(FALSE)
diff --git a/code/modules/tgs/core/README.md b/code/modules/tgs/core/README.md
index b82d8f49e297f..965e21b549a3e 100644
--- a/code/modules/tgs/core/README.md
+++ b/code/modules/tgs/core/README.md
@@ -3,7 +3,7 @@
This folder contains all DMAPI code not directly involved in an API.
- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals.
+- [byond_world_export.dm](./byond_world_export.dm) contains the default `/datum/tgs_http_handler` implementation which uses `world.Export()`.
- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code.
- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement.
- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition
--
diff --git a/code/modules/tgs/core/byond_world_export.dm b/code/modules/tgs/core/byond_world_export.dm
new file mode 100644
index 0000000000000..6ef8d841b8f76
--- /dev/null
+++ b/code/modules/tgs/core/byond_world_export.dm
@@ -0,0 +1,22 @@
+/datum/tgs_http_handler/byond_world_export
+
+/datum/tgs_http_handler/byond_world_export/PerformGet(url)
+ // This is an infinite sleep until we get a response
+ var/export_response = world.Export(url)
+ TGS_DEBUG_LOG("byond_world_export: Export complete")
+
+ if(!export_response)
+ TGS_ERROR_LOG("byond_world_export: Failed request: [url]")
+ return new /datum/tgs_http_result(null, FALSE)
+
+ var/content = export_response["CONTENT"]
+ if(!content)
+ TGS_ERROR_LOG("byond_world_export: Failed request, missing content!")
+ return new /datum/tgs_http_result(null, FALSE)
+
+ var/response_json = TGS_FILE2TEXT_NATIVE(content)
+ if(!response_json)
+ TGS_ERROR_LOG("byond_world_export: Failed request, failed to load content!")
+ return new /datum/tgs_http_result(null, FALSE)
+
+ return new /datum/tgs_http_result(response_json, TRUE)
diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm
index 15622228e91fe..63cb5a2c35147 100644
--- a/code/modules/tgs/core/core.dm
+++ b/code/modules/tgs/core/core.dm
@@ -1,4 +1,4 @@
-/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
+/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE, datum/tgs_http_handler/http_handler = null)
var/current_api = TGS_READ_GLOBAL(tgs)
if(current_api)
TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?")
@@ -55,7 +55,10 @@
TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]")
event_handler = null
- var/datum/tgs_api/new_api = new api_datum(event_handler, version)
+ if(!http_handler)
+ http_handler = new /datum/tgs_http_handler/byond_world_export
+
+ var/datum/tgs_api/new_api = new api_datum(event_handler, version, http_handler)
TGS_WRITE_GLOBAL(tgs, new_api)
diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm
index f734fd0527f0e..3ca53e9bf7c65 100644
--- a/code/modules/tgs/core/datum.dm
+++ b/code/modules/tgs/core/datum.dm
@@ -6,7 +6,7 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
var/list/warned_deprecated_command_runs
-/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version)
+/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version, datum/tgs_http_handler/http_handler)
..()
src.event_handler = event_handler
src.version = version
diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm
index 23b714f9d0643..f5118ed55a3c2 100644
--- a/code/modules/tgs/includes.dm
+++ b/code/modules/tgs/includes.dm
@@ -1,4 +1,5 @@
#include "core\_definitions.dm"
+#include "core\byond_world_export.dm"
#include "core\core.dm"
#include "core\datum.dm"
#include "core\tgs_version.dm"
diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm
index 05d0dee25b3c2..3e328fc7c27d5 100644
--- a/code/modules/tgs/v5/api.dm
+++ b/code/modules/tgs/v5/api.dm
@@ -31,9 +31,12 @@
var/detached = FALSE
-/datum/tgs_api/v5/New()
+ var/datum/tgs_http_handler/http_handler
+
+/datum/tgs_api/v5/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version, datum/tgs_http_handler/http_handler)
. = ..()
interop_version = version
+ src.http_handler = http_handler
TGS_DEBUG_LOG("V5 API created: [json_encode(args)]")
/datum/tgs_api/v5/ApiVersion()
diff --git a/code/modules/tgs/v5/bridge.dm b/code/modules/tgs/v5/bridge.dm
index 0c5e701a32b60..62201fcc9e58b 100644
--- a/code/modules/tgs/v5/bridge.dm
+++ b/code/modules/tgs/v5/bridge.dm
@@ -78,27 +78,24 @@
WaitForReattach(FALSE)
TGS_DEBUG_LOG("Bridge request start")
- // This is an infinite sleep until we get a response
- var/export_response = world.Export(bridge_request)
+ var/datum/tgs_http_result/result = http_handler.PerformGet(bridge_request)
TGS_DEBUG_LOG("Bridge request complete")
- if(!export_response)
- TGS_ERROR_LOG("Failed bridge request: [bridge_request]")
+ if(isnull(result))
+ TGS_ERROR_LOG("Failed bridge request, handler returned null!")
return
- var/content = export_response["CONTENT"]
- if(!content)
- TGS_ERROR_LOG("Failed bridge request, missing content!")
+ if(!istype(result) || result.type != /datum/tgs_http_result)
+ TGS_ERROR_LOG("Failed bridge request, handler returned non-[/datum/tgs_http_result]!")
return
- var/response_json = TGS_FILE2TEXT_NATIVE(content)
- if(!response_json)
- TGS_ERROR_LOG("Failed bridge request, failed to load content!")
+ if(!result.success)
+ TGS_DEBUG_LOG("Failed bridge request, HTTP request failed!")
return
- var/list/bridge_response = json_decode(response_json)
+ var/list/bridge_response = json_decode(result.response_text)
if(!bridge_response)
- TGS_ERROR_LOG("Failed bridge request, bad json: [response_json]")
+ TGS_ERROR_LOG("Failed bridge request, bad json: [result.response_text]")
return
var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE]
diff --git a/code/modules/transport/elevator/elev_music_zone.dm b/code/modules/transport/elevator/elev_music_zone.dm
index 8379e742caea5..f5b3de8a67cc4 100644
--- a/code/modules/transport/elevator/elev_music_zone.dm
+++ b/code/modules/transport/elevator/elev_music_zone.dm
@@ -83,6 +83,8 @@ GLOBAL_LIST_EMPTY(elevator_music)
/datum/proximity_monitor/advanced/elevator_music_area/field_turf_uncrossed(mob/exited, turf/old_location, turf/new_location)
if (!(exited in tracked_mobs))
return
+ if ((new_location in field_turfs) || (new_location in edge_turfs))
+ return
qdel(tracked_mobs[exited])
tracked_mobs -= exited
UnregisterSignal(exited, COMSIG_QDELETING)
diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png
index f34414bdc13d3..61b7c36d94a02 100644
Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png differ
diff --git a/code/modules/uplink/uplink_items/dangerous.dm b/code/modules/uplink/uplink_items/dangerous.dm
index 691f4f2c8f37f..faf3751d7a51e 100644
--- a/code/modules/uplink/uplink_items/dangerous.dm
+++ b/code/modules/uplink/uplink_items/dangerous.dm
@@ -91,7 +91,7 @@
/datum/uplink_item/dangerous/revolver
name = "Syndicate Revolver"
- desc = "Waffle Co.'s modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum."
+ desc = "Waffle Corp's modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum."
item = /obj/item/gun/ballistic/revolver/syndicate
cost = 13
surplus = 50
diff --git a/code/modules/uplink/uplink_items/job.dm b/code/modules/uplink/uplink_items/job.dm
index bfb9aa3f332cd..b64e8a11706b4 100644
--- a/code/modules/uplink/uplink_items/job.dm
+++ b/code/modules/uplink/uplink_items/job.dm
@@ -109,7 +109,7 @@
/datum/uplink_item/role_restricted/ez_clean_bundle
name = "EZ Clean Grenade Bundle"
- desc = "A box with three cleaner grenades using the trademark Waffle Co. formula. Serves as a cleaner and causes acid damage to anyone standing nearby. \
+ desc = "A box with three cleaner grenades using the trademark Waffle Corp. formula. Serves as a cleaner and causes acid damage to anyone standing nearby. \
The acid only affects carbon-based creatures."
item = /obj/item/storage/box/syndie_kit/ez_clean
cost = 6
@@ -164,7 +164,7 @@
/datum/uplink_item/role_restricted/gorillacube
name = "Gorilla Cube"
- desc = "A Waffle Co. brand gorilla cube. Eat big to get big. \
+ desc = "A Waffle Corp. brand gorilla cube. Eat big to get big. \
Caution: Product may rehydrate when exposed to water."
item = /obj/item/food/monkeycube/gorilla
cost = 6
diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm
index 80df9de47cfbc..9b86a91b0264c 100644
--- a/code/modules/uplink/uplink_items/nukeops.dm
+++ b/code/modules/uplink/uplink_items/nukeops.dm
@@ -194,7 +194,7 @@
/datum/uplink_item/weapon_kits/medium_cost/revolvercase
name = "Syndicate Revolver Case (Moderate)"
- desc = "Waffle Co.'s modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum. \
+ desc = "Waffle Corp's modernized Syndicate revolver. Fires 7 brutal rounds of .357 Magnum. \
A classic operative weapon, brought to the modern era. Comes with 3 additional speedloaders of .357."
item = /obj/item/storage/toolbox/guncase/revolver
diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm
index c8e77f2e888e4..34216db38d3cd 100644
--- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm
@@ -120,7 +120,6 @@
if(isnull(victim)) //get gibbed stoopid
return ..()
victim.adjustOxyLoss(round(clamp_damage/2))
- victim.updatehealth()
victim.visible_message(span_danger("[chassis] squeezes [victim]!"), \
span_userdanger("[chassis] squeezes you!"),\
span_hear("You hear something crack."))
diff --git a/html/changelogs/archive/2024-08.yml b/html/changelogs/archive/2024-08.yml
index 27ac50a47b3a1..216751eaba1ee 100644
--- a/html/changelogs/archive/2024-08.yml
+++ b/html/changelogs/archive/2024-08.yml
@@ -142,3 +142,74 @@
necromanceranne:
- bugfix: Shoving someone onto a table now causes them to become vulnerable to being
stunned.
+2024-08-03:
+ Watermelon914:
+ - bugfix: Fixed an infinite TC glitch dupe
+ Y0SH1M4S73R:
+ - admin: The "Suppress Runtime Logging" toggle in the lua editor actually does what
+ it says
+2024-08-05:
+ Ben10Omintrix:
+ - bugfix: juvenile lobstrosities will now look for food
+ OrionTheFox:
+ - image: added and updated belt/suit/mask storage sprites for several knives missing
+ them
+ SmArtKar:
+ - bugfix: Lizards no longer die from cold on icebox despite wearing insulation
+ - bugfix: Fixed handyman assistants spawning without a PDA
+ Y0SH1M4S73R:
+ - bugfix: lua scripting now works on linux
+2024-08-06:
+ Ben10Omintrix:
+ - refactor: refactors pet collars and cultist pets into elements
+ EnterTheJake:
+ - image: Ash Blade has received a new sprite.
+ Gaxeer:
+ - rscdel: Remove narsie and ratvar plushies from loadout
+ SmArtKar:
+ - bugfix: Plasmamen helmets now display their smiles + can be painted with spraycans
+ - bugfix: Elevator music no longer restarts when you take a step
+ - image: Resprited teleporter beacons
+ - code_imp: Removed multiple cases of unnecessary updatehealth
+ - bugfix: Bitrunning crate capture zones can no longer be destroyed
+ mc-oofert:
+ - admin: fix hard restart option
+2024-08-07:
+ Absolucy:
+ - bugfix: Fixed a runtime error after draining a heretic influence.
+ LT3:
+ - bugfix: Fixed players being incorrectly immune to certain virus severities
+ MrMelbert, SmArtKar:
+ - bugfix: Holding someone at gunpoint no longer makes all shots count as point blank
+ SmArtKar:
+ - image: Updated clipboard sprite, adds white and black clipboard skins for med/sci
+ and security
+ - bugfix: Tinacusiate no longer changes hearing spans for every single person in-game
+2024-08-08:
+ MTandi:
+ - bugfix: Smartfridges properly dispense `\Improper` items
+ Rhials:
+ - sound: Zipties no longer make handcuff noises when picked up or dropped.
+2024-08-09:
+ SmArtKar:
+ - bugfix: Circuit UI scale no longer has weird rounding
+ - bugfix: Circuit UI no longer gets covered by components menu
+ - bugfix: Fixed Charlie MOD installer not installing MODsuit unless you have a backpack
+ to drop
+2024-08-10:
+ FlufflesTheDog:
+ - bugfix: tadpoles can actually be scooped from ponds
+2024-08-11:
+ DaCoolBoss:
+ - spellcheck: fixed many incorrect spellings of Waffle Corp and Donk Co.
+2024-08-12:
+ SmArtKar:
+ - bugfix: You no longer kill yourself in cockroach form if you attempt to unposess
+ it
+ grungussuss:
+ - sound: ore and sandstone blocks have their own sound
+ grungussuss and kayozz:
+ - sound: white noise from some ambience sounds has been pruned
+2024-08-13:
+ Majkl-J:
+ - bugfix: Felinids no longer phase through diagonal gaps upon seeing a laser
diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi
index 4f844c4fa320f..724a29de21b0f 100644
Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ
diff --git a/icons/mob/clothing/belt_mirror.dmi b/icons/mob/clothing/belt_mirror.dmi
index 1138dffc8bd31..0507a0301944e 100644
Binary files a/icons/mob/clothing/belt_mirror.dmi and b/icons/mob/clothing/belt_mirror.dmi differ
diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi
index 0dad7a30d0b23..ac40c153dd784 100644
Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ
diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi
index d15a47206f984..14f35aa9ef050 100644
Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index 88ad954734bf5..102417e36f5b7 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 86396dcaa8c67..ebcfea5967596 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 2cbe944aecc52..b8fd65ec07206 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/obj/devices/tracker.dmi b/icons/obj/devices/tracker.dmi
index 39be63ef4de81..161904825735e 100644
Binary files a/icons/obj/devices/tracker.dmi and b/icons/obj/devices/tracker.dmi differ
diff --git a/icons/obj/service/bureaucracy.dmi b/icons/obj/service/bureaucracy.dmi
index b400b7aee8b72..f52379a72b36e 100644
Binary files a/icons/obj/service/bureaucracy.dmi and b/icons/obj/service/bureaucracy.dmi differ
diff --git a/icons/obj/weapons/khopesh.dmi b/icons/obj/weapons/khopesh.dmi
index 3c4ba40b34ac1..6f4a040f6a410 100644
Binary files a/icons/obj/weapons/khopesh.dmi and b/icons/obj/weapons/khopesh.dmi differ
diff --git a/sound/ambience/ambigen1.ogg b/sound/ambience/ambigen1.ogg
index 6a5a2d27c92e3..500f0a0bbf6a1 100644
Binary files a/sound/ambience/ambigen1.ogg and b/sound/ambience/ambigen1.ogg differ
diff --git a/sound/ambience/ambigen12.ogg b/sound/ambience/ambigen12.ogg
index 27885070f4c71..2b82bc33348c4 100644
Binary files a/sound/ambience/ambigen12.ogg and b/sound/ambience/ambigen12.ogg differ
diff --git a/sound/items/stones/attribution.txt b/sound/items/stones/attribution.txt
new file mode 100644
index 0000000000000..9095ff55594aa
--- /dev/null
+++ b/sound/items/stones/attribution.txt
@@ -0,0 +1,7 @@
+{
+stone_drop1.ogg - https://freesound.org/people/kernschall/sounds/425035/ , license: CC BY 4.0
+stone_drop2.ogg - https://freesound.org/people/kernschall/sounds/425035/ , license: CC BY 4.0
+stone_drop3.og - https://freesound.org/people/Benboncan/sounds/74445/ , license: CC BY 4.0
+stone_pick_up1.ogg - https://freesound.org/people/kernschall/sounds/425035/ , license: CC BY 4.0
+stone_pick_up2.ogg - https://freesound.org/people/Benboncan/sounds/74445/ , license: CC BY 4.0
+} edited by sadboysuss
\ No newline at end of file
diff --git a/sound/items/stones/stone_drop1.ogg b/sound/items/stones/stone_drop1.ogg
new file mode 100644
index 0000000000000..a645ff7eb689f
Binary files /dev/null and b/sound/items/stones/stone_drop1.ogg differ
diff --git a/sound/items/stones/stone_drop2.ogg b/sound/items/stones/stone_drop2.ogg
new file mode 100644
index 0000000000000..3fd4415e29e69
Binary files /dev/null and b/sound/items/stones/stone_drop2.ogg differ
diff --git a/sound/items/stones/stone_drop3.ogg b/sound/items/stones/stone_drop3.ogg
new file mode 100644
index 0000000000000..650dbf8749754
Binary files /dev/null and b/sound/items/stones/stone_drop3.ogg differ
diff --git a/sound/items/stones/stone_pick_up1.ogg b/sound/items/stones/stone_pick_up1.ogg
new file mode 100644
index 0000000000000..af89dc415abdd
Binary files /dev/null and b/sound/items/stones/stone_pick_up1.ogg differ
diff --git a/sound/items/stones/stone_pick_up2.ogg b/sound/items/stones/stone_pick_up2.ogg
new file mode 100644
index 0000000000000..85b7f5a688150
Binary files /dev/null and b/sound/items/stones/stone_pick_up2.ogg differ
diff --git a/strings/antagonist_flavor/traitor_flavor.json b/strings/antagonist_flavor/traitor_flavor.json
index 2eae0d17f6e60..590e4ce99e3e2 100644
--- a/strings/antagonist_flavor/traitor_flavor.json
+++ b/strings/antagonist_flavor/traitor_flavor.json
@@ -40,7 +40,7 @@
"uplink": "You have been supplied the tools for the job in the form of a standard syndicate uplink."
},
"Donk Corporation": {
- "allies": "Members of Waffle Co. are to be killed on sight; they are not allowed to be on the station while we're around.",
+ "allies": "Members of Waffle Corp. are to be killed on sight; they are not allowed to be on the station while we're around.",
"goal": "We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto.",
"introduction": "You are the Donk Co. Traitor.",
"roundend_report": "was an employee from Donk Corporation.",
@@ -98,8 +98,8 @@
},
"Waffle Corporation": {
"allies": "Members of Donk Co. are to be killed on sight; they are not allowed to be on the station while we're around. Do not trust fellow members of the Waffle.co (but try not to rat them out), as they might have been assigned opposing objectives.",
- "goal": "You are not here for a station-wide demonstration. Again, other Waffle Co. Traitors may be, so watch out. Your job is to only accomplish your objectives.",
- "introduction": "You are the Waffle Co. Traitor.",
+ "goal": "You are not here for a station-wide demonstration. Again, other Waffle Corp. Traitors may be, so watch out. Your job is to only accomplish your objectives.",
+ "introduction": "You are the Waffle Corp. Traitor.",
"roundend_report": "was an employee from Waffle Corporation.",
"ui_theme": "syndicate",
"uplink": "You have been provided with a standard uplink to accomplish your task."
diff --git a/tgstation.dme b/tgstation.dme
index 56c2b58309f10..2931b5c6e8ace 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1510,6 +1510,8 @@
#include "code\datums\elements\organ_set_bonus.dm"
#include "code\datums\elements\permanent_fire_overlay.dm"
#include "code\datums\elements\pet_bonus.dm"
+#include "code\datums\elements\pet_collar.dm"
+#include "code\datums\elements\pet_cult.dm"
#include "code\datums\elements\plant_backfire.dm"
#include "code\datums\elements\point_of_interest.dm"
#include "code\datums\elements\poster_tearer.dm"
@@ -4912,7 +4914,6 @@
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_hoarding.dm"
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_perching.dm"
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parroting_action.dm"
-#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult.dm"
#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_abilities.dm"
#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_ai.dm"
#include "code\modules\mob\living\basic\ruin_defender\cybersun_aicore.dm"
diff --git a/tgui/packages/tgui/components/InfinitePlane.jsx b/tgui/packages/tgui/components/InfinitePlane.jsx
index 5277f2ad79682..3be047f1a0361 100644
--- a/tgui/packages/tgui/components/InfinitePlane.jsx
+++ b/tgui/packages/tgui/components/InfinitePlane.jsx
@@ -123,6 +123,7 @@ export class InfinitePlane extends Component {
imageWidth,
initialLeft = 0,
initialTop = 0,
+ scalePadding,
...rest
} = this.props;
const { left, top, zoom } = this.state;
@@ -169,23 +170,25 @@ export class InfinitePlane extends Component {
{children}
-