Archived
Various Mod Updates for SPT 3.11
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
[General]
|
||||
gameName=spt
|
||||
modid=0
|
||||
version=d2025.1.4.0
|
||||
version=d2025.5.13.0
|
||||
newestVersion=
|
||||
category="1,2"
|
||||
nexusFileStatus=1
|
||||
installationFile=fika-server.zip
|
||||
repository=
|
||||
installationFile=fika-server-2.4.8.zip
|
||||
repository=Nexus
|
||||
ignoredVersion=
|
||||
comments=
|
||||
notes=
|
||||
|
||||
@@ -11,7 +11,7 @@ Server-side changes to make multiplayer work.
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Node 20.x](https://nodejs.org/en/download)
|
||||
- [Node 22.x](https://nodejs.org/en/download)
|
||||
|
||||
## Build
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"client": {
|
||||
"useBtr": true,
|
||||
"friendlyFire": true,
|
||||
"dynamicVExfils": false,
|
||||
"allowFreeCam": false,
|
||||
"allowSpectateFreeCam": false,
|
||||
"allowItemSending": true,
|
||||
"blacklistedItems": [],
|
||||
"forceSaveOnDeath": false,
|
||||
"mods": {
|
||||
"required": [],
|
||||
"optional": []
|
||||
},
|
||||
"useInertia": true,
|
||||
"sharedQuestProgression": false,
|
||||
"canEditRaidSettings": true,
|
||||
"enableTransits": true
|
||||
},
|
||||
"server": {
|
||||
"giftedItemsLoseFIR": true,
|
||||
"launcherListAllProfiles": false,
|
||||
"sessionTimeout": 5,
|
||||
"showDevProfile": false,
|
||||
"showNonStandardProfile": false
|
||||
},
|
||||
"natPunchServer": {
|
||||
"enable": false,
|
||||
"port": 6790,
|
||||
"natIntroduceAmount": 1
|
||||
},
|
||||
"dedicated": {
|
||||
"profiles": {
|
||||
"amount": 0
|
||||
},
|
||||
"scripts": {
|
||||
"generate": true,
|
||||
"forceIp": ""
|
||||
}
|
||||
},
|
||||
"background": {
|
||||
"enable": true,
|
||||
"easteregg": false
|
||||
}
|
||||
}
|
||||
@@ -43,9 +43,10 @@
|
||||
"F_MMUI_StartButton": "开始",
|
||||
"F_MMUI_LoadingScreenHeader": "加载中",
|
||||
"F_MMUI_LoadingScreenDescription": "请稍候,正在初始化... 这可能需要一些时间。",
|
||||
"F_MMUI_JoinAsSpectator": "观战",
|
||||
"F_UI_StartRaid": "开始战局",
|
||||
"F_UI_StartRaidDescription": "启动战局\n后续玩家将无法进入",
|
||||
"F_MMUI_JoinAsSpectator": "旁观者模式",
|
||||
"F_MMUI_JoinAsSpectator_D": "以旁观者模式加入游戏",
|
||||
"F_UI_StartRaid": "启动战局",
|
||||
"F_UI_StartRaidDescription": "开始战局\n点击此附加项后其他玩家不能加入",
|
||||
"F_UI_CannotJoinRaidOtherMap": "不可以加入另一个地图的行动\n行动地图: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "不可以加入另一个时间的行动.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "你不能以PMC身份加入SCAV行动",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "错误绑定",
|
||||
"F_UI_ErrorBindIP": "{0} 不是一个有效的绑定IP地址!请检查“强制IP”设置",
|
||||
"F_UI_NoDedicatedClients": "现在没有可用的专用客户端。",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "开始战局\n其他玩家能够在加载战局状态时加入",
|
||||
"F_UI_WaitForHostStartRaid": "正在等待主机开始战局...",
|
||||
"F_UI_WaitForHostFinishInit": "正在等待主机完成战局初始化",
|
||||
"F_UI_WaitForOtherPlayers": "正在等待其他玩家完成加载",
|
||||
"F_UI_RetrieveSpawnInfo": "正在从服务器获取生成信息...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "游戏模式",
|
||||
"F_BepInEx_OfficialVersion_T": "官方版本",
|
||||
"F_BepInEx_OfficialVersion_D": "显示官方版本而不是Fika版本。",
|
||||
"F_BepInEx_UseHeadless_T": "自动使用Headless",
|
||||
"F_BepInEx_UseHeadless_D": "如果可用请保持勾选来使用无Headless的客户端",
|
||||
"F_BepInEx_ShowFeed_T": "显示战局信息",
|
||||
"F_BepInEx_ShowFeed_D": "启用玩家死亡、撤离、击杀BOSS时的自定义通知",
|
||||
"F_BepInEx_AutoExtract_T": "自动撤离",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "最小姓名牌尺寸",
|
||||
"F_BepInEx_UseOcclusion_T": "使用遮挡功能",
|
||||
"F_BepInEx_UseOcclusion_D": "使用遮挡后,当玩家不在视野范围内时隐藏名称板",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "任务类型",
|
||||
"F_BepInEx_QuestTypes_D": "要接收和发送的任务类型。PlaceBeacon 包含了标记和物品任务",
|
||||
"F_BepInEx_QSNotifications_T": "显示通知",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "动态AI应该多久扫描一次所有玩家的范围",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "忽略狙击手",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "动态AI是否应该忽略狙击手Scav。",
|
||||
"F_BepInEx_FikaGC_T": "使用 Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "如果使用自定义垃圾收集器来缓解内存使用问题。\n警告:这是一个实验性功能,可能对您的系统没有任何影响。",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "强制生成上限",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "在生成机器人时强制生成上限,确保不会超过原版的极限。 这主要会影响到使用生成模组或修改机器人限制的任何东西。不会阻止像boss这样的特殊机器人的生成。",
|
||||
"F_BepInEx_DespawnFurthest_T": "取消最远生成",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "连接超时",
|
||||
"F_BepInEx_ConnectionTimeout_D": "如果没有收到数据包,判定连接丢失所需的时间。",
|
||||
"F_BepInEx_SendRate_T": "发送速率",
|
||||
"F_BepInEx_SendRate_D": "每秒发送移动数据包的频率(值越低=使用的带宽越少,但插值期间的延迟略高)。\n此设置仅影响主机,并会同步到所有客户端。\n单位为每秒发送次数:\n\n非常低 = 10\n低 = 15\n中 = 20\n高 = 30\n\n建议保持在不高于\"中\"的设置,因为更高的设置带来的性能提升微乎其微。",
|
||||
"F_BepInEx_SmoothingRate_T": "平滑速率",
|
||||
"F_BepInEx_SmoothingRate_D": "本地模拟延迟为(发送速率 * 平滑速率)。这样可以确保缓冲区中始终有足够的快照,以在插值期间减轻延迟和抖动的影响。\n\n低 = 1.5 \n中 = 2 \n高 = 2.5 \n\n如果运动不流畅,将此设置为“高”。无法在突袭过程中更改。",
|
||||
"F_BepInEx_SendRate_D": "每秒发送移动数据包的频率(值越低=使用的带宽越少,但插值过程中延迟稍大)。\n此设置仅影响主机,并会同步到所有客户端。\n每秒发送次数:\n\n低 = 10\n中 = 20\n高 = 30\n\n建议保持使用不高于\"中\"的设置,因为更高的设置带来的性能提升几乎微乎其微。",
|
||||
"F_BepInEx_NetMultiThread_T": "使用多线程技术",
|
||||
"F_BepInEx_NetMultiThread_D": "是否启用多线程网络组件。这可能会缓解游戏延迟时的问题,使网络管理器在低FPS期间仍能处理和排队数据包。\n这是一个实验性功能,只能在高端PC上启用,并且只会在无头客户端上启用。",
|
||||
"F_BepInEx_VOIP_T": "允许VOIP通话",
|
||||
"F_BepInEx_VOIP_D": "是否在您主持游戏时启动VOIP通话。",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "禁用AI新陈代谢",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "禁用AI新陈代谢,防止其在长时间战局中因饥饿/脱水而死亡",
|
||||
"F_MMUI_OnlinePlayers": "在线玩家: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "在藏身处中",
|
||||
"F_MMUI_InFlea": "在跳蚤市场中",
|
||||
"F_MMUI_RaidDetails": "作为 {0} 在 {1} 上游玩\n时间:{2}",
|
||||
"F_Mod_VerificationFailure": "Fika.Core.dll 文件中的\"Crc32\"检验操作失败,您无法与其他人一起联机游玩!\n请查看您的日志文件以获取更多信息。",
|
||||
"F_UI_LocaleError_H": "语言文件错误",
|
||||
"F_UI_LocaleError_D": "加载Fika语言时发生错误。现在正在为失效的翻译条目切换为后备模式。 请将此报告给开发者!\n\n失效的文本键值: {0}"
|
||||
"F_UI_LocaleError_D": "加载Fika语言时发生错误。现在正在为失效的翻译条目切换为后备模式。 请将此报告给开发者!\n\n失效的文本键值: {0}",
|
||||
"F_UI_EFTVersionError": "你在尝试使用与运行战局的服务器主机版本不同的EFT\n客户端:{0}\n主机:{1}",
|
||||
"F_UI_FikaVersionError": "你在尝试使用与运行战局的服务器主机版本不同的Fika\n客户端:{0}\n主机:{1}",
|
||||
"F_UI_PlayerConnected": "{0} 已连接",
|
||||
"F_UI_PlayerDisconnected": "{0} 已断开连接",
|
||||
"F_UI_DisabledByServerHost": "服务器已禁用"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "Založit RAID",
|
||||
"F_MMUI_JoinButton": "PŘIPOJIT",
|
||||
"F_MMUI_SelectAmountHeader": "VYBERTE POČET",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "NASTAVENÍ RELACE",
|
||||
"F_MMUI_SelectAmountDescription": "Kolik lidí (včetně vás) bude hrát?",
|
||||
"F_MMUI_UseDedicatedHost": "Použít Dedikovaného Hosta",
|
||||
"F_MMUI_StartButton": "SPUSTIT",
|
||||
"F_MMUI_LoadingScreenHeader": "NAČÍTÁNÍ",
|
||||
"F_MMUI_LoadingScreenDescription": "Počkejte prosím, než se raid spustí... může to chvíli trvat.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Přihlížet",
|
||||
"F_MMUI_JoinAsSpectator_D": "Připojit se do hry jako přihlížející",
|
||||
"F_UI_StartRaid": "Začít Raid",
|
||||
"F_UI_StartRaidDescription": "Začne Raid\nPo kliknutí nebude možné připojení dalších hráčů",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Nelze se připojit k raidu na jiné mapě.\nMapa raidu: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Nelze se připojit k raidu v jiném čase.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Ke scav raidu se jako PMC nemůžete připojit.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "CHYBA BINDOVÁNÍ",
|
||||
"F_UI_ErrorBindIP": "{0} není platná IP adresa pro připojení! Zkontrolujte nastavení 'Vynutit Bindování IP'.",
|
||||
"F_UI_NoDedicatedClients": "Dedikovaný klient není k dispozici.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Začít Raid\nDalší hráči se budou moci připojit během načítací obrazovky",
|
||||
"F_UI_WaitForHostStartRaid": "Čeká se na hosta, než zapne hru...",
|
||||
"F_UI_WaitForHostFinishInit": "Čekáme na zakladatele hry aby dokončil raid inicializaci...",
|
||||
"F_UI_WaitForOtherPlayers": "Čekání na ostatní hráče co se načítají...",
|
||||
"F_UI_RetrieveSpawnInfo": "Obdržuji informace o spawnu ze serveru...",
|
||||
@@ -91,55 +93,57 @@
|
||||
"F_UI_WaitForPlayers": "Čekání na {0} hráčů",
|
||||
"F_UI_ToSLong": "Vítejte u Fika!\n\nFika je kooperativní mod pro SPT, který vám umožňuje hrát s přáteli. Fika je a vždy bude zdarma, pokud jste za ni zaplatili, byli jste podvedeni. Také není dovoleno provozovat veřejné servery s monetizací nebo přijímáním darů.\n\n\"Počkejte, až tato zpráva zmizí, abyste přijali naše podmínky služby.\"\n\nMůžete se připojit na náš Discord zde: https://discord.gg/project-fika",
|
||||
"F_UI_ToSShort": "Vítejte u Fika!\n\nFika je kooperativní mod pro SPT, který vám umožňuje hrát s přáteli. Fika je a vždy bude zdarma, pokud jste za ni zaplatili, byli jste podvedeni. Také není dovoleno provozovat veřejné servery s monetizací nebo přijímáním darů.\n\nMůžete se připojit na náš Discord zde: https://discord.gg/project-fika",
|
||||
"F_UI_RaidSettingsDescription": "In this mode, you can play online co-op with your friends without the risk of meeting others.\nAll game mechanics in the co-op mode (weather, bots, bosses, etc.) are identical to the online mechanics.\nOnly the hosts settings will take effect.",
|
||||
"F_UI_CoopGameMode": "Fika Co-op Game Mode",
|
||||
"F_UI_CoopRaidSettings": "Fika Co-op Raid Settings",
|
||||
"F_UI_FikaAlwaysCoop": "Co-op is always enabled in Fika",
|
||||
"F_UI_UpnpFailed": "UPnP mapping failed. Make sure the selected port is not already open!\nDisable UPnP if you are using a VPN.",
|
||||
"F_UI_InitWeather": "Generating weather...",
|
||||
"F_Notification_RaidStarted": "{0} started a raid on {1}",
|
||||
"F_Notification_ItemReceived": "You received a {0} from {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Editing of RaidSettings is disabled by the server host",
|
||||
"F_UI_ExtractMessage": "Press {0} to extract",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_BepInEx_H_Advanced": "Advanced",
|
||||
"F_UI_RaidSettingsDescription": "V tomto režimu můžete hrát online co-op se svými přáteli, bez rizika setkání se s ostatními.\nVšechny herní mechaniky v co-op režimu (počasí, boti, bosové, atd..) jsou identické k online mechanikám.\nBude použito pouze nastavení hostitele.",
|
||||
"F_UI_CoopGameMode": "Herní mód Fika Co-op",
|
||||
"F_UI_CoopRaidSettings": "Fika Co-op Raid Nastavení",
|
||||
"F_UI_FikaAlwaysCoop": "Ve Fika je co-op vždy povolen",
|
||||
"F_UI_UpnpFailed": "UPnP mapování se nezdařilo. Ujistěte se že jste vybral port, který ještě není otevřený! Vypněte UPnP pokud používáte VPN.",
|
||||
"F_UI_InitWeather": "Generuju počasí...",
|
||||
"F_Notification_RaidStarted": "{0} spustil raid na {1}",
|
||||
"F_Notification_ItemReceived": "Dostal jsi {0} od {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Hostitel serveru vypnul upravování nastavení Raidu",
|
||||
"F_UI_ExtractMessage": "Zmáčkni {0} abys extrahoval",
|
||||
"F_UI_DownloadProfile": "STÁHNOUT PROFIL",
|
||||
"F_BepInEx_H_Advanced": "Pokročilé",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | Name Plates",
|
||||
"F_BepInEx_H_Coop_QuestSharing": "Coop | Quest Sharing",
|
||||
"F_BepInEx_H_Coop_Pinging": "Coop | Pinging",
|
||||
"F_BepInEx_H_Coop_Debug": "Coop | Debug",
|
||||
"F_BepInEx_H_Performance": "Performance",
|
||||
"F_BepInEx_H_PerformanceBots": "Performance | Max Bots",
|
||||
"F_BepInEx_H_Network": "Network",
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Official Version",
|
||||
"F_BepInEx_OfficialVersion_D": "Show official version instead of Fika version.",
|
||||
"F_BepInEx_ShowFeed_T": "Show Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Enable custom notifications when a player dies, extracts, kills a boss, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extract",
|
||||
"F_BepInEx_AutoExtract_D": "Automatically extracts after the extraction countdown. As a host, this will only work if there are no clients connected.",
|
||||
"F_BepInEx_ShowExtractMessage_T": "Show Extract Message",
|
||||
"F_BepInEx_ShowExtractMessage_D": "Whether to show the extract message after dying/extracting.",
|
||||
"F_BepInEx_ExtractKey_T": "Extract Key",
|
||||
"F_BepInEx_ExtractKey_D": "The key used to extract from the raid.",
|
||||
"F_BepInEx_EnableChat_T": "Enable Chat",
|
||||
"F_BepInEx_EnableChat_D": "Toggle to enable chat in game. Cannot be change mid raid.",
|
||||
"F_BepInEx_ChatKey_T": "Chat Key",
|
||||
"F_BepInEx_ChatKey_D": "The key used to open the chat window.",
|
||||
"F_BepInEx_EnableOnlinePlayers_T": "Enable Online Players",
|
||||
"F_BepInEx_EnableOnlinePlayers_D": "If the online players menu should be shown in the menu.",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Online Players Scale",
|
||||
"F_BepInEx_OnlinePlayersScale_D": "The scale of the window that displays online players. Only change if it looks out of proportion.\n\nRequires a refresh of the main menu to take effect.",
|
||||
"F_BepInEx_UseNamePlates_T": "Show Player Name Plates",
|
||||
"F_BepInEx_UseNamePlates_D": "If name plates should be shown above teammates.",
|
||||
"F_BepInEx_HideHealthBar_T": "Hide Health Bar",
|
||||
"F_BepInEx_HideHealthBar_D": "Completely hides the health bar.",
|
||||
"F_BepInEx_UsePercent_T": "Show HP% instead of bar",
|
||||
"F_BepInEx_UsePercent_D": "Shows health in % amount instead of using the bar.",
|
||||
"F_BepInEx_ShowEffects_T": "Show Effects",
|
||||
"F_BepInEx_ShowEffects_D": "If status effects should be displayed below the health bar.",
|
||||
"F_BepInEx_ShowFactionIcon_T": "Show Player Faction Icon",
|
||||
"F_BepInEx_ShowFactionIcon_D": "Shows the player faction icon next to the HP bar.",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | Štítky jmen",
|
||||
"F_BepInEx_H_Coop_QuestSharing": "Coop | Sdílení úkolů",
|
||||
"F_BepInEx_H_Coop_Pinging": "Coop | Vyznačení",
|
||||
"F_BepInEx_H_Coop_Debug": "Coop | Debugování",
|
||||
"F_BepInEx_H_Performance": "Výkon",
|
||||
"F_BepInEx_H_PerformanceBots": "Výkon | Maximum Botů",
|
||||
"F_BepInEx_H_Network": "Síť",
|
||||
"F_BepInEx_H_Gameplay": "Hra",
|
||||
"F_BepInEx_OfficialVersion_T": "Oficiální verze",
|
||||
"F_BepInEx_OfficialVersion_D": "Zobrazit oficální verzi místo Fika verze.",
|
||||
"F_BepInEx_UseHeadless_T": "Automaticky použij Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Pokud je to možné zaškrtni pole pro použití Headless klienta",
|
||||
"F_BepInEx_ShowFeed_T": "Zobrazit Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Zapne oznámení když hráč umře, extrahuje, zabije bosse, atd.",
|
||||
"F_BepInEx_AutoExtract_T": "Automaticky Extrahovat",
|
||||
"F_BepInEx_AutoExtract_D": "Automaticky extrahovat poté co skončí odpočet. Toto bude pro hostitele fungovat pouze když nejsou připojeni žádní klienti.",
|
||||
"F_BepInEx_ShowExtractMessage_T": "Zobrazit Zprávu Extrahování",
|
||||
"F_BepInEx_ShowExtractMessage_D": "Zobrazení zprávy o extrahování po smrti/extrahování",
|
||||
"F_BepInEx_ExtractKey_T": "Extrahovací Tlačítko",
|
||||
"F_BepInEx_ExtractKey_D": "Tlačítko pro extrahování z raidu.",
|
||||
"F_BepInEx_EnableChat_T": "Povolit Chat",
|
||||
"F_BepInEx_EnableChat_D": "Přepínač k povolování chatu ve hře. Nelze změnit během raidu.",
|
||||
"F_BepInEx_ChatKey_T": "Tlačítko Chatu",
|
||||
"F_BepInEx_ChatKey_D": "Tlačítko používané k otevření chatovacího okna",
|
||||
"F_BepInEx_EnableOnlinePlayers_T": "Povolit Online Hráče",
|
||||
"F_BepInEx_EnableOnlinePlayers_D": "Zobrazení tabulky online hráčů v menu.",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Měřítko okna online hráčů",
|
||||
"F_BepInEx_OnlinePlayersScale_D": "Měřítko okna online hráčů v menu. Změňte pouze pokud okno vypadá divně.\n\nJe potřeba aktualizovat hlavní menu, aby se změna mohla projevit.",
|
||||
"F_BepInEx_UseNamePlates_T": "Zobrazit Štítky Jmen Hráčů",
|
||||
"F_BepInEx_UseNamePlates_D": "Zobrazení štítků se jmény nad spoluhráčema.",
|
||||
"F_BepInEx_HideHealthBar_T": "Schovat lištu s životy.",
|
||||
"F_BepInEx_HideHealthBar_D": "Zcela skrýt lištu s životy.",
|
||||
"F_BepInEx_UsePercent_T": "Zobrazit % životů místo lišty",
|
||||
"F_BepInEx_UsePercent_D": "Zobrazit životy v % místo používání lišty.",
|
||||
"F_BepInEx_ShowEffects_T": "Zobrazit efekty",
|
||||
"F_BepInEx_ShowEffects_D": "Zobrazit status efekty pod lištou se životy.",
|
||||
"F_BepInEx_ShowFactionIcon_T": "Zobrazit Ikonku Frakce Hráče",
|
||||
"F_BepInEx_ShowFactionIcon_D": "Zobrazit ikonku frakce vedle HP baru.",
|
||||
"F_BepInEx_HideInOptic_T": "Hide Name Plate in Optic",
|
||||
"F_BepInEx_HideInOptic_D": "Hides the name plate when viewing through PiP scopes.",
|
||||
"F_BepInEx_OpticUseZoom_T": "Name Plates Use Optic Zoom",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_UseOcclusion_T": "Use Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Show Notifications",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -217,7 +227,7 @@
|
||||
"F_BepInEx_DespawnMinDistance_T": "Despawn Minimum Distance",
|
||||
"F_BepInEx_DespawnMinDistance_D": "The minimum distance to despawn a bot.",
|
||||
"F_BepInEx_MaxBots_T": "Max Bots {0}",
|
||||
"F_BepInEx_MaxBots_D": "Max amount of bots that can be active at the same time on {0}. Useful if you have a weaker PC. Set to 0 to use vanilla limits. Cannot be changed during a raid.",
|
||||
"F_BepInEx_MaxBots_D": "Maximální počet botů kteří mohou být aktivní ve stejný moment na {0}. Vhodné když máte slabší PC. Zadejte 0 abyste použili vanilla limity. Nemůže být změněno během raidu.",
|
||||
"F_BepInEx_NativeSockets_T": "Native Sockets",
|
||||
"F_BepInEx_NativeSockets_D": "Use NativeSockets for gameplay traffic. This uses direct socket calls for send/receive to drastically increase speed and reduce GC pressure. Only for Windows/Linux and might not always work.",
|
||||
"F_BepInEx_ForceIP_T": "Force IP",
|
||||
@@ -233,18 +243,26 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Lokální simulace je pozadu o (Send Rate * Smoothing Rate). Toto garantuje že vždy budeme mít dostatečný počet snapshotů v bufferu, abychom předešli lagům během interpolace.\n\nNízké = 1.5\nStřední = 2\nVysoké = 2.5\n\nNastavte na Vysoké, pokud pohyb není plynulý. Nemůže být změněno během raidu.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
"F_MMUI_InMenu": "In Menu",
|
||||
"F_MMUI_InRaid": "In Raid",
|
||||
"F_MMUI_InRaid": "V Raidu",
|
||||
"F_MMUI_InStash": "In Stash",
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_MMUI_RaidDetails": "Hraje jako {0} na {1}\nČas v raidu: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "Pokoušíte se použít jinou verzi EFT než má hostitel raidu.\nVáš Client: {0}\nHostitel: {1}",
|
||||
"F_UI_FikaVersionError": "Pokoušíte se použít jinou verzi Fika než má hostitel raidu.\nVaše verze: {0}\nHostitel: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -43,9 +43,10 @@
|
||||
"F_MMUI_StartButton": "START",
|
||||
"F_MMUI_LoadingScreenHeader": "LOADING",
|
||||
"F_MMUI_LoadingScreenDescription": "Please wait while the raid is initializing... this might take some time.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_MMUI_JoinAsSpectator": "Spectate",
|
||||
"F_MMUI_JoinAsSpectator_D": "Join the game as a spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nAfter clicking this additional players will not be able to join",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Cannot join a raid that is on another map.\nRaid map: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Cannot join a raid that is on another time.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "You cannot join a scav raid as a PMC.",
|
||||
@@ -65,6 +66,7 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERROR BINDING",
|
||||
"F_UI_ErrorBindIP": "'{0}' is not a valid IP address to bind to! Check your 'Force Bind IP' setting.",
|
||||
"F_UI_NoDedicatedClients": "No dedicated clients are available.",
|
||||
"F_UI_HostRaidTooltip": "Starts a raid\nOther players will be able to join you during the loading screen",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_WaitForHostFinishInit": "Waiting for host to finish raid initialization...",
|
||||
"F_UI_WaitForOtherPlayers": "Waiting for other players to finish loading...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Official Version",
|
||||
"F_BepInEx_OfficialVersion_D": "Show official version instead of Fika version.",
|
||||
"F_BepInEx_UseHeadless_T": "Auto Use Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Always tick the box to use the Headless Client if available",
|
||||
"F_BepInEx_ShowFeed_T": "Show Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Enable custom notifications when a player dies, extracts, kills a boss, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extract",
|
||||
@@ -158,6 +162,12 @@
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_UseOcclusion_T": "Use Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_NamePlateColor_T": "Name Plate Text Color",
|
||||
"F_BepInEx_NamePlateColor_D": "The color of the text above the name plate.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Show Notifications",
|
||||
@@ -210,6 +220,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -233,9 +245,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
@@ -245,6 +259,12 @@
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -43,9 +43,10 @@
|
||||
"F_MMUI_StartButton": "COMENZAR",
|
||||
"F_MMUI_LoadingScreenHeader": "CARGANDO",
|
||||
"F_MMUI_LoadingScreenDescription": "Por favor, espere mientras la inclusión se está inicializando... esto puede tomar algún tiempo.",
|
||||
"F_MMUI_JoinAsSpectator": "Unirse como espectador",
|
||||
"F_MMUI_JoinAsSpectator": "Spectate",
|
||||
"F_MMUI_JoinAsSpectator_D": "Join the game as a spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nAfter clicking this additional players will not be able to join",
|
||||
"F_UI_CannotJoinRaidOtherMap": "No puedes unirte a una incursión que está en otro mapa.\nMapa de incursión: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "No puedes unirte a una incursión que esté en otro horario.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "No puedes unirte a una incursión de SCAV como PMC.",
|
||||
@@ -65,6 +66,7 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERROR ENLAZANDO",
|
||||
"F_UI_ErrorBindIP": "'{0}' no es una dirección IP válida para enlazar! Compruebe su configuración de 'Forzar enlace IP'.",
|
||||
"F_UI_NoDedicatedClients": "No hay clientes dedicados disponibles.",
|
||||
"F_UI_HostRaidTooltip": "Starts a raid\nOther players will be able to join you during the loading screen",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_WaitForHostFinishInit": "Esperando por el anfitrión para inicializar de la incursión...",
|
||||
"F_UI_WaitForOtherPlayers": "Esperando por otros jugadores para terminar la carga...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Jugabilidad",
|
||||
"F_BepInEx_OfficialVersion_T": "Versión Oficial",
|
||||
"F_BepInEx_OfficialVersion_D": "Muestra la versión oficial en vez de la versión de Fika..",
|
||||
"F_BepInEx_UseHeadless_T": "Auto Use Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Always tick the box to use the Headless Client if available",
|
||||
"F_BepInEx_ShowFeed_T": "Show Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Habilitar notificaciones personalizadas cuando un jugador muere, extrae, mata a un jefe, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extracción",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "La escala mínima de las placas de nombre.",
|
||||
"F_BepInEx_UseOcclusion_T": "Usar oclusión",
|
||||
"F_BepInEx_UseOcclusion_D": "Usar la oclusión para ocultar las placas de nombre cuando el jugador está fuera de vista.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Mostrar Notificaciones",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Qué tan seguido la IA Dinámica debe buscar el rango de los todos los jugadores.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignorar Francotiradores",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Cuánto tiempo se tarda en que una conexión se considere abandonada si no se han recibido paquetes.",
|
||||
"F_BepInEx_SendRate_T": "Tasa de Envío",
|
||||
"F_BepInEx_SendRate_D": "Que tan seguido se deben enviar los paquetes de movimiento por segundo (menor = menos ancho de banda utilizado, ligeramente más retraso durante la interpolación)\nEsto solo afecta al anfitrión y será sincronizado con todos los clientes.\nLa cantidad es por segundo:\n\nMuy Bajo = 10\nBajo = 15\nMedio = 20\nAlto = 30\n\nRecomendado no dejarlo más alto que Medio ya que las ganancias son insignificantes.",
|
||||
"F_BepInEx_SmoothingRate_T": "Tasa de Suavizado",
|
||||
"F_BepInEx_SmoothingRate_D": "La simulación local está retrasada por (Tasa de Envío * Tasa de Suavizado). Esto garantiza que siempre habrán suficientes tomas instantáneas en el buffer para mitigar retrasos e irregularidades durante la interpolación.\n\nBajo = 1.5\nMedio = 2\nAlto = 2.5\n\nEstablecer en \"Alto\" si el movimiento no es suave. No se puede cambiar durante una incursión.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "JUGADORES EN LÍNEA: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "RAID HOST",
|
||||
"F_MMUI_JoinButton": "UNIRSE",
|
||||
"F_MMUI_SelectAmountHeader": "SELECCIONAR CANTIDAD",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "CONFIGURACIÓN DE SESIÓN",
|
||||
"F_MMUI_SelectAmountDescription": "¿Cuántas personas (incluyéndote a ti) jugarán?",
|
||||
"F_MMUI_UseDedicatedHost": "Utilice un host dedicado",
|
||||
"F_MMUI_StartButton": "INICIAR",
|
||||
"F_MMUI_LoadingScreenHeader": "CARGANDO",
|
||||
"F_MMUI_LoadingScreenDescription": "Espere mientras la raid se inicializa... esto podría llevar algún tiempo.",
|
||||
"F_MMUI_JoinAsSpectator": "Unirse como espectador",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Modo espectador",
|
||||
"F_MMUI_JoinAsSpectator_D": "Unirse como espectador",
|
||||
"F_UI_StartRaid": "Comenzar Incursión",
|
||||
"F_UI_StartRaidDescription": "Inicia la incursión\nDespués de hacer clic aquí no se podrán unir más jugadores",
|
||||
"F_UI_CannotJoinRaidOtherMap": "No puedes unirte a una partida en otro mapa. Mapa de la partida: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "No puedes unirte a una partida en horario distinto.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "No puedes unirte a una partida scav como PMC.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERROR DE UNIÓN",
|
||||
"F_UI_ErrorBindIP": "'{0}' no es una IP válida a la que forzar la unión! Comprueba tus ajustes de 'Forzar Unión de IP'.",
|
||||
"F_UI_NoDedicatedClients": "No hay clientes dedicados disponibles.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Inicia una incursión\nOtros jugadores podrán unirse durante la pantalla de carga",
|
||||
"F_UI_WaitForHostStartRaid": "Esperando a que el anfitrión inicie la incursión...",
|
||||
"F_UI_WaitForHostFinishInit": "Esperando a que el anfitrión inicialice la partida...",
|
||||
"F_UI_WaitForOtherPlayers": "Esperando a que otros jugadores terminen de cargar...",
|
||||
"F_UI_RetrieveSpawnInfo": "Recuperando información de reaparición del servidor...",
|
||||
@@ -101,7 +103,7 @@
|
||||
"F_Notification_ItemReceived": "Recibiste un {0} de {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "La edición de RaidSettings ha sido desactivada por el anfitrión del servidor",
|
||||
"F_UI_ExtractMessage": "Presiona {0} para extraer",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "DESCARGAR PERFIL",
|
||||
"F_BepInEx_H_Advanced": "Avanzado",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Cocina | Placas de nombre",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Jugabilidad",
|
||||
"F_BepInEx_OfficialVersion_T": "Versión Oficial",
|
||||
"F_BepInEx_OfficialVersion_D": "Mostrar versión oficial en lugar de la versión de Fika.",
|
||||
"F_BepInEx_UseHeadless_T": "Utilizar automáticamente Headless Client",
|
||||
"F_BepInEx_UseHeadless_D": "Marque la casilla para utilizar el Headless Client siempre que esté disponible",
|
||||
"F_BepInEx_ShowFeed_T": "Mostrar fuente",
|
||||
"F_BepInEx_ShowFeed_D": "Habilitar notificaciones personalizadas cuando un jugador muere, extrae, mata a un jefe, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extracción",
|
||||
@@ -158,11 +162,15 @@
|
||||
"F_BepInEx_MinPlateScale_D": "La escala mínima de las placas de nombre.",
|
||||
"F_BepInEx_UseOcclusion_T": "Usar oclusión",
|
||||
"F_BepInEx_UseOcclusion_D": "Usar la oclusión para ocultar las placas de nombre cuando el jugador está fuera de vista.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Tipos de Misión",
|
||||
"F_BepInEx_QuestTypes_D": "Los tipos de misiones a recibir y enviar. PlaceBeacon son tanto marcadores como objetos.",
|
||||
"F_BepInEx_QSNotifications_T": "Mostrar Notificaciones",
|
||||
"F_BepInEx_QSNotifications_D": "If a notification should be shown when quest progress is shared with out.",
|
||||
"F_BepInEx_EasyKillConditions_T": "Easy Kill Conditions",
|
||||
"F_BepInEx_QSNotifications_D": "Mostrar una notificación cuando el progreso de una misión se comparta.",
|
||||
"F_BepInEx_EasyKillConditions_T": "Condiciones de Baja sencillas",
|
||||
"F_BepInEx_EasyKillConditions_D": "Habilita las condiciones de baja fáciles. Cuando esto es utilizado, siempre que un jugador amistoso mate algo, cuenta como si lo hubieras matado tú para tus misiones siempre y cuando se cumplan las condiciones.\nEsto puede ser inconsistente y no siempre funciona.",
|
||||
"F_BepInEx_SharedKillXP_T": "Experiencia de Baja Compartida",
|
||||
"F_BepInEx_SharedKillXP_D": "De ser activado, recibirás la ½ de la experiencia cuando un jugador amistoso mate a un enemigo (no a un jefe).",
|
||||
@@ -176,43 +184,45 @@
|
||||
"F_BepInEx_PingColor_D": "El color de tus marcas cuando se muestran a otros jugadores.",
|
||||
"F_BepInEx_PingSize_T": "Tamaño de la Marca",
|
||||
"F_BepInEx_PingSize_D": "The multiplier of the ping size.",
|
||||
"F_BepInEx_PingTime_T": "Ping Time",
|
||||
"F_BepInEx_PingTime_D": "How long pings should be displayed.",
|
||||
"F_BepInEx_PingAnimation_T": "Play Ping Animation",
|
||||
"F_BepInEx_PingAnimation_D": "Plays the pointing animation automatically when pinging. Can interfere with gameplay.",
|
||||
"F_BepInEx_PingOptics_T": "Show Ping During Optics",
|
||||
"F_BepInEx_PingOptics_D": "If pings should be displayed while aiming down an optics scope.",
|
||||
"F_BepInEx_PingOpticZoom_T": "Ping Use Optic Zoom",
|
||||
"F_BepInEx_PingOpticZoom_D": "If ping location should be displayed using the PiP optic camera.",
|
||||
"F_BepInEx_PingScaleDistance_T": "Ping Scale With Distance",
|
||||
"F_BepInEx_PingScaleDistance_D": "If ping size should scale with distance from player.",
|
||||
"F_BepInEx_PingMinOpac_T": "Ping Minimum Opacity",
|
||||
"F_BepInEx_PingMinOpac_D": "The minimum opacity of pings when looking straight at them.",
|
||||
"F_BepInEx_PingRange_T": "Show Ping Range",
|
||||
"F_BepInEx_PingRange_D": "Shows the range from your player to the ping if enabled.",
|
||||
"F_BepInEx_PingSound_T": "Ping Sound",
|
||||
"F_BepInEx_PingSound_D": "The audio that plays on ping",
|
||||
"F_BepInEx_FreeCamButton_T": "Free Camera Button",
|
||||
"F_BepInEx_FreeCamButton_D": "Button used to toggle free camera.",
|
||||
"F_BepInEx_SpectateBots_T": "Allow Spectating Bots",
|
||||
"F_BepInEx_SpectateBots_D": "If we should allow spectating bots if all players are dead/extracted.",
|
||||
"F_BepInEx_AZERTYMode_T": "AZERTY Mode",
|
||||
"F_BepInEx_AZERTYMode_D": "If free camera should use AZERTY keys for input.",
|
||||
"F_BepInEx_DroneMode_T": "Drone Mode",
|
||||
"F_BepInEx_DroneMode_D": "If the free camera should move only along the vertical axis like a drone.",
|
||||
"F_BepInEx_KeybindOverlay_T": "Keybind Overlay",
|
||||
"F_BepInEx_KeybindOverlay_D": "If an overlay with all free cam keybinds should show.",
|
||||
"F_BepInEx_PingTime_T": "Tiempo de Ping",
|
||||
"F_BepInEx_PingTime_D": "Durante cuanto deberían mostrarse los Pings.",
|
||||
"F_BepInEx_PingAnimation_T": "Reproducir animación de Ping",
|
||||
"F_BepInEx_PingAnimation_D": "Utilizar la animación de señalar automáticamente al hacer Ping. Puede interferir en el juego.",
|
||||
"F_BepInEx_PingOptics_T": "Mostrar Ping cuando apuntas con ópticas",
|
||||
"F_BepInEx_PingOptics_D": "Si los Ping debería mostrarse mientras apuntas con una óptica.",
|
||||
"F_BepInEx_PingOpticZoom_T": "Mostrar Ping cuando apuntas con ópticas de magnificación",
|
||||
"F_BepInEx_PingOpticZoom_D": "Si los Ping deberían mostrarse mientras apuntas con una mira de magnificación.",
|
||||
"F_BepInEx_PingScaleDistance_T": "Escalar Ping a distancia",
|
||||
"F_BepInEx_PingScaleDistance_D": "Si el tamaño de las Marcas debería escalar dependiendo de la distancia del jugador.",
|
||||
"F_BepInEx_PingMinOpac_T": "Opacidad mínima del Ping",
|
||||
"F_BepInEx_PingMinOpac_D": "La opacidad mínima de los Pings cuando los miras directamente.",
|
||||
"F_BepInEx_PingRange_T": "Mostrar distancia del Ping",
|
||||
"F_BepInEx_PingRange_D": "Muestra la distancia de tu personaje hasta el Ping si está activado.",
|
||||
"F_BepInEx_PingSound_T": "Sonido del Ping",
|
||||
"F_BepInEx_PingSound_D": "El audio que suena al hacer Ping",
|
||||
"F_BepInEx_FreeCamButton_T": "Botón de Cámara Libre",
|
||||
"F_BepInEx_FreeCamButton_D": "Botón usado para alternar a Cámara Libre.",
|
||||
"F_BepInEx_SpectateBots_T": "Permitir espectar Bots",
|
||||
"F_BepInEx_SpectateBots_D": "Permitir espectar a los bots si todos los jugadores han muerto/extraído.",
|
||||
"F_BepInEx_AZERTYMode_T": "Modo teclado AZERTY",
|
||||
"F_BepInEx_AZERTYMode_D": "Si la cámara debe usar teclas en formato AZERTY para moverse.",
|
||||
"F_BepInEx_DroneMode_T": "Modo Dron",
|
||||
"F_BepInEx_DroneMode_D": "Si la cámara libre debería moverse solo en el eje vertical como un dron.",
|
||||
"F_BepInEx_KeybindOverlay_T": "Mostrar Leyenda",
|
||||
"F_BepInEx_KeybindOverlay_D": "Si debería haber una leyenda con todas las teclas usadas para la cámara libre.",
|
||||
"F_BepInEx_DynamicAI_T": "IA Dinámica",
|
||||
"F_BepInEx_DynamicAI_D": "Utilizar el sistema de IA dinámico, desactivando la IA cuando están fuera de rango de todos los jugadores.",
|
||||
"F_BepInEx_DynamicAIRange_T": "Rango de la IA Dinámica",
|
||||
"F_BepInEx_DynamicAIRange_D": "El rango en el que la IA se desactivará automáticamente.",
|
||||
"F_BepInEx_DynamicAIRate_T": "Dynamic AI Rate",
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAIRate_T": "Tasa de actualización de IA dinámica",
|
||||
"F_BepInEx_DynamicAIRate_D": "Con que frecuencia debería la IA Dinámica escanear el rango de todos los jugadores.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignorar Francotiradores",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Debería la IA Dinámica ignorar los Scav francotiradores.",
|
||||
"F_BepInEx_FikaGC_T": "Usar el GC de Fika",
|
||||
"F_BepInEx_FikaGC_D": "Si debería usarse un Garbage Collector personalizado para aliviar problemas con el uso de memoria.\nCUIDADO: Experimental, puede que no tenga ningún efecto en tu sistema.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Límites forzados de Spawn",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Fuerza un límite de reaparición para los bots, haciendo que no sobrepase los límites de Vanilla. Esta opción principalmente funciona con mods que ajustan la reaparición o el límite de bots. No bloquea el spawn de bots especiales como bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Eliminar el más lejano",
|
||||
"F_BepInEx_DespawnFurthest_D": "When enforcing spawn limits, should the furthest bot be de-spawned instead of blocking the spawn. This will make for a much more active raid on a lower Max Bots count. Helpful for weaker PCs. Will only despawn pmcs and scavs. If you don't run a dynamic spawn mod, this will however quickly exhaust the spawns on the map, making the raid very dead instead.",
|
||||
"F_BepInEx_DespawnMinDistance_T": "Despawn Minimum Distance",
|
||||
"F_BepInEx_DespawnMinDistance_D": "The minimum distance to despawn a bot.",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Cuánto tiempo se tarda en que una conexión se considere abandonada si no se han recibido paquetes.",
|
||||
"F_BepInEx_SendRate_T": "Tasa de Envío",
|
||||
"F_BepInEx_SendRate_D": "Que tan seguido se deben enviar los paquetes de movimiento por segundo (menor = menos ancho de banda utilizado, ligeramente más retraso durante la interpolación)\nEsto solo afecta al anfitrión y será sincronizado con todos los clientes.\nLa cantidad es por segundo:\n\nMuy Bajo = 10\nBajo = 15\nMedio = 20\nAlto = 30\n\nRecomendado no dejarlo más alto que Medio ya que las ganancias son insignificantes.",
|
||||
"F_BepInEx_SmoothingRate_T": "Tasa de Suavizado",
|
||||
"F_BepInEx_SmoothingRate_D": "La simulación local está retrasada por (Tasa de Envío * Tasa de Suavizado). Esto garantiza que siempre habrán suficientes tomas instantáneas en el buffer para mitigar retrasos e irregularidades durante la interpolación.\n\nBajo = 1.5\nMedio = 2\nAlto = 2.5\n\nEstablecer en \"Alto\" si el movimiento no es suave. No se puede cambiar durante una incursión.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "JUGADORES EN LÍNEA: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "En el Escondite",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Jugando como {0} en {1}\nTiempo: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "HÉBERGER UN RAID",
|
||||
"F_MMUI_JoinButton": "REJOINDRE",
|
||||
"F_MMUI_SelectAmountHeader": "SÉLECTIONNER LE MONTANT",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "PARAMÈTRES DE SESSION",
|
||||
"F_MMUI_SelectAmountDescription": "Combien de joueurs (vous inclus) vont participer ?",
|
||||
"F_MMUI_UseDedicatedHost": "Utiliser un hôte dédié",
|
||||
"F_MMUI_StartButton": "DÉMARRER",
|
||||
"F_MMUI_LoadingScreenHeader": "CHARGEMENT",
|
||||
"F_MMUI_LoadingScreenDescription": "Veuillez patienter pendant l'initialisation du raid... Cela peut prendre un certain temps.",
|
||||
"F_MMUI_JoinAsSpectator": "Rejoindre comme spectateur",
|
||||
"F_MMUI_JoinAsSpectator": "Spectateur",
|
||||
"F_MMUI_JoinAsSpectator_D": "Rejoindre le jeu en tant que spectateur",
|
||||
"F_UI_StartRaid": "Lancer le raid",
|
||||
"F_UI_StartRaidDescription": "Lance le raid\nLes nouveaux joueurs ne pourront plus rejoindre",
|
||||
"F_UI_StartRaidDescription": "Lancer le raid\nAucun autre joueur ne pourra rejoindre après avoir cliqué",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Impossible de rejoindre un raid dont la carte est différente.\nCarte du raid : {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Impossible de rejoindre un raid dont l'horaire est différent.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Vous ne pouvez pas rejoindre un raid SCAV en tant que SMP.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERREUR AFFECTATION IP",
|
||||
"F_UI_ErrorBindIP": "'{0}' n'est pas une adresse IP valide ! Vérifiez le paramètre 'Force Bind IP'.",
|
||||
"F_UI_NoDedicatedClients": "Aucun client dédié n'est disponible.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Lance un raid\nD'autres joueurs pourront vous rejoindre pendant l'écran de chargement",
|
||||
"F_UI_WaitForHostStartRaid": "En attente du lancement du raid par l'hôte...",
|
||||
"F_UI_WaitForHostFinishInit": "En attente de la fin de l'initialisation du raid par l'hôte...",
|
||||
"F_UI_WaitForOtherPlayers": "En attente du chargement des autres joueurs...",
|
||||
"F_UI_RetrieveSpawnInfo": "Récupération des informations d'apparitions depuis le serveur...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Jouabilité",
|
||||
"F_BepInEx_OfficialVersion_T": "Version officielle",
|
||||
"F_BepInEx_OfficialVersion_D": "Afficher la version officielle au lieu de la version Fika.",
|
||||
"F_BepInEx_UseHeadless_T": "Utiliser automatiquement le client sans interface graphique",
|
||||
"F_BepInEx_UseHeadless_D": "Toujours cocher la case pour utiliser le client sans interface graphique si disponible",
|
||||
"F_BepInEx_ShowFeed_T": "Afficher le flux",
|
||||
"F_BepInEx_ShowFeed_D": "Activer les notifications personnalisées lorsqu'un joueur meurt, s'extrait, tue un boss, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Extraction Automatique",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "L'échelle minimale des plaques de nom.",
|
||||
"F_BepInEx_UseOcclusion_T": "Utiliser l'Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Utilisez l'occlusion pour masquer la plaque de nom lorsque le joueur est hors de vue.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Types de quêtes",
|
||||
"F_BepInEx_QuestTypes_D": "Quels types de quêtes à recevoir et à envoyer. PlaceBeacon est à la fois marqueurs et objets.",
|
||||
"F_BepInEx_QSNotifications_T": "Afficher les Notifications",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "À quelle fréquence DynamicAI devrait rechercher la portée de tous les joueurs.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore les snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Si l'IA dynamique doit ignorer les scavs sniper.",
|
||||
"F_BepInEx_FikaGC_T": "Utiliser Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "Si un récupérateur de mémoire personnalisé doit être utilisé pour résoudre les problèmes d'utilisation de la mémoire.\nAVERTISSEMENT : Expérimental, peut n'avoir aucun effet sur votre système.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Limites dapparition imposées",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Impose les limites d'apparition lors de l'apparition des bots, en s'assurant de ne pas dépasser les limites vanilla. Cela agit principalement lorsque vous utilisez des mods d'apparition ou tout ce qui modifie les limites de bots. Ne bloquera pas les spawn de bots spéciaux comme les boss.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Fait disparaitre le plus éloigné",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Délai de connexion dépassé",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Combien de temps faut-il pour qu'une connexion soit considérée comme abandonnée si aucun paquet réseau n'est reçu.",
|
||||
"F_BepInEx_SendRate_T": "Taux denvoi",
|
||||
"F_BepInEx_SendRate_D": "Combien de fois par seconde les paquets de mouvement doivent être envoyés (plus faible = moins de bande passante utilisée, un peu plus de latence lors de l'interpolation)\nCeci affecte uniquement l'hôte et sera synchronisé avec tous les clients.\nLe montant est par seconde :\n\nTrès Bas = 10\nBas = 15\nMoyen = 20\nHaut = 30\n\nRecommandé de laisser au plus haut sur Moyen car les gains sont insignifiants après.",
|
||||
"F_BepInEx_SmoothingRate_T": "Taux de lissage",
|
||||
"F_BepInEx_SmoothingRate_D": "La simulation locale est en retard par (Débit d'envoi* Taux de lissage). Cela garantit que nous ayons toujours assez de snapshots dans le tampon pour atténuer les retards et le jitter lors de l'interpolation.\n\nBas = 1.5\nMoyenne = 2\nHaut = 2.5\n\nRéglez ceci sur \"Haut\" si le mouvement n'est pas fluide. Ne peut pas être changé pendant un raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Utiliser le MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "Si le composant réseau doit utiliser le multithreading, cela peut potentiellement atténuer les problèmes de latence du jeu, permettant au gestionnaire réseau de continuer à traiter et à mettre en file d'attente les paquets même avec un faible nombre d'images par seconde.\nCette fonctionnalité est expérimentale et ne doit être activée que sur les PC haut de gamme et sur un client sans interface graphique.",
|
||||
"F_BepInEx_VOIP_T": "Autoriser le VOIP",
|
||||
"F_BepInEx_VOIP_D": "Si le VOIP sera activé lorsque vous hébergez.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Désactiver le métabolisme des bots",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Désactive le métabolisme des bots, les empêchant de mourir d'une perte d'énergie/hydratation lors de longs raids.",
|
||||
"F_MMUI_OnlinePlayers": "JOUEURS EN LIGNE : {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "Dans la Planque",
|
||||
"F_MMUI_InFlea": "Dans le commerce",
|
||||
"F_MMUI_RaidDetails": "Jouer en tant que {0} sur {1}\nTemps : {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "ERREUR LOCALE",
|
||||
"F_UI_LocaleError_D": "Des erreurs se sont produites lors du chargement des paramètres régionaux Fika. La traduction utilise désormais des solutions de secours pour les en-têtes défaillants. Veuillez signaler ce problème aux développeurs !\n\nClés défaillantes : {0}",
|
||||
"F_UI_EFTVersionError": "Vous essayez d'utiliser une version d'EFT différente de celle de l'hôte.\nClient : {0}\nHôte : {1}",
|
||||
"F_UI_FikaVersionError": "Vous essayez d'utiliser une version de Fika différente de celle de l'hôte du raid.\nClient : {0}\nHôte : {1}",
|
||||
"F_UI_PlayerConnected": "{0} s'est connecté",
|
||||
"F_UI_PlayerDisconnected": "{0} s'est déconnecté",
|
||||
"F_UI_DisabledByServerHost": "Désactivé par l'hôte du serveur"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "RAID HOSTEN",
|
||||
"F_MMUI_JoinButton": "BEITRETEN",
|
||||
"F_MMUI_SelectAmountHeader": "ANZAHL AUSWÄHLEN",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "SITZUNGS EINSTELLUNGEN",
|
||||
"F_MMUI_SelectAmountDescription": "Wie viele Spieler (inklusive dir) werden spielen?",
|
||||
"F_MMUI_UseDedicatedHost": "Dedizierten Host benutzen",
|
||||
"F_MMUI_StartButton": "START",
|
||||
"F_MMUI_LoadingScreenHeader": "LADEN",
|
||||
"F_MMUI_LoadingScreenDescription": "Bitte warten, während der Raid initialisiert wird... dies könnte eine Weile dauern.",
|
||||
"F_MMUI_JoinAsSpectator": "Als Zuschauer beitreten",
|
||||
"F_MMUI_JoinAsSpectator": "Zuschauen",
|
||||
"F_MMUI_JoinAsSpectator_D": "Als Zuschauer beitreten",
|
||||
"F_UI_StartRaid": "Starte Raid",
|
||||
"F_UI_StartRaidDescription": "Starte den Raid\nneue Spieler können nicht mehr joinen",
|
||||
"F_UI_StartRaidDescription": "Raid starten\nNach dem Klicken können keine anderen Spieler mehr joinen",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Du kannst keinem Raid beitreten, der sich auf einer anderen Karte befindet.\nDer Raid befindet sich auf Karte: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Kann keinem Raid beitreten, der zu einer anderen Tageszeit stattfindet.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Du kannst als PMC keinem Scav Raid beitreten.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "Fehler beim IP Binding",
|
||||
"F_UI_ErrorBindIP": "'{0}' ist keine gültige IP-Adresse zum BINDING! Überprüfe die 'Force Bind IP'-Einstellung.",
|
||||
"F_UI_NoDedicatedClients": "Keine dedizierten Clients verfügbar.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Raid starten\nAndere Spieler können während des Ladebildschirms noch joinen",
|
||||
"F_UI_WaitForHostStartRaid": "Warte darauf, dass der Host den Raid startet...",
|
||||
"F_UI_WaitForHostFinishInit": "Warte darauf, dass der Host die Initialisierung des Raids vollendet...",
|
||||
"F_UI_WaitForOtherPlayers": "Warte darauf, dass andere Spieler das Laden beendet haben...",
|
||||
"F_UI_RetrieveSpawnInfo": "Spawn-Info wird vom Server abgerufen...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Offizielle Version",
|
||||
"F_BepInEx_OfficialVersion_D": "Zeige die offizielle Version anstelle der Fika-Version.",
|
||||
"F_BepInEx_UseHeadless_T": "Headless Client automatisch nutzen",
|
||||
"F_BepInEx_UseHeadless_D": "Aktiviere diese Checkbox um immer den Headless Client zu nutzen, wenn verfügbar",
|
||||
"F_BepInEx_ShowFeed_T": "Feed anzeigen",
|
||||
"F_BepInEx_ShowFeed_D": "Aktiviere benutzerdefinierte Benachrichtigungen, wenn ein Spieler stirbt, extractet, einen Boss tötet, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extract",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "Die minimale Skalierung der Namensplaketten.",
|
||||
"F_BepInEx_UseOcclusion_T": "Occlusion verwenden",
|
||||
"F_BepInEx_UseOcclusion_D": "Verwende Verdeckung, um das Namensschild auszublenden, wenn der Spieler außerhalb des Sichtfelds ist.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest-Typen",
|
||||
"F_BepInEx_QuestTypes_D": "Welche AufgabenTypen sollen empfangen und gesendet werden. Platzierungen gelten für beides, Markierer und Gegenstände.",
|
||||
"F_BepInEx_QSNotifications_T": "Benachrichtigungen anzeigen",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Frequenz, in der die DynamicAI nach der Reichweite aller Spieler suchen soll.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignoriere Scharfschützen",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Ob Sniper Scavs von der dynamische AI ignoriert werden sollen.",
|
||||
"F_BepInEx_FikaGC_T": "Benuzter Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "Ob ein benutzerdefinierter Garbagecollector verwendet werden sollt, um Probleme mit der Speicherauslastung zu lindern.\nWARNUNG: Experimentell, könnte überhaupt keine Wirkung auf dein System haben.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Erzwinge Spawn Limitierungen",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Erzwingt Spawn Limitierungen, wenn Bots spawnen. Stelle sicher, dass du nicht oberhalb der Vanilla Limitierungen bist. Diese Einstellung wird hauptsächlich Effekte haben wenn du Spawn Modifikationen benutzt. Blockiert keine speziellen Bots wie Bosse.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn am weitesten entfernt",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Verbindungsauszeit",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Wie lange es dauert, bis eine Verbindung als abgebrochen betrachtet wird, wenn keine Pakete empfangen werden.",
|
||||
"F_BepInEx_SendRate_T": "Senderate",
|
||||
"F_BepInEx_SendRate_D": "Wie oft pro Sekunde Bewegungspakete gesendet werden sollen (niedriger = weniger Bandbreite, führt zu geringfügig mehr Verzögerung während der Interpolation)\nDies betrifft nur den Host und wird mit allen Clients synchronisiert.\nBetrag ist pro Sekunde:\n\nSehr niedrig = 10\nNiedrig = 15\nMittel = 20\nHigh = 30\n\nEmpfohlen nicht höher als Mittel zu lassen, da die Zuwächse danach unbedeutend sind.",
|
||||
"F_BepInEx_SmoothingRate_T": "Glättungsrate",
|
||||
"F_BepInEx_SmoothingRate_D": "Lokale Simulation liegt hinter der Formel (Send Rate * Smoothing Rate). Dies garantiert, dass wir immer genug Schnappschüsse im Puffer haben, um Verzögerungen und Jitter während der Interpolation zu lindern.\n\nNiedrig = 1,5\nMittel = 2\nHoch = 2,5\n\nSetze dies auf \"Hoch\", wenn die Bewegung nicht glatt ist. Kann während eines Raids nicht geändert werden.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "MultiThreading benutzen",
|
||||
"F_BepInEx_NetMultiThread_D": "Ob die Netzwerkkomponente MultiThreading verwenden soll. Dies kann möglicherweise Probleme verringern, wenn das Spiel nicht funktioniert, was es dem Netzwerk-Manager erlaubt, Pakete während des niedrigen FPS immer noch zu bearbeiten und Warteschlangen durchzuführen.\nDies ist eine experimentelle Funktion und sollte nur auf High-End-PCs aktiviert werden und wird nur auf einem Headless-Client aktiviert.",
|
||||
"F_BepInEx_VOIP_T": "VOIP aktivieren",
|
||||
"F_BepInEx_VOIP_D": "VOIP aktivieren, wenn du einen Raid hostest.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Bot Metabolismus deaktivieren",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Deaktiviert den Metabolismus an Bots. Verhindert das Bots aufgrund von Energie-/Wassermangel in längeren Raids sterben.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE-SPIELER: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "Im Versteck",
|
||||
"F_MMUI_InFlea": "Im Flohmarkt",
|
||||
"F_MMUI_RaidDetails": "Spielt als {0} auf {1}\nZeit: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "Fehler beim Laden der Fika-Locales. Die Übersetzung verwendet jetzt Fallbacks für die fehlgeschlagenen Kopfzeilen. Bitte melden Sie dies den Entwicklern!\n\nfehlgeschlagene Schlüssel: {0}",
|
||||
"F_UI_EFTVersionError": "Du möchtest mit einer unterschiedlichen EFT Version als der Host beitreten. \nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "Du möchtest mit einer unterschiedlichen Fika Version als der Host beitreten. \nClient: {0}\nHost: {1}",
|
||||
"F_UI_PlayerConnected": "{0} verbunden",
|
||||
"F_UI_PlayerDisconnected": "{0} getrennt",
|
||||
"F_UI_DisabledByServerHost": "Vom Serverhost deaktiviert"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "RAID LÉTREHOZÁSA",
|
||||
"F_MMUI_JoinButton": "CSATLAKOZÁS",
|
||||
"F_MMUI_SelectAmountHeader": "ÖSSZEG KIVÁLASZTÁSA",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION BEÁLLÍTÁSOK",
|
||||
"F_MMUI_SelectAmountDescription": "Hány ember fog játszani (beleértve téged is)?",
|
||||
"F_MMUI_UseDedicatedHost": "Dedicated Host használata",
|
||||
"F_MMUI_StartButton": "INDITÁS",
|
||||
"F_MMUI_LoadingScreenHeader": "BETÖLTÉS",
|
||||
"F_MMUI_LoadingScreenDescription": "Kérjük, várjon, amíg a raid betölt... ez eltarthat egy ideig.",
|
||||
"F_MMUI_JoinAsSpectator": "Csatlakozás nézőként",
|
||||
"F_MMUI_JoinAsSpectator": "Nézd",
|
||||
"F_MMUI_JoinAsSpectator_D": "Csatlakozz nézőként",
|
||||
"F_UI_StartRaid": "Raid kezdése",
|
||||
"F_UI_StartRaidDescription": "Raid elkezdése, új játékosok nem fognak tudni csatlakozni",
|
||||
"F_UI_StartRaidDescription": "Elindít egy raid-et\nA gombra kattintás után más játékosok nem tudnak majd csatlakozni",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Nem lehet csatlakozni egy másik pályán lévő raidhez.\nRaid pálya: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Nem lehet csatlakozni egy olyan raidhez, amely más időn van.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Nem csatlakozhatsz scav raid-hez PMC-ként.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "KÖTÉSI HIBA",
|
||||
"F_UI_ErrorBindIP": "A '{0}' nem érvényes IP-cím a kötéshez! Ellenőrizze a „Force Bind IP” beállítást.",
|
||||
"F_UI_NoDedicatedClients": "Nincsenek dedikált kliensek.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Elindít egy raid-et\nMás játékosok tudnak rád csatlakozni a töltőkép közben",
|
||||
"F_UI_WaitForHostStartRaid": "Várakozás a host-ra, hogy indítsa a raid-et...",
|
||||
"F_UI_WaitForHostFinishInit": "Várakozás, hogy a host befejezze a raid inicializálását...",
|
||||
"F_UI_WaitForOtherPlayers": "Várakozás, amíg a többi játékos befejezi a betöltést...",
|
||||
"F_UI_RetrieveSpawnInfo": "Spawn információk lekérése a szerverről...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Játék",
|
||||
"F_BepInEx_OfficialVersion_T": "Eredeti Verzió",
|
||||
"F_BepInEx_OfficialVersion_D": "Eredeti Verzió mutatása a Fika verziója helyett.",
|
||||
"F_BepInEx_UseHeadless_T": "Automatán használjon Headless-t",
|
||||
"F_BepInEx_UseHeadless_D": "Mindig pipáld be a négyzetet, hogy használjon Headless klienst, ha elérhető",
|
||||
"F_BepInEx_ShowFeed_T": "Információ megjelenítése",
|
||||
"F_BepInEx_ShowFeed_D": "Egyedi értesítések engedélyezése, amikor egy játékos meghal, extractol, megöl egy bosst satöbbi.",
|
||||
"F_BepInEx_AutoExtract_T": "Meccs automatikus elhagyása",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "A névtáblák minimum áttetszősége.",
|
||||
"F_BepInEx_UseOcclusion_T": "Okklúzió használata",
|
||||
"F_BepInEx_UseOcclusion_D": "Okklúzió használata a névtábla elrejtéséhez, amikor a játékos nincs a látóteredben.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Küldetés formák",
|
||||
"F_BepInEx_QuestTypes_D": "Milyen típusú küldetéseket kell fogadni és elküldeni. A PlaceBeacon jelölőket és elemeket is tartalmaz.",
|
||||
"F_BepInEx_QSNotifications_T": "Értesítések mutatása",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Milyen gyakran keressen játékost a DynamicAI a hatótávján belül.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Mesterlövészek kihagyása",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "A dinamikus AI figyelmen kívül hagyja-e a mesterlövész scav-eket.",
|
||||
"F_BepInEx_FikaGC_T": "Használjon Fika GC-t",
|
||||
"F_BepInEx_FikaGC_D": "Az egyedi szemétszedő használva legyen-e, hogy enyhítse a memória használati gondokat.\nFIGYELEM: Kísérleti funkció, lehet nem is változtat a rendszereden.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Kényszerített spawn limitek",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Kikényszeríti a spawn korlátokat a botok spawnalásakór, ügyelve arra, hogy ne lépje túl a vanilla korlátokat. Ez főként spawn modok vagy bármi más, ami módosítja a botkorlátokat, használatakor érvényesül. Nem blokkolja a speciális botok, például a bossok megjelenését.",
|
||||
"F_BepInEx_DespawnFurthest_T": "A legtávolabbi eltüntetése",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Kapcsolati időtullépés",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Mennyi időbe telik, amíg a kapcsolat megszakadtnak minősül, ha nem érkezik packet.",
|
||||
"F_BepInEx_SendRate_T": "Küldési arány",
|
||||
"F_BepInEx_SendRate_D": "Milyen gyakran kell másodpercenként küldeni a mozgáscsomagokat (alacsonyabb = kevesebb sávszélességet használnak, kicsit több késleltetés az interpoláció során)\nEz csak a Hosztot érinti, és minden klienssel szinkronizálva lesz.\nAz összeg másodpercenként:\n\nNagyon alacsony = 10\nAlacsony = 15\nKözepes = 20\nMagas = 30\n\nJavasoljuk, hogy a közepesnél nem magasabb értéket hagyja, mivel a nyereség utána jelentéktelen.",
|
||||
"F_BepInEx_SmoothingRate_T": "Simítási arány",
|
||||
"F_BepInEx_SmoothingRate_D": "A helyi szimuláció mögött van (Küldési sebesség * Simítási sebesség). Ez garantálja, hogy mindig legyen elegendő pillanatképünk a pufferben az interpoláció közbeni késések és jitter csökkentéséhez.\n\nAlacsony = 1,5\nKözepes = 2\nMagas = 2,5\n\nÁllítsa ezt a 'Magas' értékre, ha a mozgás nem egyenletes. Raid közben nem változtatható.",
|
||||
"F_BepInEx_SendRate_D": "Milyen gyakran legyenek a mozgási packetek elküldve másodpercenként (kisebb = alacsonyabb sávszélesség, kicsivel több késés interpoláció közben)\nEz csak a host-ot érinti és minden kliensen szinkronizálva lesz.\nEnnek száma másodpercenként:\nAlacsony = 10\nKözepes = 20\nMagas = 30\n\nKözepes felé nem ajánlott állítani, mert a különbség elhanyagolható.",
|
||||
"F_BepInEx_NetMultiThread_T": "Használjon MultiThreading-et",
|
||||
"F_BepInEx_NetMultiThread_D": "A hálózati komponens használja-e a multi-threading-et. Ez potenciálisan enyhítheti a lag problémákat, engedélyezi a hálózat manager-nek, hogy tovább dolgozhassa fel és sorba rendezhesse a packet-eket alacsony FPS-nél.",
|
||||
"F_BepInEx_VOIP_T": "Engedélyezze a VOIP-t",
|
||||
"F_BepInEx_VOIP_D": "A VOIP be legyen kapcsolva, ha host-olsz.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Bot metabolizmus kikapcsolása",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Kikapcsolja a metabolizmust botoknak, megakadályozza őket abban, hogy meghaljanak az energiavesztéstől/dehidratáltságtól a hosszú játék során.",
|
||||
"F_MMUI_OnlinePlayers": "Online játékosok: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "Bunkerben",
|
||||
"F_MMUI_InFlea": "Aukciós házban",
|
||||
"F_MMUI_RaidDetails": "Játék {0} ként {1}-en\nIdő: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_Mod_VerificationFailure": "A Crc32-es jóváhagyása a Fika.Core.dll fájlnak sikertelen, nem tudsz másokkal játszani!\nNézd meg a log fájlaidat további információkért.",
|
||||
"F_UI_LocaleError_H": "FORDÍTÁSI HIBA",
|
||||
"F_UI_LocaleError_D": "Problémák léptek fel a Fika helyi fordításainál. Most tartalékokat fog használni a hibás fejlécekhez. Kérlek, jelentsd a készítőknek!\n\nHibás kulcsok: {0}",
|
||||
"F_UI_EFTVersionError": "Egy másik EFT verzióval próbálsz csatlakozni, mint amit a host futtat.\nKliens crc: {0}\nHost crc: {1}",
|
||||
"F_UI_FikaVersionError": "Egy másik Fika verzióval próbálsz csatlakozni, mint amit a host futtat.\nKliens crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} csatlakozott",
|
||||
"F_UI_PlayerDisconnected": "{0} elhagyta a játékot",
|
||||
"F_UI_DisabledByServerHost": "Kikapcsolva a szerver host által"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "HOSTA RAID",
|
||||
"F_MMUI_JoinButton": "UNISCITI",
|
||||
"F_MMUI_SelectAmountHeader": "SELEZIONA QUANTITÀ",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "IMPOSTAZIONI SESSIONE",
|
||||
"F_MMUI_SelectAmountDescription": "Quante persone (incluso te) giocheranno?",
|
||||
"F_MMUI_UseDedicatedHost": "Usa Host Dedicato",
|
||||
"F_MMUI_StartButton": "AVVIA",
|
||||
"F_MMUI_LoadingScreenHeader": "CARICAMENTO",
|
||||
"F_MMUI_LoadingScreenDescription": "Attendere mentre il raid sta partendo... questo potrebbe richiedere un po' di tempo.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Modalità Spettatore",
|
||||
"F_MMUI_JoinAsSpectator_D": "Unisciti alla partita come spettatore",
|
||||
"F_UI_StartRaid": "Avvia Raid",
|
||||
"F_UI_StartRaidDescription": "Inizia il raid\nDopo aver cliccato nessun giocatore aggiuntivo sarà in grado di unirsi",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Impossibile entrare in un raid che è su un'altra mappa.\nMappa raid: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Impossibile entrare in un raid che è in un altro orario.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Non puoi partecipare a un raid scav come PMC.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERRORE BINDING",
|
||||
"F_UI_ErrorBindIP": "'{0}' non è un indirizzo IP valido per il binding! Controlla l'impostazione 'Forza Bind IP'.",
|
||||
"F_UI_NoDedicatedClients": "Nessun client dedicato è disponibile.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Avvia un raid\nGli altri giocatori potranno unirsi a te durante la schermata di caricamento",
|
||||
"F_UI_WaitForHostStartRaid": "In attesa che l'host avvii il raid...",
|
||||
"F_UI_WaitForHostFinishInit": "In attesa che l'host concluda l'inizializzazione del raid...",
|
||||
"F_UI_WaitForOtherPlayers": "In attesa che gli altri giocatori finiscano di caricare...",
|
||||
"F_UI_RetrieveSpawnInfo": "Recupero informazioni di generazione dal server...",
|
||||
@@ -101,7 +103,7 @@
|
||||
"F_Notification_ItemReceived": "Hai ricevuto {0} da {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "La modifica di RaidSettings è stata disabilitata dall' host del server",
|
||||
"F_UI_ExtractMessage": "Premi {0} per estrarre",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "SCARICA PROFILO",
|
||||
"F_BepInEx_H_Advanced": "Avanzato",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | Targhette Nome",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Versione Ufficiale",
|
||||
"F_BepInEx_OfficialVersion_D": "Mostra la versione ufficiale invece della versione Fika",
|
||||
"F_BepInEx_UseHeadless_T": "Uso Automatico Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Spuntare la casella per usare sempre il client Headless se disponibile",
|
||||
"F_BepInEx_ShowFeed_T": "Mostra Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Mostra notifiche personalizzate quando un giocate muore, estrae, uccide un boss, ecc.",
|
||||
"F_BepInEx_AutoExtract_T": "Estrazione automatica",
|
||||
@@ -128,7 +132,7 @@
|
||||
"F_BepInEx_ChatKey_D": "Il tasto usato per aprire la chat",
|
||||
"F_BepInEx_EnableOnlinePlayers_T": "Abilita Giocatori Online",
|
||||
"F_BepInEx_EnableOnlinePlayers_D": ".",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Online Players Scale",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Dimensione Giocatori Online",
|
||||
"F_BepInEx_OnlinePlayersScale_D": "Grandezza della finestra che mostra i giocatori online. Modifica solo se sproporzionata.\n\nRichiede un riavvio per visualizzare le modifiche",
|
||||
"F_BepInEx_UseNamePlates_T": "Mostra le Targhette Nome dei Giocatori",
|
||||
"F_BepInEx_UseNamePlates_D": "Se le targhette dei nomi devono essere mostrare sopra i compagni di squadra.",
|
||||
@@ -137,27 +141,31 @@
|
||||
"F_BepInEx_UsePercent_T": "Mostra HP% invece della barra",
|
||||
"F_BepInEx_UsePercent_D": "Mostra la salute in % invece che usare la barra.",
|
||||
"F_BepInEx_ShowEffects_T": "Mostra Effetti",
|
||||
"F_BepInEx_ShowEffects_D": "If status effects should be displayed below the health bar.",
|
||||
"F_BepInEx_ShowEffects_D": "Se gli effetti di stato devono essere visualizzati sotto la barra di salute.",
|
||||
"F_BepInEx_ShowFactionIcon_T": "Mostra Icona Fazione del Giocatore",
|
||||
"F_BepInEx_ShowFactionIcon_D": "Mostra l'icona fazione del giocatore di fianco alla balla della salute",
|
||||
"F_BepInEx_HideInOptic_T": "Nascondi Targhetta Nome mentre miri",
|
||||
"F_BepInEx_HideInOptic_D": "Nascondi targhetta nome durante la mira con mirini PiP",
|
||||
"F_BepInEx_OpticUseZoom_T": "Name Plates Use Optic Zoom",
|
||||
"F_BepInEx_OpticUseZoom_D": "If name plate location should be displayed using the PiP optic camera.",
|
||||
"F_BepInEx_DecOpacPeri_T": "Decrease Opacity In Peripheral",
|
||||
"F_BepInEx_OpticUseZoom_T": "Targhette Dei Nomi Usando Zoom Ottico",
|
||||
"F_BepInEx_OpticUseZoom_D": "Se la posizione della targhetta deve essere visualizzata usando la visuale con ottica PiP.",
|
||||
"F_BepInEx_DecOpacPeri_T": "Diminuire Opacità Nei Margini",
|
||||
"F_BepInEx_DecOpacPeri_D": "Diminuisce l'opacità delle targhette dei nomi quando non si guarda un giocatore",
|
||||
"F_BepInEx_NamePlateScale_T": "Name Plate Scale",
|
||||
"F_BepInEx_NamePlateScale_T": "Dimensione Targhette Dei Nomi",
|
||||
"F_BepInEx_NamePlateScale_D": "Grandezza delle targhette dei nomi.",
|
||||
"F_BepInEx_AdsOpac_T": "Opacità durante la mira",
|
||||
"F_BepInEx_AdsOpac_D": "The opacity of the name plates when aiming down sights.",
|
||||
"F_BepInEx_AdsOpac_D": "Opacità delle targhette mentre si è in puntamento.",
|
||||
"F_BepInEx_MaxDistance_T": "Distanza massima da mostrare",
|
||||
"F_BepInEx_MaxDistance_D": "The maximum distance at which name plates will become invisible, starts to fade at half the input value.",
|
||||
"F_BepInEx_MaxDistance_D": "La distanza massima alla quale le targhette diventeranno invisibili, inizieranno a sbiadire a metà del valore selezionato.",
|
||||
"F_BepInEx_MinOpac_T": "Opacità Minima",
|
||||
"F_BepInEx_MinOpac_D": "Opacità minima targhette dei nomi",
|
||||
"F_BepInEx_MinPlateScale_T": "Minimum Name Plate Scale",
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_MinPlateScale_T": "Dimensione Minima Targhette",
|
||||
"F_BepInEx_MinPlateScale_D": "La dimensione minima delle targhette.",
|
||||
"F_BepInEx_UseOcclusion_T": "Abilità Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_UseOcclusion_D": "Usa l'occlusione per nascondere la targhetta quando il giocatore non è visibile.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Tipi di Quest",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Mostra Notifiche",
|
||||
@@ -179,72 +187,82 @@
|
||||
"F_BepInEx_PingTime_T": "Tempo Ping",
|
||||
"F_BepInEx_PingTime_D": "Per quanto un ping deve essere mostrato",
|
||||
"F_BepInEx_PingAnimation_T": "Riproduci Animazione Ping",
|
||||
"F_BepInEx_PingAnimation_D": "Plays the pointing animation automatically when pinging. Can interfere with gameplay.",
|
||||
"F_BepInEx_PingAnimation_D": "Riproduce automaticamente l'animazione di puntamento quando si pinga. Può interferire con il gameplay.",
|
||||
"F_BepInEx_PingOptics_T": "Mostra Ping mentre Miri",
|
||||
"F_BepInEx_PingOptics_D": "If pings should be displayed while aiming down an optics scope.",
|
||||
"F_BepInEx_PingOpticZoom_T": "Ping Use Optic Zoom",
|
||||
"F_BepInEx_PingOpticZoom_D": "If ping location should be displayed using the PiP optic camera.",
|
||||
"F_BepInEx_PingScaleDistance_T": "Ping Scale With Distance",
|
||||
"F_BepInEx_PingScaleDistance_D": "If ping size should scale with distance from player.",
|
||||
"F_BepInEx_PingOptics_D": "Se il ping deve essere mostrato quando si mira con un mirino ottico.",
|
||||
"F_BepInEx_PingOpticZoom_T": "Pinga Usando Zoom Ottico",
|
||||
"F_BepInEx_PingOpticZoom_D": "Se il ping deve essere visualizzato usando la visuale con ottica PiP.",
|
||||
"F_BepInEx_PingScaleDistance_T": "Il Ping Si Ridimensiona Con La Distanza",
|
||||
"F_BepInEx_PingScaleDistance_D": "Se la grandezza del ping deve ridimensionarsi con la distanza dal giocatore.",
|
||||
"F_BepInEx_PingMinOpac_T": "Opacità Minima Ping",
|
||||
"F_BepInEx_PingMinOpac_D": "Opacità minima di un ping quando vengono guardati",
|
||||
"F_BepInEx_PingRange_T": "Mostra range del ping",
|
||||
"F_BepInEx_PingRange_D": "Mostra la distanza dal ping se abilitato",
|
||||
"F_BepInEx_PingSound_T": "Suono Ping",
|
||||
"F_BepInEx_PingSound_D": "Audio riprodotto durante il ping",
|
||||
"F_BepInEx_FreeCamButton_T": "Free Camera Button",
|
||||
"F_BepInEx_FreeCamButton_D": "Button used to toggle free camera.",
|
||||
"F_BepInEx_SpectateBots_T": "Allow Spectating Bots",
|
||||
"F_BepInEx_SpectateBots_D": "If we should allow spectating bots if all players are dead/extracted.",
|
||||
"F_BepInEx_AZERTYMode_T": "AZERTY Mode",
|
||||
"F_BepInEx_AZERTYMode_D": "If free camera should use AZERTY keys for input.",
|
||||
"F_BepInEx_DroneMode_T": "Drone Mode",
|
||||
"F_BepInEx_DroneMode_D": "If the free camera should move only along the vertical axis like a drone.",
|
||||
"F_BepInEx_KeybindOverlay_T": "Keybind Overlay",
|
||||
"F_BepInEx_KeybindOverlay_D": "If an overlay with all free cam keybinds should show.",
|
||||
"F_BepInEx_DynamicAI_T": "Dynamic AI",
|
||||
"F_BepInEx_DynamicAI_D": "Use the dynamic AI system, disabling AI when they are outside of all player's range.",
|
||||
"F_BepInEx_DynamicAIRange_T": "Dynamic AI Range",
|
||||
"F_BepInEx_DynamicAIRange_D": "The range at which AI will be disabled dynamically.",
|
||||
"F_BepInEx_DynamicAIRate_T": "Dynamic AI Rate",
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
"F_BepInEx_DespawnFurthest_D": "When enforcing spawn limits, should the furthest bot be de-spawned instead of blocking the spawn. This will make for a much more active raid on a lower Max Bots count. Helpful for weaker PCs. Will only despawn pmcs and scavs. If you don't run a dynamic spawn mod, this will however quickly exhaust the spawns on the map, making the raid very dead instead.",
|
||||
"F_BepInEx_DespawnMinDistance_T": "Despawn Minimum Distance",
|
||||
"F_BepInEx_DespawnMinDistance_D": "The minimum distance to despawn a bot.",
|
||||
"F_BepInEx_MaxBots_T": "Max Bots {0}",
|
||||
"F_BepInEx_MaxBots_D": "Max amount of bots that can be active at the same time on {0}. Useful if you have a weaker PC. Set to 0 to use vanilla limits. Cannot be changed during a raid.",
|
||||
"F_BepInEx_NativeSockets_T": "Native Sockets",
|
||||
"F_BepInEx_NativeSockets_D": "Use NativeSockets for gameplay traffic. This uses direct socket calls for send/receive to drastically increase speed and reduce GC pressure. Only for Windows/Linux and might not always work.",
|
||||
"F_BepInEx_ForceIP_T": "Force IP",
|
||||
"F_BepInEx_ForceIP_D": "Forces the server when hosting to use this IP when broadcasting to the backend instead of automatically trying to fetch it. Leave empty to disable.",
|
||||
"F_BepInEx_ForceBindIP_T": "Force Bind IP",
|
||||
"F_BepInEx_ForceBindIP_D": "Forces the server when hosting to use this local adapter when starting the server. Useful if you are hosting on a VPN.",
|
||||
"F_BepInEx_UDPPort_T": "UDP Port",
|
||||
"F_BepInEx_UDPPort_D": "Port to use for UDP gameplay packets.",
|
||||
"F_BepInEx_UseUPnP_T": "Use UPnP",
|
||||
"F_BepInEx_UseUPnP_D": "Attempt to open ports using UPnP. Useful if you cannot open ports yourself but the router supports UPnP.",
|
||||
"F_BepInEx_FreeCamButton_T": "Pulsante Visuale Libera",
|
||||
"F_BepInEx_FreeCamButton_D": "Pulsante usato per togliere la visuale libera.",
|
||||
"F_BepInEx_SpectateBots_T": "Permetti Modalità Spettatore Sui Bot",
|
||||
"F_BepInEx_SpectateBots_D": "Si permette di guardare i bot se tutti i giocatori sono morti/estratti.",
|
||||
"F_BepInEx_AZERTYMode_T": "Modalità AZERTY",
|
||||
"F_BepInEx_AZERTYMode_D": "Se la visuale libera deve usare i tasti AZERTY per l'input.",
|
||||
"F_BepInEx_DroneMode_T": "Modalità Drone",
|
||||
"F_BepInEx_DroneMode_D": "Se la visuale libera deve muoversi solo lungo l'asse verticale come un drone.",
|
||||
"F_BepInEx_KeybindOverlay_T": "Overlay Scorciatoie",
|
||||
"F_BepInEx_KeybindOverlay_D": "Se un overlay con tutte le scorciatoie per la visuale libera deve essere mostrato.",
|
||||
"F_BepInEx_DynamicAI_T": "IA Dinamica",
|
||||
"F_BepInEx_DynamicAI_D": "Utilizzare il sistema dinamico dell'IA, disabilitando le IA quando sono al di fuori della portata di tutti i giocatori.",
|
||||
"F_BepInEx_DynamicAIRange_T": "Portata IA Dinamica",
|
||||
"F_BepInEx_DynamicAIRange_D": "La portata in cui l'IA sarà disabilitata dinamicamente.",
|
||||
"F_BepInEx_DynamicAIRate_T": "Frequenza IA Dinamica",
|
||||
"F_BepInEx_DynamicAIRate_D": "Quante volte l'IA Dinamica dovrebbe scansionare la portata da tutti i giocatori.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignora Cecchini",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Indica se l'IA dinamica debba ignorare gli scav cecchini.",
|
||||
"F_BepInEx_FikaGC_T": "Utilizza GC Fika",
|
||||
"F_BepInEx_FikaGC_D": "Se un garbage collector personalizzato deve essere utilizzato per alleviare i problemi con l'uso di memoria.\nATTENZIONE: Sperimentale, potrebbe non avere alcun effetto sul vostro sistema.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Limiti Spawn forzati",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Forza i limiti di generazione quando si generano bot, assicurandosi di non superare i limiti vanilla. Questo ha effetto principalmente quando si usano le mod di spawn o qualsiasi cosa che modifichi i limiti del bot. Non bloccherà gli spawn di bot speciali come i boss.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Del Più Lontano",
|
||||
"F_BepInEx_DespawnFurthest_D": "Quando si applicano i limiti di spawn, il bot più lontano dovrebbe essere rimosso invece di bloccare lo spawn. Questo renderà un raid molto più attivo su un numero di bot Max più basso. Utile per i PC più deboli. Rimuoverà solo pmc e scav. Se non si esegue una mod di generazione dinamica, tuttavia, questo svuoterà rapidamente gli spawn sulla mappa, rendendo il raid molto morto invece.",
|
||||
"F_BepInEx_DespawnMinDistance_T": "Distanza Minima Di Despawn",
|
||||
"F_BepInEx_DespawnMinDistance_D": "La distanza minima per rimuovere un bot.",
|
||||
"F_BepInEx_MaxBots_T": "Bot Massimi {0}",
|
||||
"F_BepInEx_MaxBots_D": "Quantità massima di bot che possono essere attivi contemporaneamente {0}. Utile se hai un PC più debole. Imposta a 0 per usare i limiti vanilla. Non può essere modificato durante un raid.",
|
||||
"F_BepInEx_NativeSockets_T": "Socket Nativi",
|
||||
"F_BepInEx_NativeSockets_D": "Usa Socket Nativi per il traffico di gameplay. Questo utilizza le chiamate di socket dirette per inviare/ricevere aumentando drasticamente la velocità e riducendo la pressione sul GC. Solo per Windows/Linux e potrebbe non sempre funzionare.",
|
||||
"F_BepInEx_ForceIP_T": "Forza IP",
|
||||
"F_BepInEx_ForceIP_D": "Forza il server mentre l'hosta ad usare questo IP durante la trasmissione al backend invece di tentaredi recuperarlo automaticamente. Lasciare vuoto per disabilitare.",
|
||||
"F_BepInEx_ForceBindIP_T": "Forza L'IP Binding",
|
||||
"F_BepInEx_ForceBindIP_D": "Forza il server durante l'hosting a utilizzare questo adattatore locale quando si avvia il server. Utile se si sta ospitando su una VPN.",
|
||||
"F_BepInEx_UDPPort_T": "Porta UDP",
|
||||
"F_BepInEx_UDPPort_D": "Porta da utilizzare per i pacchetti di gioco UDP.",
|
||||
"F_BepInEx_UseUPnP_T": "Usa UPnP",
|
||||
"F_BepInEx_UseUPnP_D": "Tenta di aprire le porte usando UPnP. Utile se non è possibile aprire le porte manualmente e il router supporta UPnP.",
|
||||
"F_BepInEx_UseNatPunch_T": "Use NAT Punching",
|
||||
"F_BepInEx_UseNatPunch_D": "Use NAT punching when hosting a raid. Only works with fullcone NAT type routers and requires NatPunchServer to be running on the SPT server. UPnP, Force IP and Force Bind IP are disabled with this mode.",
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connessione Scaduta",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Quanto tempo ci vuole perché una connessione sia considerata scaduta se non vengono ricevuti pacchetti.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
"F_MMUI_InMenu": "In Menu",
|
||||
"F_MMUI_InRaid": "In Raid",
|
||||
"F_MMUI_InStash": "In Stash",
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Usa MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "Se il componente di rete dovrebbe usare multi-thread. Questo può potenzialmente alleviare i problemi quando il gioco lagga, consentendo al gestore di rete di elaborare e mettere in coda pacchetti durante FPS bassi.\nQuesta è una funzione sperimentale e dovrebbe essere abilitata solo sui PC di fascia alta e sarà abilitata solo su un client headless.",
|
||||
"F_BepInEx_VOIP_T": "Consenti VOIP",
|
||||
"F_BepInEx_VOIP_D": "Se VOIP sarà abilitato quando si è in hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disabilita Il Metabolismo Dei Bot",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disabilita il metabolismo sui bot, impedendo loro di morire dalla perdita di energia/idratazione durante lunghi raid.",
|
||||
"F_MMUI_OnlinePlayers": "GIOCATORI ONLINE: {0}",
|
||||
"F_MMUI_InMenu": "Nel Menu",
|
||||
"F_MMUI_InRaid": "Nel Raid",
|
||||
"F_MMUI_InStash": "Nello Stash",
|
||||
"F_MMUI_InHideout": "Nell'Hideout",
|
||||
"F_MMUI_InFlea": "Nel Flea",
|
||||
"F_MMUI_RaidDetails": "Giocando come {0} su {1}\nOrario: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "ERRORE TRADUZIONE",
|
||||
"F_UI_LocaleError_D": "Si sono verificati errori durante il caricamento delle traduzioni Fika. La traduzione ora sta usando ripieghi per le intestazioni fallite. Si prega di segnalare agli sviluppatori!\n\nChiavi fallite: {0}",
|
||||
"F_UI_EFTVersionError": "Stai tentando di utilizzare una versione diversa di EFT rispetto a quella in esecuzione dall'host del raid.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "Stai tentando di utilizzare una versione diversa di Fika rispetto a quella in esecuzione dall'host del raid.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_PlayerConnected": "{0} si è connesso",
|
||||
"F_UI_PlayerDisconnected": "{0} si è disconnesso",
|
||||
"F_UI_DisabledByServerHost": "Disabilitato dall'host del server"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "レイドをホスト",
|
||||
"F_MMUI_JoinButton": "参加",
|
||||
"F_MMUI_SelectAmountHeader": "数を選択",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "セッションの設定",
|
||||
"F_MMUI_SelectAmountDescription": "何人がプレイしますか? (あなたを含めて)",
|
||||
"F_MMUI_UseDedicatedHost": "専用ホストを使用",
|
||||
"F_MMUI_StartButton": "開始",
|
||||
"F_MMUI_LoadingScreenHeader": "読み込み中",
|
||||
"F_MMUI_LoadingScreenDescription": "レイドの初期化中ですので、しばらくお待ちください... 時間がかかる場合があります。",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "観戦",
|
||||
"F_MMUI_JoinAsSpectator_D": "観戦に参加",
|
||||
"F_UI_StartRaid": "集結開始",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nAfter clicking this additional players will not be able to join",
|
||||
"F_UI_CannotJoinRaidOtherMap": "別のマップで行われているレイドには参加できません。\nレイドマップ: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "別の時間帯で行われているレイドには参加できません。",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "PMC として SCAV レイドには参加できません。",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "バインドエラー",
|
||||
"F_UI_ErrorBindIP": "'{0}' はバインドするための有効なIPアドレスではありません! 'Force Bind IP' 設定を確認してください。",
|
||||
"F_UI_NoDedicatedClients": "専用クライアントは利用できません。",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Starts a raid\nOther players will be able to join you during the loading screen",
|
||||
"F_UI_WaitForHostStartRaid": "ホストの襲撃開始を待っています…",
|
||||
"F_UI_WaitForHostFinishInit": "ホストがレイドの初期化を終えるのを待っています…",
|
||||
"F_UI_WaitForOtherPlayers": "他のプレイヤーが読み込みを終えるのを待っています…",
|
||||
"F_UI_RetrieveSpawnInfo": "サーバーからスポーン情報を取得しています…",
|
||||
@@ -92,14 +94,14 @@
|
||||
"F_UI_ToSLong": "Fika へようこそ!\n\nFika は SPT 用の協力プレイ Mod で、友達と一緒にプレイすることができます。Fika は無料であり、今後も無料で提供されます。もしお金を支払った場合、それは詐欺です。また、収益化や寄付を目的とした公開サーバーのホストは許可されていません。\n\n利用規約に同意するには、このメッセージが消えるまで待ってください。\n\nDiscord への参加はこちらから: https://discord.gg/project-fika",
|
||||
"F_UI_ToSShort": "Fika へようこそ!\n\nFika は SPT 用の協力プレイ Mod で、友達と一緒にプレイすることができます。Fika は無料であり、今後も無料で提供されます。もしお金を支払った場合、それは詐欺です。また、収益化や寄付を目的とした公開サーバーのホストは許可されていません。\n\nDiscord への参加はこちらから: https://discord.gg/project-fika",
|
||||
"F_UI_RaidSettingsDescription": "In this mode, you can play online co-op with your friends without the risk of meeting others.\nAll game mechanics in the co-op mode (weather, bots, bosses, etc.) are identical to the online mechanics.\nOnly the hosts settings will take effect.",
|
||||
"F_UI_CoopGameMode": "Fika Co-op Game Mode",
|
||||
"F_UI_CoopRaidSettings": "Fika Co-op Raid Settings",
|
||||
"F_UI_FikaAlwaysCoop": "Co-op is always enabled in Fika",
|
||||
"F_UI_CoopGameMode": "フィカ・コープ・ゲームモード",
|
||||
"F_UI_CoopRaidSettings": "フィカ協力集結設定",
|
||||
"F_UI_FikaAlwaysCoop": "Fika では常に協力が有効です",
|
||||
"F_UI_UpnpFailed": "UPnP mapping failed. Make sure the selected port is not already open!\nDisable UPnP if you are using a VPN.",
|
||||
"F_UI_InitWeather": "Generating weather...",
|
||||
"F_UI_InitWeather": "天気を生成中…",
|
||||
"F_Notification_RaidStarted": "{0} started a raid on {1}",
|
||||
"F_Notification_ItemReceived": "You received a {0} from {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Editing of RaidSettings is disabled by the server host",
|
||||
"F_Notification_RaidSettingsDisabled": "サーバのホストによりレイド設定の編集は無効になっています",
|
||||
"F_UI_ExtractMessage": "Press {0} to extract",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_BepInEx_H_Advanced": "Advanced",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Official Version",
|
||||
"F_BepInEx_OfficialVersion_D": "Show official version instead of Fika version.",
|
||||
"F_BepInEx_UseHeadless_T": "Auto Use Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Always tick the box to use the Headless Client if available",
|
||||
"F_BepInEx_ShowFeed_T": "Show Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Enable custom notifications when a player dies, extracts, kills a boss, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extract",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_UseOcclusion_T": "Use Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Show Notifications",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "레이드 호스트하기",
|
||||
"F_MMUI_JoinButton": "참가",
|
||||
"F_MMUI_SelectAmountHeader": "양을 선택하십시오.",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "세션 설정",
|
||||
"F_MMUI_SelectAmountDescription": "당신을 포함하여 몇 명의 플레이어가 참가합니까?",
|
||||
"F_MMUI_UseDedicatedHost": "전담 호스트를 사용하여 주십시오",
|
||||
"F_MMUI_StartButton": "시작",
|
||||
"F_MMUI_LoadingScreenHeader": "로딩 중",
|
||||
"F_MMUI_LoadingScreenDescription": "레이드를 동기화하는 중입니다... 잠시만 기다려주십시오.",
|
||||
"F_MMUI_JoinAsSpectator": "관전모드로 참여하기",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Spectate",
|
||||
"F_MMUI_JoinAsSpectator_D": "Join the game as a spectator",
|
||||
"F_UI_StartRaid": "레이드 시작",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nAfter clicking this additional players will not be able to join",
|
||||
"F_UI_CannotJoinRaidOtherMap": "다른 맵에서 진행중인 레이드에는 참가 할 수 없습니다.\n레이드 맵: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "다른 시간대의 레이드에는 참가할 수 없습니다.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "PMC 캐릭터로는 Scav레이드에 참가 할 수없습니다.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "바인딩 에러",
|
||||
"F_UI_ErrorBindIP": "{0} 은 바인드하기 유효한 IP주소가 아닙니다. IP 강제 바인드 설정을 확인해주십시오.",
|
||||
"F_UI_NoDedicatedClients": "사용가능한 전담 클라이언트가 없습니다.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Starts a raid\nOther players will be able to join you during the loading screen",
|
||||
"F_UI_WaitForHostStartRaid": "호스트가 레이드 시작하기 기다리는 중...",
|
||||
"F_UI_WaitForHostFinishInit": "호스트의 레이드 초기화 대기중",
|
||||
"F_UI_WaitForOtherPlayers": "다른 플레이어들의 로딩 대기중",
|
||||
"F_UI_RetrieveSpawnInfo": "서버에서 스폰 정보 받아오는중",
|
||||
@@ -101,7 +103,7 @@
|
||||
"F_Notification_ItemReceived": "{1} 에게서 {0} 를 받았습니다",
|
||||
"F_Notification_RaidSettingsDisabled": "레이드 설정 편집이 서버 호스트에 의해서 비활성화 되어있습니다.",
|
||||
"F_UI_ExtractMessage": "{0} 을 눌러 탈출을 완료하세요",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "프로필 다운로드",
|
||||
"F_BepInEx_H_Advanced": "고급",
|
||||
"F_BepInEx_H_Coop": "코옵",
|
||||
"F_BepInEx_H_Coop_NamePlates": "코옵 | 네임 플레이트",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "게임플레이",
|
||||
"F_BepInEx_OfficialVersion_T": "공식 버전",
|
||||
"F_BepInEx_OfficialVersion_D": "피카 버전 대신 공식 버전 보이기",
|
||||
"F_BepInEx_UseHeadless_T": "Auto Use Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Always tick the box to use the Headless Client if available",
|
||||
"F_BepInEx_ShowFeed_T": "피드 보이기",
|
||||
"F_BepInEx_ShowFeed_D": "플레이어가 죽거나 탈출하거나 보스 킬 등을 할 경우 뜨는 커스텀 메시지 알림 활성화",
|
||||
"F_BepInEx_AutoExtract_T": "자동 탈출완료",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "네임 플레이트들의 최소 비율",
|
||||
"F_BepInEx_UseOcclusion_T": "오클루전 사용",
|
||||
"F_BepInEx_UseOcclusion_D": "오크루전으로 플레이어가 시야에서 벗어나면 네임플레이트를 숨깁니다.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "퀘스트 타입",
|
||||
"F_BepInEx_QuestTypes_D": "보내거나 받을 퀘스트 타입. 비컨 설치하기는 마커랑 아이템 둘 다 해당됩니다.",
|
||||
"F_BepInEx_QSNotifications_T": "알림 보이기",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "다이나믹 Ai 적용 시 플레이어로부터 거리를 얼마나 자주 스캔할지",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "스나이퍼 무시",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "다이나믹 AI 적용 시 스나이퍼 스캐브는 건너뛸지 여부",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "스폰 제한 강제",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "봇 스폰 시에 최대 스폰 수 제한 적용, 바닐라 제한 넘지 않도록 주의. 봇 스폰 관련 모드를 사용하게되면 이 제한에 영항을 받게 됩니다. 보스같은 특수 봇 타입은 영향을 받지 않습니다.",
|
||||
"F_BepInEx_DespawnFurthest_T": "최대거리 봇 디스폰",
|
||||
@@ -233,18 +243,26 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "연결 타임아웃",
|
||||
"F_BepInEx_ConnectionTimeout_D": "해당 시간동안 패킷을 받지 못하면 연결을 드랍한걸로 간주함",
|
||||
"F_BepInEx_SendRate_T": "전송률",
|
||||
"F_BepInEx_SendRate_D": "초당 얼마나 움직임 패킷을 보낼 지 설정.(적을수록 대역폭을 적게 사용하지만 보간과정에서 시간 더 소요)\n호스트만 영향을 받으며 모든 클라이언트와 동기화 됨.\n초당 값임\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nMedium 보다 높히지 않을것을 권장함. 그 이상은 마진이 미비함.",
|
||||
"F_BepInEx_SmoothingRate_T": "평활화 레이트",
|
||||
"F_BepInEx_SmoothingRate_D": "로컬 시뮬레이션은 전송률*평활화 레이트 이하로 따라감. 이를 통해서 버퍼에 스냅샷을 충분히 유지하여 보간 과정에서 랙과 끊김을 완화시킴.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\n움직임이 부드럽지 않으면 High로 설정하기를 권장. 레이드 도중에 변경할 수 없음.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "봇 신진대사 비활성화",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "봇 신진대사 가능 비활성화, 물/밥 부족으로 봇들이 죽는것 방지.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
"F_MMUI_InMenu": "In Menu",
|
||||
"F_MMUI_InRaid": "In Raid",
|
||||
"F_MMUI_InStash": "In Stash",
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_MMUI_OnlinePlayers": "온라인 플레이어 수: {0}",
|
||||
"F_MMUI_InMenu": "메뉴",
|
||||
"F_MMUI_InRaid": "레이드 중",
|
||||
"F_MMUI_InStash": "스태쉬",
|
||||
"F_MMUI_InHideout": "하이드아웃",
|
||||
"F_MMUI_InFlea": "플리마켓",
|
||||
"F_MMUI_RaidDetails": "{1} 에서 {0}로 플레이\n시간: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "언어설정 오류",
|
||||
"F_UI_LocaleError_D": "피카 언어 DB를 불러오던 중에 오류가 발생하였습니다. 불러오기 실패한 부분은 대체언어를 사용하겠습니다.\n실패한 키들: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "HOSTUJ RAID",
|
||||
"F_MMUI_JoinButton": "DOŁĄCZ",
|
||||
"F_MMUI_SelectAmountHeader": "WYBIERZ ILOŚĆ",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "USTAWIENIA SESJI",
|
||||
"F_MMUI_SelectAmountDescription": "Ile osób (łącznie z tobą) będzie grało?",
|
||||
"F_MMUI_UseDedicatedHost": "Użyj Dedykowanego Gospodarza",
|
||||
"F_MMUI_StartButton": "START",
|
||||
"F_MMUI_LoadingScreenHeader": "ŁADOWANIE",
|
||||
"F_MMUI_LoadingScreenDescription": "Proszę czekać na inicjalizację raidu... to może chwilę potrwać.",
|
||||
"F_MMUI_JoinAsSpectator": "Dołącz jako obserwator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Obserwuj",
|
||||
"F_MMUI_JoinAsSpectator_D": "Dołącz do gry jako widz",
|
||||
"F_UI_StartRaid": "Rozpocznij Raid",
|
||||
"F_UI_StartRaidDescription": "Rozpoczyna raid\nPo kliknięciu tego dodatkowi gracze nie będą mogli dołączać",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Nie można dołączyć do raidu który odgrywa się na innej mapie.\nRaid odgrywa się na mapie: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Nie możesz dołączyć do raidu który odgrywa się o innej porze.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Nie możesz dołączyć do raidu scavów jako PMC.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "BŁĄD POWIĄZANIA",
|
||||
"F_UI_ErrorBindIP": "'{0}' nie jest prawidłowym adresem IP do powiązania! Sprawdź ustawienie 'Wymuś powiązanie IP'.",
|
||||
"F_UI_NoDedicatedClients": "Brak dostępnych dedykowanych klientów.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Rozpoczyna raid\nInni gracze będą mogli dołączyć podczas ekranu ładowania",
|
||||
"F_UI_WaitForHostStartRaid": "Oczekiwanie na rozpoczęcie raidu przez hosta...",
|
||||
"F_UI_WaitForHostFinishInit": "Oczekiwanie na zakończenie inicjalizacji raidu przez gospodarza...",
|
||||
"F_UI_WaitForOtherPlayers": "Oczekiwanie na zakończenie ładowania pozostałych graczy...",
|
||||
"F_UI_RetrieveSpawnInfo": "Pobieranie informacji o spawnie z serwera...",
|
||||
@@ -101,7 +103,7 @@
|
||||
"F_Notification_ItemReceived": "Otrzymałeś {0} od {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Edytowanie ustawień raidu jest wyłączone przez hosta serwera",
|
||||
"F_UI_ExtractMessage": "Wciśnij {0} aby wyjść",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "POBIERZ PROFIL",
|
||||
"F_BepInEx_H_Advanced": "Zaawansowane",
|
||||
"F_BepInEx_H_Coop": "Kooperacja",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Kooperacja | Nazwy Graczy",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Rozgrywka",
|
||||
"F_BepInEx_OfficialVersion_T": "Oficjalna Wersja",
|
||||
"F_BepInEx_OfficialVersion_D": "Pokazuj oficjalną wersję zamiast wersji Fika.",
|
||||
"F_BepInEx_UseHeadless_T": "Automatycznie używaj trybu headless",
|
||||
"F_BepInEx_UseHeadless_D": "Zawsze zaznacz pole, aby użyć trybu headless, jeśli jest dostępny",
|
||||
"F_BepInEx_ShowFeed_T": "Pokazuj Aktualności",
|
||||
"F_BepInEx_ShowFeed_D": "Włącz niestandardowe powiadomienia, gdy gracz umrze, wyjdzie z raidu, zabije bossa, itp.",
|
||||
"F_BepInEx_AutoExtract_T": "Automatyczne Wyjście",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "Minimalna skala nazw graczy.",
|
||||
"F_BepInEx_UseOcclusion_T": "Użyj Okluzji",
|
||||
"F_BepInEx_UseOcclusion_D": "Użyj okluzji, aby schować nazwy graczy, gdy gracz jest poza zasięgiem widzenia.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Typy zadań",
|
||||
"F_BepInEx_QuestTypes_D": "Które typy zadań do odebrania i wysyłania. PlaceBeacon to zarówno markery, jak i przedmioty.",
|
||||
"F_BepInEx_QSNotifications_T": "Pokazuj Powiadomienia",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Jak często dynamiczne AI powinno sprawdzać odległość od graczy.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignoruj snajperów",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Czy dynamiczne AI powinno ignorować scav snajperów",
|
||||
"F_BepInEx_FikaGC_T": "Użyj Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "Jeśli niestandardowy garbage collector powinien być użyty w celu złagodzenia problemów związanych z pamięcią.\nOSTRZEŻENIE: Funkcja eksperymentalna — może nie mieć żadnego wpływu na Twój system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Wymuszone Limity Odradzania",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Wymusza limit odrodzeń podczas odradzania botów, upewniając się, by nie przekroczyć domyślnych limitów. Ma znaczenie głównie podczas korzystania z modyfikacji zmieniających zasady odradzania lub cokolwiek co zmienia limity botów. Nie ma zastosowania do botów specjalnych tj. bossów.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Zniszcz Najdalsze",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Limit Czasu Połączenia",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Jak długo trwa ustalenie połączenia za przerwane, jeśli żadne pakiety nie przychodzą.",
|
||||
"F_BepInEx_SendRate_T": "Tempo Wysyłania Pakietów",
|
||||
"F_BepInEx_SendRate_D": "Jak często na sekundę, pakiety powiązane z ruchem powinny być przesyłane (mniej = mniejsze użycie sieci, lekko zwiększone opóźnienie podczas interpolacji)\nTa opcja ma efekt tylko dla hosta i jest synchronizowania pomiędzy klientami.\nIlość na sekundę:\n\nBardzo niska = 10\nNiska = 15\nŚrednia = 20\nWysoka = 30\n\nZalecane używanie wartości nie wyżej niż \"Średnie\" gdyż wyższe wartości nie powodują znacznej poprawy.",
|
||||
"F_BepInEx_SmoothingRate_T": "Częstotliwość Wygładzania",
|
||||
"F_BepInEx_SmoothingRate_D": "Lokalna symulacja jest opóźniona o (Częstotliwość wysyłania * częstotliwość wygładzania). To gwarantuje wystarczającą ilość próbek w buforze w celu uniknięcia lagów i przeskakiwania podczas interpolacji.\n\nNiski = 1.5\nŚredni = 2\nWysoki = 2.5\n\nUstaw tę opcję na \"Wysoki\" jeśli ruch jest poszarpany. Nie można zmienić w czasie raidu.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Używaj wielowątkowości",
|
||||
"F_BepInEx_NetMultiThread_D": "Jeżeli komponent sieci powinien stosować wielowątkowanie. Może to potencjalnie złagodzić problemy związane z lagami, umożliwiając menedżerowi sieci przetwarzanie i kolejkowanie pakietów gdy FPSy są niskie.\nJest to funkcja eksperymentalna i powinna być włączona tylko na wysokiej klasy komputerach i będzie włączona tylko na kliencie headless.",
|
||||
"F_BepInEx_VOIP_T": "Zezwalaj na VOIP",
|
||||
"F_BepInEx_VOIP_D": "Czy VOIP ma zostać włączony podczas hostowania.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Wyłącz Metabolizm Botów",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Wyłącza metabolizm botów, zapobiegając ich umieraniu z powodu utraty energi/nawodnienia podczas długich raidów.",
|
||||
"F_MMUI_OnlinePlayers": "GRACZE ONLINE: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "W Kryjówce",
|
||||
"F_MMUI_InFlea": "Przegląda Rynek",
|
||||
"F_MMUI_RaidDetails": "Gra jako {0} na obszarze {1}\nCzas: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "BŁĄD TŁUMACZEŃ",
|
||||
"F_UI_LocaleError_D": "Podczas wczytywania tłumaczeń Fika wystąpiły błędy. Tłumaczenie korzysta teraz z zapasowych plików dla nieudanych nagłówków. Proszę zgłosić to deweloperom!\n\nNieudane klucze: {0}",
|
||||
"F_UI_EFTVersionError": "Próbujesz użyć innej wersji EFT niż ta, w której host uruchomił raid.\nKlient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "Próbujesz użyć innej wersji Fika niż ta, w której host uruchomił raid.\nKlient: {0}\nHost: {1}",
|
||||
"F_UI_PlayerConnected": "{0} połączył się",
|
||||
"F_UI_PlayerDisconnected": "{0} rozłączył się",
|
||||
"F_UI_DisabledByServerHost": "Wyłączone przez hosta serwera"
|
||||
}
|
||||
@@ -43,9 +43,10 @@
|
||||
"F_MMUI_StartButton": "INICIAR",
|
||||
"F_MMUI_LoadingScreenHeader": "Carregando",
|
||||
"F_MMUI_LoadingScreenDescription": "Aguarde enquanto a incursão é inicializada... Isso pode levar algum tempo.",
|
||||
"F_MMUI_JoinAsSpectator": "Junte-se como espectador",
|
||||
"F_MMUI_JoinAsSpectator": "Assistir",
|
||||
"F_MMUI_JoinAsSpectator_D": "Entrar no jogo como espectador",
|
||||
"F_UI_StartRaid": "Começar Incursão",
|
||||
"F_UI_StartRaidDescription": "Começa a Incursão\nNovos jogadores não poderão entrar",
|
||||
"F_UI_StartRaidDescription": "Começa a incursão\nApós clicar nisso jogadores adicionais não serão capazes de entrar",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Não é possível se juntar a uma incursão que está em outro mapa.\nMapa da Incursão: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Não é possível participar de uma incursão que está em outra hora.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Você não pode entrar em um incursão de Scav como um PMC.",
|
||||
@@ -65,6 +66,7 @@
|
||||
"F_UI_ErrorBindIPHeader": "ERRO DE VINCULAÇÃO",
|
||||
"F_UI_ErrorBindIP": "'{0}' não é um endereço IP válido para vincular! Verifique sua configuração 'Forçar vinculação de IP'.",
|
||||
"F_UI_NoDedicatedClients": "Não há clientes dedicados disponíveis.",
|
||||
"F_UI_HostRaidTooltip": "Inicia uma incursão\nOutros jogadores poderão entrar enquanto está na tela de carregamento",
|
||||
"F_UI_WaitForHostStartRaid": "Esperando o anfitrião iniciar a incursão...",
|
||||
"F_UI_WaitForHostFinishInit": "Esperando o host terminar a inicialização da incursão...",
|
||||
"F_UI_WaitForOtherPlayers": "Esperando que outros jogadores terminem de carregar...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Jogabilidade",
|
||||
"F_BepInEx_OfficialVersion_T": "Versão Oficial",
|
||||
"F_BepInEx_OfficialVersion_D": "Mostrar versão oficial ao invés da versão Fika.",
|
||||
"F_BepInEx_UseHeadless_T": "Usar Automaticamente Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Sempre marque a caixa para usar o Cliente Headless se disponível",
|
||||
"F_BepInEx_ShowFeed_T": "Exibir Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Ativar notificações personalizadas quando um jogador morrer, extrair, matar um chefe, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extrair",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "A escala mínima das placas de nomes.",
|
||||
"F_BepInEx_UseOcclusion_T": "Usar Oclusão",
|
||||
"F_BepInEx_UseOcclusion_D": "Use oclusão para esconder a placa de nome quando o jogador estiver fora de vista.",
|
||||
"F_BepInEx_HealthColorFull_T": "Cor de Saúde Cheia",
|
||||
"F_BepInEx_HealthColorFull_D": "A cor mostrada quando em Saúde cheia. Ela irá gradualmente mover em direção à 'Cor de Saúde Baixa' quando HP diminuir.",
|
||||
"F_BepInEx_HealthColorLow_T": "Cor de Saúde Baixa",
|
||||
"F_BepInEx_HealthColorLow_D": "A cor mostrada quando em Saúde BAIXA. Ela irá gradualmente mover em direção à 'Cor de Saúde Cheia' quando HP aumentar.",
|
||||
"F_BepInEx_QuestTypes_T": "Tipos de Missão",
|
||||
"F_BepInEx_QuestTypes_D": "Quais tipos de missões receber e enviar. Colocar Itens são marcadores e itens.",
|
||||
"F_BepInEx_QSNotifications_T": "Mostrar notificações",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Com que frequência a IA Dinâmica deve procurar o intervalo entre todos os jogadores.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignorar Franco-atiradores",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Se AI Dinâmica deve ignorar os Franco-Atiradores.",
|
||||
"F_BepInEx_FikaGC_T": "Usar GC do Fika",
|
||||
"F_BepInEx_FikaGC_D": "Se um coletor de lixo (GC) customizado deve ser usado para aliviar problemas com uso de memória.\nAVISO: Experimental, talvez não tenha efeito no seu sistema.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Limite de Spawn forçado",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Força limites de spawn ao gerar bots, certifique-se de não ultrapassar os limites padrões. Isso afeta principalmente ao usar mods de spawn ou qualquer coisa que modifique os limites do bot. Não bloqueará bots especiais, como chefes.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawnar o mais longe",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Tempo de Limite de Conexão",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Quanto tempo leva para uma conexão ser considerada perdida se nenhum pacote for recebido.",
|
||||
"F_BepInEx_SendRate_T": "Taxa de Envio",
|
||||
"F_BepInEx_SendRate_D": "Com que frequência por segundo pacotes de movimento devem ser enviados (menor = menos largura de banda usada, um pouco mais de atraso durante a interpolação)\nIsto só afeta o anfitrião e será sincronizado com todos os clientes.\nValor é por segundo:\n\nMuito Baixo = 10\nBaixo = 15\nMédio = 20\nAlto = 30\n\nRecomendado deixar não mais que médio, já que os ganhos são insignificantes depois.",
|
||||
"F_BepInEx_SmoothingRate_T": "Taxa de Suavização",
|
||||
"F_BepInEx_SmoothingRate_D": "Simulação local está atrasada em (Taxa de envio * Taxa de Suavização). Isto garante que sempre temos snapshots suficientes no buffer para mitigar lags e jitter durante a interpolação.\n\nBaixa = 1,5\nMédio = 2\nAlto = 2,5\n\nDefina isto para 'Alto' se o movimento não for suave. Não pode ser alterado durante uma incursão.",
|
||||
"F_BepInEx_SendRate_D": "Com que frequência os pacotes de movimento devem ser enviados por segundo (Baixo = menor largura de banda usada, leve aumento de atraso durante interpolação)\nIsso afeta apenas o host e irá ser sincronizado para todos os clientes.\nQuantidade é por secundo:\nBaixo = 10\nMédio = 20\nAlto = 30\n\nRecomendado a deixar em alto ao invés de médio como os ganhos serão insignificantes depois.",
|
||||
"F_BepInEx_NetMultiThread_T": "Utilizar MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "Se o componente de rede deveria usar multi-threading. Isso pode potencialmente aliviar problema quando o jogo da lag, permitindo o gerenciador de rede processar a fila de pacotes durante FPS baixo.\nIsso é um recurso experimental e deve ser somente ativado em PCs de alta performance e deverá ser ativado apenas em cliesntes headless.",
|
||||
"F_BepInEx_VOIP_T": "Permitir VOIP",
|
||||
"F_BepInEx_VOIP_D": "Se VOIP estará ativo quando você hospedar.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Desativar o metabolismo do Bot",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Desabilita o metabolismo dos Bots, impedindo que eles morram por perda de energia/hidratação durante longas incursões.",
|
||||
"F_MMUI_OnlinePlayers": "JOGADORES ON-LINE: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "No esconderijo",
|
||||
"F_MMUI_InFlea": "Na pulga",
|
||||
"F_MMUI_RaidDetails": "Jogando como {0} em {1}\nHora: {2}",
|
||||
"F_Mod_VerificationFailure": "A verificação Crc32 do Fika.Core.dll falhou, você não poderá jogar com outras pessoas!\nVerifique seu arquivo de log para mais informações.",
|
||||
"F_UI_LocaleError_H": "ERRO NAS LOCALIZAÇÕES",
|
||||
"F_UI_LocaleError_D": "Houve erros ao carregar as localizações do Fika. A tradução agora está usando os originais para os cabeçalhos que falharam. Por favor, reporte isso para os desenvolvedores!\n\nChaves falhas: {0}"
|
||||
"F_UI_LocaleError_D": "Houve erros ao carregar as localizações do Fika. A tradução agora está usando os originais para os cabeçalhos que falharam. Por favor, reporte isso para os desenvolvedores!\n\nChaves falhas: {0}",
|
||||
"F_UI_EFTVersionError": "Você está usando uma versão diferente do EFT do qual o host da incursão atual está usando.\nCliente: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "Você está usando uma versão diferente do Fika do qual o host da incursão atual está usando.\nCliente: {0}\nHost: {1}",
|
||||
"F_UI_PlayerConnected": "{0} se conectou",
|
||||
"F_UI_PlayerDisconnected": "{0} se desconectou",
|
||||
"F_UI_DisabledByServerHost": "Desabilitado pelo hospedeiro do servidor"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "GĂZDUIEȘTE RAID",
|
||||
"F_MMUI_JoinButton": "ALĂTURĂ-TE",
|
||||
"F_MMUI_SelectAmountHeader": "SELECTAȚI SUMA",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "SETĂRI SESIUNE",
|
||||
"F_MMUI_SelectAmountDescription": "Câți oameni (inclusiv dumneavoastră) vor juca?",
|
||||
"F_MMUI_UseDedicatedHost": "Utilizați o gazdă dedicată",
|
||||
"F_MMUI_StartButton": "Începe",
|
||||
"F_MMUI_LoadingScreenHeader": "Se încarcă",
|
||||
"F_MMUI_LoadingScreenDescription": "Vă rugăm să așteptați până la inițializarea raidului... acest lucru poate dura un timp.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Spectate",
|
||||
"F_MMUI_JoinAsSpectator_D": "Alătură-te jocului ca spectator",
|
||||
"F_UI_StartRaid": "Începe Raid",
|
||||
"F_UI_StartRaidDescription": "Începe raid-ul\nDupă apăsare, alți jucători nu se vor mai putea alătura",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Nu vă puteți alătura unui raid care se află pe altă hartă. Hartă raid: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Nu vă puteți alătura unui raid care are loc pe alt interval de timp.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Nu vă puteți alătura unui raid scav ca PMC.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "EROAREDE DE LEGARE",
|
||||
"F_UI_ErrorBindIP": "„{0}” nu este o adresă IP validă la care să vă legați! Verificați setarea „Forțare legare IP”.",
|
||||
"F_UI_NoDedicatedClients": "Nu sunt disponibili clienți dedicați.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Începe un raid\nAlți jucători se vor putea alătura pe durata ecranului de încărcare",
|
||||
"F_UI_WaitForHostStartRaid": "Se așteaptă ca gazda să înceapă raid-ul...",
|
||||
"F_UI_WaitForHostFinishInit": "Se așteaptă ca gazda să termine inițializarea raidului...",
|
||||
"F_UI_WaitForOtherPlayers": "Se așteaptă ca alți jucători să termine încărcarea...",
|
||||
"F_UI_RetrieveSpawnInfo": "Se preiau informații despre punctele de apariție de pe server...",
|
||||
@@ -101,19 +103,21 @@
|
||||
"F_Notification_ItemReceived": "Ai primit un/o {0} de la {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Editing of RaidSettings is disabled by the server host",
|
||||
"F_UI_ExtractMessage": "Press {0} to extract",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_BepInEx_H_Advanced": "Advanced",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_UI_DownloadProfile": "DESCARCĂ PROFIL",
|
||||
"F_BepInEx_H_Advanced": "Avansat",
|
||||
"F_BepInEx_H_Coop": "Cooperativ",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | Name Plates",
|
||||
"F_BepInEx_H_Coop_QuestSharing": "Coop | Quest Sharing",
|
||||
"F_BepInEx_H_Coop_Pinging": "Coop | Pinging",
|
||||
"F_BepInEx_H_Coop_Debug": "Coop | Debug",
|
||||
"F_BepInEx_H_Performance": "Performance",
|
||||
"F_BepInEx_H_Performance": "Performanță",
|
||||
"F_BepInEx_H_PerformanceBots": "Performance | Max Bots",
|
||||
"F_BepInEx_H_Network": "Network",
|
||||
"F_BepInEx_H_Network": "Rețea",
|
||||
"F_BepInEx_H_Gameplay": "Gameplay",
|
||||
"F_BepInEx_OfficialVersion_T": "Official Version",
|
||||
"F_BepInEx_OfficialVersion_D": "Show official version instead of Fika version.",
|
||||
"F_BepInEx_UseHeadless_T": "Auto Use Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Always tick the box to use the Headless Client if available",
|
||||
"F_BepInEx_ShowFeed_T": "Show Feed",
|
||||
"F_BepInEx_ShowFeed_D": "Enable custom notifications when a player dies, extracts, kills a boss, etc.",
|
||||
"F_BepInEx_AutoExtract_T": "Auto Extract",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_UseOcclusion_T": "Use Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Show Notifications",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "СОЗДАТЬ РЕЙД",
|
||||
"F_MMUI_JoinButton": "ВОЙТИ",
|
||||
"F_MMUI_SelectAmountHeader": "ВЫБЕРИТЕ КОЛ-ВО",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "НАСТРОЙКИ СЕССИИ",
|
||||
"F_MMUI_SelectAmountDescription": "Сколько человек (включая вас) будет играть?",
|
||||
"F_MMUI_UseDedicatedHost": "Использовать выделенный хост",
|
||||
"F_MMUI_StartButton": "НАЧАТЬ",
|
||||
"F_MMUI_LoadingScreenHeader": "ЗАГРУЗКА",
|
||||
"F_MMUI_LoadingScreenDescription": "Пожалуйста, подождите, пока рейд инициализируется... это может занять некоторое время.",
|
||||
"F_MMUI_JoinAsSpectator": "Присоединиться как зритель",
|
||||
"F_MMUI_JoinAsSpectator": "Наблюдать",
|
||||
"F_MMUI_JoinAsSpectator_D": "Присоединиться к игре как наблюдатель",
|
||||
"F_UI_StartRaid": "Начать Рейд",
|
||||
"F_UI_StartRaidDescription": "Начать рейд\nНовые игроки не смогут присоединиться",
|
||||
"F_UI_StartRaidDescription": "Начинает рейд\nПосле нажатия, другие игроки не смогут присоединиться",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Невозможно присоединиться к рейду на другой карте.\nРейд на карте: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Невозможно присоединиться к рейду в другом времени.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Вы не можете присоединиться к рейду дикого как ЧВК.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "ОШИБКА ЗАПИСИ",
|
||||
"F_UI_ErrorBindIP": "'{0}' не является допустимым IP-адресом для привязки! Проверьте параметр 'Принудительная привязка к IP'.",
|
||||
"F_UI_NoDedicatedClients": "Нет выделенных клиентов.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Начинает рейд\nДругие игроки смогут присоединиться к вам во время экрана загрузки",
|
||||
"F_UI_WaitForHostStartRaid": "Ожидание начала рейда хостом...",
|
||||
"F_UI_WaitForHostFinishInit": "Ожидание завершения инициализации рейда...",
|
||||
"F_UI_WaitForOtherPlayers": "Ожидание загрузки других игроков...",
|
||||
"F_UI_RetrieveSpawnInfo": "Получение информации о спавне с сервера...",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Геймплей",
|
||||
"F_BepInEx_OfficialVersion_T": "Официальная версия",
|
||||
"F_BepInEx_OfficialVersion_D": "Показывать официальную версию вместо Fika.",
|
||||
"F_BepInEx_UseHeadless_T": "Автоматически использовать Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Всегда отмечать галочку для использования Headless-клиента при его наличии",
|
||||
"F_BepInEx_ShowFeed_T": "Лента событий",
|
||||
"F_BepInEx_ShowFeed_D": "Включить пользовательские уведомления, когда игрок умирает, выходит с рейда, убивает босса и т. д.",
|
||||
"F_BepInEx_AutoExtract_T": "Автоматический выход",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "Устанавливает минимальный размер табличек с именами игроков.",
|
||||
"F_BepInEx_UseOcclusion_T": "Использовать окклюзию",
|
||||
"F_BepInEx_UseOcclusion_D": "Использовать окклюзию, чтобы скрыть табличку с именем, когда игрок вне поля зрения.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Типы заданий",
|
||||
"F_BepInEx_QuestTypes_D": "Определяет, какие типы квестов получать и отправлять. Тип квеста «Установить маячок» включает в себя как маркеры, так и предметы.",
|
||||
"F_BepInEx_QSNotifications_T": "Показывать уведомления",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "Определяет, как часто динамическая система ИИ должна проверять расстояние от всех игроков для определения необходимости отключения ботов.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Динамический ИИ: игнорировать снайперов",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Определяет, должна ли динамическая система ИИ игнорировать снайперов при определении необходимости их отключения.",
|
||||
"F_BepInEx_FikaGC_T": "Использовать Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "Если следует использовать пользовательский сборщик мусора для уменьшения проблем с использованием памяти.\nВНИМАНИЕ: Экспериментальная функция, возможно, не окажет никакого эффекта на вашей системе.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Принудительные лимиты спавна",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Принудительно ограничивает количество одновременно появляющихся ботов, не допуская превышения лимитов, установленных в оригинальной игре. В основном влияет на игру при использовании модов, изменяющих количество ботов. Не блокирует появление особых ботов, таких как боссы.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Удалять самого дальнего бота при достижении лимита",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Время ожидания соединения",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Определяет, через какое время соединение будет считаться разорванным, если от клиента или сервера не поступает никаких пакетов данных.",
|
||||
"F_BepInEx_SendRate_T": "Скорость отправки",
|
||||
"F_BepInEx_SendRate_D": "Как часто в секунду перемещать пакеты передвижения(меньше = меньше использованной пропускной способности, чуть больше задержек во время интерполяции)\nЭто влияет только на хост и будет синхронизировано со всеми клиентами.\nКоличество в секунду:\n\nОчень Низко = 10\nНизко = 15\nСредне = 20\nВысоко = 30\n\nРекомендуется оставить не выше среднего, так как приросты после незначительны.",
|
||||
"F_BepInEx_SmoothingRate_T": "Уровень сглаживания",
|
||||
"F_BepInEx_SmoothingRate_D": "Локальная симуляция отстает на (Скорость отправки * Скорость сглаживания). Это гарантирует, что у нас всегда будет достаточно кадров в буфере для уменьшения задержек и джиттера при интерполяции.\n\nНизкий = 1,5\nСредний = 2\nВысокий = 2,5\n\nУстановите значение «Высокий», если движение не является плавным. Не может быть изменено во время рейда.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Использовать многопоточность",
|
||||
"F_BepInEx_NetMultiThread_D": "Если сетевой компонент должен использовать многопоточность. Это может потенциально устранить проблемы с лагами в игре, позволяя сетевому менеджеру продолжать обрабатывать и ставить пакеты в очередь даже при низком FPS.\nЭто экспериментальная функция, и её следует включать только на высокопроизводительных ПК. Кроме того, она будет активна только на headless-клиенте.",
|
||||
"F_BepInEx_VOIP_T": "Разрешить VOIP",
|
||||
"F_BepInEx_VOIP_D": "Включает VOIP, когда вы являетесь хостом.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Отключить метаболизм у ботов",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Отключает метаболизм у ботов, не давая им умереть от потери энергии/воды во время длительных рейдов.",
|
||||
"F_MMUI_OnlinePlayers": "ОНЛАЙН ИГРОКОВ: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "В Убежище",
|
||||
"F_MMUI_InFlea": "На Барахолке",
|
||||
"F_MMUI_RaidDetails": "Играет за {0} на {1}\nВремя: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "ОШИБКА ЛОКАЛИЗАЦИИ",
|
||||
"F_UI_LocaleError_D": "Возникли ошибки при загрузке языковых настроек Fika. Перевод теперь использует резервные варианты для неудачных заголовков. Пожалуйста, сообщите об этом разработчикам!\nКлючи с ошибкой: {0}",
|
||||
"F_UI_EFTVersionError": "Вы пытаетесь использовать другую версию EFT отличную от хоста.\nКлиент: {0}\nХост: {1}",
|
||||
"F_UI_FikaVersionError": "Вы пытаетесь использовать другую версию Fika отличную от хоста.\nКлиент: {0}\nХост: {1}",
|
||||
"F_UI_PlayerConnected": "{0} Подключился",
|
||||
"F_UI_PlayerDisconnected": "{0} Отключился",
|
||||
"F_UI_DisabledByServerHost": "Отключено хостом сервера"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "VYTVORIŤ RAID",
|
||||
"F_MMUI_JoinButton": "PRIPOJIŤ SA",
|
||||
"F_MMUI_SelectAmountHeader": "ZVOLIŤ MNOŽSTVO",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "Nastavenia relácie",
|
||||
"F_MMUI_SelectAmountDescription": "Koľko ľudí (vrátane teba) bude hrať?",
|
||||
"F_MMUI_UseDedicatedHost": "Použiť dedikovaný server",
|
||||
"F_MMUI_StartButton": "ZAČAŤ",
|
||||
"F_MMUI_LoadingScreenHeader": "NAČÍTAVANIE",
|
||||
"F_MMUI_LoadingScreenDescription": "Prosím čakaj kým sa inicializuje raid... Môže to chvíľu trvať.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "Sledovať",
|
||||
"F_MMUI_JoinAsSpectator_D": "Pripojiť sa k hre ako sledovateľ",
|
||||
"F_UI_StartRaid": "Zapnúť raid",
|
||||
"F_UI_StartRaidDescription": "Zapnúť raid\nPo kliknutí sa nebudú môcť pripojiť ďalší hráči",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Nemôžeš sa pripojiť k raidu ktorý je na inej mape.\nMapa: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Nemôžeš sa pripojiť k raidu ktorý je v inom čase.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "Nemôžeš sa pripojiť k scav raidu ako PMC.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "CHYBA PRIRADZOVANIA",
|
||||
"F_UI_ErrorBindIP": "'{0}' nie je validna IP adresa pre priradenie! Prosím skontroluj 'Force IP' nastavenie.",
|
||||
"F_UI_NoDedicatedClients": "Žiadny dedikovaný klienti nie sú dostupný.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Zapnúť raid\nOstatní hráči sa budú môcť pripojiť počas načítacej obrazovky",
|
||||
"F_UI_WaitForHostStartRaid": "Čakám na spustenie raidu hostiteľom...",
|
||||
"F_UI_WaitForHostFinishInit": "Čakám na hosta kým inicializuje raid...",
|
||||
"F_UI_WaitForOtherPlayers": "Čakám na načítanie ostatných hráčov...",
|
||||
"F_UI_RetrieveSpawnInfo": "Získavam dáta o spawne zo serveru...",
|
||||
@@ -76,32 +78,32 @@
|
||||
"F_UI_RetrieveInteractables": "Získavam interagovateľné objekty zo serveru...",
|
||||
"F_UI_InitCoopGame": "Inicializujem coop hru...",
|
||||
"F_UI_AllPlayersJoined": "Všetci hráči pripojený, spúšťam hru...",
|
||||
"F_UI_WaitingForConnect": "Waiting for client to connect to server... If there is no notification it failed.",
|
||||
"F_UI_ErrorConnectingToRaid": "Unable to connect to the raid server. Make sure ports are forwarded and/or UPnP is enabled and supported.",
|
||||
"F_UI_FinishingRaidInit": "Finishing raid initialization...",
|
||||
"F_UI_SyncThrowables": "Syncing throwables...",
|
||||
"F_UI_SyncInteractables": "Syncing interactables...",
|
||||
"F_UI_WaitingForConnect": "Čakám na pripojenie klienta k serveru... Ak nevyskočila notifikácia, operácia zlyhala.",
|
||||
"F_UI_ErrorConnectingToRaid": "Nemožno pripojiť sa k raid serveru. Uistite sa že porty sú otvorené a/alebo UPnP je zapnuté a podporované.",
|
||||
"F_UI_FinishingRaidInit": "Dokončovanie inicializácie raidu...",
|
||||
"F_UI_SyncThrowables": "Synchronizácia vrhacích predmetov...",
|
||||
"F_UI_SyncInteractables": "Synchronizácia interagovateľných predmetov...",
|
||||
"F_UI_SyncLampStates": "Syncing lamp states...",
|
||||
"F_UI_SyncWindows": "Syncing windows...",
|
||||
"F_UI_SyncWindows": "Synchronizácia okien...",
|
||||
"F_UI_ReceiveOwnPlayer": "Receiving own player...",
|
||||
"F_UI_FinishReconnect": "Finishing reconnect...",
|
||||
"F_Client_FreeCamInputDisabled": "Free cam input disabled",
|
||||
"F_Client_FreeCamInputEnabled": "Free cam input enabled",
|
||||
"F_UI_WaitForPlayer": "Waiting for {0} player",
|
||||
"F_UI_WaitForPlayers": "Waiting for {0} players",
|
||||
"F_UI_ToSLong": "Welcome to Fika!\r\n\r\nFika is a co-op mod for SPT, allowing you to play with your friends. Fika is and will always be free, if you paid for it you got scammed. You are also not allowed to host public servers with monetization or donations.\r\n\r\nWait for this message to fade to accept our Terms of Service.\r\n\r\nYou can join our Discord here: https://discord.gg/project-fika",
|
||||
"F_UI_ToSShort": "Welcome to Fika!\r\n\r\nFika is a co-op mod for SPT, allowing you to play with your friends. Fika is and will always be free, if you paid for it you got scammed. You are also not allowed to host public servers with monetization or donations.\r\n\r\nYou can join our Discord here: https://discord.gg/project-fika",
|
||||
"F_UI_RaidSettingsDescription": "In this mode, you can play online co-op with your friends without the risk of meeting others.\nAll game mechanics in the co-op mode (weather, bots, bosses, etc.) are identical to the online mechanics.\nOnly the hosts settings will take effect.",
|
||||
"F_UI_CoopGameMode": "Fika Co-op Game Mode",
|
||||
"F_UI_CoopRaidSettings": "Fika Co-op Raid Settings",
|
||||
"F_UI_FikaAlwaysCoop": "Co-op is always enabled in Fika",
|
||||
"F_UI_UpnpFailed": "UPnP mapping failed. Make sure the selected port is not already open!\nDisable UPnP if you are using a VPN.",
|
||||
"F_UI_InitWeather": "Generating weather...",
|
||||
"F_Notification_RaidStarted": "{0} started a raid on {1}",
|
||||
"F_Notification_ItemReceived": "You received a {0} from {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Editing of RaidSettings is disabled by the server host",
|
||||
"F_UI_FinishReconnect": "Dokončovanie znovu-napojenia...",
|
||||
"F_Client_FreeCamInputDisabled": "Vstup pre voľnú kameru vypnutý",
|
||||
"F_Client_FreeCamInputEnabled": "Vstup pre voľnú kameru zapnutý",
|
||||
"F_UI_WaitForPlayer": "Čakanie na {0} hráča",
|
||||
"F_UI_WaitForPlayers": "Čakanie na {0} hráčov",
|
||||
"F_UI_ToSLong": "Vitajte vo Fike!\n\nFika je co-op mód pre SPT, umožňuje vám hrať s vašimi priateľmi. Fika je a vždy bude ZDARMA, ak ste za ňu zaplatili, boli ste oklamaní. Tiež je zakázané hostovať verejné servery s monetizáciou (platením) alebo za donácie. \n\nPočkajte kým táto správa zmizne SAMA pre prijatie našich Podmienok používania. \n\nMôžete sa pridať na náš Discord tu: https://discord.gg/project-fika",
|
||||
"F_UI_ToSShort": "Vitajte vo Fike!\n\nFika je co-op mód pre SPT, umožňuje vám hrať s vašimi priateľmi. Fika je a vždy bude ZDARMA, ak ste za ňu zaplatili, boli ste oklamaní. Tiež je zakázané hostovať verejné servery s monetizáciou (platením) alebo za donácie. \n\nMôžete sa pridať na náš Discord tu: https://discord.gg/project-fika",
|
||||
"F_UI_RaidSettingsDescription": "V tomto hernom móde môžete hrať online co-op s vašimi priateľmi bez risku stretnutia cudzích alebo nežiadúcich ľudí a hráčov.\nVšetky herné mechaniky v co-op režime (počasie, boti, bossovia, atp.) sú identické s online mechanikami.\nJedine nastavenia hosťa ovplyvnia hru.",
|
||||
"F_UI_CoopGameMode": "Fika Co-op herný režim",
|
||||
"F_UI_CoopRaidSettings": "Fika Co-op nastavenia raidu",
|
||||
"F_UI_FikaAlwaysCoop": "Co-op je vždy zapnutý vo Fike",
|
||||
"F_UI_UpnpFailed": "UPnP mapovanie zlyhalo. Uistite sa že vybraný port nie je otvorený!\nVypnite UPnP ak používate VPN.",
|
||||
"F_UI_InitWeather": "Generujem počasie...",
|
||||
"F_Notification_RaidStarted": "{0} spustil raid na {1}",
|
||||
"F_Notification_ItemReceived": "Dostal si {0} od {1}",
|
||||
"F_Notification_RaidSettingsDisabled": "Úprava nastavení Raidu je vypnutá hosťom serveru",
|
||||
"F_UI_ExtractMessage": "Stlač {0} pre extrakt",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "STIAHNUŤ PROFIL",
|
||||
"F_BepInEx_H_Advanced": "Pokročilé",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | Menovky",
|
||||
@@ -113,30 +115,32 @@
|
||||
"F_BepInEx_H_Network": "Sieť",
|
||||
"F_BepInEx_H_Gameplay": "Hrateľnosť",
|
||||
"F_BepInEx_OfficialVersion_T": "Oficiálna verzia",
|
||||
"F_BepInEx_OfficialVersion_D": "Show official version instead of Fika version.",
|
||||
"F_BepInEx_OfficialVersion_D": "Zobraziť oficiálnu verziu hry namiesto FIKA verzie.",
|
||||
"F_BepInEx_UseHeadless_T": "Automaticky používať Headless",
|
||||
"F_BepInEx_UseHeadless_D": "Vždy zakliknúť pole pre použitie Headless klienta pokiaľ je k dispozícií",
|
||||
"F_BepInEx_ShowFeed_T": "Zobraziť informačný kanál",
|
||||
"F_BepInEx_ShowFeed_D": "Enable custom notifications when a player dies, extracts, kills a boss, etc.",
|
||||
"F_BepInEx_ShowFeed_D": "Zapne oznámenia keď hráč zomrie, extrahuje, zabije bossa, atp.",
|
||||
"F_BepInEx_AutoExtract_T": "Automatický exfil",
|
||||
"F_BepInEx_AutoExtract_D": "Automatically extracts after the extraction countdown. As a host, this will only work if there are no clients connected.",
|
||||
"F_BepInEx_ShowExtractMessage_T": "Show Extract Message",
|
||||
"F_BepInEx_ShowExtractMessage_D": "Whether to show the extract message after dying/extracting.",
|
||||
"F_BepInEx_ExtractKey_T": "Extract Key",
|
||||
"F_BepInEx_ExtractKey_D": "The key used to extract from the raid.",
|
||||
"F_BepInEx_EnableChat_T": "Enable Chat",
|
||||
"F_BepInEx_EnableChat_D": "Toggle to enable chat in game. Cannot be change mid raid.",
|
||||
"F_BepInEx_ChatKey_T": "Chat Key",
|
||||
"F_BepInEx_ChatKey_D": "The key used to open the chat window.",
|
||||
"F_BepInEx_EnableOnlinePlayers_T": "Enable Online Players",
|
||||
"F_BepInEx_EnableOnlinePlayers_D": "If the online players menu should be shown in the menu.",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Online Players Scale",
|
||||
"F_BepInEx_AutoExtract_D": "Automaticky extrahovať potom ako skončí odpočet. Toto bude pre hostiteľa fungovať iba ak nie sú pripojení žiadny klienti.",
|
||||
"F_BepInEx_ShowExtractMessage_T": "Zobraziť správu o extrakcií",
|
||||
"F_BepInEx_ShowExtractMessage_D": "Zobrazenie správy o extrahovaní po smrti/extrahovaní.",
|
||||
"F_BepInEx_ExtractKey_T": "Tlačidlo pre extrakciu",
|
||||
"F_BepInEx_ExtractKey_D": "Tlačidlo pre extrakciu z raidu.",
|
||||
"F_BepInEx_EnableChat_T": "Zapnúť chat",
|
||||
"F_BepInEx_EnableChat_D": "Prepínanie zobrazenia chatu v hre. Nemožno meniť hodnotu počas raidu.",
|
||||
"F_BepInEx_ChatKey_T": "Tlačidlo pre chat",
|
||||
"F_BepInEx_ChatKey_D": "Tlačítko pre otvorenie okna s chatom.",
|
||||
"F_BepInEx_EnableOnlinePlayers_T": "Zapnúť online hráčov",
|
||||
"F_BepInEx_EnableOnlinePlayers_D": "Zobrazenie tabuľky hráčov v hlavnom menu.",
|
||||
"F_BepInEx_OnlinePlayersScale_T": "Škála online hráčov",
|
||||
"F_BepInEx_OnlinePlayersScale_D": "The scale of the window that displays online players. Only change if it looks out of proportion.\n\nRequires a refresh of the main menu to take effect.",
|
||||
"F_BepInEx_UseNamePlates_T": "Show Player Name Plates",
|
||||
"F_BepInEx_UseNamePlates_T": "Zobraziť menovky hráčov",
|
||||
"F_BepInEx_UseNamePlates_D": "If name plates should be shown above teammates.",
|
||||
"F_BepInEx_HideHealthBar_T": "Hide Health Bar",
|
||||
"F_BepInEx_HideHealthBar_D": "Completely hides the health bar.",
|
||||
"F_BepInEx_HideHealthBar_T": "Skryť ukazovateľ zdravia",
|
||||
"F_BepInEx_HideHealthBar_D": "Kompletne skryje ukazovateľ zdravia.",
|
||||
"F_BepInEx_UsePercent_T": "Show HP% instead of bar",
|
||||
"F_BepInEx_UsePercent_D": "Shows health in % amount instead of using the bar.",
|
||||
"F_BepInEx_ShowEffects_T": "Show Effects",
|
||||
"F_BepInEx_ShowEffects_T": "Zobraziť efekty",
|
||||
"F_BepInEx_ShowEffects_D": "If status effects should be displayed below the health bar.",
|
||||
"F_BepInEx_ShowFactionIcon_T": "Show Player Faction Icon",
|
||||
"F_BepInEx_ShowFactionIcon_D": "Shows the player faction icon next to the HP bar.",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "The minimum scale of the name plates.",
|
||||
"F_BepInEx_UseOcclusion_T": "Use Occlusion",
|
||||
"F_BepInEx_UseOcclusion_D": "Use occlusion to hide the name plate when the player is out of sight.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Quest Types",
|
||||
"F_BepInEx_QuestTypes_D": "Which quest types to receive and send. PlaceBeacon is both markers and items.",
|
||||
"F_BepInEx_QSNotifications_T": "Show Notifications",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "How often DynamicAI should scan for the range from all players.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Ignore Snipers",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Whether Dynamic AI should ignore sniper scavs.",
|
||||
"F_BepInEx_FikaGC_T": "Use Fika GC",
|
||||
"F_BepInEx_FikaGC_D": "If a custom garbage collector should be used to alleviate issues with memory usage.\nWARNING: Experimental, might have no effect at all on your system.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Enforced Spawn Limits",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Enforces spawn limits when spawning bots, making sure to not go over the vanilla limits. This mainly takes affect when using spawn mods or anything that modifies the bot limits. Will not block spawns of special bots like bosses.",
|
||||
"F_BepInEx_DespawnFurthest_T": "Despawn Furthest",
|
||||
@@ -233,9 +243,11 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Connection Timeout",
|
||||
"F_BepInEx_ConnectionTimeout_D": "How long it takes for a connection to be considered dropped if no packets are received.",
|
||||
"F_BepInEx_SendRate_T": "Send Rate",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\n\nVery Low = 10\nLow = 15\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_SmoothingRate_T": "Smoothing Rate",
|
||||
"F_BepInEx_SmoothingRate_D": "Local simulation is behind by (Send Rate * Smoothing Rate). This guarantees that we always have enough snapshots in the buffer to mitigate lags & jitter during interpolation.\n\nLow = 1.5\nMedium = 2\nHigh = 2.5\n\nSet this to 'High' if movement isn't smooth. Cannot be changed during a raid.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "Use MultiThreading",
|
||||
"F_BepInEx_NetMultiThread_D": "If the network component should use multi-threading. This can potentially alleviate problems when the game lags, allowing the network manager to still process and queue packets during low FPS.\nThis is an experimental feature and should only be enabled on high-end PCs and will only be enabled on a headless client.",
|
||||
"F_BepInEx_VOIP_T": "Allow VOIP",
|
||||
"F_BepInEx_VOIP_D": "If VOIP will be enabled when you are hosting.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Disable Bot Metabolism",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Disables metabolism on bots, preventing them from dying from loss of energy/hydration during long raids.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
@@ -245,6 +257,12 @@
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}",
|
||||
"F_UI_EFTVersionError": "You are attempting to use a different version of EFT than what the raid host is running.\nClient: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "You are attempting to use a different version of Fika than what the raid host is running.\nClient crc: {0}\nHost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} has connected",
|
||||
"F_UI_PlayerDisconnected": "{0} has disconnected",
|
||||
"F_UI_DisabledByServerHost": "Disabled by server host"
|
||||
}
|
||||
@@ -37,15 +37,16 @@
|
||||
"F_MMUI_HostRaidButton": "BASKIN OLUŞTUR",
|
||||
"F_MMUI_JoinButton": "KATIL",
|
||||
"F_MMUI_SelectAmountHeader": "MİKTAR SEÇİNİZ",
|
||||
"F_MMUI_SessionSettingsHeader": "SESSION SETTINGS",
|
||||
"F_MMUI_SessionSettingsHeader": "OTURUM AYARLARI",
|
||||
"F_MMUI_SelectAmountDescription": "Kaç kişi (siz dahil) oynayacak?",
|
||||
"F_MMUI_UseDedicatedHost": "Özel Host Kullanın",
|
||||
"F_MMUI_StartButton": "BAŞLAT",
|
||||
"F_MMUI_LoadingScreenHeader": "YÜKLENİYOR",
|
||||
"F_MMUI_LoadingScreenDescription": "Baskın başlatılırken lütfen bekleyin... bu biraz zaman alabilir.",
|
||||
"F_MMUI_JoinAsSpectator": "Join as spectator",
|
||||
"F_UI_StartRaid": "Start Raid",
|
||||
"F_UI_StartRaidDescription": "Starts the raid\nNew players will not be able to join",
|
||||
"F_MMUI_JoinAsSpectator": "İzleyin",
|
||||
"F_MMUI_JoinAsSpectator_D": "Oyuna seyirci olarak katılın",
|
||||
"F_UI_StartRaid": "Baskını başlat",
|
||||
"F_UI_StartRaidDescription": "Baskını başlatır\nBuna tıkladıktan sonra ek oyuncular katılamayacaktır",
|
||||
"F_UI_CannotJoinRaidOtherMap": "Başka bir haritada olan bir baskına katılamazsınız.\nBaskın haritası: {0}",
|
||||
"F_UI_CannotJoinRaidOtherTime": "Başka bir zamanda olan bir baskına katılamazsınız.",
|
||||
"F_UI_CannotJoinRaidScavAsPMC": "PMC olarak bir SCAV baskınına katılamazsınız.",
|
||||
@@ -65,7 +66,8 @@
|
||||
"F_UI_ErrorBindIPHeader": "HATA BAĞLANTISI",
|
||||
"F_UI_ErrorBindIP": "'{0}' bağlanmak için geçerli bir IP adresi değil! 'IP'yi Bağlamaya Zorla' ayarınızı kontrol edin.",
|
||||
"F_UI_NoDedicatedClients": "Özel istemci bulunmamaktadır.",
|
||||
"F_UI_WaitForHostStartRaid": "Waiting for host to start the raid...",
|
||||
"F_UI_HostRaidTooltip": "Baskını başlatır\nBuna tıkladıktan sonra başka oyuncular katılamayacaktır",
|
||||
"F_UI_WaitForHostStartRaid": "Ana bilgisayarın baskını başlatması bekleniyor...",
|
||||
"F_UI_WaitForHostFinishInit": "Ana bilgisayarın raid başlatmayı bitirmesi bekleniyor...",
|
||||
"F_UI_WaitForOtherPlayers": "Diğer oyuncuların yüklemeyi bitirmesini bekleniliyor...",
|
||||
"F_UI_RetrieveSpawnInfo": "Sunucudan spawn bilgisi alınıyor...",
|
||||
@@ -101,7 +103,7 @@
|
||||
"F_Notification_ItemReceived": "{1}'den bir {0} aldınız",
|
||||
"F_Notification_RaidSettingsDisabled": "Baskın Ayarlarının düzenlenmesi sunucu ana bilgisayarı tarafından devre dışı bırakılır",
|
||||
"F_UI_ExtractMessage": "Çıkarmak için {0} tuşuna basın",
|
||||
"F_UI_DownloadProfile": "DOWNLOAD PROFILE",
|
||||
"F_UI_DownloadProfile": "PROFİLİ İNDİR",
|
||||
"F_BepInEx_H_Advanced": "Gelişmiş",
|
||||
"F_BepInEx_H_Coop": "Coop",
|
||||
"F_BepInEx_H_Coop_NamePlates": "Coop | İsim Plakaları",
|
||||
@@ -114,6 +116,8 @@
|
||||
"F_BepInEx_H_Gameplay": "Oynanış",
|
||||
"F_BepInEx_OfficialVersion_T": "Resmi Versiyon",
|
||||
"F_BepInEx_OfficialVersion_D": "Fika versiyonu yerine resmi versiyonu gösterin.",
|
||||
"F_BepInEx_UseHeadless_T": "Otomatik Kullanım Başlıksız",
|
||||
"F_BepInEx_UseHeadless_D": "Varsa, Başsız İstemciyi kullanmak için her zaman kutuyu işaretleyin",
|
||||
"F_BepInEx_ShowFeed_T": "Beslemeyi Göster",
|
||||
"F_BepInEx_ShowFeed_D": "Bir oyuncu öldüğünde, çıkarıldığında, bir boss öldürdüğünde vb. özel bildirimleri etkinleştirin.",
|
||||
"F_BepInEx_AutoExtract_T": "Otomatik Exfill",
|
||||
@@ -158,6 +162,10 @@
|
||||
"F_BepInEx_MinPlateScale_D": "İsim plakalarının minimum ölçeği.",
|
||||
"F_BepInEx_UseOcclusion_T": "Oklüzyon Kullanın",
|
||||
"F_BepInEx_UseOcclusion_D": "Oyuncu görüş alanının dışındayken isim plakasını gizlemek için oklüzyon kullanın.",
|
||||
"F_BepInEx_HealthColorFull_T": "Full Health Color",
|
||||
"F_BepInEx_HealthColorFull_D": "The color displayed when at full health. This will gradually move towards 'Low Health Color' when HP decreases.",
|
||||
"F_BepInEx_HealthColorLow_T": "Low Health Color",
|
||||
"F_BepInEx_HealthColorLow_D": "The color displayed when at low health. This will gradually move towards 'Full Health Color' when HP increases.",
|
||||
"F_BepInEx_QuestTypes_T": "Görev Tipleri",
|
||||
"F_BepInEx_QuestTypes_D": "Hangi görev türlerinin alınacağı ve gönderileceği. PlaceBeacon hem işaretleyiciler hem de öğelerdir.",
|
||||
"F_BepInEx_QSNotifications_T": "Bildirimleri Göster",
|
||||
@@ -210,6 +218,8 @@
|
||||
"F_BepInEx_DynamicAIRate_D": "DynamicAI'nin tüm oyuncuların menzilini ne sıklıkla taraması gerektiği.",
|
||||
"F_BepInEx_DynamicAINoSnipers_T": "Keskin Nişancıları Görmezden Gel",
|
||||
"F_BepInEx_DynamicAINoSnipers_D": "Dinamik Yapay Zekanın keskin nişancı görmezden gelip gelmeyeceği.",
|
||||
"F_BepInEx_FikaGC_T": "Fika GC kullanın",
|
||||
"F_BepInEx_FikaGC_D": "Bellek kullanımıyla ilgili sorunları hafifletmek için özel bir çöp toplayıcı kullanılması gerekiyorsa.\nUYARI: Deneyseldir, sisteminiz üzerinde hiçbir etkisi olmayabilir.",
|
||||
"F_BepInEx_EnforcedSpawnLimits_T": "Zorunlu Spawn Limiti",
|
||||
"F_BepInEx_EnforcedSpawnLimits_D": "Botlar ortaya çıkarken ortaya çıkma sınırlarını zorlar, vanilya sınırlarını aşmadığından emin olur. Bu, esas olarak spawn modları veya bot sınırlarını değiştiren herhangi bir şey kullanıldığında etkili olur. Bosslar gibi özel botların ortaya çıkmasını engellemez.",
|
||||
"F_BepInEx_DespawnFurthest_T": "En Uzakta Despawn",
|
||||
@@ -233,18 +243,26 @@
|
||||
"F_BepInEx_ConnectionTimeout_T": "Bağlantı Zaman Aşımı",
|
||||
"F_BepInEx_ConnectionTimeout_D": "Hiçbir paket alınmadığında bir bağlantının düşmüş sayılması için ne kadar süre geçmesi gerektiği.",
|
||||
"F_BepInEx_SendRate_T": "Oran Gönder",
|
||||
"F_BepInEx_SendRate_D": "Hareket paketlerinin saniye başına ne sıklıkta gönderilmesi gerektiği (daha düşük = daha az bant genişliği kullanılır, enterpolasyon sırasında biraz daha fazla gecikme)\nBu yalnızca ana bilgisayarı etkiler ve tüm istemcilerle senkronize edilir.\nMiktar saniye başına:\n\nÇok Düşük = 10\nDüşük = 15\nOrta = 20\nYüksek = 30\n\nSonrasında kazançlar önemsiz olduğu için Orta'dan daha yüksek bir seviyede bırakılmaması önerilir.",
|
||||
"F_BepInEx_SmoothingRate_T": "Düzeltme Oranı",
|
||||
"F_BepInEx_SmoothingRate_D": "Yerel simülasyon (Gönderme Oranı * Düzeltme Oranı) ile geride kalır. Bu, enterpolasyon sırasında gecikmeleri ve titreşimi azaltmak için tamponda her zaman yeterli anlık görüntüye sahip olduğumuzu garanti eder.\n\nDüşük = 1,5\nOrta = 2\nYüksek = 2,5\n\nHareket düzgün değilse bunu 'Yüksek' olarak ayarlayın. Baskın sırasında değiştirilemez.",
|
||||
"F_BepInEx_SendRate_D": "How often per second movement packets should be sent (lower = less bandwidth used, slight more delay during interpolation)\nThis only affects the host and will be synchronized to all clients.\nAmount is per second:\nLow = 10\nMedium = 20\nHigh = 30\n\nRecommended to leave at no higher than Medium as the gains are insignificant after.",
|
||||
"F_BepInEx_NetMultiThread_T": "MultiThreading Kullanın",
|
||||
"F_BepInEx_NetMultiThread_D": "Ağ bileşeninin çoklu iş parçacığı kullanması gerekiyorsa. Bu, oyun geciktiğinde sorunları potansiyel olarak hafifletebilir ve ağ yöneticisinin düşük FPS sırasında paketleri işlemeye ve sıraya koymaya devam etmesine izin verir.\nBu deneysel bir özelliktir ve yalnızca üst düzey bilgisayarlarda etkinleştirilmelidir ve yalnızca başsız bir istemcide etkinleştirilecektir.",
|
||||
"F_BepInEx_VOIP_T": "VOIP'e İzin Ver",
|
||||
"F_BepInEx_VOIP_D": "Ev sahipliği yaparken VOIP etkinleştirilecekse.",
|
||||
"F_BepInEx_DisableBotMetabolism_T": "Bot Metabolizmasını Devre Dışı Bırak",
|
||||
"F_BepInEx_DisableBotMetabolism_D": "Botlarda metabolizmayı devre dışı bırakarak uzun akınlar sırasında enerji/hidrasyon kaybından ölmelerini önler.",
|
||||
"F_MMUI_OnlinePlayers": "ONLINE PLAYERS: {0}",
|
||||
"F_MMUI_InMenu": "In Menu",
|
||||
"F_MMUI_InRaid": "In Raid",
|
||||
"F_MMUI_InStash": "In Stash",
|
||||
"F_MMUI_InHideout": "In Hideout",
|
||||
"F_MMUI_InFlea": "In Flea",
|
||||
"F_MMUI_RaidDetails": "Playing as a {0} on {1}\nTime: {2}",
|
||||
"F_UI_LocaleError_H": "LOCALES ERROR",
|
||||
"F_UI_LocaleError_D": "There were errors when loading the Fika locales. Translation is now using fallbacks for the failed headers. Please report this to the developers!\n\nFailed keys: {0}"
|
||||
"F_MMUI_OnlinePlayers": "{0} ONLINE OYUNCU",
|
||||
"F_MMUI_InMenu": "Menüde",
|
||||
"F_MMUI_InRaid": "Baskında",
|
||||
"F_MMUI_InStash": "Zulada",
|
||||
"F_MMUI_InHideout": "Sığınakta",
|
||||
"F_MMUI_InFlea": "Flea'da",
|
||||
"F_MMUI_RaidDetails": "{1} üzerinde {0} olarak oynamak\nZaman: {2}",
|
||||
"F_Mod_VerificationFailure": "Crc32 verification of the Fika.Core.dll failed, you will not be able to play with other people!\nCheck your log file for more information.",
|
||||
"F_UI_LocaleError_H": "YEREL HATA",
|
||||
"F_UI_LocaleError_D": "Fika yerel ayarları yüklenirken hatalar oluşuyordu. Çeviri artık başarısız başlıklar için geri dönüşler kullanıyor. Lütfen bunu geliştiricilere bildirin!\n\nBaşarısız anahtarlar: {0}",
|
||||
"F_UI_EFTVersionError": "Raid host'un çalıştırdığından farklı bir EFT sürümü kullanmaya çalışıyorsunuz.\nİstemci: {0}\nHost: {1}",
|
||||
"F_UI_FikaVersionError": "Raid ana bilgisayarının çalıştırdığından farklı bir Fika sürümü kullanmaya çalışıyorsunuz.\nİstemci crc: {0}\nhost crc: {1}",
|
||||
"F_UI_PlayerConnected": "{0} bağlandı",
|
||||
"F_UI_PlayerDisconnected": "{0} bağlantısı kesildi",
|
||||
"F_UI_DisabledByServerHost": "Sunucu ana bilgisayarı tarafından devre dışı bırakıldı"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
$Version = "1.1"
|
||||
$ProfileId = "${profileId}"
|
||||
$BackendUrl = "${backendUrl}"
|
||||
$WaitTime = 2
|
||||
|
||||
$Host.UI.RawUI.WindowTitle = "Fika Headless Watcher v$Version"
|
||||
|
||||
Write-Host "Fika Headless Watcher v$Version"
|
||||
Write-Host
|
||||
Write-Host "Profile Id: $ProfileId"
|
||||
Write-Host "Backend Url: $BackendUrl"
|
||||
Write-Host
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\EscapeFromTarkov.exe")) {
|
||||
Write-Host "Could not find 'EscapeFromTarkov.exe'. Please move this launch script into the root directory of your headless client SPT install." -ForegroundColor Red
|
||||
Write-Host "Press [ENTER] or close this window to exit..."
|
||||
Read-Host
|
||||
exit
|
||||
}
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\BepInEx\plugins\Fika.Headless.dll")) {
|
||||
Write-Host "Could not find 'Fika.Headless.dll'. Please install the Headless plugin before launching this script." -ForegroundColor Red
|
||||
Write-Host "Press [ENTER] or close this window to exit..."
|
||||
Read-Host
|
||||
exit
|
||||
}
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\BepInEx\plugins\Fika.Core.dll")) {
|
||||
Write-Host "Could not find 'Fika.Core.dll'. If you have not made a copy of a working SPT+Fika install, please start over from the first step of the instructions on the wiki. If you have mistakenly deleted Fika.Core.dll, please reinstall it." -ForegroundColor Red
|
||||
Write-Host "Press [ENTER] or close this window to exit..."
|
||||
Read-Host
|
||||
exit
|
||||
}
|
||||
|
||||
$graphicsMode = $false
|
||||
|
||||
for ($i = 0; $i -lt $WaitTime; $i++) {
|
||||
$countDown = $WaitTime - $i
|
||||
|
||||
Write-Progress -Activity "Starting headless in $countDown... press G to start the headless in graphics mode." -PercentComplete ((100/$WaitTime)*($i+1))
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
if ([Console]::KeyAvailable) {
|
||||
$key = [Console]::ReadKey($true).Key
|
||||
|
||||
if ($key -eq "G") {
|
||||
$graphicsMode = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Progress -Activity "Starting headless in..." -Completed
|
||||
|
||||
if ($graphicsMode) {
|
||||
Write-Host "Starting in graphics mode..."
|
||||
Start-Process "$PSScriptRoot\EscapeFromTarkov.exe" -WorkingDirectory $PSScriptRoot -ArgumentList "-token=$ProfileId", "-config={'BackendUrl':'$BackendUrl','Version':'live'}", "--enable-console true" -Wait
|
||||
exit
|
||||
}
|
||||
|
||||
Write-Host "[INFO]" -ForegroundColor Blue
|
||||
Write-Host " - This script will restart the headless client console if it crashes or closes"
|
||||
Write-Host " - To force the headless client to restart after X number of raids, change 'restartAfterAmountOfRaids' in the server mod configuration"
|
||||
Write-Host
|
||||
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Starting headless client"
|
||||
|
||||
while ($true) {
|
||||
Start-Process "$PSScriptRoot\EscapeFromTarkov.exe" -WorkingDirectory $PSScriptRoot -ArgumentList "-token=$ProfileId", "-config={'BackendUrl':'$BackendUrl','Version':'live'}", "-batchmode", "-nographics", "--enable-console true" -Wait
|
||||
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Headless client closed, restarting"
|
||||
}
|
||||
@@ -1,24 +1,27 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "2.3.6",
|
||||
"sptVersion": "~3.10",
|
||||
"version": "2.4.8",
|
||||
"sptVersion": "~3.11",
|
||||
"main": "src/mod.js",
|
||||
"scripts": {
|
||||
"setup": "npm i",
|
||||
"lint": "npx @biomejs/biome lint ./",
|
||||
"check-types": "npx tsc -noEmit -p tsconfig.types.json",
|
||||
"check-circular": "madge --circular --ts-config tsconfig.json --extensions ts ./src/",
|
||||
"build": "node ./build.mjs",
|
||||
"buildinfo": "node ./build.mjs --verbose"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.7.1",
|
||||
"@types/node": "~20.11",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
"@types/node": "22.10.5",
|
||||
"@types/ws": "~8.5",
|
||||
"archiver": "^6.0",
|
||||
"fs-extra": "~11.2",
|
||||
"ignore": "^5.2",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
"tsyringe": "~4.8",
|
||||
"typescript": "5.7.3",
|
||||
"winston": "~3.13",
|
||||
"madge": "8.0.0"
|
||||
},
|
||||
"author": "Fika",
|
||||
"license": "CC-BY-NC-SA-4.0"
|
||||
|
||||
@@ -6,12 +6,21 @@ import { ImageRouter } from "@spt/routers/ImageRouter";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { ImporterUtil } from "@spt/utils/ImporterUtil";
|
||||
|
||||
import { watch } from "node:fs";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { FileSystem } from "@spt/utils/FileSystem";
|
||||
import { JsonUtil } from "@spt/utils/JsonUtil";
|
||||
import { IFikaConfig } from "./models/fika/config/IFikaConfig";
|
||||
import { IFikaConfigBackground } from "./models/fika/config/IFikaConfigBackground";
|
||||
import { IFikaConfigDedicated } from "./models/fika/config/IFikaConfigDedicated";
|
||||
import { IFikaConfigHeadless } from "./models/fika/config/IFikaConfigHeadless";
|
||||
import { IFikaConfigNatPunchServer } from "./models/fika/config/IFikaConfigNatPunchServer";
|
||||
import { Overrider } from "./overrides/Overrider";
|
||||
import { FikaClientService } from "./services/FikaClientService";
|
||||
import { FikaPlayerRelationsCacheService } from "./services/cache/FikaPlayerRelationsCacheService";
|
||||
import { FikaDedicatedProfileService } from "./services/dedicated/FikaDedicatedProfileService";
|
||||
import { FikaHeadlessProfileService } from "./services/headless/FikaHeadlessProfileService";
|
||||
import { FikaConfig } from "./utils/FikaConfig";
|
||||
import { FikaServerTools } from "./utils/FikaServerTools";
|
||||
|
||||
@@ -19,26 +28,35 @@ import { FikaServerTools } from "./utils/FikaServerTools";
|
||||
export class Fika {
|
||||
protected modPath: string;
|
||||
protected natPunchServerConfig: IFikaConfigNatPunchServer;
|
||||
protected dedicatedConfig: IFikaConfigDedicated;
|
||||
protected headlessConfig: IFikaConfigHeadless;
|
||||
protected backgroundConfig: IFikaConfigBackground;
|
||||
|
||||
constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("Overrider") protected overrider: Overrider,
|
||||
@inject("FikaServerTools") protected fikaServerTools: FikaServerTools,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("FikaDedicatedProfileService") protected fikaDedicatedProfileService: FikaDedicatedProfileService,
|
||||
@inject("FikaClientService") protected fikaClientService: FikaClientService,
|
||||
@inject("FikaHeadlessProfileService") protected fikaHeadlessProfileService: FikaHeadlessProfileService,
|
||||
@inject("ImageRouter") protected imageRouter: ImageRouter,
|
||||
@inject("ImporterUtil") protected importerUtil: ImporterUtil,
|
||||
@inject("FikaPlayerRelationsCacheService") protected fikaPlayerRelationCacheServce: FikaPlayerRelationsCacheService
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("FileSystem") protected fileSystem: FileSystem,
|
||||
@inject("FikaPlayerRelationsCacheService") protected fikaPlayerRelationCacheServce: FikaPlayerRelationsCacheService,
|
||||
) {
|
||||
this.modPath = fikaConfig.getModPath();
|
||||
this.natPunchServerConfig = fikaConfig.getConfig().natPunchServer;
|
||||
this.dedicatedConfig = fikaConfig.getConfig().dedicated;
|
||||
this.backgroundConfig = fikaConfig.getConfig().background;
|
||||
}
|
||||
|
||||
public async preSptLoad(container: DependencyContainer): Promise<void> {
|
||||
await this.fikaConfig.preInit();
|
||||
|
||||
this.natPunchServerConfig = this.fikaConfig.getConfig().natPunchServer;
|
||||
this.headlessConfig = this.fikaConfig.getConfig().headless;
|
||||
this.backgroundConfig = this.fikaConfig.getConfig().background;
|
||||
|
||||
await this.fikaClientService.preInit();
|
||||
await this.overrider.override(container);
|
||||
}
|
||||
|
||||
@@ -47,24 +65,27 @@ export class Fika {
|
||||
this.fikaServerTools.startService("NatPunchServer");
|
||||
}
|
||||
|
||||
if (this.dedicatedConfig.profiles.amount > 0) {
|
||||
this.fikaDedicatedProfileService.init();
|
||||
if (this.headlessConfig.profiles.amount > 0) {
|
||||
await this.fikaHeadlessProfileService.init();
|
||||
}
|
||||
|
||||
this.addFikaClientLocales();
|
||||
await this.addFikaClientLocales();
|
||||
this.blacklistSpecialProfiles();
|
||||
this.fikaPlayerRelationCacheServce.postInit();
|
||||
|
||||
if (this.backgroundConfig.enable) {
|
||||
const image = this.backgroundConfig.easteregg ? "assets/images/launcher/bg-senko.png" : "assets/images/launcher/bg.png";
|
||||
this.imageRouter.addRoute("/files/launcher/bg", path.join(this.modPath, image));
|
||||
}
|
||||
|
||||
this.watchFikaConfig();
|
||||
}
|
||||
|
||||
private async addFikaClientLocales() {
|
||||
const database = this.databaseServer.getTables();
|
||||
const databasePath = path.join(this.fikaConfig.getModPath(), "assets/database/");
|
||||
const databasePath = path.join(this.fikaConfig.getModPath(), "assets/database/").replace(/\\/g, "/");
|
||||
|
||||
const locales = await this.importerUtil.loadAsync<ILocaleBase>(path.join(databasePath, "locales/"), databasePath);
|
||||
const locales = await this.importerUtil.loadAsync<ILocaleBase>(`${databasePath}locales/`, databasePath);
|
||||
|
||||
for (const folderName in locales) {
|
||||
if (folderName === "global") {
|
||||
@@ -75,4 +96,95 @@ export class Fika {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async blacklistSpecialProfiles() {
|
||||
const coreConfig: ICoreConfig = this.configServer.getConfig(ConfigTypes.CORE);
|
||||
const profileBlacklist = coreConfig.features.createNewProfileTypesBlacklist;
|
||||
|
||||
if (!this.fikaConfig.getConfig().server.showDevProfile) {
|
||||
profileBlacklist.push("SPT Developer");
|
||||
}
|
||||
|
||||
if (!this.fikaConfig.getConfig().server.showNonStandardProfile) {
|
||||
for (const id of ["Tournament", "SPT Easy start", "SPT Zero to hero"]) {
|
||||
profileBlacklist.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private watchFikaConfig(): void {
|
||||
const configPath = path.join(this.modPath, "assets/configs/fika.jsonc");
|
||||
let fileChangeTimeout = null;
|
||||
|
||||
// At the moment this doesn't reload:
|
||||
// Nat punch server (Requires additional setup)
|
||||
// SPT Http configuration (Can't be changed once initialized)
|
||||
// Backgrounds on the launcher (cached?)
|
||||
// Any client options if a client is already in-game, client will have to restart his game.
|
||||
watch(configPath, async (eventType, _filename) => {
|
||||
if (eventType === "change") {
|
||||
if (fileChangeTimeout) {
|
||||
clearTimeout(fileChangeTimeout);
|
||||
}
|
||||
|
||||
// Timeout is required here, sometimes Windows will send three events if a file has changed.
|
||||
fileChangeTimeout = setTimeout(async () => {
|
||||
let config = this.jsonUtil.deserializeJsonC<IFikaConfig>(await this.fileSystem.read(configPath));
|
||||
|
||||
if (!config) {
|
||||
this.logger.error("[Fika Server] could not hot-reload configuration, is the syntax correct?");
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHeadlessAmount = this.fikaConfig.getConfig().headless.profiles.amount;
|
||||
|
||||
if (this.fikaConfig.updateFikaConfig(config)) {
|
||||
// Re-initialize new headless profiles if the number changed.
|
||||
if (this.fikaConfig.getConfig().headless.profiles.amount > oldHeadlessAmount) {
|
||||
await this.fikaHeadlessProfileService.init();
|
||||
}
|
||||
|
||||
// Re-initialize required & optional mods
|
||||
await this.fikaClientService.preInit();
|
||||
|
||||
// Re-initialize background
|
||||
if (this.backgroundConfig.enable) {
|
||||
const image = this.backgroundConfig.easteregg ? "assets/images/launcher/bg-senko.png" : "assets/images/launcher/bg.png";
|
||||
this.imageRouter.addRoute("/files/launcher/bg", path.join(this.modPath, image));
|
||||
}
|
||||
|
||||
// Re-initialize profile preset blacklist
|
||||
const coreConfig: ICoreConfig = this.configServer.getConfig(ConfigTypes.CORE);
|
||||
|
||||
// Re-initialize showing of dev profile
|
||||
if (this.fikaConfig.getConfig().server.showDevProfile) {
|
||||
// Remove the blacklisted developer template
|
||||
coreConfig.features.createNewProfileTypesBlacklist = coreConfig.features.createNewProfileTypesBlacklist.filter((item) => item !== "SPT Developer");
|
||||
} else {
|
||||
// Re-add the blacklisted developer template
|
||||
if (!coreConfig.features.createNewProfileTypesBlacklist.includes("SPT Developer")) {
|
||||
coreConfig.features.createNewProfileTypesBlacklist.push("SPT Developer");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fikaConfig.getConfig().server.showNonStandardProfile) {
|
||||
for (const id of ["Tournament", "SPT Easy start", "SPT Zero to hero"]) {
|
||||
// Remove each blacklisted template
|
||||
coreConfig.features.createNewProfileTypesBlacklist = coreConfig.features.createNewProfileTypesBlacklist.filter((item) => item !== id);
|
||||
}
|
||||
} else {
|
||||
for (const id of ["Tournament", "SPT Easy start", "SPT Zero to hero"]) {
|
||||
// Re-add the blacklisted templates
|
||||
if (!coreConfig.features.createNewProfileTypesBlacklist.includes(id)) {
|
||||
coreConfig.features.createNewProfileTypesBlacklist.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.info("[Fika Server] Configuration hot-reloaded successfully");
|
||||
}
|
||||
}, 750);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ export class FikaClientCallbacks {
|
||||
return this.httpResponseUtil.noBody(this.fikaClientController.handleClientConfig());
|
||||
}
|
||||
|
||||
/** Handle /fika/client/config */
|
||||
/** Handle /fika/natpunchserver/config */
|
||||
public handleNatPunchServerConfig(_url: string, _info: IFikaRaidServerIdRequestData, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaClientController.handleNatPunchServerConfig());
|
||||
}
|
||||
|
||||
/** Handle /fika/client/check/mods */
|
||||
public handleCheckMods(_url: string, info: IFikaCheckModRequestData, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaClientController.handleCheckMods(info));
|
||||
public handleCheckMods(_url: string, info: IFikaCheckModRequestData, sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaClientController.handleCheckMods(info, sessionID));
|
||||
}
|
||||
|
||||
/** Handle /fika/profile/download */
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
|
||||
import { IQuest } from "@spt/models/eft/common/tables/IQuest";
|
||||
import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData";
|
||||
import { FikaHeadlessController } from "../controllers/FikaHeadlessController";
|
||||
import { IFikaRaidServerIdRequestData } from "../models/fika/routes/raid/IFikaRaidServerIdRequestData";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessCallbacks {
|
||||
constructor(
|
||||
@inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil,
|
||||
@inject("FikaHeadlessController") protected fikaHeadlessController: FikaHeadlessController,
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/** Handle /fika/headless/get */
|
||||
public handleGetHeadlesses(_url: string, _info: IFikaRaidServerIdRequestData, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaHeadlessController.handleGetHeadlesses());
|
||||
}
|
||||
|
||||
/** Handle /fika/headless/available */
|
||||
public handleAvailableHeadlesses(_url: string, _info: IFikaRaidServerIdRequestData, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaHeadlessController.handleGetAvailableHeadlesses());
|
||||
}
|
||||
|
||||
/** Handle /fika/headless/restartafterraidamount */
|
||||
public handleRestartAfterRaidAmount(_url: string, _info: IFikaRaidServerIdRequestData, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaHeadlessController.handleRestartAfterRaidAmount());
|
||||
}
|
||||
|
||||
/** Handle /fika/headless/questtemplates */
|
||||
public handleGetAllQuestTemplates(_url: string, _info: any, _sessionID: string): IGetBodyResponseData<IQuest[]> {
|
||||
return this.httpResponseUtil.getBody(this.fikaHeadlessController.handleGetAllQuestTemplates());
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
|
||||
import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData";
|
||||
import { EEFTNotificationIconType } from "../models/enums/EEFTNotificationIconType";
|
||||
import { EFikaNotifications } from "../models/enums/EFikaNotifications";
|
||||
import { IPushNotification } from "../models/fika/websocket/notifications/IPushNotification";
|
||||
import { FikaNotificationWebSocket } from "../websockets/FikaNotificationWebSocket";
|
||||
import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData";
|
||||
import { EFikaNotifications } from "../models/enums/EFikaNotifications";
|
||||
import { EEFTNotificationIconType } from "../models/enums/EEFTNotificationIconType";
|
||||
|
||||
@injectable()
|
||||
export class FikaNotificationCallbacks {
|
||||
@@ -18,7 +18,7 @@ export class FikaNotificationCallbacks {
|
||||
}
|
||||
|
||||
/** Handle /fika/notification/push */
|
||||
public handlePushNotification(_url: string, info: IPushNotification, _sessionID: string): INullResponseData {
|
||||
public async handlePushNotification(_url: string, info: IPushNotification, _sessionID: string): Promise<INullResponseData> {
|
||||
// Yes, technically this needs a controller to fit into this format. But I cant be bothered setting up a whole controller for a few checks.
|
||||
if (!info.notification) {
|
||||
return this.httpResponseUtil.nullResponse();
|
||||
@@ -36,7 +36,7 @@ export class FikaNotificationCallbacks {
|
||||
info.notificationIcon = EEFTNotificationIconType.Default;
|
||||
}
|
||||
|
||||
this.fikaNotificationWebSocket.broadcast(info);
|
||||
await this.fikaNotificationWebSocket.broadcast(info);
|
||||
|
||||
return this.httpResponseUtil.nullResponse();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
import { FikaRaidController } from "../controllers/FikaRaidController";
|
||||
import { IFikaRaidServerIdRequestData } from "../models/fika/routes/raid/IFikaRaidServerIdRequestData";
|
||||
import { IFikaRaidCreateRequestData } from "../models/fika/routes/raid/create/IFikaRaidCreateRequestData";
|
||||
import { IStartDedicatedRequest } from "../models/fika/routes/raid/dedicated/IStartDedicatedRequest";
|
||||
import { IStatusDedicatedRequest } from "../models/fika/routes/raid/dedicated/IStatusDedicatedRequest";
|
||||
import { IStartHeadlessRequest } from "../models/fika/routes/raid/headless/IStartHeadlessRequest";
|
||||
import { IFikaRaidJoinRequestData } from "../models/fika/routes/raid/join/IFikaRaidJoinRequestData";
|
||||
import { IFikaRaidLeaveRequestData } from "../models/fika/routes/raid/leave/IFikaRaidLeaveRequestData";
|
||||
|
||||
@@ -48,22 +47,12 @@ export class FikaRaidCallbacks {
|
||||
return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidGetSettings(info));
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/start */
|
||||
public handleRaidStartDedicated(_url: string, info: IStartDedicatedRequest, sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidStartDedicated(sessionID, info));
|
||||
/** Handle /fika/raid/headless/start */
|
||||
public async handleRaidStartHeadless(_url: string, info: IStartHeadlessRequest, sessionID: string): Promise<string> {
|
||||
return this.httpResponseUtil.noBody(await this.fikaRaidController.handleRaidStartHeadless(sessionID, info));
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/status */
|
||||
public handleRaidStatusDedicated(_url: string, info: IStatusDedicatedRequest, sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidStatusDedicated(sessionID, info));
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/getstatus */
|
||||
public handleRaidGetStatusDedicated(_url: string, _info: any, _sessionID: string): string {
|
||||
return this.httpResponseUtil.noBody(this.fikaRaidController.handleRaidGetStatusDedicated());
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/registerPlayer */
|
||||
/** Handle /fika/raid/registerPlayer */
|
||||
public handleRaidRegisterPlayer(_url: string, info: IRegisterPlayerRequestData, sessionID: string): INullResponseData {
|
||||
this.fikaRaidController.handleRaidRegisterPlayer(sessionID, info);
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ export class FikaSendItemCallbacks {
|
||||
// empty
|
||||
}
|
||||
|
||||
public handleSendItem(pmcData: IPmcData, body: IFikaSendItemRequestData, sessionID: string): IItemEventRouterResponse {
|
||||
return this.fikaSendItemController.sendItem(pmcData, body, sessionID);
|
||||
public async handleSendItem(pmcData: IPmcData, body: IFikaSendItemRequestData, sessionID: string): Promise<IItemEventRouterResponse> {
|
||||
return await this.fikaSendItemController.sendItem(pmcData, body, sessionID);
|
||||
}
|
||||
|
||||
/** Handle /fika/senditem/availablereceivers */
|
||||
|
||||
@@ -4,6 +4,7 @@ import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseDat
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
|
||||
import { FikaUpdateController } from "../controllers/FikaUpdateController";
|
||||
import { EFikaMatchStatus } from "../models/enums/EFikaMatchStatus";
|
||||
import { IFikaUpdateRaidAddPlayerData } from "../models/fika/routes/raid/join/IFikaRaidAddPlayerData";
|
||||
import { IFikaUpdatePingRequestData } from "../models/fika/routes/update/IFikaUpdatePingRequestData";
|
||||
import { IFikaUpdatePlayerspawnRequestData } from "../models/fika/routes/update/IFikaUpdatePlayerspawnRequestData";
|
||||
@@ -41,8 +42,13 @@ export class FikaUpdateCallbacks {
|
||||
}
|
||||
|
||||
/** Handle /fika/update/setstatus */
|
||||
public handleSetStatus(_url: string, info: IFikaUpdateSetStatusRequestData, _sessionID: string): INullResponseData {
|
||||
this.fikaUpdateController.handleSetStatus(info);
|
||||
public async handleSetStatus(_url: string, info: IFikaUpdateSetStatusRequestData, _sessionID: string): Promise<INullResponseData> {
|
||||
// Handle conversion of Enum so it can be properly used.
|
||||
if (Object.keys(EFikaMatchStatus).includes(info.status.toString())) {
|
||||
info.status = EFikaMatchStatus[info.status.toString()];
|
||||
}
|
||||
|
||||
await this.fikaUpdateController.handleSetStatus(info);
|
||||
|
||||
return this.httpResponseUtil.nullResponse();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export class FikaAchievementController {
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
getAchievementStatistics(_sessionID: string): ICompletedAchievementsResponse {
|
||||
public getAchievementStatistics(_sessionID: string): ICompletedAchievementsResponse {
|
||||
const achievements = this.databaseService.getAchievements();
|
||||
const stats: Record<string, number> = {};
|
||||
|
||||
@@ -21,7 +21,7 @@ export class FikaAchievementController {
|
||||
for (const achievement of achievements) {
|
||||
let percentage = 0;
|
||||
for (const profile of profiles) {
|
||||
if (profile.info?.password === "fika-dedicated") {
|
||||
if (profile.info?.password === "fika-headless") {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,125 +2,63 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IFikaConfigClient } from "../models/fika/config/IFikaConfigClient";
|
||||
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
|
||||
import { FikaClientModHashesHelper } from "../helpers/FikaClientModHashesHelper";
|
||||
import { IFikaConfigHeadless } from "../models/fika/config/IFikaConfigHeadless";
|
||||
import { IFikaConfigNatPunchServer } from "../models/fika/config/IFikaConfigNatPunchServer";
|
||||
import { IFikaCheckModRequestData } from "../models/fika/routes/client/check/IFikaCheckModRequestData";
|
||||
import { IFikaCheckModResponse, IVersionCheckResponse } from "../models/fika/routes/client/check/IFikaCheckModResponse";
|
||||
import { FikaClientService } from "../services/FikaClientService";
|
||||
import { FikaConfig } from "../utils/FikaConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaClientController {
|
||||
protected requiredMods: Set<string>;
|
||||
protected allowedMods: Set<string>;
|
||||
protected requiredMods: string[] = [];
|
||||
protected allowedMods: string[] = [];
|
||||
protected hasRequiredOrOptionalMods: boolean = true;
|
||||
|
||||
constructor(
|
||||
@inject("FikaClientModHashesHelper") protected fikaClientModHashesHelper: FikaClientModHashesHelper,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
const config = this.fikaConfig.getConfig();
|
||||
|
||||
const sanitizedRequiredMods = this.filterEmptyMods(config.client.mods.required);
|
||||
const sanitizedOptionalMods = this.filterEmptyMods(config.client.mods.optional);
|
||||
|
||||
if (sanitizedRequiredMods.length === 0 && sanitizedOptionalMods.length === 0) {
|
||||
this.hasRequiredOrOptionalMods = false;
|
||||
}
|
||||
|
||||
this.requiredMods = new Set([...sanitizedRequiredMods, "com.fika.core", "com.SPT.custom", "com.SPT.singleplayer", "com.SPT.core", "com.SPT.debugging"]);
|
||||
this.allowedMods = new Set([...this.requiredMods, ...sanitizedOptionalMods, "com.bepis.bepinex.configurationmanager", "com.fika.dedicated"]);
|
||||
}
|
||||
|
||||
protected filterEmptyMods(array: string[]): string[] {
|
||||
return array.filter((str) => str.trim() !== "");
|
||||
}
|
||||
|
||||
constructor(@inject("FikaClientService") protected fikaClientService: FikaClientService) {}
|
||||
/**
|
||||
* Handle /fika/client/config
|
||||
*/
|
||||
public handleClientConfig(): IFikaConfigClient {
|
||||
return this.fikaConfig.getConfig().client;
|
||||
const clientConfig = this.fikaClientService.getClientConfig();
|
||||
|
||||
//Here be dragons, this is technically not in the client config, or well it was.. But it was decided it was better for this configuration
|
||||
//To be together with 'sentItemsLoseFIR' so users could find both options easier.
|
||||
//Keep this here as this is really only supposed to be a 'client' config and it's really only used on the client.
|
||||
(clientConfig as any).allowItemSending = this.fikaClientService.getIsItemSendingAllowed();
|
||||
|
||||
return clientConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/natpunchserver/config
|
||||
*/
|
||||
public handleNatPunchServerConfig(): IFikaConfigNatPunchServer {
|
||||
return this.fikaConfig.getConfig().natPunchServer;
|
||||
return this.fikaClientService.getNatPunchServerConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/client/check/mods
|
||||
*/
|
||||
public handleCheckMods(request: IFikaCheckModRequestData): IFikaCheckModResponse {
|
||||
const mismatchedMods: IFikaCheckModResponse = {
|
||||
forbidden: [],
|
||||
missingRequired: [],
|
||||
hashMismatch: [],
|
||||
};
|
||||
|
||||
// if no configuration was made, allow all mods
|
||||
if (!this.hasRequiredOrOptionalMods) {
|
||||
return mismatchedMods;
|
||||
}
|
||||
|
||||
//check for missing required mods first
|
||||
for (const pluginId of this.requiredMods) {
|
||||
if (!request[pluginId]) {
|
||||
mismatchedMods.missingRequired.push(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
// no need to check anything else since it's missing required mods
|
||||
if (mismatchedMods.missingRequired.length > 0) {
|
||||
return mismatchedMods;
|
||||
}
|
||||
|
||||
for (const [pluginId, hash] of Object.entries(request)) {
|
||||
// check if the mod isn't allowed
|
||||
if (!this.allowedMods.has(pluginId)) {
|
||||
mismatchedMods.forbidden.push(pluginId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// first request made will fill in at the very least all the required mods hashes, following requests made by different clients will add any optional mod not added by the first request, otherwise will check against the first request data
|
||||
if (!this.fikaClientModHashesHelper.exists(pluginId)) {
|
||||
this.fikaClientModHashesHelper.addHash(pluginId, hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.fikaClientModHashesHelper.getHash(pluginId) !== hash) {
|
||||
mismatchedMods.hashMismatch.push(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
return mismatchedMods;
|
||||
public handleCheckMods(request: IFikaCheckModRequestData, sessionID: string): IFikaCheckModResponse {
|
||||
return this.fikaClientService.getCheckModsResponse(request, sessionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/profile/download
|
||||
*/
|
||||
public handleProfileDownload(sessionID: string): any {
|
||||
const profile = this.saveServer.getProfile(sessionID);
|
||||
if (profile) {
|
||||
this.logger.info(`${sessionID} has downloaded their profile`);
|
||||
return profile;
|
||||
}
|
||||
|
||||
this.logger.error(`${sessionID} wants to download their profile but we don't have it`);
|
||||
return null;
|
||||
return this.fikaClientService.getProfileBySessionID(sessionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/client/check/version
|
||||
*/
|
||||
public handleVersionCheck(): IVersionCheckResponse {
|
||||
const version = this.fikaConfig.getVersion();
|
||||
return { version };
|
||||
return this.fikaClientService.getVersion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { inject, injectAll, injectable } from "tsyringe";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot";
|
||||
import { DialogueHelper } from "@spt/helpers/DialogueHelper";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { IFriendRequestSendResponse } from "@spt/models/eft/dialog/IFriendRequestSendResponse";
|
||||
import { IGetFriendListDataResponse } from "@spt/models/eft/dialog/IGetFriendListDataResponse";
|
||||
import { BackendErrorCodes } from "@spt/models/enums/BackendErrorCodes";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
|
||||
import { DialogueController } from "@spt/controllers/DialogueController";
|
||||
import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest";
|
||||
import { IMessage } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { IMessage, IReplyTo } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { MessageType } from "@spt/models/enums/MessageType";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler";
|
||||
@@ -25,22 +25,21 @@ import { IFriendRequestListResponse } from "../models/eft/dialog/IFriendRequestL
|
||||
export class FikaDialogueController {
|
||||
constructor(
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("DialogueHelper") protected dialogueHelper: DialogueHelper,
|
||||
@inject("FikaFriendRequestsHelper") protected fikaFriendRequestsHelper: FikaFriendRequestsHelper,
|
||||
@inject("FikaPlayerRelationsHelper") protected fikaPlayerRelationsHelper: FikaPlayerRelationsHelper,
|
||||
@inject("DialogueController") protected dialogController: DialogueController,
|
||||
@inject("DialogueController") protected dialogueController: DialogueController,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("SptWebSocketConnectionHandler") protected webSocketHandler: SptWebSocketConnectionHandler,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
|
||||
public getFriendList(sessionID: string): IGetFriendListDataResponse {
|
||||
// Cast to any to get rid of protected error
|
||||
const dialogueChatBots: IDialogueChatBot[] = (this.dialogController as any).dialogueChatBots;
|
||||
let botsAndFriends = dialogueChatBots.map((v) => v.getChatBot());
|
||||
let botsAndFriends = (this.dialogueController as any).getActiveChatBots();
|
||||
|
||||
const friendsIds = this.fikaPlayerRelationsHelper.getFriendsList(sessionID);
|
||||
|
||||
@@ -76,7 +75,7 @@ export class FikaDialogueController {
|
||||
const profiles = this.saveServer.getProfiles();
|
||||
if (!(sessionID in profiles) || !(request.dialogId in profiles)) {
|
||||
// if it's not to another player let SPT handle it
|
||||
return DialogueController.prototype.sendMessage.call(this.dialogController, sessionID, request);
|
||||
return DialogueController.prototype.sendMessage.call(this.dialogueController, sessionID, request);
|
||||
}
|
||||
|
||||
const receiverProfile = profiles[request.dialogId];
|
||||
@@ -175,10 +174,17 @@ export class FikaDialogueController {
|
||||
rewardCollected: false,
|
||||
};
|
||||
|
||||
if (request.replyTo) {
|
||||
const replyMessage = this.getMessageToReplyTo(request.dialogId, request.replyTo, sessionID);
|
||||
if (replyMessage) {
|
||||
message.replyTo = replyMessage;
|
||||
}
|
||||
}
|
||||
|
||||
senderDialog.messages.push(message);
|
||||
receiverDialog.messages.push(message);
|
||||
|
||||
this.webSocketHandler.sendMessage(receiverProfile.info.id, {
|
||||
this.webSocketHandler.sendMessageAsync(receiverProfile.info.id, {
|
||||
type: "new_message",
|
||||
eventId: "new_message",
|
||||
EventId: "new_message",
|
||||
@@ -189,6 +195,37 @@ export class FikaDialogueController {
|
||||
return message._id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param recipientId The id of the recipient
|
||||
* @param replyToId The id of the message to reply to
|
||||
* @param dialogueId The id of the dialogue (traderId or profileId)
|
||||
* @returns A new instance with data from the found message, otherwise undefined
|
||||
*/
|
||||
private getMessageToReplyTo(recipientId: string, replyToId: string, dialogueId: string): IReplyTo | undefined {
|
||||
let message: IReplyTo | undefined = undefined;
|
||||
const currentDialogue = this.dialogueHelper.getDialogueFromProfile(recipientId, dialogueId);
|
||||
|
||||
if (!currentDialogue) {
|
||||
this.logger.warning(`Could not find dialogue ${dialogueId} from sender`);
|
||||
return message;
|
||||
}
|
||||
|
||||
for (const dialogueMessage of currentDialogue.messages) {
|
||||
if (dialogueMessage._id === replyToId) {
|
||||
message = {
|
||||
_id: dialogueMessage._id,
|
||||
dt: dialogueMessage.dt,
|
||||
type: dialogueMessage.type,
|
||||
uid: dialogueMessage.uid,
|
||||
text: dialogueMessage.text,
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public listOutbox(sessionID: string): IFriendRequestListResponse[] {
|
||||
const sentFriendRequests = this.fikaFriendRequestsHelper.getSentFriendRequests(sessionID) as IFriendRequestListResponse[];
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { QuestHelper } from "@spt/helpers/QuestHelper";
|
||||
import { IQuest } from "@spt/models/eft/common/tables/IQuest";
|
||||
import { QuestStatus } from "@spt/models/enums/QuestStatus";
|
||||
import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper";
|
||||
import { IHeadlessAvailableClients } from "../models/fika/headless/IHeadlessAvailableClients";
|
||||
import { IHeadlessClients } from "../models/fika/headless/IHeadlessClients";
|
||||
import { IHeadlessRestartAfterAmountOfRaids } from "../models/fika/headless/IHeadlessRestartAfterAmountOfRaids";
|
||||
import { FikaConfig } from "../utils/FikaConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessController {
|
||||
constructor(
|
||||
@inject("FikaHeadlessHelper") protected fikaHeadlessHelper: FikaHeadlessHelper,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("QuestHelper") protected questHelper: QuestHelper,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Handle /fika/headless/get
|
||||
*/
|
||||
public handleGetHeadlesses(): IHeadlessClients {
|
||||
const data: IHeadlessClients = {
|
||||
headlesses: {},
|
||||
};
|
||||
|
||||
for (const [headlessSessionID, headless] of this.fikaHeadlessHelper.getHeadlessClients()) {
|
||||
data.headlesses[headlessSessionID] = {
|
||||
state: headless.state,
|
||||
players: headless.players,
|
||||
requesterSessionID: headless.requesterSessionID,
|
||||
hasNotifiedRequester: headless.hasNotifiedRequester,
|
||||
};
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/headless/available
|
||||
*/
|
||||
public handleGetAvailableHeadlesses(): IHeadlessAvailableClients[] {
|
||||
return this.fikaHeadlessHelper.getAvailableHeadlessClients();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/headless/restartafterraidamount
|
||||
*/
|
||||
public handleRestartAfterRaidAmount(): IHeadlessRestartAfterAmountOfRaids {
|
||||
const data: IHeadlessRestartAfterAmountOfRaids = {
|
||||
amount: this.fikaConfig.getConfig().headless.restartAfterAmountOfRaids,
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/headless/questtemplates
|
||||
*/
|
||||
public handleGetAllQuestTemplates(): IQuest[] {
|
||||
const quests = this.questHelper.getQuestsFromDb();
|
||||
|
||||
for (const quest of quests) {
|
||||
quest.sptStatus = QuestStatus.AvailableForStart;
|
||||
}
|
||||
|
||||
return quests;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,16 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IGetRaidConfigurationRequestData } from "@spt/models/eft/match/IGetRaidConfigurationRequestData";
|
||||
|
||||
import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper";
|
||||
import { IFikaRaidsResponse } from "../models/fika/routes/location/IFikaRaidsResponse";
|
||||
import { FikaMatchService } from "../services/FikaMatchService";
|
||||
|
||||
@injectable()
|
||||
export class FikaLocationController {
|
||||
constructor(@inject("FikaMatchService") protected fikaMatchService: FikaMatchService) {
|
||||
constructor(
|
||||
@inject("FikaMatchService") protected fikaMatchService: FikaMatchService,
|
||||
@inject("FikaHeadlessHelper") protected fikaHeadlessHelper: FikaHeadlessHelper,
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -25,15 +29,23 @@ export class FikaLocationController {
|
||||
players[profileId] = player.isDead;
|
||||
}
|
||||
|
||||
let hostUsername = match.hostUsername;
|
||||
|
||||
if (match.isHeadless) {
|
||||
hostUsername = this.fikaHeadlessHelper.getHeadlessNickname(matchId);
|
||||
}
|
||||
|
||||
matches.push({
|
||||
serverId: matchId,
|
||||
hostUsername: match.hostUsername,
|
||||
hostUsername: hostUsername,
|
||||
playerCount: match.players.size,
|
||||
status: match.status,
|
||||
location: match.raidConfig.location,
|
||||
side: match.side,
|
||||
time: match.time,
|
||||
players: players,
|
||||
isHeadless: match.isHeadless,
|
||||
headlessRequesterNickname: this.fikaHeadlessHelper.getRequesterUsername(matchId) || "", //Set this to an empty string if there is no requester.
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,36 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { WebSocket } from "ws";
|
||||
|
||||
import { InraidController } from "@spt/controllers/InraidController";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
import { IRegisterPlayerRequestData } from "@spt/models/eft/inRaid/IRegisterPlayerRequestData";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
|
||||
import { EDedicatedStatus } from "../models/enums/EDedicatedStatus";
|
||||
import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper";
|
||||
import { EFikaMatchEndSessionMessage } from "../models/enums/EFikaMatchEndSessionMessages";
|
||||
import { EFikaNotifications } from "../models/enums/EFikaNotifications";
|
||||
import { IHeadlessAvailableClients } from "../models/fika/headless/IHeadlessAvailableClients";
|
||||
import { IFikaRaidServerIdRequestData } from "../models/fika/routes/raid/IFikaRaidServerIdRequestData";
|
||||
import { IFikaRaidCreateRequestData } from "../models/fika/routes/raid/create/IFikaRaidCreateRequestData";
|
||||
import { IFikaRaidCreateResponse } from "../models/fika/routes/raid/create/IFikaRaidCreateResponse";
|
||||
import { IGetStatusDedicatedResponse } from "../models/fika/routes/raid/dedicated/IGetStatusDedicatedResponse";
|
||||
import { IStartDedicatedRequest } from "../models/fika/routes/raid/dedicated/IStartDedicatedRequest";
|
||||
import { IStartDedicatedResponse } from "../models/fika/routes/raid/dedicated/IStartDedicatedResponse";
|
||||
import { IStatusDedicatedRequest } from "../models/fika/routes/raid/dedicated/IStatusDedicatedRequest";
|
||||
import { IStatusDedicatedResponse } from "../models/fika/routes/raid/dedicated/IStatusDedicatedResponse";
|
||||
import { IFikaRaidGethostResponse } from "../models/fika/routes/raid/gethost/IFikaRaidGethostResponse";
|
||||
import { IFikaRaidSettingsResponse } from "../models/fika/routes/raid/getsettings/IFikaRaidSettingsResponse";
|
||||
import { IStartHeadlessRequest } from "../models/fika/routes/raid/headless/IStartHeadlessRequest";
|
||||
import { IStartHeadlessResponse } from "../models/fika/routes/raid/headless/IStartHeadlessResponse";
|
||||
import { IFikaRaidJoinRequestData } from "../models/fika/routes/raid/join/IFikaRaidJoinRequestData";
|
||||
import { IFikaRaidJoinResponse } from "../models/fika/routes/raid/join/IFikaRaidJoinResponse";
|
||||
import { IFikaRaidLeaveRequestData } from "../models/fika/routes/raid/leave/IFikaRaidLeaveRequestData";
|
||||
import { IStartRaidNotification } from "../models/fika/websocket/notifications/IStartRaidNotification";
|
||||
import { FikaMatchService } from "../services/FikaMatchService";
|
||||
import { FikaDedicatedRaidService } from "../services/dedicated/FikaDedicatedRaidService";
|
||||
import { FikaDedicatedRaidWebSocket } from "../websockets/FikaDedicatedRaidWebSocket";
|
||||
import { FikaHeadlessService } from "../services/headless/FikaHeadlessService";
|
||||
import { FikaNotificationWebSocket } from "../websockets/FikaNotificationWebSocket";
|
||||
|
||||
@injectable()
|
||||
export class FikaRaidController {
|
||||
constructor(
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("FikaMatchService") protected fikaMatchService: FikaMatchService,
|
||||
@inject("FikaDedicatedRaidService") protected fikaDedicatedRaidService: FikaDedicatedRaidService,
|
||||
@inject("FikaDedicatedRaidWebSocket") protected fikaDedicatedRaidWebSocket: FikaDedicatedRaidWebSocket,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("FikaHeadlessHelper") protected fikaHeadlessHelper: FikaHeadlessHelper,
|
||||
@inject("FikaHeadlessService") protected fikaHeadlessService: FikaHeadlessService,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("InraidController") protected inraidController: InraidController,
|
||||
@inject("FikaNotificationWebSocket") protected fikaNotificationWebSocket: FikaNotificationWebSocket,
|
||||
@@ -50,10 +43,19 @@ export class FikaRaidController {
|
||||
* @param request
|
||||
*/
|
||||
public handleRaidCreate(request: IFikaRaidCreateRequestData): IFikaRaidCreateResponse {
|
||||
let hostUsername = request.hostUsername;
|
||||
|
||||
if (this.fikaHeadlessHelper.isHeadlessClient(request.serverId)) {
|
||||
hostUsername = this.fikaHeadlessHelper.getHeadlessNickname(request.serverId);
|
||||
}
|
||||
|
||||
const notification: IStartRaidNotification = {
|
||||
type: EFikaNotifications.StartedRaid,
|
||||
nickname: request.hostUsername,
|
||||
nickname: hostUsername,
|
||||
location: request.settings.location,
|
||||
isHeadlessRaid: this.fikaHeadlessHelper.isHeadlessClient(request.serverId),
|
||||
headlessRequesterName: this.fikaHeadlessHelper.getRequesterUsername(request.serverId) || "",
|
||||
raidTime: request.time
|
||||
};
|
||||
|
||||
this.fikaNotificationWebSocket.broadcast(notification);
|
||||
@@ -74,7 +76,7 @@ export class FikaRaidController {
|
||||
serverId: request.serverId,
|
||||
timestamp: match.timestamp,
|
||||
gameVersion: match.gameVersion,
|
||||
fikaVersion: match.fikaVersion,
|
||||
crc32: match.crc32,
|
||||
raidCode: match.raidCode,
|
||||
};
|
||||
}
|
||||
@@ -106,7 +108,7 @@ export class FikaRaidController {
|
||||
ips: match.ips,
|
||||
port: match.port,
|
||||
natPunch: match.natPunch,
|
||||
isDedicated: match.isDedicated,
|
||||
isHeadless: match.isHeadless,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,113 +130,34 @@ export class FikaRaidController {
|
||||
};
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/start */
|
||||
handleRaidStartDedicated(sessionID: string, info: IStartDedicatedRequest): IStartDedicatedResponse {
|
||||
if (!this.fikaDedicatedRaidService.isDedicatedClientAvailable()) {
|
||||
/** Handle /fika/raid/headless/start */
|
||||
public async handleRaidStartHeadless(sessionID: string, info: IStartHeadlessRequest): Promise<IStartHeadlessResponse> {
|
||||
if (!this.fikaHeadlessHelper.isHeadlessClientAvailable(info.headlessSessionID)) {
|
||||
return {
|
||||
matchId: null,
|
||||
error: "No dedicated clients available.",
|
||||
error: "This headless client is not available.",
|
||||
};
|
||||
}
|
||||
|
||||
if (sessionID in this.fikaDedicatedRaidService.dedicatedClients) {
|
||||
if (this.fikaHeadlessHelper.isHeadlessClient(sessionID)) {
|
||||
return {
|
||||
matchId: null,
|
||||
error: "You are trying to connect to a dedicated client while having Fika.Dedicated installed. Please remove Fika.Dedicated from your client and try again.",
|
||||
error: "You are trying to connect to a headless client while having Fika.Headless installed. Please remove Fika.Headless from your client and try again.",
|
||||
};
|
||||
}
|
||||
|
||||
let dedicatedClient: string | undefined = undefined;
|
||||
let dedicatedClientWs: WebSocket | undefined = undefined;
|
||||
const headlessClientId = await this.fikaHeadlessService.startHeadlessRaid(info.headlessSessionID, sessionID, info);
|
||||
|
||||
for (const dedicatedSessionId in this.fikaDedicatedRaidService.dedicatedClients) {
|
||||
const dedicatedClientInfo = this.fikaDedicatedRaidService.dedicatedClients[dedicatedSessionId];
|
||||
|
||||
if (dedicatedClientInfo.state != EDedicatedStatus.READY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dedicatedClientWs = this.fikaDedicatedRaidWebSocket.clientWebSockets[dedicatedSessionId];
|
||||
|
||||
if (!dedicatedClientWs || dedicatedClientWs.readyState == WebSocket.CLOSED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dedicatedClient = dedicatedSessionId;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dedicatedClient) {
|
||||
return {
|
||||
matchId: null,
|
||||
error: "No dedicated clients available at this time.",
|
||||
};
|
||||
}
|
||||
|
||||
const pmcDedicatedClientProfile: IPmcData = this.profileHelper.getPmcProfile(dedicatedClient);
|
||||
const requesterProfile: IPmcData = this.profileHelper.getPmcProfile(sessionID);
|
||||
|
||||
this.logger.debug(`Dedicated: ${pmcDedicatedClientProfile.Info.Nickname} ${pmcDedicatedClientProfile.Info.Level} - Requester: ${requesterProfile.Info.Nickname} ${requesterProfile.Info.Level}`);
|
||||
|
||||
//Set level of the dedicated profile to the person that has requested the raid to be started.
|
||||
pmcDedicatedClientProfile.Info.Level = requesterProfile.Info.Level;
|
||||
pmcDedicatedClientProfile.Info.Experience = requesterProfile.Info.Experience;
|
||||
|
||||
this.fikaDedicatedRaidService.requestedSessions[dedicatedClient] = sessionID;
|
||||
|
||||
dedicatedClientWs.send(
|
||||
JSON.stringify({
|
||||
type: "fikaDedicatedStartRaid",
|
||||
...info,
|
||||
}),
|
||||
);
|
||||
|
||||
this.logger.info(`Sent WS fikaDedicatedStartRaid to ${dedicatedClient}`);
|
||||
this.logger.info(`Sent WS fikaHeadlessStartRaid to ${headlessClientId}`);
|
||||
|
||||
return {
|
||||
// This really isn't required, I just want to make sure on the client
|
||||
matchId: dedicatedClient,
|
||||
matchId: headlessClientId,
|
||||
error: null,
|
||||
};
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/status */
|
||||
public handleRaidStatusDedicated(sessionId: string, info: IStatusDedicatedRequest): IStatusDedicatedResponse {
|
||||
// Temp fix because the enum gets deserialized as a string instead of an integer
|
||||
switch (info.status.toString()) {
|
||||
case "READY":
|
||||
info.status = EDedicatedStatus.READY;
|
||||
break;
|
||||
case "IN_RAID":
|
||||
info.status = EDedicatedStatus.IN_RAID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (info.status == EDedicatedStatus.READY && !this.fikaDedicatedRaidService.isDedicatedClientAvailable()) {
|
||||
if (this.fikaDedicatedRaidService.onDedicatedClientAvailable) {
|
||||
this.fikaDedicatedRaidService.onDedicatedClientAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
this.fikaDedicatedRaidService.dedicatedClients[sessionId] = {
|
||||
state: info.status,
|
||||
lastPing: Date.now(),
|
||||
};
|
||||
|
||||
return {
|
||||
sessionId: info.sessionId,
|
||||
status: info.status,
|
||||
};
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/getstatus */
|
||||
public handleRaidGetStatusDedicated(): IGetStatusDedicatedResponse {
|
||||
return {
|
||||
available: this.fikaDedicatedRaidService.isDedicatedClientAvailable(),
|
||||
};
|
||||
}
|
||||
|
||||
/** Handle /fika/raid/dedicated/registerPlayer */
|
||||
/** Handle /fika/raid/registerPlayer */
|
||||
public handleRaidRegisterPlayer(sessionId: string, info: IRegisterPlayerRequestData): void {
|
||||
this.inraidController.addPlayer(sessionId, info);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
import { IItem } from "@spt/models/eft/common/tables/IItem";
|
||||
import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
@@ -25,7 +25,6 @@ export class FikaSendItemController {
|
||||
constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@@ -37,7 +36,7 @@ export class FikaSendItemController {
|
||||
// empty
|
||||
}
|
||||
|
||||
public sendItem(_pmcData: IPmcData, body: IFikaSendItemRequestData, sessionID: string): IItemEventRouterResponse {
|
||||
public async sendItem(_pmcData: IPmcData, body: IFikaSendItemRequestData, sessionID: string): Promise<IItemEventRouterResponse> {
|
||||
const fikaConfig = this.fikaConfig.getConfig();
|
||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||
|
||||
@@ -72,7 +71,7 @@ export class FikaSendItemController {
|
||||
return this.httpResponse.appendErrorToOutput(output, "Item not found in inventory");
|
||||
}
|
||||
|
||||
if (fikaConfig.server.giftedItemsLoseFIR) {
|
||||
if (fikaConfig.server.sentItemsLoseFIR) {
|
||||
for (const item of itemsToSend) {
|
||||
item.upd ??= {};
|
||||
|
||||
@@ -80,12 +79,7 @@ export class FikaSendItemController {
|
||||
}
|
||||
}
|
||||
|
||||
this.mailSendService.sendSystemMessageToPlayer(
|
||||
body.target,
|
||||
`You have received a gift from ${senderProfile?.characters?.pmc?.Info?.Nickname ?? "unknown"}`,
|
||||
itemsToSend,
|
||||
604800
|
||||
);
|
||||
this.mailSendService.sendSystemMessageToPlayer(body.target, `You have received a gift from ${senderProfile?.characters?.pmc?.Info?.Nickname ?? "unknown"}`, itemsToSend, 604800);
|
||||
|
||||
this.inventoryHelper.removeItem(senderProfile.characters.pmc, body.id, sessionID, output);
|
||||
|
||||
@@ -96,7 +90,7 @@ export class FikaSendItemController {
|
||||
itemName: `${itemsToSend[0]._tpl} ShortName`,
|
||||
};
|
||||
|
||||
this.fikaNotificationWebSocket.send(body.target, notification);
|
||||
await this.fikaNotificationWebSocket.sendAsync(body.target, notification);
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -119,7 +113,7 @@ export class FikaSendItemController {
|
||||
//Uninitialized profiles can cause this to error out, skip these.
|
||||
if (!profile.characters?.pmc?.Info) continue;
|
||||
|
||||
if (profile.info.password === "fika-dedicated") continue;
|
||||
if (profile.info.password === "fika-headless") continue;
|
||||
|
||||
const nickname = profile.characters.pmc.Info.Nickname;
|
||||
if (!(nickname in result) && nickname !== sender.characters.pmc.Info.Nickname) {
|
||||
|
||||
@@ -34,15 +34,15 @@ export class FikaUpdateController {
|
||||
* @param request
|
||||
*/
|
||||
public handleSethost(request: IFikaUpdateSethostRequestData): void {
|
||||
this.fikaMatchService.setMatchHost(request.serverId, request.ips, request.port, request.natPunch, request.isDedicated);
|
||||
this.fikaMatchService.setMatchHost(request.serverId, request.ips, request.port, request.natPunch, request.isHeadless);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /fika/update/setstatus
|
||||
* @param request
|
||||
*/
|
||||
public handleSetStatus(request: IFikaUpdateSetStatusRequestData): void {
|
||||
this.fikaMatchService.setMatchStatus(request.serverId, request.status);
|
||||
public async handleSetStatus(request: IFikaUpdateSetStatusRequestData): Promise<void> {
|
||||
await this.fikaMatchService.setMatchStatus(request.serverId, request.status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,21 +4,18 @@ import { FikaConfig } from "../utils/FikaConfig";
|
||||
|
||||
import { Overrider } from "../overrides/Overrider";
|
||||
import { DialogueCallbacksOverride } from "../overrides/callbacks/DialogueCallbacks";
|
||||
import { LocationLifecycleServiceOverride } from "../overrides/services/LocationLifecycleService";
|
||||
import { AchievementControllerOverride } from "../overrides/controllers/AchievementController";
|
||||
import { DialogueControllerOverride } from "../overrides/controllers/DialogueController";
|
||||
import { ProfileControllerOverride } from "../overrides/controllers/ProfileController";
|
||||
// import { LocalesOverride } from "../overrides/other/Locales";
|
||||
import { HttpRouterOverride } from "../overrides/routers/HttpRouter";
|
||||
import { LauncherControllerOverride } from "../overrides/controllers/LauncherController";
|
||||
import { MatchControllerOverride } from "../overrides/controllers/MatchController";
|
||||
import { LocationLifecycleServiceOverride } from "../overrides/services/LocationLifecycleService";
|
||||
|
||||
import { FikaInsuranceService } from "../services/FikaInsuranceService";
|
||||
import { FikaMatchService } from "../services/FikaMatchService";
|
||||
import { FikaPresenceService } from "../services/FikaPresenceService";
|
||||
import { FikaFriendRequestsCacheService } from "../services/cache/FikaFriendRequestsCacheService";
|
||||
import { FikaPlayerRelationsCacheService } from "../services/cache/FikaPlayerRelationsCacheService";
|
||||
import { FikaDedicatedRaidService } from "../services/dedicated/FikaDedicatedRaidService";
|
||||
import { FikaInsuranceService } from "../services/FikaInsuranceService";
|
||||
import { FikaPresenceService } from "../services/FikaPresenceService";
|
||||
|
||||
import { FikaClientModHashesHelper } from "../helpers/FikaClientModHashesHelper";
|
||||
import { FikaFriendRequestsHelper } from "../helpers/FikaFriendRequestsHelper";
|
||||
@@ -34,27 +31,36 @@ import { FikaUpdateController } from "../controllers/FikaUpdateController";
|
||||
|
||||
import { FikaClientCallbacks } from "../callbacks/FikaClientCallbacks";
|
||||
import { FikaLocationCallbacks } from "../callbacks/FikaLocationCallbacks";
|
||||
import { FikaPresenceCallbacks } from "../callbacks/FikaPresenceCallbacks";
|
||||
import { FikaRaidCallbacks } from "../callbacks/FikaRaidCallbacks";
|
||||
import { FikaSendItemCallbacks } from "../callbacks/FikaSendItemCallbacks";
|
||||
import { FikaUpdateCallbacks } from "../callbacks/FikaUpdateCallbacks";
|
||||
import { FikaPresenceCallbacks } from "../callbacks/FikaPresenceCallbacks";
|
||||
|
||||
import { FikaItemEventRouter } from "../routers/item_events/FikaItemEventRouter";
|
||||
import { FikaClientStaticRouter } from "../routers/static/FikaClientStaticRouter";
|
||||
import { FikaLocationStaticRouter } from "../routers/static/FikaLocationStaticRouter";
|
||||
import { FikaPresenceStaticRouter } from "../routers/static/FikaPresenceStaticRouter";
|
||||
import { FikaRaidStaticRouter } from "../routers/static/FikaRaidStaticRouter";
|
||||
import { FikaSendItemStaticRouter } from "../routers/static/FikaSendItemStaticRouter";
|
||||
import { FikaUpdateStaticRouter } from "../routers/static/FikaUpdateStaticRouter";
|
||||
import { FikaPresenceStaticRouter } from "../routers/static/FikaPresenceStaticRouter";
|
||||
|
||||
import { FikaDedicatedRaidWebSocket } from "../websockets/FikaDedicatedRaidWebSocket";
|
||||
import { FikaNotificationWebSocket } from "../websockets/FikaNotificationWebSocket";
|
||||
|
||||
import { ClientLogCallbacks } from "@spt/callbacks/ClientLogCallbacks";
|
||||
import { Fika } from "../Fika";
|
||||
import { FikaDedicatedProfileService } from "../services/dedicated/FikaDedicatedProfileService";
|
||||
import { FikaServerTools } from "../utils/FikaServerTools";
|
||||
import { FikaNotificationStaticRouter } from "../routers/static/FikaNotificationStaticRouter";
|
||||
import { FikaHeadlessCallbacks } from "../callbacks/FikaHeadlessCallbacks";
|
||||
import { FikaNotificationCallbacks } from "../callbacks/FikaNotificationCallbacks";
|
||||
import { FikaHeadlessController } from "../controllers/FikaHeadlessController";
|
||||
import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper";
|
||||
import { ClientLogCallbacksOverride } from "../overrides/callbacks/ClientLogCallbacks";
|
||||
import { FikaHeadlessStaticRouter } from "../routers/static/FikaHeadlessStaticRouter";
|
||||
import { FikaNotificationStaticRouter } from "../routers/static/FikaNotificationStaticRouter";
|
||||
import { FikaClientService } from "../services/FikaClientService";
|
||||
import { FikaHeadlessProfileService } from "../services/headless/FikaHeadlessProfileService";
|
||||
import { FikaHeadlessService } from "../services/headless/FikaHeadlessService";
|
||||
import { FikaServerTools } from "../utils/FikaServerTools";
|
||||
import { FikaHeadlessClientWebSocket } from "../websockets/FikaHeadlessClientWebSocket";
|
||||
import { FikaHeadlessRequesterWebSocket } from "../websockets/FikaHeadlessRequesterWebSocket";
|
||||
|
||||
export class Container {
|
||||
public static register(container: DependencyContainer): void {
|
||||
@@ -86,11 +92,10 @@ export class Container {
|
||||
container.registerType("Overrides", "HttpRouterOverride");
|
||||
// container.registerType("Overrides", "LocalesOverride");
|
||||
container.registerType("Overrides", "AchievementControllerOverride");
|
||||
container.registerType("Overrides", "LauncherControllerOverride");
|
||||
container.registerType("Overrides", "LocationLifecycleServiceOverride");
|
||||
container.registerType("Overrides", "MatchControllerOverride");
|
||||
|
||||
container.registerType("StaticRoutes", "FikaClientStaticRouter");
|
||||
container.registerType("StaticRoutes", "FikaHeadlessStaticRouter");
|
||||
container.registerType("StaticRoutes", "FikaLocationStaticRouter");
|
||||
container.registerType("StaticRoutes", "FikaRaidStaticRouter");
|
||||
container.registerType("StaticRoutes", "FikaSendItemStaticRouter");
|
||||
@@ -100,8 +105,9 @@ export class Container {
|
||||
|
||||
container.registerType("IERouters", "FikaItemEventRouter");
|
||||
|
||||
container.registerType("WebSocketConnectionHandler", "FikaDedicatedRaidWebSocket");
|
||||
container.registerType("WebSocketConnectionHandler", "FikaNotificationWebSocket");
|
||||
container.registerType("WebSocketConnectionHandler", "FikaHeadlessClientWebSocket");
|
||||
container.registerType("WebSocketConnectionHandler", "FikaHeadlessRequesterWebSocket");
|
||||
}
|
||||
|
||||
private static registerUtils(container: DependencyContainer): void {
|
||||
@@ -111,35 +117,37 @@ export class Container {
|
||||
|
||||
private static registerOverrides(container: DependencyContainer): void {
|
||||
container.register<DialogueCallbacksOverride>("DialogueCallbacksOverride", DialogueCallbacksOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<ClientLogCallbacksOverride>("ClientLogCallbacksOverride", ClientLogCallbacksOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<DialogueControllerOverride>("DialogueControllerOverride", DialogueControllerOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<ProfileControllerOverride>("ProfileControllerOverride", ProfileControllerOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<HttpRouterOverride>("HttpRouterOverride", HttpRouterOverride, { lifecycle: Lifecycle.Singleton });
|
||||
// container.register<LocalesOverride>("LocalesOverride", LocalesOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<Overrider>("Overrider", Overrider, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<AchievementControllerOverride>("AchievementControllerOverride", AchievementControllerOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<LauncherControllerOverride>("LauncherControllerOverride", LauncherControllerOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<LocationLifecycleServiceOverride>("LocationLifecycleServiceOverride", LocationLifecycleServiceOverride, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<MatchControllerOverride>("MatchControllerOverride", MatchControllerOverride, { lifecycle: Lifecycle.Singleton });
|
||||
}
|
||||
|
||||
private static registerServices(container: DependencyContainer): void {
|
||||
container.register<FikaClientService>("FikaClientService", FikaClientService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaMatchService>("FikaMatchService", FikaMatchService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaFriendRequestsCacheService>("FikaFriendRequestsCacheService", FikaFriendRequestsCacheService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaPlayerRelationsCacheService>("FikaPlayerRelationsCacheService", FikaPlayerRelationsCacheService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaDedicatedRaidService>("FikaDedicatedRaidService", FikaDedicatedRaidService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaDedicatedProfileService>("FikaDedicatedProfileService", FikaDedicatedProfileService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaHeadlessProfileService>("FikaHeadlessProfileService", FikaHeadlessProfileService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaInsuranceService>("FikaInsuranceService", FikaInsuranceService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaPresenceService>("FikaPresenceService", FikaPresenceService, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaHeadlessService>("FikaHeadlessService", FikaHeadlessService, { lifecycle: Lifecycle.Singleton });
|
||||
}
|
||||
|
||||
private static registerHelpers(container: DependencyContainer): void {
|
||||
container.register<FikaClientModHashesHelper>("FikaClientModHashesHelper", FikaClientModHashesHelper, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaFriendRequestsHelper>("FikaFriendRequestsHelper", FikaFriendRequestsHelper, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaPlayerRelationsHelper>("FikaPlayerRelationsHelper", FikaPlayerRelationsHelper, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaFriendRequestsHelper>("FikaFriendRequestsHelper", { useClass: FikaFriendRequestsHelper });
|
||||
container.register<FikaPlayerRelationsHelper>("FikaPlayerRelationsHelper", { useClass: FikaPlayerRelationsHelper });
|
||||
container.register<FikaHeadlessHelper>("FikaHeadlessHelper", { useClass: FikaHeadlessHelper });
|
||||
}
|
||||
|
||||
private static registerControllers(container: DependencyContainer): void {
|
||||
container.register<FikaClientController>("FikaClientController", { useClass: FikaClientController });
|
||||
container.register<FikaHeadlessController>("FikaHeadlessController", { useClass: FikaHeadlessController });
|
||||
container.register<FikaDialogueController>("FikaDialogueController", { useClass: FikaDialogueController });
|
||||
container.register<FikaLocationController>("FikaLocationController", { useClass: FikaLocationController });
|
||||
container.register<FikaRaidController>("FikaRaidController", { useClass: FikaRaidController });
|
||||
@@ -150,6 +158,7 @@ export class Container {
|
||||
|
||||
private static registerCallbacks(container: DependencyContainer): void {
|
||||
container.register<FikaClientCallbacks>("FikaClientCallbacks", { useClass: FikaClientCallbacks });
|
||||
container.register<FikaHeadlessCallbacks>("FikaHeadlessCallbacks", { useClass: FikaHeadlessCallbacks });
|
||||
container.register<FikaLocationCallbacks>("FikaLocationCallbacks", { useClass: FikaLocationCallbacks });
|
||||
container.register<FikaRaidCallbacks>("FikaRaidCallbacks", { useClass: FikaRaidCallbacks });
|
||||
container.register<FikaSendItemCallbacks>("FikaSendItemCallbacks", { useClass: FikaSendItemCallbacks });
|
||||
@@ -160,6 +169,7 @@ export class Container {
|
||||
|
||||
private static registerRouters(container: DependencyContainer): void {
|
||||
container.register<FikaClientStaticRouter>("FikaClientStaticRouter", { useClass: FikaClientStaticRouter });
|
||||
container.register<FikaHeadlessStaticRouter>("FikaHeadlessStaticRouter", { useClass: FikaHeadlessStaticRouter });
|
||||
container.register<FikaLocationStaticRouter>("FikaLocationStaticRouter", { useClass: FikaLocationStaticRouter });
|
||||
container.register<FikaRaidStaticRouter>("FikaRaidStaticRouter", { useClass: FikaRaidStaticRouter });
|
||||
container.register<FikaSendItemStaticRouter>("FikaSendItemStaticRouter", { useClass: FikaSendItemStaticRouter });
|
||||
@@ -170,7 +180,8 @@ export class Container {
|
||||
}
|
||||
|
||||
private static registerWebSockets(container: DependencyContainer): void {
|
||||
container.register<FikaDedicatedRaidWebSocket>("FikaDedicatedRaidWebSocket", FikaDedicatedRaidWebSocket, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaNotificationWebSocket>("FikaNotificationWebSocket", FikaNotificationWebSocket, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaHeadlessClientWebSocket>("FikaHeadlessClientWebSocket", FikaHeadlessClientWebSocket, { lifecycle: Lifecycle.Singleton });
|
||||
container.register<FikaHeadlessRequesterWebSocket>("FikaHeadlessRequesterWebSocket", FikaHeadlessRequesterWebSocket, { lifecycle: Lifecycle.Singleton });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HashUtil } from "@spt/utils/HashUtil";
|
||||
|
||||
import { IFikaFriendRequests } from "../models/fika/IFikaFriendRequests";
|
||||
import { FikaFriendRequestsCacheService } from "../services/cache/FikaFriendRequestsCacheService";
|
||||
import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { LogTextColor } from "@spt/models/spt/logging/LogTextColor";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { LogTextColor } from "@spt/models/spt/logging/LogTextColor";
|
||||
import { IFikaFriendRequests } from "../models/fika/IFikaFriendRequests";
|
||||
import { FikaFriendRequestsCacheService } from "../services/cache/FikaFriendRequestsCacheService";
|
||||
|
||||
@injectable()
|
||||
export class FikaFriendRequestsHelper {
|
||||
@@ -69,7 +69,7 @@ export class FikaFriendRequestsHelper {
|
||||
if (profile) {
|
||||
this.logger.logWithColor(`Sending WebSocket message to ${toProfileId}`, LogTextColor.GREEN);
|
||||
|
||||
this.webSocketHandler.sendMessage(toProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(toProfileId, {
|
||||
type: "friendListNewRequest",
|
||||
eventId: "friendListNewRequest",
|
||||
_id: fromProfileId,
|
||||
@@ -109,7 +109,7 @@ export class FikaFriendRequestsHelper {
|
||||
switch (reason) {
|
||||
case "accept": {
|
||||
const profile = this.saveServer.getProfile(toProfileId);
|
||||
this.webSocketHandler.sendMessage(fromProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(fromProfileId, {
|
||||
type: "friendListRequestAccept",
|
||||
eventId: "friendListRequestAccept",
|
||||
profile: {
|
||||
@@ -131,7 +131,7 @@ export class FikaFriendRequestsHelper {
|
||||
}
|
||||
case "cancel": {
|
||||
const profile = this.saveServer.getProfile(fromProfileId);
|
||||
this.webSocketHandler.sendMessage(toProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(toProfileId, {
|
||||
type: "friendListRequestCancel",
|
||||
eventId: "friendListRequestCancel",
|
||||
profile: {
|
||||
@@ -153,7 +153,7 @@ export class FikaFriendRequestsHelper {
|
||||
}
|
||||
case "decline": {
|
||||
const profile = this.saveServer.getProfile(toProfileId);
|
||||
this.webSocketHandler.sendMessage(fromProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(fromProfileId, {
|
||||
type: "friendListRequestDecline",
|
||||
eventId: "friendListRequestDecline",
|
||||
profile: {
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { EHeadlessStatus } from "../models/enums/EHeadlessStatus";
|
||||
import { IHeadlessAvailableClients } from "../models/fika/headless/IHeadlessAvailableClients";
|
||||
import { IHeadlessClientInfo } from "../models/fika/headless/IHeadlessClientInfo";
|
||||
import { FikaHeadlessProfileService } from "../services/headless/FikaHeadlessProfileService";
|
||||
import { FikaHeadlessService } from "../services/headless/FikaHeadlessService";
|
||||
import { FikaConfig } from "../utils/FikaConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessHelper {
|
||||
constructor(
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("FikaHeadlessService") protected FikaHeadlessService: FikaHeadlessService,
|
||||
@inject("FikaHeadlessProfileService") protected fikaHeadlessProfileService: FikaHeadlessProfileService,
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all currently logged in headlesses
|
||||
*
|
||||
* @returns A map where the key is the sessionID and the value is an IHeadlessClientInfo object
|
||||
*/
|
||||
public getHeadlessClients(): Map<string, IHeadlessClientInfo> {
|
||||
return this.FikaHeadlessService.getHeadlessClients();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for checking if a SessionID is a headless client
|
||||
*
|
||||
* @param sessionId The sessionID to check
|
||||
* @returns Returns true if the passed sessionID is a headless, returns false if not.
|
||||
*/
|
||||
public isHeadlessClient(sessionId: string): boolean {
|
||||
return this.fikaHeadlessProfileService.getHeadlessProfiles().some((profile) => profile.info.id === sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for checking if the given headless client is available
|
||||
*
|
||||
* @returns Returns true if it's available, returns false if it isn't available.
|
||||
*/
|
||||
public isHeadlessClientAvailable(headlessSessionID: string): boolean {
|
||||
const headless = this.FikaHeadlessService.getHeadlessClients().get(headlessSessionID);
|
||||
|
||||
if (!headless) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (headless.state === EHeadlessStatus.READY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the requester's username for a headless client if there is any.
|
||||
*
|
||||
* @returns The nickname if the headless has been requested by a user, returns null if not.
|
||||
*/
|
||||
public getRequesterUsername(headlessSessionID: string): string | null {
|
||||
const headlessClient = this.FikaHeadlessService.getHeadlessClients().get(headlessSessionID);
|
||||
|
||||
if (!headlessClient) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!headlessClient.requesterSessionID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.saveServer.getProfile(headlessClient.requesterSessionID).characters.pmc.Info.Nickname;
|
||||
}
|
||||
|
||||
/***
|
||||
* Gets the alias (If it has been given one) or nickname of the headless client
|
||||
*
|
||||
* @returns the alias, or nickname or the headless client.
|
||||
*/
|
||||
public getHeadlessNickname(headlessSessionID: string): string {
|
||||
const AliasName = this.fikaConfig.getConfig().headless.profiles.aliases[headlessSessionID];
|
||||
|
||||
if (!AliasName) {
|
||||
return this.saveServer.getProfile(headlessSessionID).characters.pmc.Info.Nickname;
|
||||
}
|
||||
|
||||
return AliasName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available headless clients
|
||||
*
|
||||
* @returns Returns an array of available headless clients
|
||||
*/
|
||||
public getAvailableHeadlessClients(): IHeadlessAvailableClients[] {
|
||||
const headlessClients: IHeadlessAvailableClients[] = [];
|
||||
|
||||
for (const [headlessSessionID, headless] of this.getHeadlessClients()) {
|
||||
if (headless.state === EHeadlessStatus.READY) {
|
||||
const availableHeadlessClient: IHeadlessAvailableClients = {
|
||||
headlessSessionID: headlessSessionID,
|
||||
alias: this.getHeadlessNickname(headlessSessionID),
|
||||
};
|
||||
|
||||
headlessClients.push(availableHeadlessClient);
|
||||
}
|
||||
}
|
||||
|
||||
return headlessClients;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { FikaPlayerRelationsCacheService } from "../services/cache/FikaPlayerRelationsCacheService";
|
||||
import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ISptProfile } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { FikaPlayerRelationsCacheService } from "../services/cache/FikaPlayerRelationsCacheService";
|
||||
|
||||
@injectable()
|
||||
export class FikaPlayerRelationsHelper {
|
||||
@@ -90,7 +90,7 @@ export class FikaPlayerRelationsHelper {
|
||||
this.logger.info(`removeFriend: ${fromProfileId}->${toProfileId}`);
|
||||
|
||||
const profile = this.saveServer.getProfile(fromProfileId);
|
||||
this.webSocketHandler.sendMessage(toProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(toProfileId, {
|
||||
type: "youAreRemovedFromFriendList",
|
||||
eventId: "youAreRemovedFromFriendList",
|
||||
profile: {
|
||||
@@ -125,7 +125,7 @@ export class FikaPlayerRelationsHelper {
|
||||
this.fikaPlayerRelationsCacheService.storeValue(fromProfileId, playerRelations);
|
||||
|
||||
let profile: ISptProfile = this.saveServer.getProfile(fromProfileId);
|
||||
this.webSocketHandler.sendMessage(toProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(toProfileId, {
|
||||
type: "youAreAddToIgnoreList",
|
||||
eventId: "youAreAddToIgnoreList",
|
||||
_id: fromProfileId,
|
||||
@@ -161,7 +161,7 @@ export class FikaPlayerRelationsHelper {
|
||||
this.fikaPlayerRelationsCacheService.storeValue(fromProfileId, playerRelations);
|
||||
|
||||
let profile: ISptProfile = this.saveServer.getProfile(fromProfileId);
|
||||
this.webSocketHandler.sendMessage(toProfileId, {
|
||||
this.webSocketHandler.sendMessageAsync(toProfileId, {
|
||||
type: "youAreRemoveFromIgnoreList",
|
||||
eventId: "youAreRemoveFromIgnoreList",
|
||||
_id: fromProfileId,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { IPreSptLoadModAsync } from "@spt/models/external/IPreSptLoadModAsync";
|
||||
import { IPostSptLoadModAsync } from "@spt/models/external/IPostSptLoadModAsync";
|
||||
import { IPreSptLoadModAsync } from "@spt/models/external/IPreSptLoadModAsync";
|
||||
|
||||
import { Fika } from "./Fika";
|
||||
import { Container } from "./di/Container";
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MemberCategory } from "@spt/models/enums/MemberCategory";
|
||||
|
||||
export interface IWsProfile {
|
||||
type: string;
|
||||
eventId: string;
|
||||
_id?: string;
|
||||
profile: {
|
||||
_id: string;
|
||||
aid: number;
|
||||
Info: {
|
||||
Nickname: string;
|
||||
Side: string;
|
||||
Level: number;
|
||||
MemberCategory: MemberCategory;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -13,5 +13,5 @@ export enum EEFTNotificationIconType {
|
||||
WishlistHideout = 11,
|
||||
WishlistTrading = 12,
|
||||
WishlistEquipment = 13,
|
||||
WishlistOther = 14
|
||||
WishlistOther = 14,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum EFikaHeadlessWSMessageTypes {
|
||||
KeepAlive = 0,
|
||||
HeadlessStartRaid = 1,
|
||||
RequesterJoinMatch = 2,
|
||||
}
|
||||
@@ -2,5 +2,5 @@ export enum EFikaNotifications {
|
||||
KeepAlive = 0,
|
||||
StartedRaid = 1,
|
||||
SentItem = 2,
|
||||
PushNotification = 3
|
||||
PushNotification = 3,
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
export enum EDedicatedStatus {
|
||||
export enum EHeadlessStatus {
|
||||
READY = 1,
|
||||
IN_RAID = 2,
|
||||
}
|
||||
@@ -11,7 +11,7 @@ export interface IFikaMatch {
|
||||
port: number;
|
||||
hostUsername: string;
|
||||
timestamp: string;
|
||||
fikaVersion: string;
|
||||
crc32: number;
|
||||
gameVersion: string;
|
||||
raidConfig: IGetRaidConfigurationRequestData;
|
||||
locationData: ILocationBase;
|
||||
@@ -22,6 +22,6 @@ export interface IFikaMatch {
|
||||
time: EFikaTime;
|
||||
raidCode: string;
|
||||
natPunch: boolean;
|
||||
isDedicated: boolean;
|
||||
isHeadless: boolean;
|
||||
raids: number;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { IFikaConfigClient } from "./IFikaConfigClient";
|
||||
import { IFikaConfigServer } from "./IFikaConfigServer";
|
||||
import { IFikaConfigNatPunchServer } from "./IFikaConfigNatPunchServer";
|
||||
import { IFikaConfigDedicated } from "./IFikaConfigDedicated";
|
||||
import { IFikaConfigBackground } from "./IFikaConfigBackground";
|
||||
import { IFikaConfigClient } from "./IFikaConfigClient";
|
||||
import { IFikaConfigHeadless } from "./IFikaConfigHeadless";
|
||||
import { IFikaConfigNatPunchServer } from "./IFikaConfigNatPunchServer";
|
||||
import { IFikaConfigServer } from "./IFikaConfigServer";
|
||||
|
||||
export interface IFikaConfig {
|
||||
client: IFikaConfigClient;
|
||||
server: IFikaConfigServer;
|
||||
natPunchServer: IFikaConfigNatPunchServer;
|
||||
dedicated: IFikaConfigDedicated;
|
||||
background: IFikaConfigBackground
|
||||
headless: IFikaConfigHeadless;
|
||||
background: IFikaConfigBackground;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ export interface IFikaConfigClient {
|
||||
dynamicVExfils: boolean;
|
||||
allowFreeCam: boolean;
|
||||
allowSpectateFreeCam: boolean;
|
||||
allowItemSending: boolean;
|
||||
blacklistedItems: string[],
|
||||
blacklistedItems: string[];
|
||||
forceSaveOnDeath: boolean;
|
||||
mods: {
|
||||
required: string[];
|
||||
@@ -15,4 +14,5 @@ export interface IFikaConfigClient {
|
||||
sharedQuestProgression: boolean;
|
||||
canEditRaidSettings: boolean;
|
||||
enableTransits: boolean;
|
||||
anyoneCanStartRaid: boolean;
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
export interface IFikaConfigDedicated {
|
||||
profiles: {
|
||||
amount: number;
|
||||
}
|
||||
scripts: {
|
||||
generate: boolean;
|
||||
forceIp: string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export interface IFikaConfigHeadless {
|
||||
profiles: {
|
||||
amount: number;
|
||||
aliases: Record<string, string>;
|
||||
};
|
||||
scripts: {
|
||||
generate: boolean;
|
||||
forceIp: string;
|
||||
};
|
||||
/** If this is true, sets the headless's average level to that of the entire lobby, if set to false it will take the level of the requester. */
|
||||
setLevelToAverageOfLobby: boolean;
|
||||
restartAfterAmountOfRaids: number;
|
||||
}
|
||||
@@ -1,7 +1,22 @@
|
||||
export interface IFikaConfigServer {
|
||||
giftedItemsLoseFIR: boolean;
|
||||
SPT: IFikaSPTServerConfig;
|
||||
allowItemSending: boolean;
|
||||
sentItemsLoseFIR: boolean;
|
||||
launcherListAllProfiles: boolean;
|
||||
sessionTimeout: number;
|
||||
showDevProfile: boolean;
|
||||
showNonStandardProfile: boolean;
|
||||
logClientModsInConsole: boolean;
|
||||
}
|
||||
|
||||
export interface IFikaSPTServerConfig {
|
||||
http: IFikaSPTHttpServerConfig;
|
||||
disableSPTChatBots: boolean;
|
||||
}
|
||||
|
||||
export interface IFikaSPTHttpServerConfig {
|
||||
ip: string;
|
||||
port: number;
|
||||
backendIp: string;
|
||||
backendPort: number;
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
import { EDedicatedStatus } from "../../enums/EDedicatedStatus";
|
||||
|
||||
export interface IDedicatedClientInfo {
|
||||
state: EDedicatedStatus;
|
||||
lastPing: number;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export interface IHeadlessAvailableClients {
|
||||
/** SessionID of the headless client */
|
||||
headlessSessionID: string;
|
||||
/** The alias of the headless client, if it has any assigned. If it doesn't have any assigned uses the nickname */
|
||||
alias: string;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { SPTWebSocket } from "@spt/servers/ws/SPTWebsocket";
|
||||
import { EHeadlessStatus } from "../../enums/EHeadlessStatus";
|
||||
|
||||
export interface IHeadlessClientInfo {
|
||||
/** Websocket of the headless client */
|
||||
webSocket: SPTWebSocket;
|
||||
/** State of the headless client */
|
||||
state: EHeadlessStatus;
|
||||
/** The players that are playing on this headless client, only set if the state is IN_RAID */
|
||||
players?: string[];
|
||||
/** SessionID of the person who has requested the headless client, it will only ever be set if the status is IN_RAID */
|
||||
requesterSessionID?: string;
|
||||
/** Allows for checking if the requester has been notified the match has started through the requester WebSocket so he can auto-join */
|
||||
hasNotifiedRequester?: boolean;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { EHeadlessStatus } from "../../enums/EHeadlessStatus";
|
||||
|
||||
/** A copy of IHeadlessClientInfo but for /fika/headless/get */
|
||||
export interface IHeadlessClient {
|
||||
/** State of the headless client */
|
||||
state: EHeadlessStatus;
|
||||
/** The players that are playing on this headless client, only set if the state is IN_RAID */
|
||||
players?: string[];
|
||||
/** SessionID of the person who has requested the headless client, it will only ever be set if the status is IN_RAID */
|
||||
requesterSessionID?: string;
|
||||
/** Allows for checking if the requester has been notified the match has started through the requester WebSocket so he can auto-join */
|
||||
hasNotifiedRequester?: boolean;
|
||||
}
|
||||
|
||||
export interface IHeadlessClients {
|
||||
headlesses: Record<string, IHeadlessClient>;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export interface IHeadlessRestartAfterAmountOfRaids {
|
||||
amount: number;
|
||||
}
|
||||
+1
-1
@@ -7,4 +7,4 @@ export interface IFikaPlayerPresence {
|
||||
activity: EFikaPlayerPresences;
|
||||
activityStartedTimestamp: number;
|
||||
raidInformation?: IFikaRaidPresence;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,4 +5,4 @@ export interface IFikaRaidPresence {
|
||||
location: string;
|
||||
side: EFikaSide;
|
||||
time: EFikaTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EFikaPlayerPresences } from "../../enums/EFikaPlayerPresences";
|
||||
import { IFikaRaidPresence } from "./IFikaRaidPresence";
|
||||
|
||||
export interface IFikaSetPresence{
|
||||
export interface IFikaSetPresence {
|
||||
activity: EFikaPlayerPresences;
|
||||
raidInformation?: IFikaRaidPresence;
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -11,6 +11,8 @@ export interface IFikaRaidResponse {
|
||||
side: EFikaSide;
|
||||
time: EFikaTime;
|
||||
players: Record<string, boolean>;
|
||||
isHeadless: boolean;
|
||||
headlessRequesterNickname: string;
|
||||
}
|
||||
|
||||
export type IFikaRaidsResponse = IFikaRaidResponse[];
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ export interface IFikaRaidCreateRequestData {
|
||||
timestamp: string;
|
||||
settings: IGetRaidConfigurationRequestData;
|
||||
gameVersion: string;
|
||||
fikaVersion: string;
|
||||
crc32: number;
|
||||
side: EFikaSide;
|
||||
time: EFikaTime;
|
||||
isSpectator: boolean;
|
||||
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
export interface IGetStatusDedicatedResponse {
|
||||
available: boolean;
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
export interface IStartDedicatedResponse {
|
||||
matchId: string;
|
||||
error: string;
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
import { EDedicatedStatus } from "../../../../enums/EDedicatedStatus";
|
||||
|
||||
export interface IStatusDedicatedRequest {
|
||||
sessionId: string;
|
||||
status: EDedicatedStatus;
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
import { EDedicatedStatus } from "../../../../enums/EDedicatedStatus";
|
||||
|
||||
export interface IStatusDedicatedResponse {
|
||||
sessionId: string;
|
||||
status: EDedicatedStatus;
|
||||
}
|
||||
+1
-1
@@ -2,5 +2,5 @@ export interface IFikaRaidGethostResponse {
|
||||
ips: string[];
|
||||
port: number;
|
||||
natPunch: boolean;
|
||||
isDedicated: boolean;
|
||||
isHeadless: boolean;
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ export interface IFikaRaidSettingsResponse {
|
||||
metabolismDisabled: boolean;
|
||||
playersSpawnPlace: PlayersSpawnPlace;
|
||||
hourOfDay: number;
|
||||
timeFlowType: TimeFlowType
|
||||
timeFlowType: TimeFlowType;
|
||||
}
|
||||
|
||||
+2
-1
@@ -3,7 +3,8 @@ import { DateTime } from "@spt/models/enums/DateTime";
|
||||
import { PlayersSpawnPlace } from "@spt/models/enums/PlayersSpawnPlace";
|
||||
import { SideType } from "@spt/models/enums/SideType";
|
||||
|
||||
export interface IStartDedicatedRequest {
|
||||
export interface IStartHeadlessRequest {
|
||||
headlessSessionID: string;
|
||||
time: DateTime;
|
||||
locationId: string;
|
||||
spawnPlace: PlayersSpawnPlace;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export interface IStartHeadlessResponse {
|
||||
matchId: string;
|
||||
error: string;
|
||||
}
|
||||
+1
-1
@@ -2,6 +2,6 @@ export interface IFikaRaidJoinResponse {
|
||||
serverId: string;
|
||||
timestamp: string;
|
||||
gameVersion: string;
|
||||
fikaVersion: string;
|
||||
crc32: number;
|
||||
raidCode: string;
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ export interface IFikaUpdateSethostRequestData {
|
||||
ips: string[];
|
||||
port: number;
|
||||
natPunch: boolean;
|
||||
isDedicated: boolean;
|
||||
isHeadless: boolean;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { EFikaHeadlessWSMessageTypes } from "../../enums/EFikaHeadlessWSMessageTypes";
|
||||
|
||||
export interface IFikaHeadlessBase {
|
||||
type: EFikaHeadlessWSMessageTypes;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { IFikaHeadlessBase } from "../IFikaHeadlessBase";
|
||||
|
||||
export interface IHeadlessRequesterJoinRaid extends IFikaHeadlessBase {
|
||||
matchId: string;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { IStartHeadlessRequest } from "../../routes/raid/headless/IStartHeadlessRequest";
|
||||
import { IFikaHeadlessBase } from "../IFikaHeadlessBase";
|
||||
|
||||
export interface IStartHeadlessRaid extends IFikaHeadlessBase {
|
||||
startRequest: IStartHeadlessRequest;
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { IFikaNotificationBase } from "../IFikaNotificationBase";
|
||||
import { EEFTNotificationIconType } from "../../../enums/EEFTNotificationIconType";
|
||||
import { IFikaNotificationBase } from "../IFikaNotificationBase";
|
||||
|
||||
export interface IPushNotification extends IFikaNotificationBase {
|
||||
notificationIcon : EEFTNotificationIconType;
|
||||
notificationIcon: EEFTNotificationIconType;
|
||||
notification: string;
|
||||
}
|
||||
|
||||
+3
@@ -3,4 +3,7 @@ import { IFikaNotificationBase } from "../IFikaNotificationBase";
|
||||
export interface IStartRaidNotification extends IFikaNotificationBase {
|
||||
nickname: string;
|
||||
location: string;
|
||||
isHeadlessRaid: boolean;
|
||||
headlessRequesterName: string;
|
||||
raidTime: number;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { ClientLogCallbacks } from "@spt/callbacks/ClientLogCallbacks";
|
||||
import { ClientLogController } from "@spt/controllers/ClientLogController";
|
||||
import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData";
|
||||
import { IClientLogRequest } from "@spt/models/spt/logging/IClientLogRequest";
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
import { Override } from "../../di/Override";
|
||||
import { FikaHeadlessHelper } from "../../helpers/FikaHeadlessHelper";
|
||||
|
||||
@injectable()
|
||||
export class ClientLogCallbacksOverride extends Override {
|
||||
constructor(
|
||||
@inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil,
|
||||
@inject("FikaHeadlessHelper") protected fikaHeadlessHelper: FikaHeadlessHelper,
|
||||
@inject("ClientLogController") protected clientLogController: ClientLogController,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public execute(container: DependencyContainer): void {
|
||||
container.afterResolution(
|
||||
"ClientLogCallbacks",
|
||||
(_t, result: ClientLogCallbacks) => {
|
||||
result.clientLog = (url: string, info: IClientLogRequest, sessionID: string): INullResponseData => {
|
||||
if (this.fikaHeadlessHelper.isHeadlessClient(sessionID)) {
|
||||
this.clientLogController.clientLog(info);
|
||||
|
||||
return this.httpResponseUtil.nullResponse();
|
||||
}
|
||||
|
||||
return ClientLogCallbacks.prototype.clientLog.call(result, url, info, sessionID);
|
||||
};
|
||||
},
|
||||
{ frequency: "Always" },
|
||||
);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,9 +3,9 @@ import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
import { DialogueController } from "@spt/controllers/DialogueController";
|
||||
import { IGetFriendListDataResponse } from "@spt/models/eft/dialog/IGetFriendListDataResponse";
|
||||
|
||||
import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest";
|
||||
import { FikaDialogueController } from "../../controllers/FikaDialogueController";
|
||||
import { Override } from "../../di/Override";
|
||||
import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest";
|
||||
|
||||
@injectable()
|
||||
export class DialogueControllerOverride extends Override {
|
||||
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
|
||||
import { LauncherController } from "@spt/controllers/LauncherController";
|
||||
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IConnectResponse } from "@spt/models/eft/profile/IConnectResponse";
|
||||
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
import { Override } from "../../di/Override";
|
||||
import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig";
|
||||
|
||||
@injectable()
|
||||
export class LauncherControllerOverride extends Override {
|
||||
protected coreConfig: ICoreConfig;
|
||||
|
||||
constructor(
|
||||
@inject("LauncherController") protected launcherController: LauncherController,
|
||||
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE);
|
||||
}
|
||||
|
||||
public execute(container: DependencyContainer): void {
|
||||
container.afterResolution(
|
||||
"LauncherController",
|
||||
(_t, result: LauncherController) => {
|
||||
result.connect = (): IConnectResponse => {
|
||||
let editions = this.databaseService.getProfiles();
|
||||
|
||||
if (!this.fikaConfig.getConfig().server.showDevProfile) {
|
||||
// biome-ignore lint/performance/noDelete: Only ran once.
|
||||
delete editions["SPT Developer"];
|
||||
}
|
||||
|
||||
if (!this.fikaConfig.getConfig().server.showNonStandardProfile) {
|
||||
for (const id of ["Tournament", "SPT Easy start", "SPT Zero to hero"]) {
|
||||
delete editions[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Stop TS from throwing a tantrum over protected methods
|
||||
const launchController = this.launcherController as any;
|
||||
|
||||
return {
|
||||
backendUrl: this.httpServerHelper.getBackendUrl(),
|
||||
name: this.coreConfig.serverName,
|
||||
editions: Object.keys(editions),
|
||||
profileDescriptions: launchController.getProfileDescriptions(),
|
||||
};
|
||||
};
|
||||
},
|
||||
{ frequency: "Always" },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
import { MatchController } from "@spt/controllers/MatchController";
|
||||
import { Override } from "../../di/Override";
|
||||
import { FikaInsuranceService } from "../../services/FikaInsuranceService";
|
||||
import { FikaMatchService } from "../../services/FikaMatchService";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { IEndLocalRaidRequestData } from "@spt/models/eft/match/IEndLocalRaidRequestData";
|
||||
|
||||
@injectable()
|
||||
export class MatchControllerOverride extends Override {
|
||||
constructor(
|
||||
@inject("FikaInsuranceService") protected fikaInsuranceService: FikaInsuranceService,
|
||||
@inject("FikaMatchService") protected fikaMatchService: FikaMatchService,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public execute(container: DependencyContainer): void {
|
||||
container.afterResolution(
|
||||
"MatchController",
|
||||
(_t, result: MatchController) => {
|
||||
result.endLocalRaid = (sessionId: string, request: IEndLocalRaidRequestData) => {
|
||||
this.fikaInsuranceService.onEndLocalRaidRequest(sessionId, this.fikaInsuranceService.getMatchId(sessionId), request);
|
||||
};
|
||||
},
|
||||
{ frequency: "Always" },
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
-60
@@ -3,8 +3,6 @@ import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
import { ProfileController } from "@spt/controllers/ProfileController";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { IMiniProfile } from "@spt/models/eft/launcher/IMiniProfile";
|
||||
import { IGetOtherProfileRequest } from "@spt/models/eft/profile/IGetOtherProfileRequest";
|
||||
import { IGetOtherProfileResponse } from "@spt/models/eft/profile/IGetOtherProfileResponse";
|
||||
import { ISearchFriendRequestData } from "@spt/models/eft/profile/ISearchFriendRequestData";
|
||||
import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse";
|
||||
|
||||
@@ -40,7 +38,7 @@ export class ProfileControllerOverride extends Override {
|
||||
const matches: ISearchFriendResponse[] = [];
|
||||
|
||||
for (const profile of Object.values(profiles)) {
|
||||
if (profile.info?.password === "fika-dedicated") continue;
|
||||
if (profile.info?.password === "fika-headless") continue;
|
||||
|
||||
if (profile.characters?.pmc?.Info) {
|
||||
if (profile.characters.pmc.Info.Nickname.toLowerCase().startsWith(searchNicknameLowerCase)) {
|
||||
@@ -52,6 +50,7 @@ export class ProfileControllerOverride extends Override {
|
||||
Side: profile.characters.pmc.Info.Side,
|
||||
Level: profile.characters.pmc.Info.Level,
|
||||
MemberCategory: profile.characters.pmc.Info.MemberCategory,
|
||||
SelectedMemberCategory: profile.characters.pmc.Info.SelectedMemberCategory,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -60,63 +59,6 @@ export class ProfileControllerOverride extends Override {
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
result.getOtherProfile = (sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse => {
|
||||
const profiles = this.profileHelper.getProfiles();
|
||||
|
||||
// default to player profile
|
||||
let profileId = sessionId;
|
||||
|
||||
for (const profile of Object.values(profiles)) {
|
||||
if (profile.characters.pmc.aid === Number(request.accountId)) {
|
||||
profileId = profile.characters.pmc._id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const player = this.profileHelper.getFullProfile(profileId);
|
||||
const playerPmc = player.characters.pmc;
|
||||
const playerScav = player.characters.scav;
|
||||
|
||||
return {
|
||||
id: playerPmc._id,
|
||||
aid: playerPmc.aid,
|
||||
info: {
|
||||
nickname: playerPmc.Info.Nickname,
|
||||
side: playerPmc.Info.Side,
|
||||
experience: playerPmc.Info.Experience,
|
||||
memberCategory: playerPmc.Info.MemberCategory,
|
||||
bannedState: playerPmc.Info.BannedState,
|
||||
bannedUntil: playerPmc.Info.BannedUntil,
|
||||
registrationDate: playerPmc.Info.RegistrationDate,
|
||||
},
|
||||
customization: {
|
||||
head: playerPmc.Customization.Head,
|
||||
body: playerPmc.Customization.Body,
|
||||
feet: playerPmc.Customization.Feet,
|
||||
hands: playerPmc.Customization.Hands,
|
||||
},
|
||||
skills: playerPmc.Skills,
|
||||
equipment: {
|
||||
Id: playerPmc.Inventory.equipment,
|
||||
Items: playerPmc.Inventory.items,
|
||||
},
|
||||
achievements: playerPmc.Achievements,
|
||||
favoriteItems: playerPmc.Inventory.favoriteItems ?? [],
|
||||
pmcStats: {
|
||||
eft: {
|
||||
totalInGameTime: playerPmc.Stats.Eft.TotalInGameTime,
|
||||
overAllCounters: playerPmc.Stats.Eft.OverallCounters,
|
||||
},
|
||||
},
|
||||
scavStats: {
|
||||
eft: {
|
||||
totalInGameTime: playerScav.Stats.Eft.TotalInGameTime,
|
||||
overAllCounters: playerScav.Stats.Eft.OverallCounters,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
{ frequency: "Always" },
|
||||
);
|
||||
|
||||
@@ -6,8 +6,10 @@ import { HttpRouter } from "@spt/routers/HttpRouter";
|
||||
|
||||
import { Override } from "../../di/Override";
|
||||
|
||||
// Thanks to DrakiaXYZ for this implementation
|
||||
|
||||
/**
|
||||
* This override is essential for setups where the backendIp or NAT port mapping differs from the SPT server’s backend port.
|
||||
* Without it, SPT constructs an incorrect backend URL, causing connection issues (e.g., using 0.0.0.0 instead of the correct address).
|
||||
*/
|
||||
@injectable()
|
||||
export class HttpRouterOverride extends Override {
|
||||
constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {
|
||||
|
||||
+10
-20
@@ -2,37 +2,32 @@ import { DependencyContainer, inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt/context/ContextVariableType";
|
||||
import { LocationController } from "@spt/controllers/LocationController";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { ILocationBase } from "@spt/models/eft/common/ILocationBase";
|
||||
import { IEndLocalRaidRequestData, ILocationTransit } from "@spt/models/eft/match/IEndLocalRaidRequestData";
|
||||
import { IStartLocalRaidRequestData } from "@spt/models/eft/match/IStartLocalRaidRequestData";
|
||||
import { IStartLocalRaidResponseData } from "@spt/models/eft/match/IStartLocalRaidResponseData";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { BotGenerationCacheService } from "@spt/services/BotGenerationCacheService";
|
||||
import { BotLootCacheService } from "@spt/services/BotLootCacheService";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
import { LocationLifecycleService } from "@spt/services/LocationLifecycleService";
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
import { TimeUtil } from "@spt/utils/TimeUtil";
|
||||
|
||||
import { TransitionType } from "@spt/models/enums/TransitionType";
|
||||
import { Override } from "../../di/Override";
|
||||
import { FikaInsuranceService } from "../../services/FikaInsuranceService";
|
||||
import { FikaMatchService } from "../../services/FikaMatchService";
|
||||
|
||||
@injectable()
|
||||
export class LocationLifecycleServiceOverride extends Override {
|
||||
constructor(
|
||||
@inject("FikaInsuranceService") protected fikaInsuranceService: FikaInsuranceService,
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("LocationController") protected locationController: LocationController,
|
||||
@inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil,
|
||||
@inject("FikaMatchService") protected fikaMatchService: FikaMatchService,
|
||||
@inject("LocationLifecycleService") protected locationLifecycleService: LocationLifecycleService,
|
||||
@inject("BotGenerationCacheService") protected botGenerationCacheService: BotGenerationCacheService,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService,
|
||||
@inject("PrimaryLogger") protected logger: ILogger,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -70,12 +65,12 @@ export class LocationLifecycleServiceOverride extends Override {
|
||||
profile: { insuredItems: playerProfile.InsuredItems },
|
||||
locationLoot: locationLoot,
|
||||
transition: {
|
||||
isLocationTransition: false,
|
||||
transitionType: TransitionType.Common,
|
||||
transitionRaidId: "66f5750951530ca5ae09876d",
|
||||
transitionCount: 0,
|
||||
visitedLocations: [],
|
||||
},
|
||||
};
|
||||
} as IStartLocalRaidResponseData;
|
||||
|
||||
// Only has value when transitioning into map from previous one
|
||||
if (request.transition) {
|
||||
@@ -83,11 +78,8 @@ export class LocationLifecycleServiceOverride extends Override {
|
||||
}
|
||||
|
||||
// Get data stored at end of previous raid (if any)
|
||||
const transitionData = this.applicationContext
|
||||
.getLatestValue(ContextVariableType.TRANSIT_INFO)
|
||||
?.getValue<ILocationTransit>();
|
||||
const transitionData = this.applicationContext.getLatestValue(ContextVariableType.TRANSIT_INFO)?.getValue<ILocationTransit>();
|
||||
if (transitionData) {
|
||||
result.transition.isLocationTransition = true;
|
||||
result.transition.transitionRaidId = transitionData.transitionRaidId;
|
||||
result.transition.transitionCount += 1;
|
||||
result.transition.visitedLocations.push(transitionData.sptLastVisitedLocation);
|
||||
@@ -115,11 +107,6 @@ export class LocationLifecycleServiceOverride extends Override {
|
||||
// Get match id from player session id
|
||||
const matchId = this.fikaMatchService.getMatchIdByPlayer(sessionId);
|
||||
|
||||
if (sessionId == matchId) {
|
||||
// Clear bot loot cache only if host ended raid
|
||||
this.botLootCacheService.clearCache();
|
||||
}
|
||||
|
||||
// Find player that exited the raid
|
||||
const player = this.fikaMatchService.getPlayerInMatch(matchId, sessionId);
|
||||
|
||||
@@ -129,8 +116,11 @@ export class LocationLifecycleServiceOverride extends Override {
|
||||
}
|
||||
}
|
||||
|
||||
this.fikaInsuranceService.onEndLocalRaidRequest(sessionId, this.fikaInsuranceService.getMatchId(sessionId), request);
|
||||
|
||||
// Execute the original method if not a spectator
|
||||
if (!isSpectator) {
|
||||
//Prototype callback because apparently setting a original callback before overriding doesn't allow some stuff to work.
|
||||
LocationLifecycleService.prototype.endLocalRaid.call(result, sessionId, request);
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ export class FikaItemEventRouter extends ItemEventRouterDefinition {
|
||||
public override async handleItemEvent(url: string, pmcData: IPmcData, body: any, sessionID: string): Promise<IItemEventRouterResponse> {
|
||||
switch (url) {
|
||||
case "SendToPlayer":
|
||||
return this.fikaSendItemCallbacks.handleSendItem(pmcData, body, sessionID);
|
||||
return await this.fikaSendItemCallbacks.handleSendItem(pmcData, body, sessionID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RouteAction, StaticRouter } from "@spt/di/Router";
|
||||
|
||||
import { IQuest } from "@spt/models/eft/common/tables/IQuest";
|
||||
import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData";
|
||||
import { FikaHeadlessCallbacks } from "../../callbacks/FikaHeadlessCallbacks";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessStaticRouter extends StaticRouter {
|
||||
constructor(@inject("FikaHeadlessCallbacks") protected fikaHeadlessCallbacks: FikaHeadlessCallbacks) {
|
||||
super([
|
||||
new RouteAction("/fika/headless/get", async (url: string, info: any, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaHeadlessCallbacks.handleGetHeadlesses(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/headless/available", async (url: string, info: any, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaHeadlessCallbacks.handleAvailableHeadlesses(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/headless/restartafterraidamount", async (url: string, info: any, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaHeadlessCallbacks.handleRestartAfterRaidAmount(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/headless/questtemplates", async (url: string, info: any, sessionID: string, _output: string): Promise<IGetBodyResponseData<IQuest[]>> => {
|
||||
return this.fikaHeadlessCallbacks.handleGetAllQuestTemplates(url, info, sessionID);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ export class FikaNotificationStaticRouter extends StaticRouter {
|
||||
constructor(@inject("FikaNotificationCallbacks") protected fikaNotificationCallbacks: FikaNotificationCallbacks) {
|
||||
super([
|
||||
new RouteAction("/fika/notification/push", async (url: string, info: IPushNotification, sessionID: string, _output: string): Promise<any> => {
|
||||
return this.fikaNotificationCallbacks.handlePushNotification(url, info, sessionID);
|
||||
return await this.fikaNotificationCallbacks.handlePushNotification(url, info, sessionID);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ import { inject, injectable } from "tsyringe";
|
||||
import { RouteAction, StaticRouter } from "@spt/di/Router";
|
||||
import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData";
|
||||
|
||||
import { IRegisterPlayerRequestData } from "@spt/models/eft/inRaid/IRegisterPlayerRequestData";
|
||||
import { FikaRaidCallbacks } from "../../callbacks/FikaRaidCallbacks";
|
||||
import { IFikaRaidServerIdRequestData } from "../../models/fika/routes/raid/IFikaRaidServerIdRequestData";
|
||||
import { IFikaRaidCreateRequestData } from "../../models/fika/routes/raid/create/IFikaRaidCreateRequestData";
|
||||
import { IStartHeadlessRequest } from "../../models/fika/routes/raid/headless/IStartHeadlessRequest";
|
||||
import { IFikaRaidJoinRequestData } from "../../models/fika/routes/raid/join/IFikaRaidJoinRequestData";
|
||||
import { IFikaRaidLeaveRequestData } from "../../models/fika/routes/raid/leave/IFikaRaidLeaveRequestData";
|
||||
import { IStartDedicatedRequest } from "../../models/fika/routes/raid/dedicated/IStartDedicatedRequest";
|
||||
import { IStatusDedicatedRequest } from "../../models/fika/routes/raid/dedicated/IStatusDedicatedRequest";
|
||||
import { IRegisterPlayerRequestData } from "@spt/models/eft/inRaid/IRegisterPlayerRequestData";
|
||||
|
||||
@injectable()
|
||||
export class FikaRaidStaticRouter extends StaticRouter {
|
||||
@@ -31,14 +30,8 @@ export class FikaRaidStaticRouter extends StaticRouter {
|
||||
new RouteAction("/fika/raid/getsettings", async (url: string, info: IFikaRaidServerIdRequestData, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaRaidCallbacks.handleRaidGetSettings(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/raid/dedicated/start", async (url: string, info: IStartDedicatedRequest, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaRaidCallbacks.handleRaidStartDedicated(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/raid/dedicated/status", async (url: string, info: IStatusDedicatedRequest, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaRaidCallbacks.handleRaidStatusDedicated(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/raid/dedicated/getstatus", async (url: string, info: any, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaRaidCallbacks.handleRaidGetStatusDedicated(url, info, sessionID);
|
||||
new RouteAction("/fika/raid/headless/start", async (url: string, info: IStartHeadlessRequest, sessionID: string, _output: string): Promise<string> => {
|
||||
return this.fikaRaidCallbacks.handleRaidStartHeadless(url, info, sessionID);
|
||||
}),
|
||||
new RouteAction("/fika/raid/registerPlayer", async (url: string, info: IRegisterPlayerRequestData, sessionID: string, _output: string): Promise<INullResponseData> => {
|
||||
return this.fikaRaidCallbacks.handleRaidRegisterPlayer(url, info, sessionID);
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IFikaConfigClient } from "../models/fika/config/IFikaConfigClient";
|
||||
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
|
||||
import { FikaClientModHashesHelper } from "../helpers/FikaClientModHashesHelper";
|
||||
import { IFikaConfigHeadless } from "../models/fika/config/IFikaConfigHeadless";
|
||||
import { IFikaConfigNatPunchServer } from "../models/fika/config/IFikaConfigNatPunchServer";
|
||||
import { IFikaCheckModRequestData } from "../models/fika/routes/client/check/IFikaCheckModRequestData";
|
||||
import { IFikaCheckModResponse, IVersionCheckResponse } from "../models/fika/routes/client/check/IFikaCheckModResponse";
|
||||
import { FikaConfig } from "../utils/FikaConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaClientService {
|
||||
protected requiredMods: string[] = [];
|
||||
protected allowedMods: string[] = [];
|
||||
protected hasRequiredOrOptionalMods: boolean = true;
|
||||
|
||||
constructor(
|
||||
@inject("FikaClientModHashesHelper") protected fikaClientModHashesHelper: FikaClientModHashesHelper,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {}
|
||||
|
||||
public async preInit(): Promise<void> {
|
||||
const config = this.fikaConfig.getConfig();
|
||||
|
||||
const sanitizedRequiredMods = this.filterEmptyMods(config.client.mods.required);
|
||||
const sanitizedOptionalMods = this.filterEmptyMods(config.client.mods.optional);
|
||||
|
||||
if (sanitizedRequiredMods.length === 0 && sanitizedOptionalMods.length === 0) {
|
||||
this.hasRequiredOrOptionalMods = false;
|
||||
}
|
||||
|
||||
this.requiredMods = [...sanitizedRequiredMods, "com.fika.core", "com.SPT.custom", "com.SPT.singleplayer", "com.SPT.core", "com.SPT.debugging"];
|
||||
this.allowedMods = [...this.requiredMods, ...sanitizedOptionalMods, "com.bepis.bepinex.configurationmanager", "com.fika.headless"];
|
||||
}
|
||||
|
||||
protected filterEmptyMods(array: string[]): string[] {
|
||||
return array.filter((str) => str.trim() !== "");
|
||||
}
|
||||
|
||||
public getClientConfig(): IFikaConfigClient {
|
||||
return this.fikaConfig.getConfig().client;
|
||||
}
|
||||
|
||||
public getIsItemSendingAllowed(): boolean {
|
||||
return this.fikaConfig.getConfig().server.allowItemSending;
|
||||
}
|
||||
|
||||
public getNatPunchServerConfig(): IFikaConfigNatPunchServer {
|
||||
return this.fikaConfig.getConfig().natPunchServer;
|
||||
}
|
||||
|
||||
public getHeadlessConfig(): IFikaConfigHeadless {
|
||||
return this.fikaConfig.getConfig().headless;
|
||||
}
|
||||
|
||||
public getVersion(): IVersionCheckResponse {
|
||||
const version = this.fikaConfig.getVersion();
|
||||
return { version };
|
||||
}
|
||||
|
||||
public getCheckModsResponse(request: IFikaCheckModRequestData, sessionID: string): IFikaCheckModResponse {
|
||||
const mismatchedMods: IFikaCheckModResponse = {
|
||||
forbidden: [],
|
||||
missingRequired: [],
|
||||
hashMismatch: [],
|
||||
};
|
||||
|
||||
if (this.fikaConfig.getConfig().server.logClientModsInConsole) {
|
||||
const username = this.saveServer.getProfile(sessionID).info.username;
|
||||
const mods = Object.keys(request);
|
||||
|
||||
this.logger.info(`${username} (${sessionID}) connected with ${mods.length} client mods: ${mods.join(", ")}`);
|
||||
}
|
||||
|
||||
// if no configuration was made, allow all mods
|
||||
if (!this.hasRequiredOrOptionalMods) {
|
||||
return mismatchedMods;
|
||||
}
|
||||
|
||||
//check for missing required mods first
|
||||
for (const pluginId of this.requiredMods) {
|
||||
if (!request[pluginId]) {
|
||||
mismatchedMods.missingRequired.push(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
// no need to check anything else since it's missing required mods
|
||||
if (mismatchedMods.missingRequired.length > 0) {
|
||||
return mismatchedMods;
|
||||
}
|
||||
|
||||
for (const [pluginId, hash] of Object.entries(request)) {
|
||||
// check if the mod isn't allowed
|
||||
if (!this.allowedMods.includes(pluginId)) {
|
||||
mismatchedMods.forbidden.push(pluginId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// first request made will fill in at the very least all the required mods hashes, following requests made by different clients will add any optional mod not added by the first request, otherwise will check against the first request data
|
||||
if (!this.fikaClientModHashesHelper.exists(pluginId)) {
|
||||
this.fikaClientModHashesHelper.addHash(pluginId, hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.fikaClientModHashesHelper.getHash(pluginId) !== hash) {
|
||||
mismatchedMods.hashMismatch.push(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
return mismatchedMods;
|
||||
}
|
||||
|
||||
public getProfileBySessionID(sessionID: string): any {
|
||||
const profile = this.saveServer.getProfile(sessionID);
|
||||
if (profile) {
|
||||
this.logger.info(`${sessionID} has downloaded their profile`);
|
||||
return profile;
|
||||
}
|
||||
|
||||
this.logger.error(`${sessionID} wants to download their profile but we don't have it`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
|
||||
import { MatchController } from "@spt/controllers/MatchController";
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { IEndLocalRaidRequestData } from "@spt/models/eft/match/IEndLocalRaidRequestData";
|
||||
import { BaseClasses } from "@spt/models/enums/BaseClasses";
|
||||
@@ -16,7 +15,6 @@ export class FikaInsuranceService {
|
||||
constructor(
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("MatchController") protected matchController: MatchController,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
this.matchInsuranceInfo = {};
|
||||
@@ -42,7 +40,7 @@ export class FikaInsuranceService {
|
||||
endedRaid: false,
|
||||
lostItems: [],
|
||||
foundItems: [],
|
||||
inventory: [],
|
||||
inventory: [],
|
||||
};
|
||||
|
||||
this.matchInsuranceInfo[matchId].push(player);
|
||||
@@ -51,9 +49,6 @@ export class FikaInsuranceService {
|
||||
public onEndLocalRaidRequest(sessionID: string, matchId: string, endLocalRaidRequest: IEndLocalRaidRequestData): void {
|
||||
if (!(matchId in this.matchInsuranceInfo)) {
|
||||
this.logger.error("[Fika Insurance] onEndLocalRaidRequest: matchId not found!");
|
||||
|
||||
// Pass back to SPT so that the player can save.
|
||||
MatchController.prototype.endLocalRaid.call(this.matchController, sessionID, endLocalRaidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,9 +64,6 @@ export class FikaInsuranceService {
|
||||
player.inventory = endLocalRaidRequest.results.profile.Inventory.items.map((i) => i._id);
|
||||
player.endedRaid = true;
|
||||
}
|
||||
|
||||
// Pass back to SPT so that the player can save.
|
||||
MatchController.prototype.endLocalRaid.call(this.matchController, sessionID, endLocalRaidRequest);
|
||||
}
|
||||
|
||||
public onMatchEnd(matchId: string): void {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { LocationLifecycleService } from "@spt/services/LocationLifecycleService";
|
||||
|
||||
@@ -11,10 +11,11 @@ import { IFikaMatch } from "../models/fika/IFikaMatch";
|
||||
import { IFikaPlayer } from "../models/fika/IFikaPlayer";
|
||||
import { IFikaRaidCreateRequestData } from "../models/fika/routes/raid/create/IFikaRaidCreateRequestData";
|
||||
|
||||
import { FikaHeadlessHelper } from "../helpers/FikaHeadlessHelper";
|
||||
import { FikaConfig } from "../utils/FikaConfig";
|
||||
import { FikaInsuranceService } from "./FikaInsuranceService";
|
||||
import { FikaPresenceService } from "./FikaPresenceService";
|
||||
import { FikaDedicatedRaidService } from "./dedicated/FikaDedicatedRaidService";
|
||||
import { FikaHeadlessService } from "./headless/FikaHeadlessService";
|
||||
|
||||
@injectable()
|
||||
export class FikaMatchService {
|
||||
@@ -26,7 +27,8 @@ export class FikaMatchService {
|
||||
@inject("LocationLifecycleService") protected locationLifecycleService: LocationLifecycleService,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("FikaDedicatedRaidService") protected fikaDedicatedRaidService: FikaDedicatedRaidService,
|
||||
@inject("FikaHeadlessHelper") protected fikaHeadlessHelper: FikaHeadlessHelper,
|
||||
@inject("FikaHeadlessService") protected fikaHeadlessService: FikaHeadlessService,
|
||||
@inject("FikaInsuranceService") protected fikaInsuranceService: FikaInsuranceService,
|
||||
@inject("FikaPresenceService") protected fikaPresenceService: FikaPresenceService,
|
||||
) {
|
||||
@@ -97,15 +99,7 @@ export class FikaMatchService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all match ids
|
||||
* @returns
|
||||
*/
|
||||
public getAllMatchIds(): string[] {
|
||||
return Array.from(this.matches.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player with the given id in the given match, undefined if either match or player does not exist
|
||||
* Returns the player with the given id in the given match, returns undefined if either match or player does not exist
|
||||
* @param matchId
|
||||
* @param playerId
|
||||
* @returns
|
||||
@@ -123,28 +117,12 @@ export class FikaMatchService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all playerIds in the given match, undefined if match does not exist
|
||||
*
|
||||
* Note:
|
||||
* - host player is the one where playerId is equal to matchId
|
||||
* @param matchId
|
||||
* @returns
|
||||
*/
|
||||
public getPlayersIdsByMatch(matchId: string): string[] {
|
||||
if (!this.matches.has(matchId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Array.from(this.matches.get(matchId).players.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the match id that has a player with the given player id, undefined if the player isn't in a match
|
||||
* Returns the match id that has a player with the given player id, returns undefined if the player isn't in a match
|
||||
*
|
||||
* @param playerId
|
||||
* @returns
|
||||
*/
|
||||
public getMatchIdByPlayer(playerId: string): string {
|
||||
public getMatchIdByPlayer(playerId: string): string | undefined {
|
||||
for (const [key, value] of this.matches.entries()) {
|
||||
if (value.players.has(playerId)) {
|
||||
return key;
|
||||
@@ -155,14 +133,14 @@ export class FikaMatchService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the match id that has a player with the given session id, undefined if the player isn't in a match
|
||||
* Returns the match id that has a player with the given session id, returns undefined if the player isn't in a match
|
||||
*
|
||||
* Note:
|
||||
* - First tries to find pmc, then scav
|
||||
* @param sessionId
|
||||
* @returns
|
||||
*/
|
||||
public getMatchIdByProfile(sessionId: string): string {
|
||||
public getMatchIdByProfile(sessionId: string): string | undefined {
|
||||
const profile = this.saveServer.getProfile(sessionId);
|
||||
|
||||
// check if pmc is in match
|
||||
@@ -200,20 +178,24 @@ export class FikaMatchService {
|
||||
locationData: locationData,
|
||||
status: EFikaMatchStatus.LOADING,
|
||||
timeout: 0,
|
||||
players: new Map(),
|
||||
players: new Map<string, IFikaPlayer>(),
|
||||
gameVersion: data.gameVersion,
|
||||
fikaVersion: data.fikaVersion,
|
||||
crc32: data.crc32,
|
||||
side: data.side,
|
||||
time: data.time,
|
||||
raidCode: data.raidCode,
|
||||
natPunch: false,
|
||||
isDedicated: false,
|
||||
isHeadless: false,
|
||||
raids: 0,
|
||||
});
|
||||
|
||||
this.addTimeoutInterval(data.serverId);
|
||||
|
||||
this.addPlayerToMatch(data.serverId, data.serverId, { groupId: null, isDead: false, isSpectator: data.isSpectator });
|
||||
this.addPlayerToMatch(data.serverId, data.serverId, {
|
||||
groupId: null,
|
||||
isDead: false,
|
||||
isSpectator: data.isSpectator,
|
||||
});
|
||||
|
||||
return this.matches.has(data.serverId) && this.timeoutIntervals.has(data.serverId);
|
||||
}
|
||||
@@ -240,8 +222,8 @@ export class FikaMatchService {
|
||||
public endMatch(matchId: string, reason: EFikaMatchEndSessionMessage): void {
|
||||
this.logger.info(`Coop session ${matchId} has ended: ${reason}`);
|
||||
|
||||
if (this.fikaDedicatedRaidService.requestedSessions.hasOwnProperty(matchId)) {
|
||||
delete this.fikaDedicatedRaidService.requestedSessions[matchId];
|
||||
if (this.fikaHeadlessHelper.isHeadlessClient(matchId)) {
|
||||
this.fikaHeadlessService.endHeadlessRaid(matchId);
|
||||
}
|
||||
|
||||
this.fikaInsuranceService.onMatchEnd(matchId);
|
||||
@@ -253,15 +235,15 @@ export class FikaMatchService {
|
||||
* @param matchId
|
||||
* @param status
|
||||
*/
|
||||
public setMatchStatus(matchId: string, status: EFikaMatchStatus): void {
|
||||
public async setMatchStatus(matchId: string, status: EFikaMatchStatus): Promise<void> {
|
||||
if (!this.matches.has(matchId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.matches.get(matchId).status = status;
|
||||
|
||||
if (status.toString() == "COMPLETE") {
|
||||
this.fikaDedicatedRaidService.handleRequestedSessions(matchId);
|
||||
if (status === EFikaMatchStatus.COMPLETE) {
|
||||
await this.fikaHeadlessService.sendJoinMessageToRequester(matchId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +253,7 @@ export class FikaMatchService {
|
||||
* @param ips
|
||||
* @param port
|
||||
*/
|
||||
public setMatchHost(matchId: string, ips: string[], port: number, natPunch: boolean, isDedicated: boolean): void {
|
||||
public setMatchHost(matchId: string, ips: string[], port: number, natPunch: boolean, isHeadless: boolean): void {
|
||||
if (!this.matches.has(matchId)) {
|
||||
return;
|
||||
}
|
||||
@@ -281,7 +263,7 @@ export class FikaMatchService {
|
||||
match.ips = ips;
|
||||
match.port = port;
|
||||
match.natPunch = natPunch;
|
||||
match.isDedicated = isDedicated;
|
||||
match.isHeadless = isHeadless;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,9 +294,11 @@ export class FikaMatchService {
|
||||
|
||||
this.fikaInsuranceService.addPlayerToMatchId(matchId, playerId);
|
||||
|
||||
this.fikaPresenceService.updatePlayerPresence(playerId, this.fikaPresenceService.generateSetPresence(
|
||||
EFikaPlayerPresences.IN_RAID,
|
||||
this.fikaPresenceService.generateRaidPresence(match.locationData.Id, match.side, match.time)));
|
||||
if (this.fikaHeadlessHelper.isHeadlessClient(matchId)) {
|
||||
this.fikaHeadlessService.addPlayerToHeadlessMatch(matchId, playerId);
|
||||
}
|
||||
|
||||
this.fikaPresenceService.updatePlayerPresence(playerId, this.fikaPresenceService.generateSetPresence(EFikaPlayerPresences.IN_RAID, this.fikaPresenceService.generateRaidPresence(match.locationData.Id, match.side, match.time)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { TimeUtil } from "@spt/utils/TimeUtil";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { TimeUtil } from "@spt/utils/TimeUtil";
|
||||
|
||||
import { EFikaPlayerPresences } from "../models/enums/EFikaPlayerPresences";
|
||||
import { EFikaSide } from "../models/enums/EFikaSide";
|
||||
import { EFikaTime } from "../models/enums/EFikaTime";
|
||||
import { IFikaPlayerPresence } from "../models/fika/presence/IFikaPlayerPresence";
|
||||
import { IFikaRaidPresence } from "../models/fika/presence/IFikaRaidPresence";
|
||||
import { IFikaSetPresence } from "../models/fika/presence/IFikaSetPresence";
|
||||
import { EFikaSide } from "../models/enums/EFikaSide";
|
||||
import { EFikaTime } from "../models/enums/EFikaTime";
|
||||
|
||||
@injectable()
|
||||
export class FikaPresenceService {
|
||||
|
||||
Vendored
+7
-7
@@ -1,7 +1,7 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { FileSystemSync } from "@spt/utils/FileSystemSync";
|
||||
import { JsonUtil } from "@spt/utils/JsonUtil";
|
||||
import { VFS } from "@spt/utils/VFS";
|
||||
|
||||
import { IFikaFriendRequests } from "../../models/fika/IFikaFriendRequests";
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
@@ -14,16 +14,16 @@ export class FikaFriendRequestsCacheService {
|
||||
|
||||
constructor(
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("VFS") protected vfs: VFS,
|
||||
@inject("FileSystemSync") protected fileSystemSync: FileSystemSync,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
) {
|
||||
this.friendRequestsFullPath = `./${this.fikaConfig.getModPath()}${this.friendRequestsPath}`;
|
||||
|
||||
if (!this.vfs.exists(this.friendRequestsFullPath)) {
|
||||
this.vfs.writeFile(this.friendRequestsFullPath, "[]");
|
||||
if (!this.fileSystemSync.exists(this.friendRequestsFullPath)) {
|
||||
this.fileSystemSync.write(this.friendRequestsFullPath, "[]");
|
||||
}
|
||||
|
||||
this.friendRequests = this.jsonUtil.deserialize(this.vfs.readFile(this.friendRequestsFullPath), this.friendRequestsFullPath);
|
||||
this.friendRequests = this.jsonUtil.deserialize(this.fileSystemSync.read(this.friendRequestsFullPath), this.friendRequestsFullPath);
|
||||
}
|
||||
|
||||
public getAllFriendRequests(): IFikaFriendRequests[] {
|
||||
@@ -50,12 +50,12 @@ export class FikaFriendRequestsCacheService {
|
||||
|
||||
this.friendRequests.splice(index, 1);
|
||||
|
||||
this.vfs.writeFile(this.friendRequestsFullPath, this.jsonUtil.serialize(this.friendRequests));
|
||||
this.fileSystemSync.write(this.friendRequestsFullPath, this.jsonUtil.serialize(this.friendRequests));
|
||||
}
|
||||
|
||||
public storeFriendRequest(value: IFikaFriendRequests): void {
|
||||
this.friendRequests.push(value);
|
||||
|
||||
this.vfs.writeFile(this.friendRequestsFullPath, this.jsonUtil.serialize(this.friendRequests));
|
||||
this.fileSystemSync.write(this.friendRequestsFullPath, this.jsonUtil.serialize(this.friendRequests));
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+8
-8
@@ -1,9 +1,9 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { FileSystemSync } from "@spt/utils/FileSystemSync";
|
||||
import { JsonUtil } from "@spt/utils/JsonUtil";
|
||||
import { VFS } from "@spt/utils/VFS";
|
||||
|
||||
import { IFikaPlayerRelations } from "../../models/fika/IFikaPlayerRelations";
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
@@ -18,16 +18,16 @@ export class FikaPlayerRelationsCacheService {
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("VFS") protected vfs: VFS,
|
||||
@inject("FileSystemSync") protected fileSystemSync: FileSystemSync,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
) {
|
||||
this.playerRelationsFullPath = `./${this.fikaConfig.getModPath()}${this.playerRelationsPath}`;
|
||||
|
||||
if (!this.vfs.exists(this.playerRelationsFullPath)) {
|
||||
this.vfs.writeFile(this.playerRelationsFullPath, "{}");
|
||||
if (!this.fileSystemSync.exists(this.playerRelationsFullPath)) {
|
||||
this.fileSystemSync.write(this.playerRelationsFullPath, "{}");
|
||||
}
|
||||
|
||||
this.playerRelations = this.jsonUtil.deserialize(this.vfs.readFile(this.playerRelationsFullPath), this.playerRelationsFullPath);
|
||||
this.playerRelations = this.jsonUtil.deserialize(this.fileSystemSync.read(this.playerRelationsFullPath), this.playerRelationsFullPath);
|
||||
}
|
||||
|
||||
public postInit() {
|
||||
@@ -73,7 +73,7 @@ export class FikaPlayerRelationsCacheService {
|
||||
}
|
||||
|
||||
if (shouldSave) {
|
||||
this.vfs.writeFile(this.playerRelationsFullPath, this.jsonUtil.serialize(this.playerRelations));
|
||||
this.fileSystemSync.write(this.playerRelationsFullPath, this.jsonUtil.serialize(this.playerRelations));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,6 @@ export class FikaPlayerRelationsCacheService {
|
||||
public storeValue(key: string, value: IFikaPlayerRelations): void {
|
||||
this.playerRelations[key] = value;
|
||||
|
||||
this.vfs.writeFile(this.playerRelationsFullPath, this.jsonUtil.serialize(this.playerRelations));
|
||||
this.fileSystemSync.write(this.playerRelationsFullPath, this.jsonUtil.serialize(this.playerRelations));
|
||||
}
|
||||
}
|
||||
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { LauncherController } from "@spt/controllers/LauncherController";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { TimeUtil } from "@spt/utils/TimeUtil";
|
||||
import { RandomUtil } from "@spt/utils/RandomUtil";
|
||||
import { HashUtil } from "@spt/utils/HashUtil";
|
||||
import { Info, ISptProfile } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { ProfileController } from "@spt/controllers/ProfileController";
|
||||
import { IProfileCreateRequestData } from "@spt/models/eft/profile/IProfileCreateRequestData";
|
||||
import { IFikaConfigDedicated } from "../../models/fika/config/IFikaConfigDedicated";
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaDedicatedProfileService {
|
||||
readonly scriptsPath = path.join(__dirname, "../../../assets/scripts");
|
||||
readonly HEAD_USEC_4 = "5fdb4139e4ed5b5ea251e4ed"; // _parent: 5cc085e214c02e000c6bea67
|
||||
readonly VOICE_USEC_4 = "6284d6a28e4092597733b7a6"; // _parent: 5fc100cf95572123ae738483
|
||||
|
||||
protected httpConfig: IHttpConfig;
|
||||
protected dedicatedConfig: IFikaConfigDedicated;
|
||||
public dedicatedProfiles: ISptProfile[] = [];
|
||||
|
||||
constructor(
|
||||
@inject("LauncherController") protected launcherController: LauncherController,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("ProfileController") protected profileController: ProfileController,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
) {
|
||||
this.dedicatedConfig = fikaConfig.getConfig().dedicated;
|
||||
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.dedicatedProfiles = this.loadDedicatedProfiles();
|
||||
|
||||
this.logger.info(`Found ${this.dedicatedProfiles.length} dedicated client profiles.`);
|
||||
|
||||
const profileAmount = this.dedicatedConfig.profiles.amount;
|
||||
|
||||
if (this.dedicatedProfiles.length < profileAmount) {
|
||||
const createdProfiles = this.createDedicatedProfiles(profileAmount);
|
||||
|
||||
this.logger.success(`Created ${createdProfiles.length} dedicated client profiles!`);
|
||||
|
||||
if (this.dedicatedConfig.scripts.generate) {
|
||||
let ip = this.httpConfig.ip;
|
||||
const port = this.httpConfig.port;
|
||||
|
||||
const forceIp = this.dedicatedConfig.scripts.forceIp;
|
||||
|
||||
if (forceIp != "") {
|
||||
ip = forceIp;
|
||||
}
|
||||
|
||||
if (ip == "0.0.0.0") {
|
||||
ip = "127.0.0.1";
|
||||
}
|
||||
|
||||
const backendUrl = `http://${ip}:${port}`;
|
||||
|
||||
for (const profile of createdProfiles) {
|
||||
this.generateLaunchScript(profile, backendUrl, this.scriptsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public loadDedicatedProfiles(): ISptProfile[] {
|
||||
let profiles: ISptProfile[] = [];
|
||||
|
||||
for (const profileId in this.saveServer.getProfiles()) {
|
||||
const profile = this.saveServer.getProfile(profileId);
|
||||
|
||||
if (profile.info.password == "fika-dedicated") {
|
||||
profiles.push(profile);
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public createDedicatedProfiles(profileAmount: number): ISptProfile[] {
|
||||
let profileCount = this.dedicatedProfiles.length;
|
||||
let profileAmountToCreate = profileAmount - profileCount;
|
||||
let createdProfiles: ISptProfile[] = [];
|
||||
|
||||
for (let i = 0; i < profileAmountToCreate; i++) {
|
||||
const profile = this.createDedicatedProfile();
|
||||
createdProfiles.push(profile);
|
||||
}
|
||||
|
||||
return createdProfiles;
|
||||
}
|
||||
|
||||
public createDedicatedProfile(): ISptProfile {
|
||||
// Generate a unique username
|
||||
const username = `dedicated_${this.generateUniqueId()}`;
|
||||
// Using a password allows us to know which profiles are dedicated client profiles.
|
||||
const password = "fika-dedicated";
|
||||
// Random edition. Doesn't matter
|
||||
const edition = "Edge Of Darkness";
|
||||
|
||||
// Create mini profile
|
||||
const profileId = this.createMiniProfile(username, password, edition);
|
||||
|
||||
// Random character configs. Doesn't matter.
|
||||
const newProfileData: IProfileCreateRequestData = {
|
||||
side: "usec",
|
||||
nickname: username, // Use the username as the nickname to ensure it is unique.
|
||||
headId: this.HEAD_USEC_4,
|
||||
voiceId: this.VOICE_USEC_4,
|
||||
};
|
||||
|
||||
const profile = this.createFullProfile(newProfileData, profileId);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
public createMiniProfile(username: string, password: string, edition: string): string {
|
||||
const profileId = this.generateUniqueId();
|
||||
const scavId = this.generateUniqueId();
|
||||
|
||||
const newProfileDetails: Info = {
|
||||
id: profileId,
|
||||
scavId: scavId,
|
||||
aid: this.hashUtil.generateAccountId(),
|
||||
username: username,
|
||||
password: password,
|
||||
wipe: true,
|
||||
edition: edition,
|
||||
};
|
||||
|
||||
this.saveServer.createProfile(newProfileDetails);
|
||||
|
||||
this.saveServer.loadProfile(profileId);
|
||||
this.saveServer.saveProfile(profileId);
|
||||
|
||||
return profileId;
|
||||
}
|
||||
|
||||
public createFullProfile(profileData: IProfileCreateRequestData, profileId: string) {
|
||||
this.profileController.createProfile(profileData, profileId);
|
||||
|
||||
const profile = this.saveServer.getProfile(profileId);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
public generateLaunchScript(profile: ISptProfile, backendUrl: string, targetFolderPath: string) {
|
||||
const scriptName = `Start_${profile.info.username}.bat`;
|
||||
const scriptPath = path.join(targetFolderPath, scriptName);
|
||||
const scriptContent = `@echo off
|
||||
if NOT EXIST ".\\BepInEx\\plugins\\Fika.Dedicated.dll" (
|
||||
echo Could not find 'Fika.Dedicated.dll', please install the dedicated plugin before starting the client.
|
||||
pause
|
||||
) else (
|
||||
start "" EscapeFromTarkov.exe -token=${profile.info.id} -config={"BackendUrl":"${backendUrl}","Version":"live"} -batchmode -nographics --enable-console true & exit
|
||||
)`;
|
||||
|
||||
try {
|
||||
if (!fs.existsSync(targetFolderPath)) {
|
||||
fs.mkdirSync(targetFolderPath);
|
||||
}
|
||||
|
||||
fs.writeFileSync(scriptPath, scriptContent);
|
||||
|
||||
this.logger.success(`Generated launch script: /fika-server/assets/scripts/${scriptName}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to generate launch script: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// generateProfileId
|
||||
protected generateUniqueId(): string {
|
||||
const timestamp = this.timeUtil.getTimestamp();
|
||||
|
||||
return this.formatID(timestamp, timestamp * this.randomUtil.getInt(1, 1000000));
|
||||
}
|
||||
|
||||
protected formatID(timeStamp: number, counter: number): string {
|
||||
const timeStampStr = timeStamp.toString(16).padStart(8, "0");
|
||||
const counterStr = counter.toString(16).padStart(16, "0");
|
||||
|
||||
return timeStampStr.toLowerCase() + counterStr.toLowerCase();
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
|
||||
import { IDedicatedClientInfo } from "../../models/fika/dedicated/IDedicatedClientInfo";
|
||||
import { FikaDedicatedRaidWebSocket } from "../../websockets/FikaDedicatedRaidWebSocket";
|
||||
|
||||
@injectable()
|
||||
export class FikaDedicatedRaidService {
|
||||
public dedicatedClients: Record<string, IDedicatedClientInfo>;
|
||||
public requestedSessions: Record<string, string>;
|
||||
public onNoDedicatedClientAvailable?: () => void;
|
||||
public onDedicatedClientAvailable?: () => void;
|
||||
public onDedicatedClientResponse?: (sessionID: string) => void;
|
||||
|
||||
constructor(
|
||||
@inject("FikaDedicatedRaidWebSocket") protected fikaDedicatedRaidWebSocket: FikaDedicatedRaidWebSocket,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
this.dedicatedClients = {};
|
||||
this.requestedSessions = {};
|
||||
|
||||
// TODO: find a more elegant solution to keep track of dedicated clients being available.
|
||||
setInterval(() => {
|
||||
const currentTime = Date.now();
|
||||
|
||||
for (const dedicatedClientSessionId in this.dedicatedClients) {
|
||||
const dedicatedClientLastPing = this.dedicatedClients[dedicatedClientSessionId].lastPing;
|
||||
|
||||
if (currentTime - dedicatedClientLastPing > 16000) {
|
||||
delete this.dedicatedClients[dedicatedClientSessionId];
|
||||
logger.info(`Dedicated client removed: ${dedicatedClientSessionId}`);
|
||||
}
|
||||
|
||||
if (!this.isDedicatedClientAvailable()) {
|
||||
if (this.onNoDedicatedClientAvailable) {
|
||||
this.onNoDedicatedClientAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
public handleRequestedSessions(matchId: string): void {
|
||||
if (matchId in this.requestedSessions) {
|
||||
const userToJoin = this.requestedSessions[matchId];
|
||||
|
||||
this.fikaDedicatedRaidWebSocket.clientWebSockets[userToJoin].send(
|
||||
JSON.stringify({
|
||||
type: "fikaDedicatedJoinMatch",
|
||||
matchId: matchId,
|
||||
}),
|
||||
);
|
||||
|
||||
this.logger.info(`Told ${userToJoin} to join raid ${matchId}`);
|
||||
}
|
||||
}
|
||||
|
||||
public isDedicatedClientAvailable(): boolean {
|
||||
return Object.keys(this.dedicatedClients).length > 0;
|
||||
}
|
||||
}
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
import path from "path";
|
||||
|
||||
import { ProfileController } from "@spt/controllers/ProfileController";
|
||||
import { IProfileCreateRequestData } from "@spt/models/eft/profile/IProfileCreateRequestData";
|
||||
import { ISptProfile, Info } from "@spt/models/eft/profile/ISptProfile";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { FileSystem } from "@spt/utils/FileSystem";
|
||||
import { HashUtil } from "@spt/utils/HashUtil";
|
||||
|
||||
import { InventoryHelper } from "@spt/helpers/InventoryHelper";
|
||||
import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
import { IItem } from "@spt/models/eft/common/tables/IItem";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessProfileService {
|
||||
readonly scriptsPath = path.join(__dirname, "../../../assets/scripts");
|
||||
readonly HEAD_USEC_4 = "5fdb4139e4ed5b5ea251e4ed"; // _parent: 5cc085e214c02e000c6bea67
|
||||
readonly VOICE_USEC_4 = "6284d6a28e4092597733b7a6"; // _parent: 5fc100cf95572123ae738483
|
||||
|
||||
protected httpConfig: IHttpConfig;
|
||||
private headlessProfiles: ISptProfile[] = [];
|
||||
|
||||
constructor(
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("ProfileController") protected profileController: ProfileController,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
|
||||
@inject("FileSystem") protected fileSystem: FileSystem,
|
||||
) {
|
||||
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
|
||||
}
|
||||
|
||||
public getHeadlessProfiles(): ISptProfile[] {
|
||||
return this.headlessProfiles;
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
const headlessConfig = this.fikaConfig.getConfig().headless;
|
||||
|
||||
this.headlessProfiles = this.loadHeadlessProfiles();
|
||||
|
||||
this.logger.info(`Found ${this.headlessProfiles.length} headless client profiles.`);
|
||||
|
||||
const profileAmount = headlessConfig.profiles.amount;
|
||||
|
||||
if (this.headlessProfiles.length < profileAmount) {
|
||||
const createdProfiles = await this.createHeadlessProfiles(profileAmount);
|
||||
|
||||
this.logger.success(`Created ${createdProfiles.length} headless client profiles!`);
|
||||
|
||||
if (headlessConfig.scripts.generate) {
|
||||
let ip = this.httpConfig.ip;
|
||||
const port = this.httpConfig.port;
|
||||
|
||||
const forceIp = headlessConfig.scripts.forceIp;
|
||||
|
||||
if (forceIp != "") {
|
||||
ip = forceIp;
|
||||
}
|
||||
|
||||
if (ip == "0.0.0.0") {
|
||||
ip = "127.0.0.1";
|
||||
}
|
||||
|
||||
const backendUrl = `https://${ip}:${port}`;
|
||||
|
||||
for (const profile of createdProfiles) {
|
||||
await this.generateLaunchScript(profile.info.id, backendUrl, this.scriptsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private loadHeadlessProfiles(): ISptProfile[] {
|
||||
let profiles: ISptProfile[] = [];
|
||||
|
||||
for (const profileId in this.saveServer.getProfiles()) {
|
||||
const profile = this.saveServer.getProfile(profileId);
|
||||
|
||||
if (profile.info.password === "fika-headless") {
|
||||
profiles.push(profile);
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public async createHeadlessProfiles(profileAmount: number): Promise<ISptProfile[]> {
|
||||
let profileCount = this.headlessProfiles.length;
|
||||
let profileAmountToCreate = profileAmount - profileCount;
|
||||
let createdProfiles: ISptProfile[] = [];
|
||||
|
||||
for (let i = 0; i < profileAmountToCreate; i++) {
|
||||
const profile = await this.createHeadlessProfile();
|
||||
createdProfiles.push(profile);
|
||||
this.headlessProfiles.push(profile);
|
||||
}
|
||||
|
||||
return createdProfiles;
|
||||
}
|
||||
|
||||
private async createHeadlessProfile(): Promise<ISptProfile> {
|
||||
// Generate a unique username
|
||||
const username = `headless_${this.hashUtil.generate()}`;
|
||||
// Using a password allows us to know which profiles are headless client profiles.
|
||||
const password = "fika-headless";
|
||||
// Random edition. Doesn't matter
|
||||
const edition = "Standard";
|
||||
|
||||
// Create mini profile
|
||||
const profileId = await this.createMiniProfile(username, password, edition);
|
||||
|
||||
// Random character configs. Doesn't matter.
|
||||
const newProfileData: IProfileCreateRequestData = {
|
||||
side: "usec",
|
||||
nickname: username, // Use the username as the nickname to ensure it is unique.
|
||||
headId: this.HEAD_USEC_4,
|
||||
voiceId: this.VOICE_USEC_4,
|
||||
};
|
||||
|
||||
const profile = await this.createFullProfile(newProfileData, profileId);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
private async createMiniProfile(username: string, password: string, edition: string): Promise<string> {
|
||||
const profileId = this.hashUtil.generate();
|
||||
const scavId = this.hashUtil.generate();
|
||||
|
||||
const newProfileDetails: Info = {
|
||||
id: profileId,
|
||||
scavId: scavId,
|
||||
aid: this.hashUtil.generateAccountId(),
|
||||
username: username,
|
||||
password: password,
|
||||
wipe: true,
|
||||
edition: edition,
|
||||
};
|
||||
|
||||
this.saveServer.createProfile(newProfileDetails);
|
||||
|
||||
await this.saveServer.loadProfile(profileId);
|
||||
await this.saveServer.saveProfile(profileId);
|
||||
|
||||
return profileId;
|
||||
}
|
||||
|
||||
private async createFullProfile(profileData: IProfileCreateRequestData, profileId: string): Promise<ISptProfile> {
|
||||
await this.profileController.createProfile(profileData, profileId);
|
||||
|
||||
const profile = this.saveServer.getProfile(profileId);
|
||||
|
||||
this.clearUnecessaryHeadlessItems(profile.characters.pmc, profileId);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
private async generateLaunchScript(profileId: string, backendUrl: string, scriptsFolderPath: string): Promise<void> {
|
||||
try {
|
||||
if (!(await this.fileSystem.exists(scriptsFolderPath))) {
|
||||
await this.fileSystem.ensureDir(scriptsFolderPath);
|
||||
}
|
||||
|
||||
const templatePath = path.join(scriptsFolderPath, "_TEMPLATE.ps1");
|
||||
const templateContent = await this.fileSystem.read(templatePath);
|
||||
|
||||
const scriptName = `Start_headless_${profileId}.ps1`;
|
||||
const scriptPath = path.join(scriptsFolderPath, scriptName);
|
||||
const scriptContent = templateContent.replace("${profileId}", profileId).replace("${backendUrl}", backendUrl);
|
||||
|
||||
await this.fileSystem.write(scriptPath, scriptContent);
|
||||
|
||||
this.logger.success(`Generated launch script: /fika-server/assets/scripts/${scriptName}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to generate launch script: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private clearUnecessaryHeadlessItems(pmcProfile: IPmcData, sessionId: string): void {
|
||||
const itemsToDelete = this.getAllHeadlessItems(pmcProfile).map((item) => item._id);
|
||||
|
||||
for (const itemIdToDelete of itemsToDelete) {
|
||||
this.inventoryHelper.removeItem(pmcProfile, itemIdToDelete, sessionId);
|
||||
}
|
||||
|
||||
pmcProfile.Inventory.fastPanel = {};
|
||||
}
|
||||
|
||||
private getAllHeadlessItems(pmcProfile: IPmcData): IItem[] {
|
||||
const inventoryItems = pmcProfile.Inventory.items ?? [];
|
||||
const equipmentRootId = pmcProfile?.Inventory?.equipment;
|
||||
const stashRootId = pmcProfile?.Inventory.stash;
|
||||
|
||||
return inventoryItems.filter((item) => item.parentId == equipmentRootId || item.parentId == stashRootId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { SPTWebSocket } from "@spt/servers/ws/SPTWebsocket";
|
||||
import { EFikaHeadlessWSMessageTypes } from "../../models/enums/EFikaHeadlessWSMessageTypes";
|
||||
import { EHeadlessStatus } from "../../models/enums/EHeadlessStatus";
|
||||
import { IHeadlessClientInfo } from "../../models/fika/headless/IHeadlessClientInfo";
|
||||
import { IStartHeadlessRequest } from "../../models/fika/routes/raid/headless/IStartHeadlessRequest";
|
||||
import { IHeadlessRequesterJoinRaid } from "../../models/fika/websocket/headless/IHeadlessRequesterJoinRaid";
|
||||
import { IStartHeadlessRaid } from "../../models/fika/websocket/headless/IHeadlessStartRaid";
|
||||
import { FikaConfig } from "../../utils/FikaConfig";
|
||||
import { FikaHeadlessRequesterWebSocket } from "../../websockets/FikaHeadlessRequesterWebSocket";
|
||||
|
||||
@injectable()
|
||||
export class FikaHeadlessService {
|
||||
private headlessClients: Map<string, IHeadlessClientInfo> = new Map();
|
||||
|
||||
constructor(
|
||||
@inject("FikaHeadlessRequesterWebSocket") protected fikaHeadlessRequesterWebSocket: FikaHeadlessRequesterWebSocket,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("FikaConfig") protected fikaConfig: FikaConfig,
|
||||
) {}
|
||||
|
||||
public getHeadlessClients(): Map<string, IHeadlessClientInfo> {
|
||||
return this.headlessClients;
|
||||
}
|
||||
|
||||
public addHeadlessClient(sessionID: string, webSocket: SPTWebSocket): void {
|
||||
this.headlessClients.set(sessionID, { webSocket: webSocket, state: EHeadlessStatus.READY });
|
||||
}
|
||||
|
||||
public removeHeadlessClient(sessionID: string): void {
|
||||
this.headlessClients.delete(sessionID);
|
||||
}
|
||||
|
||||
/** Begin setting up a raid for a headless client
|
||||
*
|
||||
* @returns returns the SessionID of the headless client that is starting this raid, returns null if no client could be found or there was an error.
|
||||
*/
|
||||
public async startHeadlessRaid(headlessSessionID: string, requesterSessionID: string, info: IStartHeadlessRequest): Promise<string | null> {
|
||||
const headlessClient = this.headlessClients.get(headlessSessionID);
|
||||
|
||||
if (!headlessClient || headlessClient?.state != EHeadlessStatus.READY) {
|
||||
return null;
|
||||
}
|
||||
|
||||
headlessClient.state = EHeadlessStatus.IN_RAID;
|
||||
headlessClient.players = [];
|
||||
headlessClient.requesterSessionID = requesterSessionID;
|
||||
headlessClient.hasNotifiedRequester = false;
|
||||
|
||||
const headlessClientWS = headlessClient.webSocket;
|
||||
|
||||
if (!headlessClientWS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (headlessClientWS.readyState === WebSocket.CLOSED) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const startRequest: IStartHeadlessRaid = {
|
||||
type: EFikaHeadlessWSMessageTypes.HeadlessStartRaid,
|
||||
startRequest: info,
|
||||
};
|
||||
|
||||
await headlessClientWS.sendAsync(JSON.stringify(startRequest));
|
||||
|
||||
return headlessSessionID;
|
||||
}
|
||||
|
||||
/** Sends a join message to the requester of a headless client */
|
||||
public async sendJoinMessageToRequester(headlessClientId: string): Promise<void> {
|
||||
const headlessClient = this.headlessClients.get(headlessClientId);
|
||||
|
||||
if (!headlessClient || headlessClient?.state === EHeadlessStatus.READY) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const message: IHeadlessRequesterJoinRaid = {
|
||||
type: EFikaHeadlessWSMessageTypes.RequesterJoinMatch,
|
||||
matchId: headlessClientId,
|
||||
};
|
||||
|
||||
await this.fikaHeadlessRequesterWebSocket.sendAsync(headlessClient.requesterSessionID, message);
|
||||
headlessClient.hasNotifiedRequester = true;
|
||||
}
|
||||
|
||||
public addPlayerToHeadlessMatch(headlessClientId: string, sessionID: string): void {
|
||||
const headlessClient = this.headlessClients.get(headlessClientId);
|
||||
|
||||
if (!headlessClient || headlessClient?.state != EHeadlessStatus.IN_RAID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (headlessClientId === sessionID) {
|
||||
return;
|
||||
}
|
||||
|
||||
headlessClient.players.push(sessionID);
|
||||
|
||||
if (!this.fikaConfig.getConfig().headless.setLevelToAverageOfLobby) {
|
||||
// Doing this everytime is unecessary if we're not setting the average level so only set it once the original requester of the headless joins.
|
||||
if (headlessClient.requesterSessionID === sessionID) {
|
||||
this.setHeadlessLevel(headlessClientId);
|
||||
}
|
||||
} else {
|
||||
this.setHeadlessLevel(headlessClientId);
|
||||
}
|
||||
}
|
||||
|
||||
private setHeadlessLevel(headlessClientId: string): void {
|
||||
const headlessClient = this.headlessClients.get(headlessClientId);
|
||||
|
||||
if (!headlessClient || headlessClient?.state != EHeadlessStatus.IN_RAID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const headlessProfile = this.saveServer.getProfile(headlessClientId);
|
||||
|
||||
// Set level of headless to that of the requester.
|
||||
if (!this.fikaConfig.getConfig().headless.setLevelToAverageOfLobby) {
|
||||
headlessProfile.characters.pmc.Info.Level = this.saveServer.getProfile(headlessClient.requesterSessionID).characters.pmc.Info.Level;
|
||||
return;
|
||||
}
|
||||
|
||||
let baseHeadlessLevel = 0;
|
||||
let players = headlessClient.players.length;
|
||||
|
||||
for (const sessionID of headlessClient.players) {
|
||||
baseHeadlessLevel += this.saveServer.getProfile(sessionID).characters.pmc.Info.Level;
|
||||
}
|
||||
|
||||
baseHeadlessLevel = Math.round(baseHeadlessLevel / players);
|
||||
|
||||
this.logger.debug(`[${headlessClientId}] Setting headless level to: ${baseHeadlessLevel} | Players: ${players}`);
|
||||
|
||||
headlessProfile.characters.pmc.Info.Level = baseHeadlessLevel;
|
||||
}
|
||||
|
||||
/** End the raid for the specified headless client, sets the state back to READY so that he can be requested to host again. */
|
||||
public endHeadlessRaid(headlessClientId: string): void {
|
||||
const headlessClient = this.headlessClients.get(headlessClientId);
|
||||
|
||||
if (!headlessClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
headlessClient.state = EHeadlessStatus.READY;
|
||||
headlessClient.players = null;
|
||||
headlessClient.requesterSessionID = null;
|
||||
headlessClient.hasNotifiedRequester = null;
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,17 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { PreSptModLoader } from "@spt/loaders/PreSptModLoader";
|
||||
import { JsonUtil } from "@spt/utils/JsonUtil";
|
||||
import { VFS } from "@spt/utils/VFS";
|
||||
|
||||
import { IFikaConfig } from "../models/fika/config/IFikaConfig";
|
||||
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig";
|
||||
import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig";
|
||||
import type { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { FileSystem } from "@spt/utils/FileSystem";
|
||||
import packageJson from "../../package.json";
|
||||
import { IFikaSPTServerConfig } from "../models/fika/config/IFikaConfigServer";
|
||||
|
||||
@injectable()
|
||||
export class FikaConfig {
|
||||
@@ -15,17 +21,176 @@ export class FikaConfig {
|
||||
protected modName: string;
|
||||
protected modPath: string;
|
||||
protected fikaConfig: IFikaConfig;
|
||||
protected defaultFikaConfig: IFikaConfig = {
|
||||
client: {
|
||||
useBtr: true,
|
||||
friendlyFire: true,
|
||||
dynamicVExfils: false,
|
||||
allowFreeCam: false,
|
||||
allowSpectateFreeCam: false,
|
||||
blacklistedItems: [],
|
||||
forceSaveOnDeath: false,
|
||||
mods: {
|
||||
required: [],
|
||||
optional: [],
|
||||
},
|
||||
useInertia: true,
|
||||
sharedQuestProgression: false,
|
||||
canEditRaidSettings: true,
|
||||
enableTransits: true,
|
||||
anyoneCanStartRaid: false,
|
||||
},
|
||||
server: {
|
||||
SPT: {
|
||||
http: {
|
||||
ip: "0.0.0.0",
|
||||
port: 6969,
|
||||
backendIp: "0.0.0.0",
|
||||
backendPort: 6969,
|
||||
},
|
||||
disableSPTChatBots: true,
|
||||
},
|
||||
allowItemSending: true,
|
||||
sentItemsLoseFIR: true,
|
||||
launcherListAllProfiles: false,
|
||||
sessionTimeout: 5,
|
||||
showDevProfile: false,
|
||||
showNonStandardProfile: false,
|
||||
logClientModsInConsole: false,
|
||||
},
|
||||
natPunchServer: {
|
||||
enable: false,
|
||||
port: 6790,
|
||||
natIntroduceAmount: 1,
|
||||
},
|
||||
headless: {
|
||||
profiles: {
|
||||
amount: 0,
|
||||
aliases: {},
|
||||
},
|
||||
scripts: {
|
||||
generate: true,
|
||||
forceIp: "",
|
||||
},
|
||||
setLevelToAverageOfLobby: true,
|
||||
restartAfterAmountOfRaids: 0,
|
||||
},
|
||||
background: {
|
||||
enable: true,
|
||||
easteregg: false,
|
||||
},
|
||||
};
|
||||
|
||||
constructor(
|
||||
@inject("PreSptModLoader") protected preSptModLoader: PreSptModLoader,
|
||||
@inject("VFS") protected vfs: VFS,
|
||||
@inject("FileSystem") protected fileSystem: FileSystem,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
) {
|
||||
this.modAuthor = packageJson.author.replace(/\W/g, "").toLowerCase();
|
||||
this.modName = packageJson.name.replace(/\W/g, "").toLowerCase();
|
||||
this.modPath = this.preSptModLoader.getModPath(this.getModFolderName());
|
||||
}
|
||||
|
||||
this.fikaConfig = this.jsonUtil.deserializeJsonC(this.vfs.readFile(path.join(this.modPath, "assets/configs/fika.jsonc")));
|
||||
public async preInit(): Promise<void> {
|
||||
const configPath = path.join(this.modPath, "assets/configs/fika.jsonc");
|
||||
|
||||
if (!(await this.fileSystem.exists(path.join(configPath)))) {
|
||||
await this.fileSystem.writeJson(configPath, this.defaultFikaConfig, "\t");
|
||||
}
|
||||
|
||||
this.fikaConfig = this.jsonUtil.deserializeJsonC(await this.fileSystem.read(configPath));
|
||||
|
||||
if (await this.checkAndAddMissingConfigProperties(this.defaultFikaConfig, this.fikaConfig)) {
|
||||
this.fikaConfig = this.sortProperties(this.defaultFikaConfig, this.fikaConfig);
|
||||
await this.fileSystem.writeJson(configPath, this.fikaConfig, "\t");
|
||||
}
|
||||
|
||||
await this.applySPTConfig(this.fikaConfig.server.SPT);
|
||||
}
|
||||
|
||||
protected async checkAndAddMissingConfigProperties(source: IFikaConfig, target: IFikaConfig): Promise<boolean> {
|
||||
let modified = false;
|
||||
for (const key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
if (typeof source[key] === "object" && !Array.isArray(source[key])) {
|
||||
if (!target.hasOwnProperty(key)) {
|
||||
target[key] = {};
|
||||
modified = true;
|
||||
}
|
||||
const nestedModified = await this.checkAndAddMissingConfigProperties(source[key], target[key]);
|
||||
if (nestedModified) {
|
||||
modified = true;
|
||||
}
|
||||
} else {
|
||||
if (!target.hasOwnProperty(key)) {
|
||||
target[key] = source[key];
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
protected sortProperties(source: IFikaConfig, target: IFikaConfig): IFikaConfig {
|
||||
// Cast as IFikaConfig as this is empty before sorting.
|
||||
const sortedTarget: IFikaConfig = {} as IFikaConfig;
|
||||
for (const key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
if (typeof source[key] === "object" && !Array.isArray(source[key])) {
|
||||
sortedTarget[key] = this.sortProperties(source[key], target[key] || {});
|
||||
} else {
|
||||
sortedTarget[key] = target[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sortedTarget;
|
||||
}
|
||||
|
||||
protected async applySPTConfig(config: IFikaSPTServerConfig): Promise<void> {
|
||||
this.logger.info("[Fika Server] Overriding SPT configuration");
|
||||
|
||||
const coreConfig = this.configServer.getConfig(ConfigTypes.CORE) as ICoreConfig;
|
||||
const httpConfig = this.configServer.getConfig(ConfigTypes.HTTP) as IHttpConfig;
|
||||
|
||||
if (config.disableSPTChatBots) {
|
||||
const commando = coreConfig.features.chatbotFeatures.ids.commando;
|
||||
const sptFriend = coreConfig.features.chatbotFeatures.ids.spt;
|
||||
|
||||
coreConfig.features.chatbotFeatures.enabledBots[commando] = false;
|
||||
coreConfig.features.chatbotFeatures.enabledBots[sptFriend] = false;
|
||||
}
|
||||
|
||||
httpConfig.ip = config.http.ip;
|
||||
httpConfig.port = config.http.port;
|
||||
httpConfig.backendIp = config.http.backendIp;
|
||||
httpConfig.backendPort = config.http.backendPort;
|
||||
}
|
||||
|
||||
public updateFikaConfig(config: IFikaConfig): boolean {
|
||||
if (config != this.fikaConfig) {
|
||||
this.fikaConfig = config;
|
||||
|
||||
const coreConfig = this.configServer.getConfig(ConfigTypes.CORE) as ICoreConfig;
|
||||
const commando = coreConfig.features.chatbotFeatures.ids.commando;
|
||||
const sptFriend = coreConfig.features.chatbotFeatures.ids.spt;
|
||||
|
||||
// Re-handle chatbot settings
|
||||
if (config.server.SPT.disableSPTChatBots) {
|
||||
coreConfig.features.chatbotFeatures.enabledBots[commando] = false;
|
||||
coreConfig.features.chatbotFeatures.enabledBots[sptFriend] = false;
|
||||
} else {
|
||||
coreConfig.features.chatbotFeatures.enabledBots[commando] = true;
|
||||
coreConfig.features.chatbotFeatures.enabledBots[sptFriend] = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public getConfig(): IFikaConfig {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user