diff --git a/_maps/map_files220/cyberiad/cyberiad.dmm b/_maps/map_files220/cyberiad/cyberiad.dmm
index c16160c4be34..dd56187a180e 100644
--- a/_maps/map_files220/cyberiad/cyberiad.dmm
+++ b/_maps/map_files220/cyberiad/cyberiad.dmm
@@ -28079,8 +28079,7 @@
/turf/simulated/floor/plating,
/area/station/command/office/ntrep)
"ciI" = (
-/obj/machinery/conveyor/west{
- dir = 10;
+/obj/machinery/conveyor/southwest{
id = "garbage"
},
/obj/effect/turf_decal/stripes/line{
@@ -96652,9 +96651,8 @@
},
/area/station/engineering/supermatter_room)
"wnR" = (
-/obj/machinery/conveyor/east{
- dir = 6;
- id = "QMLoad2"
+/obj/machinery/conveyor/southeast{
+ id = "garbage"
},
/obj/effect/turf_decal/stripes/line{
dir = 5
diff --git a/_maps/map_files220/delta/delta.dmm b/_maps/map_files220/delta/delta.dmm
index 78f3f194bd1b..9b73322f0e75 100644
--- a/_maps/map_files220/delta/delta.dmm
+++ b/_maps/map_files220/delta/delta.dmm
@@ -68204,6 +68204,9 @@
/obj/item/folder/blue,
/obj/item/pen/multi,
/obj/item/lighter/zippo/hop,
+/obj/item/storage/box/keys{
+ pixel_x = -15
+ },
/turf/simulated/floor/wood/oak,
/area/station/command/office/hop)
"lEt" = (
diff --git a/config/example/config.toml b/config/example/config.toml
index 25311d096ea9..6a33946ea878 100644
--- a/config/example/config.toml
+++ b/config/example/config.toml
@@ -871,6 +871,8 @@ enabled_away_missions = [
tts_enabled = false
# If enabled, what token does it use for API
tts_token_silero = ""
+# api url for your tts provider
+tts_api_url_silero = "http://you.tts.provider.com:port/endpoint"
# Are the audio files saved after usage
tts_cache_enabled = false
# What CPU threads are used for ffmpeg. Example valid values: "0-3" or "1,4-7"
diff --git a/modular_ss220/discord_link/code/discord.dm b/modular_ss220/discord_link/code/discord.dm
index 60ad9410814c..43f8cd426908 100644
--- a/modular_ss220/discord_link/code/discord.dm
+++ b/modular_ss220/discord_link/code/discord.dm
@@ -41,7 +41,7 @@
return
qdel(query_replace_token)
- to_chat(usr, span_darkmblue("Для завершения используйте команду ") + span_boldannounce("/привязать") + span_darkmblue(" и токен \"[token]\" в канале #дом-бота в Discord-сообществе!"))
+ to_chat(usr, span_darkmblue("Для завершения, вставьте это:
") + span_boldannounce("/привязать token:[token]") + span_darkmblue("
В канал #дом-бота в Discord-сообществе!"))
/mob/new_player/Topic(href, href_list)
if(src != usr)
diff --git a/modular_ss220/food/code/food.dm b/modular_ss220/food/code/food.dm
index dc5cd793692d..35e7650752a1 100644
--- a/modular_ss220/food/code/food.dm
+++ b/modular_ss220/food/code/food.dm
@@ -20,8 +20,8 @@
// Boiled Buckwheat
/obj/item/reagent_containers/food/snacks/boiledbuckwheat
- name = "варённая гречка"
- desc = "Это просто варённая гречка, ничего необычного."
+ name = "варёная гречка"
+ desc = "Это просто варёная гречка, ничего необычного."
icon = 'modular_ss220/food/icons/food.dmi'
icon_state = "boiledbuckwheat"
trash = /obj/item/trash/plate
@@ -36,7 +36,7 @@
// Merchant Buckwheat
/obj/item/reagent_containers/food/snacks/buckwheat_merchant
name = "гречка по-купечески"
- desc = "Тушённая гречка с овощами и мясом."
+ desc = "Тушёная гречка с овощами и мясом."
icon = 'modular_ss220/food/icons/food.dmi'
icon_state = "buckwheat_merchant"
trash = /obj/item/trash/plate
@@ -62,7 +62,7 @@
filling_color = "#C2CFAB"
bitesize = 3
list_reagents = list("nutriment" = 6, "kelotane" = 2, "vitamin" = 2)
- tastes = list("варённая картошка" = 1, "огурец" = 1, "морковка" = 1, "яйцо" = 1, "Новый Год" = 1)
+ tastes = list("варёная картошка" = 1, "огурец" = 1, "морковка" = 1, "яйцо" = 1, "Новый Год" = 1)
/datum/recipe/microwave/oliviersalad
reagents = list("cream" = 10, "sodiumchloride" = 5)
@@ -84,7 +84,7 @@
filling_color = "#C2CFAB"
bitesize = 3
list_reagents = list("nutriment" = 6, "kelotane" = 2, "vitamin" = 3)
- tastes = list("варённая картошка" = 1, "огурец" = 1, "морковка" = 1, "яйца" = 1, "странно" = 1, "Новый Год" = 1)
+ tastes = list("варёная картошка" = 1, "огурец" = 1, "морковка" = 1, "яйца" = 1, "странно" = 1, "Новый Год" = 1)
/datum/recipe/microwave/weirdoliviersalad
reagents = list("cream" = 10, "sodiumchloride" = 5)
@@ -823,7 +823,7 @@
..()
/obj/item/reagent_containers/food/snacks/boiledpelmeni
- name = "варённые пельмени"
+ name = "варёные пельмени"
desc = "Мы не знаем, какой была Сибирь, но эти вкусные пельмени определенно прибыли оттуда."
icon = 'modular_ss220/food/icons/food.dmi'
icon_state = "boiledpelmeni"
@@ -840,7 +840,7 @@
// Smoked Sausage
/obj/item/reagent_containers/food/snacks/smokedsausage
- name = "копчённая колбаска"
+ name = "копчёная колбаска"
desc = "Кусок копченой колбасы. Под пивко пойдёт."
icon = 'modular_ss220/food/icons/food.dmi'
icon_state = "smokedsausage"
diff --git a/modular_ss220/mecha_skins/code/mecha.dmi b/modular_ss220/mecha_skins/code/mecha.dmi
index 90ba2014a2e7..78244aa7d1f4 100644
Binary files a/modular_ss220/mecha_skins/code/mecha.dmi and b/modular_ss220/mecha_skins/code/mecha.dmi differ
diff --git a/modular_ss220/objects/_objects.dme b/modular_ss220/objects/_objects.dme
index 7e53f60090c9..47cddc33abe2 100644
--- a/modular_ss220/objects/_objects.dme
+++ b/modular_ss220/objects/_objects.dme
@@ -16,3 +16,4 @@
#include "code/posters.dm"
#include "code/tribune.dm"
#include "code/weapons.dm"
+#include "code/key.dm"
diff --git a/modular_ss220/objects/code/key.dm b/modular_ss220/objects/code/key.dm
new file mode 100644
index 000000000000..254b4dcbbfba
--- /dev/null
+++ b/modular_ss220/objects/code/key.dm
@@ -0,0 +1,109 @@
+
+/obj/item/door_remote/key
+ desc = "Обычный немного ржавый ключ."
+ icon = 'modular_ss220/objects/icons/key.dmi'
+ icon_state = "key"
+ /// Are you already using the key?
+ var/busy = FALSE
+ /// How fast does the key open an airlock.
+ var/hack_speed = 1 SECONDS
+
+/obj/item/door_remote/key/attack_self(mob/user)
+ return
+
+/obj/item/door_remote/key/afterattack(obj/machinery/door/airlock/attacked_airlock, mob/user, proximity)
+ if(!proximity)
+ return
+
+ if(!istype(attacked_airlock))
+ return
+
+ if(HAS_TRAIT(attacked_airlock, TRAIT_CMAGGED))
+ to_chat(user, span_danger("[src] не вставляется в панель доступа [attacked_airlock], тут повсюду слизь!"))
+ return
+
+ if(attacked_airlock.is_special)
+ to_chat(user, span_danger("[src] не помещается в панель доступа [attacked_airlock]!"))
+ return
+
+ if(!attacked_airlock.arePowerSystemsOn())
+ to_chat(user, span_danger("[attacked_airlock] без питания!"))
+ return
+
+ if(busy)
+ to_chat(user, span_warning("Ты уже используешь [src] на панели доступа [attacked_airlock]!"))
+ return
+
+ playsound(src, 'sound/items/keyring_unlock.ogg', 50)
+ attacked_airlock.add_fingerprint(user)
+
+ busy = TRUE
+ if(!do_after(user, hack_speed, target = attacked_airlock, progress = 1))
+ busy = FALSE
+ return
+ busy = FALSE
+
+ if(!attacked_airlock.check_access(ID))
+ to_chat(user, span_danger("[src] похоже не подходит к панели доступа [attacked_airlock]!"))
+ return
+
+ if(!attacked_airlock.density)
+ attacked_airlock.close()
+ return
+ attacked_airlock.open()
+
+/obj/item/door_remote/key/engineer
+ name = "\proper ключ от инженерного отдела"
+ icon_state = "eng"
+ additional_access = list(ACCESS_ENGINE,ACCESS_CONSTRUCTION)
+
+/obj/item/door_remote/key/medical
+ name = "\proper ключ от медицинского отдела"
+ icon_state = "med"
+ additional_access = list(ACCESS_MEDICAL)
+
+/obj/item/door_remote/key/supply
+ name = "\proper ключ от отдела снабжения"
+ icon_state = "supply"
+ additional_access = list(ACCESS_CARGO, ACCESS_MINING)
+
+/obj/item/door_remote/key/rnd
+ name = "\proper ключ от отдела исследований"
+ icon_state = "rnd"
+ additional_access = list(ACCESS_RESEARCH)
+
+/obj/item/door_remote/key/sec
+ name = "\proper ключ от отдела службы безопасности"
+ icon_state = "sec"
+ additional_access = list(ACCESS_SEC_DOORS)
+
+/obj/item/door_remote/key/service
+ name = "\proper ключ от отдела сервиса"
+ icon_state = "service"
+ additional_access = list(ACCESS_KITCHEN, ACCESS_BAR, ACCESS_HYDROPONICS, ACCESS_JANITOR)
+
+/obj/item/door_remote/key/command
+ name = "\proper ключ командования"
+ icon_state = "com"
+ additional_access = list(ACCESS_HEADS)
+
+/obj/item/storage/box/keys
+ name = "коробка с ключами"
+ desc = "Коробка с ключами к отделам. Имеют неполный доступ к шлюзам."
+
+/obj/item/storage/box/keys/populate_contents()
+ new /obj/item/door_remote/key/sec(src)
+ new /obj/item/door_remote/key/sec(src)
+ new /obj/item/door_remote/key/supply(src)
+ new /obj/item/door_remote/key/supply(src)
+ new /obj/item/door_remote/key/service(src)
+ new /obj/item/door_remote/key/service(src)
+ new /obj/item/door_remote/key/engineer(src)
+ new /obj/item/door_remote/key/engineer(src)
+ new /obj/item/door_remote/key/rnd(src)
+ new /obj/item/door_remote/key/rnd(src)
+ new /obj/item/door_remote/key/command(src)
+ new /obj/item/door_remote/key/command(src)
+ new /obj/item/door_remote/key/medical(src)
+ new /obj/item/door_remote/key/medical(src)
+
diff --git a/modular_ss220/objects/icons/key.dmi b/modular_ss220/objects/icons/key.dmi
new file mode 100644
index 000000000000..4740d7b5e706
Binary files /dev/null and b/modular_ss220/objects/icons/key.dmi differ
diff --git a/modular_ss220/queue/code/new_player_procs.dm b/modular_ss220/queue/code/new_player_procs.dm
index 343cb8d44cd3..366682a85c98 100644
--- a/modular_ss220/queue/code/new_player_procs.dm
+++ b/modular_ss220/queue/code/new_player_procs.dm
@@ -12,6 +12,10 @@
SSqueue.queue_bypass_list |= ckey
return
+ if(client.donator_level >= 3)
+ SSqueue.queue_bypass_list |= ckey
+ return
+
if(length(GLOB.clients) < SSqueue.queue_threshold)
SSqueue.queue_bypass_list |= ckey
return
diff --git a/modular_ss220/text_to_speech/code/configuration.dm b/modular_ss220/text_to_speech/code/configuration.dm
index 30d862197bfb..7c63ff528a12 100644
--- a/modular_ss220/text_to_speech/code/configuration.dm
+++ b/modular_ss220/text_to_speech/code/configuration.dm
@@ -13,6 +13,8 @@
var/tts_enabled = FALSE
/// TTS API token for silero provider
var/tts_token_silero = ""
+ /// TTS API url for silero provide
+ var/tts_api_url_silero = "http://s2.ss220.club:9999/voice"
/// Should oggs be cached
var/tts_cache_enabled = FALSE
/// What cpu threads should ffmpeg use
@@ -23,6 +25,7 @@
CONFIG_LOAD_STR(tts_token_silero, data["tts_token_silero"])
CONFIG_LOAD_BOOL(tts_cache_enabled, data["tts_cache_enabled"])
CONFIG_LOAD_STR(ffmpeg_cpuaffinity, data["ffmpeg_cpuaffinity"])
+ CONFIG_LOAD_STR(tts_api_url_silero, data["tts_api_url_silero"])
tts_enabled = tts_token_silero && tts_enabled
var/sanitized = regex(@"[^0-9,-]", "g").Replace(ffmpeg_cpuaffinity, "")
@@ -32,3 +35,7 @@
/datum/http_request/vv_get_var(var_name)
if(var_name == "body")
return FALSE
+
+/datum/configuration_section/tts_configuration/vv_get_var(var_name, var_value)
+ if(var_name == "tts_api_url_silero")
+ return FALSE
diff --git a/modular_ss220/text_to_speech/code/providers/silero.dm b/modular_ss220/text_to_speech/code/providers/silero.dm
index 9f3f2bba1772..c1257a6997c4 100644
--- a/modular_ss220/text_to_speech/code/providers/silero.dm
+++ b/modular_ss220/text_to_speech/code/providers/silero.dm
@@ -1,12 +1,6 @@
/datum/tts_provider/silero
name = "Silero"
is_enabled = TRUE
- api_url = "http://s2.ss220.club:9999/voice"
-
-/datum/tts_provider/silero/vv_edit_var(var_name, var_value)
- if(var_name == "api_url")
- return FALSE
- return ..()
/datum/tts_provider/silero/request(text, datum/tts_seed/silero/seed, datum/callback/proc_callback)
if(throttle_check())
@@ -28,7 +22,7 @@
req_body["format"] = "ogg"
req_body["word_ts"] = FALSE
- SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, api_url, json_encode(req_body), list("content-type" = "application/json"), proc_callback)
+ SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, GLOB.configuration.tts.tts_api_url_silero , json_encode(req_body), list("content-type" = "application/json"), proc_callback)
return TRUE