diff --git a/code/__DEFINES/client_prefs.dm b/code/__DEFINES/client_prefs.dm
index ef5ff00e4ed6..b1e194354555 100644
--- a/code/__DEFINES/client_prefs.dm
+++ b/code/__DEFINES/client_prefs.dm
@@ -22,6 +22,7 @@
#define TOGGLE_VEND_ITEM_TO_HAND (1<<15) // This toggles whether items from vendors will be automatically put into your hand.
#define TOGGLE_START_JOIN_CURRENT_SLOT (1<<16) // Whether joining at roundstart ignores assigned character slot for the job and uses currently selected slot.
#define TOGGLE_LATE_JOIN_CURRENT_SLOT (1<<17) //Whether joining during the round ignores assigned character slot for the job and uses currently selected slot.
+#define TOGGLE_ABILITY_DEACTIVATION_OFF (1<<18) // This toggles whether selecting the same ability again can toggle it off
#define JOB_SLOT_RANDOMISED_SLOT -1
#define JOB_SLOT_CURRENT_SLOT 0
diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm
index 89976c498422..22c3827022ff 100644
--- a/code/__DEFINES/tgs.dm
+++ b/code/__DEFINES/tgs.dm
@@ -1,6 +1,6 @@
// tgstation-server DMAPI
-#define TGS_DMAPI_VERSION "6.5.0"
+#define TGS_DMAPI_VERSION "6.5.2"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 0132a31d0b50..cca3edda464e 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -241,8 +241,14 @@
else
return get_step(start, EAST)
-/// Get a list of observers that can be alien candidates, optionally sorted by larva_queue_time
-/proc/get_alien_candidates(sorted = TRUE)
+/**
+ * Get a list of observers that can be alien candidates.
+ *
+ * Arguments:
+ * * hive - The hive we're filling a slot for to check if the player is banished
+ * * sorted - Whether to sort by larva_queue_time (default TRUE) or leave unsorted
+ */
+/proc/get_alien_candidates(datum/hive_status/hive = null, sorted = TRUE)
var/list/candidates = list()
for(var/mob/dead/observer/cur_obs as anything in GLOB.observer_list)
@@ -273,6 +279,15 @@
if((cur_obs.client.admin_holder && (cur_obs.client.admin_holder.rights & R_MOD)) && !cur_obs.adminlarva)
continue
+ if(hive)
+ var/banished = FALSE
+ for(var/mob_name in hive.banished_ckeys)
+ if(hive.banished_ckeys[mob_name] == cur_obs.ckey)
+ banished = TRUE
+ break
+ if(banished)
+ continue
+
candidates += cur_obs
// Optionally sort by larva_queue_time
diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm
index b95052de8824..a42ff3f22e59 100644
--- a/code/game/gamemodes/cm_initialize.dm
+++ b/code/game/gamemodes/cm_initialize.dm
@@ -384,6 +384,13 @@ Additional game mode variables.
// No cache, lets check now then
message_alien_candidates(get_alien_candidates(), dequeued = 0, cache_only = TRUE)
if(candidate_observer.larva_queue_cached_message)
+ var/datum/hive_status/cur_hive
+ for(var/hive_num in GLOB.hive_datum)
+ cur_hive = GLOB.hive_datum[hive_num]
+ for(var/mob_name in cur_hive.banished_ckeys)
+ if(cur_hive.banished_ckeys[mob_name] == xeno_candidate.ckey)
+ candidate_observer.larva_queue_cached_message += "\n" + SPAN_WARNING("NOTE: You are banished from the [cur_hive] and you may not rejoin unless the Queen re-admits you or dies. Your queue number won't update until there is a hive you aren't banished from.")
+ break
to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message)
return FALSE
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index ed06c0117f33..9c0a227008c3 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -503,23 +503,25 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
add_fingerprint(usr)
-/obj/structure/machinery/cryopod/proc/go_in_cryopod(mob/M, silent = FALSE)
+/obj/structure/machinery/cryopod/proc/go_in_cryopod(mob/mob, silent = FALSE)
if(occupant)
return
- M.forceMove(src)
- occupant = M
+ mob.forceMove(src)
+ occupant = mob
icon_state = "body_scanner_closed"
SetLuminosity(2)
time_entered = world.time
start_processing()
if(!silent)
- if(M.client)
- to_chat(M, SPAN_NOTICE("You feel cool air surround you. You go numb as your senses turn inward."))
- to_chat(M, SPAN_BOLDNOTICE("If you log out or close your client now, your character will permanently removed from the round in 10 minutes. If you ghost, timer will be decreased to 2 minutes."))
+ if(mob.client)
+ to_chat(mob, SPAN_NOTICE("You feel cool air surround you. You go numb as your senses turn inward."))
+ to_chat(mob, SPAN_BOLDNOTICE("If you log out or close your client now, your character will permanently removed from the round in 10 minutes. If you ghost, timer will be decreased to 2 minutes."))
+ if(!is_admin_level(src.z)) // Set their queue time now because the client has to actually leave to despawn and at that point the client is lost
+ mob.client.player_details.larva_queue_time = max(mob.client.player_details.larva_queue_time, world.time)
var/area/location = get_area(src)
- if(M.job != GET_MAPPED_ROLE(JOB_SQUAD_MARINE))
- message_admins("[key_name_admin(M)], [M.job], has entered \a [src] at [location] after playing for [duration2text(world.time - M.life_time_start)].")
+ if(mob.job != GET_MAPPED_ROLE(JOB_SQUAD_MARINE))
+ message_admins("[key_name_admin(mob)], [mob.job], has entered \a [src] at [location] after playing for [duration2text(world.time - mob.life_time_start)].")
playsound(src, 'sound/machines/hydraulics_3.ogg', 30)
silent_exit = silent
diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm
index 838b21a00e6f..b8e3e55f1d89 100644
--- a/code/game/machinery/vending/vendor_types/requisitions.dm
+++ b/code/game/machinery/vending/vendor_types/requisitions.dm
@@ -92,6 +92,7 @@
list("POUCHES", -1, null, null),
list("Autoinjector Pouch", round(scale * 2), /obj/item/storage/pouch/autoinjector, VENDOR_ITEM_REGULAR),
+ list("Bayonet Pouch", round(scale * 2), /obj/item/storage/pouch/bayonet, VENDOR_ITEM_REGULAR),
list("Construction Pouch", round(scale * 2), /obj/item/storage/pouch/construction, VENDOR_ITEM_REGULAR),
list("Document Pouch", round(scale * 2), /obj/item/storage/pouch/document/small, VENDOR_ITEM_REGULAR),
list("Electronics Pouch", round(scale * 2), /obj/item/storage/pouch/electronics, VENDOR_ITEM_REGULAR),
diff --git a/code/game/objects/items/pamphlets.dm b/code/game/objects/items/pamphlets.dm
index 683fbb2540f4..dd96f275ef17 100644
--- a/code/game/objects/items/pamphlets.dm
+++ b/code/game/objects/items/pamphlets.dm
@@ -96,8 +96,8 @@
user.hud_set_squad()
var/obj/item/card/id/ID = user.wear_id
- ID.set_assignment((user.assigned_squad ? (user.assigned_squad.name + " ") : "") + "Squad Spotter")
- GLOB.data_core.manifest_modify(user.real_name, WEAKREF(user), "Squad Spotter")
+ ID.set_assignment((user.assigned_squad ? (user.assigned_squad.name + " ") : "") + "Spotter")
+ GLOB.data_core.manifest_modify(user.real_name, WEAKREF(user), "Spotter")
/obj/item/pamphlet/skill/machinegunner
name = "heavy machinegunner instructional pamphlet"
diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm
index 198e5b3b9960..02e4b3866271 100644
--- a/code/game/objects/items/storage/pouch.dm
+++ b/code/game/objects/items/storage/pouch.dm
@@ -612,13 +612,12 @@
name = "explosive pouch"
desc = "It can carry grenades, plastic explosives, mine boxes, and other explosives."
icon_state = "large_explosive"
- storage_slots = 3
+ storage_slots = 6
max_w_class = SIZE_MEDIUM
can_hold = list(
/obj/item/explosive/plastic,
/obj/item/explosive/mine,
/obj/item/explosive/grenade,
- /obj/item/storage/box/explosive_mines,
)
/obj/item/storage/pouch/explosive/attackby(obj/item/W, mob/user)
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index c700a226295e..f42f350eea16 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -46,6 +46,7 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list(
/client/proc/toggle_eject_to_hand,
/client/proc/toggle_automatic_punctuation,
/client/proc/toggle_middle_mouse_click,
+ /client/proc/toggle_ability_deactivation,
/client/proc/toggle_clickdrag_override,
/client/proc/toggle_dualwield,
/client/proc/toggle_middle_mouse_swap_hands,
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index d2d69d095dbd..5698c30c0acf 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -595,6 +595,8 @@ var/const/MAX_SAVE_SLOTS = 10
[toggle_prefs & TOGGLE_HELP_INTENT_SAFETY ? "On" : "Off"]
"
dat += "Toggle Middle Mouse Ability Activation: \
[toggle_prefs & TOGGLE_MIDDLE_MOUSE_CLICK ? "On" : "Off"]
"
+ dat += "Toggle Ability Deactivation: \
+ [toggle_prefs & TOGGLE_ABILITY_DEACTIVATION_OFF ? "Off" : "On"]
"
dat += "Toggle Directional Assist: \
[toggle_prefs & TOGGLE_DIRECTIONAL_ATTACK ? "On" : "Off"]
"
dat += "Toggle Magazine Auto-Ejection: \
@@ -1229,7 +1231,7 @@ var/const/MAX_SAVE_SLOTS = 10
predator_gender = predator_gender == MALE ? FEMALE : MALE
if("pred_age")
var/new_predator_age = tgui_input_number(user, "Choose your Predator's age(175 to 3000):", "Character Preference", 1234, 3000, 175)
- if(new_predator_age)
+ if(new_predator_age)
predator_age = max(min( round(text2num(new_predator_age)), 3000),175)
if("pred_trans_type")
var/new_translator_type = tgui_input_list(user, "Choose your translator type.", "Translator Type", PRED_TRANSLATORS)
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index 9e3d9eb33766..b81411a26440 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -205,7 +205,7 @@
set name = "Toggle SpecialRole Candidacy"
set category = "Preferences"
set desc = "Toggles which special roles you would like to be a candidate for, during events."
-
+
var/list/be_special_flags = list(
"Xenomorph after unrevivable death" = BE_ALIEN_AFTER_DEATH,
"Agent" = BE_AGENT,
@@ -274,6 +274,7 @@
"Toggle 'Unload Weapon' Ejecting Magazines to Your Hands
",
"Toggle Automatic Punctuation
",
"Toggle Middle Mouse Ability Activation
",
+ "Toggle Ability Deactivation
",
"Toggle Combat Click-Drag Override
",
"Toggle Alternate-Fire Dual Wielding
",
"Toggle Middle Mouse Swapping Hands
",
@@ -287,7 +288,7 @@
for (var/pref_button in pref_buttons)
dat += "[pref_button]\n"
- var/height = 50+22*length(pref_buttons)
+ var/height = 50+24*length(pref_buttons)
show_browser(src, dat, "Toggle Preferences", "togglepreferences", "size=475x[height]")
@@ -355,6 +356,14 @@
to_chat(src, SPAN_NOTICE("Your selected ability will now be activated with shift clicking."))
prefs.save_preferences()
+/client/proc/toggle_ability_deactivation() // Toggle whether the current ability can be deactivated when re-selected
+ prefs.toggle_prefs ^= TOGGLE_ABILITY_DEACTIVATION_OFF
+ if (prefs.toggle_prefs & TOGGLE_ABILITY_DEACTIVATION_OFF)
+ to_chat(src, SPAN_NOTICE("Your current ability can no longer be toggled off when re-selected."))
+ else
+ to_chat(src, SPAN_NOTICE("Your current ability can be toggled off when re-selected."))
+ prefs.save_preferences()
+
/client/proc/toggle_clickdrag_override() //Toggle whether mousedown clicks immediately when on disarm or harm intent to prevent click-dragging from 'eating' attacks.
prefs.toggle_prefs ^= TOGGLE_COMBAT_CLICKDRAG_OVERRIDE
if(prefs.toggle_prefs & TOGGLE_COMBAT_CLICKDRAG_OVERRIDE)
diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm
index c38e540efb30..a29b49b7745a 100644
--- a/code/modules/cm_aliens/structures/special/pylon_core.dm
+++ b/code/modules/cm_aliens/structures/special/pylon_core.dm
@@ -150,7 +150,7 @@
last_larva_time = world.time
if(spawning_larva || (last_larva_queue_time + spawn_cooldown * 4) < world.time)
last_larva_queue_time = world.time
- var/list/players_with_xeno_pref = get_alien_candidates()
+ var/list/players_with_xeno_pref = get_alien_candidates(linked_hive)
if(players_with_xeno_pref && players_with_xeno_pref.len)
if(spawning_larva && spawn_burrowed_larva(players_with_xeno_pref[1]))
// We were in spawning_larva mode and successfully spawned someone
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index dbe00407d7ef..3896cd1f9ded 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -48,6 +48,10 @@
if(HAS_TRAIT(src, TRAIT_HARDCORE) || MODE_HAS_TOGGLEABLE_FLAG(MODE_HARDCORE_PERMA))
if(!(species.flags & IS_SYNTHETIC)) // Synths wont perma
status_flags |= PERMANENTLY_DEAD
+ if(HAS_TRAIT(src, TRAIT_INTENT_EYES)) //their eyes need to be 'offline'
+ r_eyes = 0
+ g_eyes = 0
+ b_eyes = 0
disable_special_flags()
disable_lights()
disable_special_items()
@@ -59,6 +63,7 @@
//Handle species-specific deaths.
if(species)
species.handle_death(src, gibbed)
+ update_body() //if species handle_death or other procs change body in some way after death, this is what will update the body.
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MARINE_DEATH, src, gibbed)
diff --git a/code/modules/mob/living/carbon/human/species/working_joe/_species.dm b/code/modules/mob/living/carbon/human/species/working_joe/_species.dm
index 874684480d15..b9044becb6f5 100644
--- a/code/modules/mob/living/carbon/human/species/working_joe/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/working_joe/_species.dm
@@ -1,6 +1,7 @@
/datum/species/synthetic/colonial/working_joe
name = SYNTH_WORKING_JOE
name_plural = "Working Joes"
+ death_message = "violently gargles fluid and seizes up, the glow in their eyes dimming..."
uses_ethnicity = FALSE
burn_mod = 0.65 // made for hazardous environments, withstanding temperatures up to 1210 degrees
mob_inherent_traits = list(TRAIT_SUPER_STRONG, TRAIT_INTENT_EYES, TRAIT_EMOTE_CD_EXEMPT, TRAIT_CANNOT_EAT)
@@ -14,6 +15,11 @@
. = ..()
give_action(joe, /datum/action/joe_emote_panel)
+// Special death noise for Working Joe
+/datum/species/synthetic/colonial/working_joe/handle_death(mob/living/carbon/human/dying_joe, gibbed)
+ if(!gibbed) //A gibbed Joe won't have a death rattle
+ playsound(dying_joe.loc, pick_weight(list('sound/voice/joe/death_normal.ogg' = 75, 'sound/voice/joe/death_silence.ogg' = 10, 'sound/voice/joe/death_tomorrow.ogg' = 10,'sound/voice/joe/death_dream.ogg' = 5)), 25, FALSE)
+ return ..()
/// Open the WJ's emote panel, which allows them to use voicelines
/datum/species/synthetic/colonial/working_joe/proc/open_emote_panel()
diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
index 01f6c1a3c238..3ba42650e49c 100644
--- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
@@ -163,7 +163,7 @@
if(!picked)
// Get a candidate from observers
- var/list/candidates = get_alien_candidates()
+ var/list/candidates = get_alien_candidates(hive)
if(candidates && candidates.len)
// If they were facehugged by a player thats still in queue, they get second dibs on the new larva.
if(hugger_ckey)
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
index 60fdda450df3..f4d4628e41f2 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
@@ -158,6 +158,8 @@
if(xeno.selected_ability == src)
if(xeno.deselect_timer > world.time)
return // We clicked the same ability in a very short time
+ if(xeno.client && xeno.client.prefs && xeno.client.prefs.toggle_prefs & TOGGLE_ABILITY_DEACTIVATION_OFF)
+ return
to_chat(xeno, "You will no longer use [ability_name] with \
[xeno.client && xeno.client.prefs && xeno.client.prefs.toggle_prefs & TOGGLE_MIDDLE_MOUSE_CLICK ? "middle-click" : "shift-click"].")
button.icon_state = "template"
diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm
index e3a69da23262..12c9b3e37c9b 100644
--- a/code/modules/mob/living/carbon/xenomorph/death.dm
+++ b/code/modules/mob/living/carbon/xenomorph/death.dm
@@ -38,7 +38,7 @@
if(GLOB.hive_datum[hivenumber].stored_larva)
GLOB.hive_datum[hivenumber].stored_larva = round(GLOB.hive_datum[hivenumber].stored_larva * 0.5) //Lose half on dead queen
- var/list/players_with_xeno_pref = get_alien_candidates()
+ var/list/players_with_xeno_pref = get_alien_candidates(GLOB.hive_datum[hivenumber])
if(players_with_xeno_pref && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core))
var/turf/larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location)
var/count = 0
diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
index 20c170b72e4e..6b37145ad7a1 100644
--- a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
+++ b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
@@ -111,6 +111,21 @@
else
to_chat(src, SPAN_NOTICE("The selected xeno ability will now be activated with shift clicking."))
+/mob/living/carbon/xenomorph/verb/ability_deactivation_toggle()
+ set name = "Toggle Ability Deactivation"
+ set desc = "Toggles whether you can deactivate your currently active ability when re-selecting it."
+ set category = "Alien"
+
+ if (!client || !client.prefs)
+ return
+
+ client.prefs.toggle_prefs ^= TOGGLE_ABILITY_DEACTIVATION_OFF
+ client.prefs.save_preferences()
+ if (client.prefs.toggle_prefs & TOGGLE_ABILITY_DEACTIVATION_OFF)
+ to_chat(src, SPAN_NOTICE("Your current ability can no longer be toggled off when re-selected."))
+ else
+ to_chat(src, SPAN_NOTICE("Your current ability can be toggled off when re-selected."))
+
/mob/living/carbon/xenomorph/verb/directional_attack_toggle()
set name = "Toggle Directional Attacks"
set desc = "Toggles the use of directional assist attacks."
diff --git a/code/modules/projectiles/ammo_datums.dm b/code/modules/projectiles/ammo_datums.dm
index 14eb6a120886..d794b725b044 100644
--- a/code/modules/projectiles/ammo_datums.dm
+++ b/code/modules/projectiles/ammo_datums.dm
@@ -309,6 +309,7 @@
name = "tranquilizer bullet"
flags_ammo_behavior = AMMO_BALLISTIC|AMMO_IGNORE_RESIST
stamina_damage = 30
+ damage = 15
//2020 rebalance: is supposed to counter runners and lurkers, dealing high damage to the only castes with no armor.
//Limited by its lack of versatility and lower supply, so marines finally have an answer for flanker castes that isn't just buckshot.
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 6d3465ee8747..983fffeb2634 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -635,7 +635,7 @@
var/mob/dead/observer/obs = mob.ghostize(FALSE)
if(obs)
obs.timeofdeath = world.time
- obs.client?.player_details.larva_queue_time = world.time
+ obs.client?.player_details.larva_queue_time = max(obs.client.player_details.larva_queue_time, world.time)
mob.moveToNullspace()
// Now that mobs are stowed, delete the shuttle
diff --git a/code/modules/tgs/core/_definitions.dm b/code/modules/tgs/core/_definitions.dm
index ebf6d17c2a07..fd98034eb716 100644
--- a/code/modules/tgs/core/_definitions.dm
+++ b/code/modules/tgs/core/_definitions.dm
@@ -1,2 +1,10 @@
+#if DM_VERSION < 510
+#error The TGS DMAPI does not support BYOND versions < 510!
+#endif
+
#define TGS_UNIMPLEMENTED "___unimplemented"
#define TGS_VERSION_PARAMETER "server_service_version"
+
+#ifndef TGS_DEBUG_LOG
+#define TGS_DEBUG_LOG(message)
+#endif
diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm
index d9bd287465b9..e65c816320dc 100644
--- a/code/modules/tgs/v3210/commands.dm
+++ b/code/modules/tgs/v3210/commands.dm
@@ -47,7 +47,7 @@
user.friendly_name = sender
// Discord hack, fix the mention if it's only numbers (fuck you IRC trolls)
- var/regex/discord_id_regex = regex(@"^[0-9]+$")
+ var/regex/discord_id_regex = regex("^\[0-9\]+$")
if(findtext(sender, discord_id_regex))
sender = "<@[sender]>"
@@ -55,4 +55,4 @@
var/datum/tgs_message_content/result = stc.Run(user, params)
result = UpgradeDeprecatedCommandResponse(result, command)
- return result?.text || TRUE
+ return result ? result.text : TRUE
diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm
index d6d3d718d471..25dd6740e3af 100644
--- a/code/modules/tgs/v4/commands.dm
+++ b/code/modules/tgs/v4/commands.dm
@@ -40,5 +40,5 @@
var/datum/tgs_message_content/result = sc.Run(u, params)
result = UpgradeDeprecatedCommandResponse(result, command)
- return result?.text
+ return result ? result.text : TRUE
return "Unknown command: [command]!"
diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm
index c7213cc24699..f973338daa03 100644
--- a/code/modules/tgs/v5/_defines.dm
+++ b/code/modules/tgs/v5/_defines.dm
@@ -5,8 +5,8 @@
#define DMAPI5_TOPIC_DATA "tgs_data"
#define DMAPI5_BRIDGE_REQUEST_LIMIT 8198
-#define DMAPI5_TOPIC_REQUEST_LIMIT 65529
-#define DMAPI5_TOPIC_RESPONSE_LIMIT 65528
+#define DMAPI5_TOPIC_REQUEST_LIMIT 65528
+#define DMAPI5_TOPIC_RESPONSE_LIMIT 65529
#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0
#define DMAPI5_BRIDGE_COMMAND_STARTUP 1
diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm
index 926ea10a8f27..34cc43f8762f 100644
--- a/code/modules/tgs/v5/api.dm
+++ b/code/modules/tgs/v5/api.dm
@@ -22,12 +22,17 @@
var/detached = FALSE
+/datum/tgs_api/v5/New()
+ . = ..()
+ TGS_DEBUG_LOG("V5 API created")
+
/datum/tgs_api/v5/ApiVersion()
return new /datum/tgs_version(
#include "__interop_version.dm"
)
/datum/tgs_api/v5/OnWorldNew(minimum_required_security_level)
+ TGS_DEBUG_LOG("OnWorldNew()")
server_port = world.params[DMAPI5_PARAM_SERVER_PORT]
access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER]
@@ -96,17 +101,28 @@
return TRUE
/datum/tgs_api/v5/proc/RequireInitialBridgeResponse()
+ TGS_DEBUG_LOG("RequireInitialBridgeResponse()")
+ var/logged = FALSE
while(!version)
+ if(!logged)
+ TGS_DEBUG_LOG("RequireInitialBridgeResponse: Starting sleep")
+ logged = TRUE
+
sleep(1)
+ TGS_DEBUG_LOG("RequireInitialBridgeResponse: Passed")
+
/datum/tgs_api/v5/OnInitializationComplete()
Bridge(DMAPI5_BRIDGE_COMMAND_PRIME)
/datum/tgs_api/v5/OnTopic(T)
+ TGS_DEBUG_LOG("OnTopic()")
RequireInitialBridgeResponse()
+ TGS_DEBUG_LOG("OnTopic passed bridge request gate")
var/list/params = params2list(T)
var/json = params[DMAPI5_TOPIC_DATA]
if(!json)
+ TGS_DEBUG_LOG("No \"[DMAPI5_TOPIC_DATA]\" entry found, ignoring...")
return FALSE // continue to /world/Topic
if(!initialized)
@@ -156,7 +172,7 @@
TGS_WARNING_LOG("Received legacy string when a [/datum/tgs_message_content] was expected. Please audit all calls to TgsChatBroadcast, TgsChatTargetedBroadcast, and TgsChatPrivateMessage to ensure they use the new /datum.")
return new /datum/tgs_message_content(message)
-/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message, list/channels)
+/datum/tgs_api/v5/ChatBroadcast(datum/tgs_message_content/message2, list/channels)
if(!length(channels))
channels = ChatChannelInfo()
@@ -165,45 +181,45 @@
var/datum/tgs_chat_channel/channel = I
ids += channel.id
- message = UpgradeDeprecatedChatMessage(message)
+ message2 = UpgradeDeprecatedChatMessage(message2)
if (!length(channels))
return
- message = message._interop_serialize()
- message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids
+ var/list/data = message2._interop_serialize()
+ data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = ids
if(intercepted_message_queue)
- intercepted_message_queue += list(message)
+ intercepted_message_queue += list(data)
else
- Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
+ Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data))
-/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message, admin_only)
+/datum/tgs_api/v5/ChatTargetedBroadcast(datum/tgs_message_content/message2, admin_only)
var/list/channels = list()
for(var/I in ChatChannelInfo())
var/datum/tgs_chat_channel/channel = I
if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only)))
channels += channel.id
- message = UpgradeDeprecatedChatMessage(message)
+ message2 = UpgradeDeprecatedChatMessage(message2)
if (!length(channels))
return
- message = message._interop_serialize()
- message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels
+ var/list/data = message2._interop_serialize()
+ data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = channels
if(intercepted_message_queue)
- intercepted_message_queue += list(message)
+ intercepted_message_queue += list(data)
else
- Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
+ Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data))
-/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message, datum/tgs_chat_user/user)
- message = UpgradeDeprecatedChatMessage(message)
- message = message._interop_serialize()
- message[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id)
+/datum/tgs_api/v5/ChatPrivateMessage(datum/tgs_message_content/message2, datum/tgs_chat_user/user)
+ message2 = UpgradeDeprecatedChatMessage(message2)
+ var/list/data = message2._interop_serialize()
+ data[DMAPI5_CHAT_MESSAGE_CHANNEL_IDS] = list(user.channel.id)
if(intercepted_message_queue)
- intercepted_message_queue += list(message)
+ intercepted_message_queue += list(data)
else
- Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message))
+ Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = data))
/datum/tgs_api/v5/ChatChannelInfo()
RequireInitialBridgeResponse()
@@ -211,6 +227,7 @@
return chat_channels.Copy()
/datum/tgs_api/v5/proc/DecodeChannels(chat_update_json)
+ TGS_DEBUG_LOG("DecodeChannels()")
var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS]
if(istype(chat_channels_json))
chat_channels.Cut()
diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm
index a832c81f172d..9557f8a08ed5 100644
--- a/code/modules/tgs/v5/commands.dm
+++ b/code/modules/tgs/v5/commands.dm
@@ -35,10 +35,10 @@
if(sc)
var/datum/tgs_message_content/response = sc.Run(u, params)
response = UpgradeDeprecatedCommandResponse(response, command)
-
+
var/list/topic_response = TopicResponse()
- topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response?.text
- topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response?._interop_serialize()
+ topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = response ? response.text : null
+ topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE] = response ? response._interop_serialize() : null
return topic_response
return TopicResponse("Unknown custom chat command: [command]!")
diff --git a/code/modules/tgs/v5/serializers.dm b/code/modules/tgs/v5/serializers.dm
index 7f9bc731b792..3a32848ad512 100644
--- a/code/modules/tgs/v5/serializers.dm
+++ b/code/modules/tgs/v5/serializers.dm
@@ -1,12 +1,12 @@
/datum/tgs_message_content/proc/_interop_serialize()
- return list("text" = text, "embed" = embed?._interop_serialize())
+ return list("text" = text, "embed" = embed ? embed._interop_serialize() : null)
/datum/tgs_chat_embed/proc/_interop_serialize()
CRASH("Base /proc/interop_serialize called on [type]!")
/datum/tgs_chat_embed/structure/_interop_serialize()
var/list/serialized_fields
- if(islist(fields))
+ if(istype(fields, /list))
serialized_fields = list()
for(var/datum/tgs_chat_embed/field/field as anything in fields)
serialized_fields += list(field._interop_serialize())
@@ -16,12 +16,12 @@
"url" = url,
"timestamp" = timestamp,
"colour" = colour,
- "image" = image?._interop_serialize(),
- "thumbnail" = thumbnail?._interop_serialize(),
- "video" = video?._interop_serialize(),
- "footer" = footer?._interop_serialize(),
- "provider" = provider?._interop_serialize(),
- "author" = author?._interop_serialize(),
+ "image" = src.image ? src.image._interop_serialize() : null,
+ "thumbnail" = thumbnail ? thumbnail._interop_serialize() : null,
+ "video" = video ? video._interop_serialize() : null,
+ "footer" = footer ? footer._interop_serialize() : null,
+ "provider" = provider ? provider._interop_serialize() : null,
+ "author" = author ? author._interop_serialize() : null,
"fields" = serialized_fields
)
@@ -43,7 +43,7 @@
. = ..()
.["iconUrl"] = icon_url
.["proxyIconUrl"] = proxy_icon_url
-
+
/datum/tgs_chat_embed/footer/_interop_serialize()
return list(
"text" = text,
diff --git a/code/modules/tgs/v5/topic.dm b/code/modules/tgs/v5/topic.dm
index 56c1824fd97d..d7d471213813 100644
--- a/code/modules/tgs/v5/topic.dm
+++ b/code/modules/tgs/v5/topic.dm
@@ -5,6 +5,7 @@
return response
/datum/tgs_api/v5/proc/ProcessTopicJson(json, check_access_identifier)
+ TGS_DEBUG_LOG("ProcessTopicJson(..., [check_access_identifier])")
var/list/result = ProcessRawTopic(json, check_access_identifier)
if(!result)
result = TopicResponse("Runtime error!")
@@ -25,16 +26,20 @@
return response_json
/datum/tgs_api/v5/proc/ProcessRawTopic(json, check_access_identifier)
+ TGS_DEBUG_LOG("ProcessRawTopic(..., [check_access_identifier])")
var/list/topic_parameters = json_decode(json)
if(!topic_parameters)
+ TGS_DEBUG_LOG("ProcessRawTopic: json_decode failed")
return TopicResponse("Invalid topic parameters json: [json]!");
var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
if(check_access_identifier && their_sCK != access_identifier)
- return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER]!")
+ TGS_DEBUG_LOG("ProcessRawTopic: access identifier check failed")
+ return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] or it does not match!")
var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]
if(!isnum(command))
+ TGS_DEBUG_LOG("ProcessRawTopic: command type check failed")
return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]!")
return ProcessTopicCommand(command, topic_parameters)
@@ -43,6 +48,7 @@
return "response[payload_id]"
/datum/tgs_api/v5/proc/ProcessTopicCommand(command, list/topic_parameters)
+ TGS_DEBUG_LOG("ProcessTopicCommand([command], ...)")
switch(command)
if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND)
@@ -55,7 +61,6 @@
return result
if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION)
- intercepted_message_queue = list()
var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]
if(!istype(event_notification))
return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!")
@@ -66,23 +71,25 @@
var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS]
if(event_parameters && !istype(event_parameters))
- return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!")
+ . = TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!")
+ else
+ var/list/response = TopicResponse()
+ . = response
+ if(event_handler != null)
+ var/list/event_call = list(event_type)
+ if(event_parameters)
+ event_call += event_parameters
+
+ intercepted_message_queue = list()
+ event_handler.HandleEvent(arglist(event_call))
+ response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
+ intercepted_message_queue = null
- var/list/event_call = list(event_type)
if (event_type == TGS_EVENT_WATCHDOG_DETACH)
detached = TRUE
chat_channels.Cut() // https://github.com/tgstation/tgstation-server/issues/1490
- if(event_parameters)
- event_call += event_parameters
-
- if(event_handler != null)
- event_handler.HandleEvent(arglist(event_call))
-
- var/list/response = TopicResponse()
- response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
- intercepted_message_queue = null
- return response
+ return
if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
@@ -122,8 +129,10 @@
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE)
+ TGS_DEBUG_LOG("ProcessTopicCommand: It's a chat update")
var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]
if(!istype(chat_update_json))
+ TGS_DEBUG_LOG("ProcessTopicCommand: failed \"[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]\" check")
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!")
DecodeChannels(chat_update_json)
@@ -138,7 +147,7 @@
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_HEALTHCHECK)
- if(event_handler?.receive_health_checks)
+ if(event_handler && event_handler.receive_health_checks)
event_handler.HandleEvent(TGS_EVENT_HEALTH_CHECK)
return TopicResponse()
diff --git a/html/changelogs/AutoChangeLog-pr-3784.yml b/html/changelogs/AutoChangeLog-pr-3784.yml
deleted file mode 100644
index ed2a39ee8e23..000000000000
--- a/html/changelogs/AutoChangeLog-pr-3784.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "realforest2001"
-delete-after: True
-changes:
- - maptweak: "Added Apollo Maintenance Controllers to the following locations."
- - maptweak: "Astronavigation, CIC Substation, Brig Substation, Req Aux Storage, Hangar & OT & Engineering workshops, Reactor Core Room and Lifeboat Control Ring."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3798.yml b/html/changelogs/AutoChangeLog-pr-3798.yml
new file mode 100644
index 000000000000..0cf3ed169ecd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3798.yml
@@ -0,0 +1,6 @@
+author: "Ben10083"
+delete-after: True
+changes:
+ - rscadd: "Working Joes now have a unique death message. Credit to Quickload for the message."
+ - soundadd: "Working Joes now have a death rattle. Credit to Quickload for shifting through Alien Isolation audio files."
+ - qol: "Things that die with intent eyes now lose color in their eyes on death."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3885.yml b/html/changelogs/AutoChangeLog-pr-3885.yml
new file mode 100644
index 000000000000..f3d6528be66b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3885.yml
@@ -0,0 +1,6 @@
+author: "Drathek"
+delete-after: True
+changes:
+ - bugfix: "Banished players will no longer be candidates for hives they are banished from."
+ - bugfix: "Cryoing will now set your larva queue time so you don't get prioritized over others that have been waiting."
+ - admin: "Shuttle intoTheSunset will set larva queue time the same as other situations."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3892.yml b/html/changelogs/AutoChangeLog-pr-3892.yml
new file mode 100644
index 000000000000..5973b1b11324
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3892.yml
@@ -0,0 +1,4 @@
+author: "theselfish"
+delete-after: True
+changes:
+ - spellcheck: "Goodbye Squad Spotter, hello regular non-squaded Spotter."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3895.yml b/html/changelogs/AutoChangeLog-pr-3895.yml
deleted file mode 100644
index e15366716ee4..000000000000
--- a/html/changelogs/AutoChangeLog-pr-3895.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-author: "Puckaboo2"
-delete-after: True
-changes:
- - spellcheck: "Some duplicate icon states have been differentiated to prevent future missing icon state errors."
- - imageadd: "Added new icon states for chemical and virology dispensers."
- - rscdel: "Removed dozens of duplicate icon states from over 50 files to reduce bloat."
- - rscdel: "Removed duplicate empty icon states."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3897.yml b/html/changelogs/AutoChangeLog-pr-3897.yml
new file mode 100644
index 000000000000..5c4c45410146
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3897.yml
@@ -0,0 +1,5 @@
+author: "Morrow"
+delete-after: True
+changes:
+ - balance: "Explosive pouch inventory size from 3 to 6"
+ - balance: "Explosive pouch can no longer hold mine boxes"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3898.yml b/html/changelogs/AutoChangeLog-pr-3898.yml
new file mode 100644
index 000000000000..abda91f2b52b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3898.yml
@@ -0,0 +1,4 @@
+author: "Morrow"
+delete-after: True
+changes:
+ - rscadd: "Added bayonet pouch to req"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3900.yml b/html/changelogs/AutoChangeLog-pr-3900.yml
new file mode 100644
index 000000000000..9f5a7f4cacf2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3900.yml
@@ -0,0 +1,4 @@
+author: "realforest2001"
+delete-after: True
+changes:
+ - balance: "Reduced tranq pistol bullet damage from 40 to 15"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3904.yml b/html/changelogs/AutoChangeLog-pr-3904.yml
new file mode 100644
index 000000000000..e3c1a56fa7ae
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3904.yml
@@ -0,0 +1,4 @@
+author: "Drathek"
+delete-after: True
+changes:
+ - qol: "Added a preference to disable xeno ability deactivation when re-selecting the same ability"
\ No newline at end of file
diff --git a/html/changelogs/archive/2023-07.yml b/html/changelogs/archive/2023-07.yml
index fc14f1bc1c6e..db8b80db6820 100644
--- a/html/changelogs/archive/2023-07.yml
+++ b/html/changelogs/archive/2023-07.yml
@@ -209,3 +209,14 @@
so they can still be found correctly.
theselfish:
- rscadd: SOs may now get coats in their vendor.
+2023-07-17:
+ Puckaboo2:
+ - spellcheck: Some duplicate icon states have been differentiated to prevent future
+ missing icon state errors.
+ - imageadd: Added new icon states for chemical and virology dispensers.
+ - rscdel: Removed dozens of duplicate icon states from over 50 files to reduce bloat.
+ - rscdel: Removed duplicate empty icon states.
+ realforest2001:
+ - maptweak: Added Apollo Maintenance Controllers to the following locations.
+ - maptweak: Astronavigation, CIC Substation, Brig Substation, Req Aux Storage, Hangar
+ & OT & Engineering workshops, Reactor Core Room and Lifeboat Control Ring.
diff --git a/sound/voice/joe/death_dream.ogg b/sound/voice/joe/death_dream.ogg
new file mode 100644
index 000000000000..366890711fe4
Binary files /dev/null and b/sound/voice/joe/death_dream.ogg differ
diff --git a/sound/voice/joe/death_normal.ogg b/sound/voice/joe/death_normal.ogg
new file mode 100644
index 000000000000..b1afd713e094
Binary files /dev/null and b/sound/voice/joe/death_normal.ogg differ
diff --git a/sound/voice/joe/death_silence.ogg b/sound/voice/joe/death_silence.ogg
new file mode 100644
index 000000000000..fea5080ccc99
Binary files /dev/null and b/sound/voice/joe/death_silence.ogg differ
diff --git a/sound/voice/joe/death_tomorrow.ogg b/sound/voice/joe/death_tomorrow.ogg
new file mode 100644
index 000000000000..dbb134005e5e
Binary files /dev/null and b/sound/voice/joe/death_tomorrow.ogg differ
diff --git a/tools/requirements.txt b/tools/requirements.txt
index abd6a512a222..316d7d2fe18d 100644
--- a/tools/requirements.txt
+++ b/tools/requirements.txt
@@ -3,5 +3,5 @@ bidict==0.22.0
Pillow==9.3.0
# changelogs
-PyYaml==5.4
+PyYaml==6.0.1
beautifulsoup4==4.9.3