From ad525c86c672b60715f689a936a8376fb36836d6 Mon Sep 17 00:00:00 2001 From: Remuchi <72476615+Remuchi@users.noreply.github.com> Date: Sat, 2 Mar 2024 21:16:27 +0700 Subject: [PATCH 1/4] =?UTF-8?q?[Fix]=20=D0=A0=D0=B0=D0=B7=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=84=D0=B8=D0=BA=D1=81=D1=8B=20(#161)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: фикс отображений в ахелпе * fix: нотисы в чат больше не отправляют сообщение в консоль * fix: исправлена текстура секретной двери * fix: ошибки перевода при вылизывании ран --- .../UI/Bwoink/BwoinkControl.xaml.cs | 66 +++++------------- .../CustomControls/PlayerListControl.xaml.cs | 10 ++- Content.Client/Popups/PopupSystem.cs | 10 ++- .../_White/SelfHeal/SelfHealSystem.cs | 15 ++-- .../components/self-healing-component.ftl | 12 ++-- .../components/self-healing-component.ftl | 12 ++-- .../doors/secretdoor/secretdoor.ftl | 10 +++ .../Doors/secret_door.rsi/assembly.png | Bin 305 -> 859 bytes .../Doors/secret_door.rsi/closed.png | Bin 171 -> 1637 bytes .../Doors/secret_door.rsi/closing.png | Bin 516 -> 3212 bytes .../Structures/Doors/secret_door.rsi/open.png | Bin 219 -> 772 bytes .../Doors/secret_door.rsi/opening.png | Bin 530 -> 2985 bytes 12 files changed, 60 insertions(+), 75 deletions(-) create mode 100644 Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/doors/secretdoor/secretdoor.ftl diff --git a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml.cs b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml.cs index af977f763c..5ab3a71bb3 100644 --- a/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml.cs +++ b/Content.Client/Administration/UI/Bwoink/BwoinkControl.xaml.cs @@ -12,7 +12,6 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Network; using Robust.Shared.Utility; -using Robust.Shared.Timing; using Robust.Shared.Configuration; namespace Content.Client.Administration.UI.Bwoink @@ -49,39 +48,11 @@ namespace Content.Client.Administration.UI.Bwoink ChannelSelector.OnSelectionChanged += sel => { _currentPlayer = sel; - SwitchToChannel(sel?.SessionId); + SwitchToChannel(sel.SessionId); ChannelSelector.PlayerListContainer.DirtyList(); }; - ChannelSelector.OverrideText += (info, text) => - { - var sb = new StringBuilder(); - - if (info.Connected) - sb.Append('●'); - else - sb.Append(info.ActiveThisRound ? '○' : '·'); - - sb.Append(' '); - if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0) - { - if (panel.Unread < 11) - sb.Append(new Rune('➀' + (panel.Unread-1))); - else - sb.Append(new Rune(0x2639)); // ☹ - sb.Append(' '); - } - - if (info.Antag && info.ActiveThisRound) - sb.Append(new Rune(0x1F5E1)); // 🗡 - - if (info.OverallPlaytime <= TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.NewPlayerThreshold))) - sb.Append(new Rune(0x23F2)); // ⏲ - - sb.AppendFormat("\"{0}\"", text); - - return sb.ToString(); - }; + ChannelSelector.OverrideText += (info, _) => FormatTabTitle(info); ChannelSelector.Comparison = (a, b) => { @@ -166,11 +137,10 @@ namespace Content.Client.Administration.UI.Bwoink ChannelSelector.PopulateList(); } - public void SelectChannel(NetUserId channel) { if (!ChannelSelector.PlayerInfo.TryFirstOrDefault( - i => i.SessionId == channel, out var info)) + i => i.SessionId == channel, out var info)) return; // clear filter if we're trying to select a channel for a player that isn't currently filtered @@ -208,33 +178,33 @@ namespace Content.Client.Administration.UI.Bwoink Follow.Disabled = !Follow.Visible || disabled; } - private string FormatTabTitle(ItemList.Item li, PlayerInfo? pl = default) + private string FormatTabTitle(PlayerInfo info) { - pl ??= (PlayerInfo) li.Metadata!; var sb = new StringBuilder(); - sb.Append(pl.Connected ? '●' : '○'); + sb.Append(info.Connected ? '●' : + info.ActiveThisRound ? '○' : '·' + ); + sb.Append(' '); - if (AHelpHelper.TryGetChannel(pl.SessionId, out var panel) && panel.Unread > 0) + if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0) { - if (panel.Unread < 11) - sb.Append(new Rune('➀' + (panel.Unread-1))); - else - sb.Append(new Rune(0x2639)); // ☹ + sb.Append(panel.Unread < 11 ? new Rune('➀' + (panel.Unread - 1)) : new Rune(0x2639)); // ☹ + sb.Append(' '); } - if (pl.Antag) + if (info.Antag) sb.Append(new Rune(0x1F5E1)); // 🗡 - if (pl.OverallPlaytime <= TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.NewPlayerThreshold))) + if (info.OverallPlaytime <= TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.NewPlayerThreshold))) sb.Append(new Rune(0x23F2)); // ⏲ - sb.AppendFormat("\"{0}\"", pl.CharacterName); + sb.Append($"\"{info.CharacterName}\""); - if (pl.IdentityName != pl.CharacterName && pl.IdentityName != string.Empty) - sb.Append(' ').AppendFormat("[{0}]", pl.IdentityName); + if (info.IdentityName != info.CharacterName && info.IdentityName != string.Empty) + sb.Append(' ').Append($"[{info.IdentityName}]"); - sb.Append(' ').Append(pl.Username); + sb.Append(' ').Append(info.Username); return sb.ToString(); } @@ -257,4 +227,4 @@ namespace Content.Client.Administration.UI.Bwoink UpdateButtons(); } } -} +} \ No newline at end of file diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs index e02b22f4a2..7366fc5633 100644 --- a/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs +++ b/Content.Client/Administration/UI/CustomControls/PlayerListControl.xaml.cs @@ -1,10 +1,12 @@ using System.Linq; using Content.Client.Administration.Systems; +using Content.Client.Stylesheets; using Content.Client.UserInterface.Controls; using Content.Client.Verbs.UI; using Content.Shared.Administration; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; @@ -26,15 +28,18 @@ namespace Content.Client.Administration.UI.CustomControls public Func? OverrideText; public Comparison? Comparison; - private IEntityManager _entManager; - private IUserInterfaceManager _uiManager; + private readonly IEntityManager _entManager; + private readonly IUserInterfaceManager _uiManager; private PlayerInfo? _selectedPlayer; + private readonly Font _fontOverride; + public PlayerListControl() { _entManager = IoCManager.Resolve(); _uiManager = IoCManager.Resolve(); + _fontOverride = IoCManager.Resolve().NotoStack(size: 12); _adminSystem = _entManager.System(); RobustXamlLoader.Load(this); // Fill the Option data @@ -137,6 +142,7 @@ namespace Content.Client.Administration.UI.CustomControls new Label { ClipText = true, + FontOverride = _fontOverride, Text = GetText(info) } } diff --git a/Content.Client/Popups/PopupSystem.cs b/Content.Client/Popups/PopupSystem.cs index 821e4a8993..77197aa8ea 100644 --- a/Content.Client/Popups/PopupSystem.cs +++ b/Content.Client/Popups/PopupSystem.cs @@ -11,6 +11,7 @@ using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Shared.Configuration; using Robust.Shared.Map; +using Robust.Shared.Network; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Replays; @@ -30,6 +31,7 @@ namespace Content.Client.Popups [Dependency] private readonly IUserInterfaceManager _uiManager = default!; [Dependency] private readonly IReplayRecordingManager _replayRecording = default!; [Dependency] private readonly IChatManager _chatManager = default!; + [Dependency] private readonly IClientNetManager _clientNet = default!; public IReadOnlyList WorldLabels => _aliveWorldLabels; public IReadOnlyList CursorLabels => _aliveCursorLabels; @@ -99,12 +101,14 @@ namespace Content.Client.Popups { PopupType.LargeCaution, "15" } }; - var fontsize = fontSizeDict.ContainsKey(type) ? fontSizeDict[type] : "10"; - var fontcolor = (type == PopupType.LargeCaution || type == PopupType.MediumCaution || type == PopupType.SmallCaution) ? "c62828" : "aeabc4"; + var fontsize = fontSizeDict.GetValueOrDefault(type, "10"); + var fontcolor = type is PopupType.LargeCaution or PopupType.MediumCaution or PopupType.SmallCaution ? "c62828" : "aeabc4"; if (isLogging) { - _chatManager.SendMessage($"notice [font size={fontsize}][color=#{fontcolor}]{message}[/color][/font]", ChatSelectChannel.Console); + var wrappedMEssage = $"[font size={fontsize}][color=#{fontcolor}]{message}[/color][/font]"; + var chatMsg = new ChatMessage(ChatChannel.Emotes, message, wrappedMEssage, GetNetEntity(EntityUid.Invalid), null); + _clientNet.DispatchLocalNetMessage(new MsgChatMessage { Message = chatMsg }); } } diff --git a/Content.Server/_White/SelfHeal/SelfHealSystem.cs b/Content.Server/_White/SelfHeal/SelfHealSystem.cs index 14c0bd9132..853d01c4b6 100644 --- a/Content.Server/_White/SelfHeal/SelfHealSystem.cs +++ b/Content.Server/_White/SelfHeal/SelfHealSystem.cs @@ -72,7 +72,7 @@ public sealed class SelfHealSystem: EntitySystem // Logic to determine the whether or not to repeat the healing action args.Repeat = (HasDamage(component, healing) && !dontRepeat); if (!args.Repeat && !dontRepeat) - _popupSystem.PopupEntity(Loc.GetString("self-heal-finished-using", ("verb", Loc.GetString("self-heal-lick")), ("name", uid)), uid, args.User); + _popupSystem.PopupEntity(Loc.GetString("self-heal-finished-using", ("name", uid)), uid, args.User); args.Handled = true; @@ -90,8 +90,8 @@ public sealed class SelfHealSystem: EntitySystem var targetString = EntityManager.ToPrettyString(uid); var healMessage = uid != args.User - ? $"{userString:user} healed {targetString:target} for {total:damage} with {Loc.GetString("self-heal-lick")}" - : $"{userString:user} healed themselves for {total:damage} with {Loc.GetString("self-heal-lick")}"; + ? $"{userString:user} healed {targetString:target} for {total:damage} by licking" + : $"{userString:user} healed themselves for {total:damage} by licking"; _adminLogger.Add(LogType.Healed, $"{healMessage}"); if (TryComp(args.User, out var selfHealComponent)) @@ -100,7 +100,7 @@ public sealed class SelfHealSystem: EntitySystem var audioParams = new AudioParams().WithVariation(2f).WithVolume(-5f); _audio.PlayPvs(audio, args.User, audioParams); - _popupSystem.PopupEntity(Loc.GetString("self-heal-using-other", ("name", uid), ("verb", Loc.GetString("self-heal-lick"))), uid); + _popupSystem.PopupEntity(Loc.GetString("self-heal-using-other", ("user", args.Args.User), ("target", uid)), uid); } } @@ -114,8 +114,7 @@ public sealed class SelfHealSystem: EntitySystem if (!HasDamage(targetDamage, component)) { - var popup = Loc.GetString("self-heal-cant-use", ("verb", Loc.GetString("self-heal-lick")), - ("name", target)); + var popup = Loc.GetString("self-heal-cant-use", ("name", target)); _popupSystem.PopupEntity(popup, user, user); return false; } @@ -128,7 +127,7 @@ public sealed class SelfHealSystem: EntitySystem EntityManager.TryGetComponent(blockedClothing, out var blocker) && blocker.Enabled) { - var popup = Loc.GetString("self-heal-cant-use-clothing", ("verb", Loc.GetString("self-heal-lick")), ("clothing", blockedClothing)); + var popup = Loc.GetString("self-heal-cant-use-clothing", ("clothing", blockedClothing)); _popupSystem.PopupEntity(popup, user, user); return false; } @@ -141,7 +140,7 @@ public sealed class SelfHealSystem: EntitySystem { if (_inventorySystem.TryGetSlotEntity(target, clothing, out var blockedClothing)) { - var popup = Loc.GetString("self-heal-cant-use-clothing-other", ("verb", Loc.GetString("self-heal-lick")), ("name", target), ("clothing", blockedClothing)); + var popup = Loc.GetString("self-heal-cant-use-clothing-other", ("name", target), ("clothing", blockedClothing)); _popupSystem.PopupEntity(popup, user, user); return false; } diff --git a/Resources/Locale/en-US/medical/components/self-healing-component.ftl b/Resources/Locale/en-US/medical/components/self-healing-component.ftl index e654d44cbf..751f084b8f 100644 --- a/Resources/Locale/en-US/medical/components/self-healing-component.ftl +++ b/Resources/Locale/en-US/medical/components/self-healing-component.ftl @@ -1,8 +1,6 @@ -self-heal-finished-using = You have finished {$verb}ing all {$name}`s wounds -self-heal-cant-use = There is no damage you can heal by {$verb}ing {$name} -self-heal-stop-bleeding = They have stopped bleeding -self-heal-lick = lick -self-heal-cant-use-clothing = You cant {$verb}ing yourself while wearing a {$clothing} -self-heal-cant-use-clothing-other = You cant {$verb}ing {$name} while {$name} is wearing a {$clothing} +self-heal-finished-using = You have finished licking all {$name}`s wounds +self-heal-cant-use = There is no damage you can heal by licking {$name} +self-heal-cant-use-clothing = You cant lick yourself while wearing a {$clothing} +self-heal-cant-use-clothing-other = You cant lick {$name} while {$name} is wearing a {$clothing} self-heal-action = Lick the wounds -self-heal-using-other = {$name} have {$verb}ed some of {$name} wounds +self-heal-using-other = {$user} have licked some of {$target} wounds diff --git a/Resources/Locale/ru-RU/medical/components/self-healing-component.ftl b/Resources/Locale/ru-RU/medical/components/self-healing-component.ftl index ec2db16b58..db06a99529 100644 --- a/Resources/Locale/ru-RU/medical/components/self-healing-component.ftl +++ b/Resources/Locale/ru-RU/medical/components/self-healing-component.ftl @@ -1,9 +1,7 @@ -self-heal-finished-using = Вы закончили {$verb} все раны {$name}! -self-heal-cant-use = {$name} не имеет ран, которые вы могли бы {$verb} -self-heal-stop-bleeding = Оно перестало кровоточить -self-heal-lick = вылизывать -self-heal-cant-use-clothing = Вы не можете {$verb}, пока на вас {$clothing} -self-heal-cant-use-clothing-other = Вы не можете {$verb} {$name}, пока {$name} носит {$clothing} +self-heal-finished-using = Вы закончили вылизывать все раны {$name}! +self-heal-cant-use = {$name} не имеет ран, которые вы могли бы вылизать +self-heal-cant-use-clothing = Вы не можете вылизываться, пока на вас {$clothing} +self-heal-cant-use-clothing-other = Вы не можете вылизать {$name}, пока {$name} носит {$clothing} self-heal-action = Зализать раны -self-heal-using-other = {$name} закончил {$verb} часть {$name} ран +self-heal-using-other = {$user} вылизывает часть ран {$target} ent-SelfHealAction = Зализать раны diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/doors/secretdoor/secretdoor.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/doors/secretdoor/secretdoor.ftl new file mode 100644 index 0000000000..fdf5e1336b --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/structures/doors/secretdoor/secretdoor.ftl @@ -0,0 +1,10 @@ +ent-BaseSecretDoor = { ent-WallSolid } + .desc = { ent-WallSolid.desc } + .suffix = секретная дверь + +ent-BaseSecretDoorAssembly = каркас секретной двери + .desc = Она открывается, закрывается, и даже может вас раздавить! + +ent-SolidSecretDoor = { ent-BaseSecretDoor } + .desc = { ent-WallSolid.desc } + \ No newline at end of file diff --git a/Resources/Textures/Structures/Doors/secret_door.rsi/assembly.png b/Resources/Textures/Structures/Doors/secret_door.rsi/assembly.png index 6518b7245c721677990edb252828d4ce34c776f5..e872d82c5d4e2781f67cad1c369e25bc5199e936 100644 GIT binary patch delta 837 zcmV-L1G@aN0^0_VBYy)TNkl6BVhr#a{B%ktrL#uQ((v*2*p=jHqDbvtXR zZg)ihM1)48#dJDWB(!dKMdqv!0(NU_i#*RU#$b$PIvuCvvwyz6zF;|5qC1@)olb`k z0?w65;lTe`wpKG-zWf2x=@GNp3_u<{_&r$|c6Z-lp)Ool6%kOX%7eYV&v^LofK(!S zy;YgBtj)0fejlhlwA)MEzWtp7*x&y`?%us~<{}1z{({wNwNYzp8v>w|qF!(D^ywc- zt6*(yL*}eJpMPOR6h(0Y2q!0RQnCTa^ZXr_{rt;)VvJaup|#@MZ@x|{;MP~S7OYpV z{>DB!cub5DqYWf=KHR*yCyx#uW3)jVO;O}n?;SBlFcGayQg~73)xktWOw|b`2DH+| z7;)Yufq(Szr*iM!PYU41jZb9G3O-<4?GE0Rgcy({cz^iym!B8G&9ZF4YP6f^7(6J2 zQi@uwmPo=WJH_(BqpQTL?k3vOsH% z_ve!XA%8>!0TG;wSYr$b75p4LAR=h3VLlVgtH4-`cWFA|X)B5xL=X|8M65Pd5^7UD z$xVSV7Ns>>Y3$W&LzGfzttnl}k3W2$l)t^bjWMPQ1EA)6fl?Zg$no*ZoOSh8IS+M7{g$&!DRAhB|tiua^;#pH5Ea1Y1QpslzP2MQM^F}UcXLThL-dRK P00000NkvXXu0mjf>J5@4 delta 279 zcmV+y0qFkQ2C)K=BYyw^b5ch_0Itp)=>Px#>q$gGR9J=WmoW;2Fc3w5G@W2!FL(;U z-eOLWLwW*lAmkd;TUZO(Vqr-}S6E1d#e7H;#=OUnfTQ}pckp7ZRY(}g(_PmE1=iY> zd`O;V=A=Lw$t%jTguje2?#s7PB6)>U3jShd5K%G-$dyIF86H$MC97GJ?!f{;Qosm$1&)_EgiUeQO~-BSs)8! zfh>>(vcP`{#2iqr&QkIZrD+;$+xD3cVugrYUDsIGHP}CNfSIGif%m|3HisSrmSssc do}Zol0zPa_Ob}aCGBE%E002ovPDHLkV1ns&N(FI-o10rdFA+o z5Q%YQSq|KMw%Zft`GC6t;O=ZTJC^0D$E6f*TT7li`P4U?Eq{l@C92A1vt^#In5Kyr zFJAJ&2ft&QCQ_<}hhb!%XF>>s5Lwry$0@Dcww3~j2Z`9E;NHFaOw+{0#Sa~-@4kD=H{bk?r%(TZi1ZJ9 z_~FOAe*Kcm%YREg`sfcmK0ddpCHL>2yE~MU5dn7)ffy%JTH3(c^Ksme($dGcJ0Lxd zap1PK;*%$T;?0{^eWoJ9!-tP~`SOBN3IJw>v$IEBUjD-2aM?+?-=AcGX zqBS;aL^245Y9QwX!Eg_hQZTbBFA++~xI+pFLAw0RtWI7E8bid~arYY^D3}$%38IMB zL>0lUpdy$V%R0Xkmz=voglfeC6}g7(v3AKB+<%Fur+51wb@fg$Lul}~hL}|}N-pHI zQmo*>FbqB3?6-{5rV&k05mHWUw|i8ZIt1LVl@zTM9It(DlW-gj0V^4^3bmP4h)aeB z@i>mX&^V6doCzf(qID8olGS>_acc-Q zQtB{=5Ub>hT_fvG3=zli#_0r{IpLc37qPP|AsA zS=jGSx-|)qOGZN=r`$ax=Y)pp6;U;SD}N%+Fpg|CyLwO%?PWrMaU2ODR#|EQcZNYJ zrLJz&z&LKYd}FNY(h{4;$c+uFxs5Ao=8aTGxqua`gmK6G=npN&oSYJ+lx8S&iK$8- zUrOQVy4SnoO)sh6jq5sdbvQ6i6T96WL|E1ZSp^N+tkY1b7FtR{Rmr*bJ;vHo+49>R#I;N~3>4WS|yBBF{)ZA~-J zx~I4kqxXG6HQ*S7Lx= zyloobzTxcb5kLR@maD5nd*_^<-eI%Z^5)H}Tjrgz+3emqw5lp{_wIe)ZckX2t8Nki z<9L0xJ3b+Vb~CCMj_r2;UVnK_3T(G0#4o@6qCZhUK%6tC&`)XkB$S0rt*^dkkA#i^Fn2U>lbw~joJUHXovwyPR zZ~MFb{)EfRUw$L+oM+FT{VH$2KjFoTA8HFe|NIM|=NU7rQfq_WzE1tAv9_*go)g>c z*tgXXwB7M;pEph0c6Xes4BcU~*|M%H?xhijcHGu}t*VbOO&ay%Eh88EcO+d1>k>7)Ls+oyt0=IN(70HC}@Q49q-WqJzUT viLp9g?1Nktuk-gfu?tbjjKzK;ADFk<3jci5&GQCmAt!^UtDnm{r-UW|7veOj diff --git a/Resources/Textures/Structures/Doors/secret_door.rsi/closing.png b/Resources/Textures/Structures/Doors/secret_door.rsi/closing.png index 0bb895b050f0d11e75d4ceed4e62cdac855c6d56..96bba25801db58b70b39c432e8bc0e48bb4017cf 100644 GIT binary patch literal 3212 zcmX|Ec|26@`#vMf*hi@lV@3#RkhLr^$nr+^ZA`X^re0$mvLr->2%(Ki^u9DA+mP2- zvJOdQG#FbYZk* zf$gjdBecz|yHJn($@y@3xyv*td3Q^`_i$xH1ErY}8_z3O=H4eHm*~LnyI(W0d%l;> zkkpLwEROx%?}-`pCi~=NWc|LEy^+;B1$eB}nW88e4J zFne4&XfT2|blhQ0nZm^G$$>~wJ(M0AL)*^n?$&4RG=Fa1WiT5V!Q^MYdQzqW`~hiZ ziUmi{eAdcX9Q+V*Mczc2hu0L%3EJk1c%J0^&w-0Rk02BPLiMmj-ctI}jJtSqJW2c@ zT3}{V8f^`QlJ=lNghyR#fzwxst$p2}g}4bP(`N@$^t(Yy`)Azp7sSyWi)xQ#9YJ?5 z8Ir%&pddl5sy^wrYLA#X(Zdd_VxV{CK)(6a9D8QTul&l-VkNNsls`Y0NftiU1$K*g z3z1lRBznlCBQQ-ng9?;=9NrPk<{nSAIOJ;0lgNY;we1Z@@II1&X-3z{N~%m;v2eJ1 zi(B=l+kb+svcGEceMf%2W*2du`(LvNgi<4T4EExy!e`Y3FB*5uKwmN11jeAc$0WGq`NvfrseQr}7St z^~plwH)gtsAtP-Cvi~fmE;=Ycf#mh?gDnaWxzJ|{J>Br(upQ#X{@0G`n%3AvKsWBH zR<8ApUmG1RGtt;;)p9=R&~?*7O(?grd3dH`1&oX826I*=a+v3V8*?(x4p8^-YkDW3 zo|K$GHt?;@z|=!{t+8MqrFWhDd(L$M;rz_yTBafj@~Kmpza-c4i|S*GV-;Bk8^79F zWy{$(TDlAK-R3TMATJlyrKYQVNVio%{&TpUC_C3d>7F!TV$I>KM*y_A%!GD#?KxaiV&gS;U zSqZhJmrR(XxC9NV@Sg(vyt=|@aWtCwnSPYW;n%}9L;S3{hzb;aFAz>7H9XmML0dwR z#_|XSASKDXiK~Dn6TPyRx7eqC#G%&%RcCQ%_}Rk*@q=cIzy~la79XZcTge8JV2qIP zLp)4GQ6^=`V=J*D>Pe622kzHab{bpFDz>Xk?F$$^jwZ@=(Dr3?&G*I!S-yZnDZ<1X zBXjEKt{H9!mY$q|AXu?ysUFbhQW<7zfsQbYDz!iT_@(%P0BZN*GZ)Eqz}4M?N!V{<;dc|RBX~Vf9%@h;Qbc1WS6{k(h+1imd=hn^GCxX!>cXRC zGj+xqcl)2{0;HIU`FSZ&kuNprrNFo>EZ8Rc@eOqH9>B-PW_^)g1#)^s#+&1khK978 z;@G^^G%c_%hF8aHn=(N#%gF*BUgUlNQSv6+8>OcueLo~>mM zbkUyile)Sj+m<;0Hq^qvYJHJuAEWQQz2&)i`d|{SLVjD;1{5 z1-i8t=P95+g}P?0v&Pb35nAe{oZ4La@2q>{etF(r1n-2H0(XLJ0zQm)ab&QZ*Fs zF#R6%I*FYD{tH{dhAyX>R;^YmjB%{p&O*U)MBx?aY$9OFJKYqx$HAcK%4tnsz2r(_ zgcT3-kPrm^!n0VrMJVEXCohmvRY$OG{tGqE=YoyD8>63GNjv?@>8Nc=1-PpPyVIK_ zId<;E#f7kCpuNO|`=uUtCH>J=PpL$uZ^!RouxHS&qR^1gl^;ylAns@?`0%*c{3= zchBfy&vNkGiE2~|{eXx1;IMM`0=ri{kZ>oH#?ag00|F{mn&4EXj`_3C9d^%2KcQ@` zg#}n!MX6yX&^6;VZ zu5J!1*s0mHYxf2N$2f3gr0DQg{}d0(U8SWsTGk@62Y;k~Hb_c0(`zfaCy8xrp;{>fGv?5oqn^mt^3S{byRmUO3;9BztPT zx5ts~*>tnT9fPqDPX%<^<$R3GxT$jpQJjrh#n#66%rf-WKj!?2 zaX+dGa?YI{@wx#h=IHFf(N=)?v>gzuofA8$SVG)Q<`o&VHXi(4;R@40u;x@yn28awv$nd*l(uDafL z{PB_CG9#JQRk^pF>YlAmu?YKm>t)HTic@}V$)W4_-hbb@{0&I(pYI-LlLZV0Tnvke zB$CsnDb9QsaW#AW_3THQ){=dpd%yi{JE#6%6=bp9{PR$Y-`3cP+wZxXC-_|^t53}B z{f8>|_b)!)di+tsX8By6>uX>B0a2 diff --git a/Resources/Textures/Structures/Doors/secret_door.rsi/open.png b/Resources/Textures/Structures/Doors/secret_door.rsi/open.png index 81862e1eade5b452853842c8baaa21f5413914aa..7ca06de1ed329debf7c292448d995390a53eaf02 100644 GIT binary patch delta 749 zcmVbk~Si?xo`s?6zgdV0FEynk{0j{n-TL9+4gA-K+W4b!HyZex}2By;!-CE8SxY=w5 zbPqTL6qP)OE;;160-R&MM0ir)p@L4WMi`pRxz2>-s;I z`{Bo@q?B;3K!3#W>n}fN4e;!zXFKcmw!*!7`I?jxRxD&KzizyG`5G%0u|m_-xDY%k zC9nw*n>|1X9&AF@cAZdDM2wJ9!Uvx{fEcs0Vu-lmXiV@eF-0^x4@FVzto~?#q!_>$ zj4||jz5EIOWrY}!uJF2dSKY@Pe6|eWeA^OZB*cJoMSpg_ZJM3sy~j+RlK2DPoqQ@Asmm1i92?0b5u5BAcgb?;q z12HBP1y#IHIBP8^9lnPdP*p?(wr7IvF0jrKeEv?@G&QKAsw7P~v0V|0?XK*@fVB=I zf*8R)`hV_Qj4_A^t#A3`_usPm7Z(>;YrACt%=W*)7(q30fB!N2e*wV3!H^JIT)#iS zxgIG6RF(Vtk2!q?gCWipgy0zt4{>K_XY~66-oJl`h;VcBHfw;(%PSU(x4W)uX0va! zt~dXr8?juz$+`qbM_+16X?O1~FCSryVLtzg#b%;pxqOq;=gE`D%w}^|t9RX5v@EXy zsH!{G>%X$%0A+d2a(Tmi{xyq5i9pwpHk);J9AG>B%Vo*o;RJVmz2M+rK+}BMM<=GL f?r7T<)d;}fZjXTCTkGe900000NkvXXu0mjfbgp&p delta 192 zcmZo+yUjR3xt@WsILO_JVcj{ImkbOHQ$1ZALn2z=UNq!tRupIn?7dvsCU4XF{e6pV z>jTL*BA1VO2E7Zjo~yKnzh~<;VLLS?LybP$DM9Pll@`5Z|7LJ3fVJ|C;?fkU19C|r ze?P6?*gj`-CPQ^Z_Dr@7-;J);pJBE+fItifq%8NGFZR34@U7t7&(9(0ZxY|<0=3S2 pzEdwMdlloGh2Ph4eY#Q2Eb>=xO`G%HHlPa`JYD@<);T3K0RX2VR2u*Q diff --git a/Resources/Textures/Structures/Doors/secret_door.rsi/opening.png b/Resources/Textures/Structures/Doors/secret_door.rsi/opening.png index 9d14324686769b131f947fdce1c02423f2cd3823..861f6fbbc341cbca6db828e396cffef6d990a175 100644 GIT binary patch literal 2985 zcmYjTc|4SB8y*Z}i6KIRv2{esl5KR%AWn8l2qhv*jj=D;37KPLUn*nkL?!z&B8+`W z$2LqD`z|4*p|N}~r|*2@QWDIxKra1Ct)<1>k|2L zN19jiCvSrkE4cQPQ8+)7y-JCzUb;{x< z9M_(C-!C?Da-t!2^U>q&Z3Q`njyaaXhY$$mU{_YDY5w$P z71qmw=PoLBw+{&sB3oBsDl3q$iu1-p*>}2{jXnEmG;dJTj~^T*w(3m-11bH})Tyb? zi4S3|2Q;dNcHV#qsy32D;>KrX&CDgZN3A)wS5;S6Be6jnlm60>qm|eGOaWgvURS0F z`uQ!2(OaT5z*vxWI9a?3Gr_V;v$cvJAo%XaVL`cN#l8_Un08Ow#^6RT;mPs(3tDPe z$>&+Kx$YA`FJ&WxV6e@GS(veLyj?LP2;p2_;~!pGse(|aI^WWk%PgMR-@oW;^1AZw z?WV)S9e;vS6m6}h?-oZWYD!?=Jdk3yl6eE0*G@{2LAV4wY5l1Z98RFIn5V7cri#N=1 z-+l-2KiwbVwhRsMc_4tr^gQ$9qz=E!2_*Fkot-VOS9(=;Q}Da+(f;{39r3tp;zQV0u4t*(-W=9^b`pw4+=Q^hJw^%ASsrQZd%0_=jx6WtCFm7eRoS?F zZYsmu4wlpp8@;~S9xS}mg!k4RYXcSR!|e1!ys_&caXnN*48hgJq7m-R5qm}>yqY)m zjHUdSI(lhFCWce|4*Ro?icBCm1rQO+rCI*i*N?Nt78?2p@rmJB87_%LaF%yQFHf#z z^PiF25GERC=~h&)s)nkZG(U;{qo#JVHQQ2ff|!^kT7Y4igDOJ`9~>`P|K+$ea#Wt<%Wmbi+x zHk7EuWnT+_kF#nwy_`-d*=5 z_D^JdsEFZkjq9^GT6_*4c_hCtPgP8OI736||(HD+Hr&M=LQ^R{Lsz+u|1TwI|d{lrDX#>u@FT z7WjdiEEz0V3zY7mFotXv7yhJ_u4TQ8RPzEL&$tF;DSV)_`##aAKq*^Mu`zsG*4Ilno zW0_az6k;`3F}nF}X5!w)Czd!&t9SeYNgZS-f!JJSL9gXACa|ENuJ=Zoxe=cP&fC34 zEEl{jL#XSh!tPzkqSJnp2^-?H^sKq>Z?|PYb#&<14ay=P-eu*gDrPhJ`Roi2t=-T@ zR+#9=CW5vrGMfF-W3AGq<&y-Q*#4fN8`X%;`&S~p4+rRzGOU!Rg>T8F(u*)Nlwo%( zDOn*$R$C152&{-;qU|zge|1XBu^{P^N2NIGN-pqITC5)ec_2W&HVGQ2sGd9^6%}M3FmK0+B8`) ztQQ!x9ok4eYo2&+UI>=gyyNebb~K0I>2YW+rzsS%Pmmd*^E(UhSIRqu`2c#brGf)PF*&lT$PR< zb$wD;Qny!<6KJ*6Qgue-G*$iR@bky=srQ}^i80(oyoOh-!&_m;S|4NHxuq_n0*5<_StP53x_lN1nQ zY9 z!Rwow3BcspTOtb2dwO_WI%Z78{m?l5FM=uS_MVcU(1H6x9%+3Y4oB_FI#ufJPPh`D z0Fz{6#63O+D%@B-1^my=o!6b2{6L-1m#z0*C7jxPbhxhwglZzK@PJw{)4RL!WU_Kg z43^m>Cwq5qEnmeF*FGBb)qfvHYXG=;`)_B1!qvi=<=`g$itO61R5~9nHjW#0C8}}P zxQBN3rVrB70Kww;WFY~ZZ-K7P5b}M%SMTq3Dq7bV1yLclTBl^4UCs0ND>=6`OFNU9 z0!fS(SQVYEP;fx<>-M!%rIpX;-~?7TMW2>EwMP5=cm;q67?r~VLqcMQ?gSIH~1<=;&m? zQOIWCm|Xiyo&zddktBP!{?rlgbjX*@x$_7VYQ<|SA!w~{>Y=a(P=1KWab~>uFPQ;) yh_UMkTn?f(#++L`k)(gG(+mf-t21tASKY|}wCPIP;_*csr1yuhcF9${$NvFp63cu5 literal 530 zcmeAS@N?(olHy`uVBq!ia0vp^2|(b=ZN&^=a>}IR_^M|M)jI(J%3XaQkgp6o;ec)3?=6WWL@`mnpgbeX^Bdhe7*MNB!yD&8I4q&LkFI z$o%#FxsI&hvkew6zE+h6Ncy)}>hM*`v_s{86n;?PHDHinV>rx^Ai==H+>pp%z{AkS zcmTKH;#FN`FPy;U?7uG?a!fdpue;f9zGk@de*rL4j-P$%N0%9gA1(N7W4+?X=5?=c ze?MXQYWsPM7u#~xOOrsV4qw@H`Cq2~zGdIn{oDTj+qVt-Za=zMBL4wR=wXq(Kw@~j zN_+e1T8Ea{+KDo9dfyoZ%f7l6RqVLK?sDU*_{oQGMeP51S&8=tSY;0}=DJ_5J+OT5 qk6HJ2|GK~L_U*&J^12c3(Vtkmw&2XHnTvsu%;4$j=d#Wzp$P!4QQz+X From ba1384faff87928172b2493c0906ea8c2b803d09 Mon Sep 17 00:00:00 2001 From: RavmorganButOnCocaine Date: Sat, 2 Mar 2024 14:17:29 +0000 Subject: [PATCH 2/4] Automatic changelog update --- Resources/Changelog/ChangelogWhite.yml | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index a91b493b02..9d80b68b7f 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -1871,3 +1871,38 @@ id: 175 time: '2024-03-02T09:10:00.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/160 +- author: Remuchi + changes: + - message: "\u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u0442\ + \u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F \u0430\u043D\u0442\u0430\ + \u0436\u043A\u0438, \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0438 \u043F\ + \u043E\u0434\u043E\u0431\u043D\u043E\u0433\u043E \u0432 \u0430\u0445\u0435\u043B\ + \u043F\u0435." + type: Fix + - message: "\u043D\u043E\u0442\u0435\u0441\u044B, \u043E\u0442\u043F\u0440\u0430\ + \u0432\u043B\u044F\u0435\u043C\u044B\u0435 \u0432 \u0447\u0430\u0442, \u0431\ + \u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\ + \u043B\u044F\u044E\u0442\u0441\u044F \u0435\u0449\u0451 \u0438 \u0432 \u043A\ + \u043E\u043D\u0441\u043E\u043B\u044C." + type: Fix + - message: "\u0442\u0435\u043A\u0441\u0442\u0443\u0440\u0430 \u0441\u0435\u043A\u0440\ + \u0435\u0442\u043D\u043E\u0439 \u0434\u0432\u0435\u0440\u0438 \u0431\u044B\u043B\ + \u0430 \u043F\u0435\u0440\u0435\u0440\u0438\u0441\u043E\u0432\u0430\u043D\u0430\ + \ \u0434\u043B\u044F \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\ + \u0438\u044F \u0441 \u0430\u043A\u0442\u0443\u0430\u043B\u044C\u043D\u044B\u043C\ + \u0438 \u0442\u0435\u043A\u0441\u0442\u0443\u0440\u0430\u043C\u0438 \u0441\u0442\ + \u0435\u043D" + type: Fix + - message: "\u0438\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u043E\u0448\ + \u0438\u0431\u043A\u0438 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u043F\ + \u0440\u0438 \u0432\u044B\u043B\u0438\u0437\u044B\u0432\u0430\u043D\u0438\u0438\ + \ \u0440\u0430\u043D \u0437\u0430 \u0444\u0435\u043B\u0438\u043D\u0438\u0434\ + \u0430" + type: Fix + - message: "\u043F\u0435\u0440\u0435\u0432\u043E\u0434\u044B \u0434\u043B\u044F\ + \ \u0441\u0435\u043A\u0440\u0435\u0442\u043D\u043E\u0439 \u0434\u0432\u0435\u0440\ + \u0438" + type: Add + id: 176 + time: '2024-03-02T14:16:27.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/161 From 477dedc014136ffdff144c2877a73480593c5a79 Mon Sep 17 00:00:00 2001 From: Remuchi <72476615+Remuchi@users.noreply.github.com> Date: Sat, 2 Mar 2024 21:17:52 +0700 Subject: [PATCH 3/4] =?UTF-8?q?[Feat]=20Mindslave=20-=20=D0=B8=D0=BC=D0=BF?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D1=82=20=D0=BF=D0=BE=D0=B4=D1=87=D0=B8=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * tweak: стандартизация названий имплантеров * add: mindslave implant * add: briefing, uplink listing, overlay icons * add: new mindslave overlay icons by JustNemo * remove: ненужный файлик удалён * fix: фикс доставания импланта подчинения --- .../Overlays/ShowMindslaveIconsSystem.cs | 67 +++++++++ .../Implants/Mindslave/MindslaveSystem.cs | 85 +++++++++++ .../Implants/SharedImplanterSystem.cs | 138 ++++++++++-------- .../Implants/SharedSubdermalImplantSystem.cs | 2 +- .../Components/MindSlaveComponent.cs | 21 +++ .../Mindslave/SharedMindslaveSystem.cs | 54 +++++++ .../ru-RU/_white/implants/mindslave.ftl | 16 ++ .../ru-RU/locales-new/autotranslate-27.ftl | 38 ++--- .../ru-RU/locales-new/autotranslate-28.ftl | 10 -- .../entities/objects/misc/implanters.ftl | 75 ++++++---- .../objects/misc/subdermal_implants.ftl | 10 ++ .../Locale/ru-RU/store/uplink-catalog.ftl | 6 +- .../ru-RU/white/items/hardlight_spear.ftl | 10 +- .../Entities/Objects/Misc/implanters.yml | 30 ++-- Resources/Prototypes/White/Catalog/uplink.yml | 10 ++ .../Entities/Objects/Misc/implanters.yml | 20 ++- .../Objects/Misc/subdermal_implants.yml | 13 ++ Resources/Prototypes/White/tags.yml | 3 + .../_White/StatusIcon/mindslave.yml | 15 ++ .../White/Overlays/mindslave.rsi/master.png | Bin 0 -> 260 bytes .../White/Overlays/mindslave.rsi/meta.json | 17 +++ .../White/Overlays/mindslave.rsi/slave.png | Bin 0 -> 251 bytes 22 files changed, 494 insertions(+), 146 deletions(-) create mode 100644 Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs create mode 100644 Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs create mode 100644 Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs create mode 100644 Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs create mode 100644 Resources/Locale/ru-RU/_white/implants/mindslave.ftl create mode 100644 Resources/Prototypes/_White/StatusIcon/mindslave.yml create mode 100644 Resources/Textures/White/Overlays/mindslave.rsi/master.png create mode 100644 Resources/Textures/White/Overlays/mindslave.rsi/meta.json create mode 100644 Resources/Textures/White/Overlays/mindslave.rsi/slave.png diff --git a/Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs b/Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs new file mode 100644 index 0000000000..90c044e0d3 --- /dev/null +++ b/Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs @@ -0,0 +1,67 @@ +using Content.Client.Overlays; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Client.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client._White.Overlays; + +public sealed class ShowMindslaveIconsSystem : EquipmentHudSystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IPlayerManager _player = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + private void OnGetStatusIconsEvent( + EntityUid uid, + MindSlaveComponent mindSlaveComponent, + ref GetStatusIconsEvent args) + { + if (!IsActive || args.InContainer) + { + return; + } + var localEnt = _player.LocalEntity; + if (!TryComp(localEnt, out MindSlaveComponent? ownerMindSlave)) + { + return; + } + + var mindSlaveIcon = MindslaveIcon(uid, ownerMindSlave); + + args.StatusIcons.AddRange(mindSlaveIcon); + } + + private IEnumerable MindslaveIcon(EntityUid uid, MindSlaveComponent mindSlave) + { + var result = new List(); + + string? iconType; + if (GetEntity(mindSlave.Master) == uid) + { + iconType = mindSlave.MasterStatusIcon; + } + else if (mindSlave.Slaves.Contains(GetNetEntity(uid))) + { + iconType = mindSlave.SlaveStatusIcon; + } + else + { + return result; + } + + if (_prototype.TryIndex(iconType, out var mindslaveIcon)) + { + result.Add(mindslaveIcon); + } + + return result; + } +} diff --git a/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs b/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs new file mode 100644 index 0000000000..d2e1f7e733 --- /dev/null +++ b/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs @@ -0,0 +1,85 @@ +using Content.Server.Chat.Managers; +using Content.Server.Roles; +using Content.Server.Roles.Jobs; +using Content.Shared._White.Implants.Mindslave; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.Chat; +using Content.Shared.Implants; +using Content.Shared.Implants.Components; + +namespace Content.Server._White.Implants.Mindslave; + +public sealed class MindslaveSystem : SharedMindslaveSystem +{ + [Dependency] private readonly RoleSystem _role = default!; + [Dependency] private readonly IChatManager _chatManager = default!; + [Dependency] private readonly JobSystem _job = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMindslaveInserted); + SubscribeLocalEvent(OnMindslaveRemoved); + } + + private void OnMindslaveInserted(Entity ent, ref SubdermalImplantInserted args) + { + if (!Tag.HasTag(ent.Owner, MindslaveTag)) + { + return; + } + + var slaveComponent = EnsureComp(args.Target); + slaveComponent.Slaves.Add(GetNetEntity(args.Target)); + slaveComponent.Master = GetNetEntity(args.User); + + var masterComponent = EnsureComp(args.User); + masterComponent.Slaves.Add(GetNetEntity(args.Target)); + masterComponent.Master = GetNetEntity(args.User); + + Dirty(args.Target, masterComponent); + + if (!Mind.TryGetMind(args.Target, out var targetMindId, out var targetMind) || targetMind.Session is null) + { + return; + } + + var jobName = _job.MindTryGetJobName(args.User); + + // send message to chat + var message = Loc.GetString("mindslave-chat-message", ("player", args.User), ("role", jobName)); + var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + _chatManager.ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, + targetMind.Session.Channel, Color.FromHex("#5e9cff")); + + // add briefing in character menu + if (TryComp(targetMindId, out var roleBriefing)) + { + roleBriefing.Briefing += Loc.GetString("mindslave-briefing", ("player", args.User), ("role", jobName)); + Dirty(targetMindId, roleBriefing); + } + else + { + _role.MindAddRole(targetMindId, new RoleBriefingComponent + { + Briefing = Loc.GetString("mindslave-briefing", ("player", args.User), ("role", jobName)) + }, targetMind); + } + } + + private void OnMindslaveRemoved(Entity ent, ref SubdermalImplantRemoved args) + { + if (!TryComp(args.Target, out MindSlaveComponent? mindslave)) + { + return; + } + + if (Mind.TryGetMind(args.Target, out var mindId, out _)) + { + _role.MindTryRemoveRole(mindId); + Popup.PopupEntity(Loc.GetString("mindslave-freed", ("player", mindslave.Master)), args.Target, args.Target); + } + + RemComp(args.Target); + } +} \ No newline at end of file diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 31cc40b3a0..2728709606 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using System.Linq; using Content.Shared.Containers.ItemSlots; using Content.Shared.DoAfter; using Content.Shared.Examine; @@ -15,24 +14,46 @@ using Robust.Shared.Utility; namespace Content.Shared.Implants; //WD EDIT START -public class SubdermalImplantInserted +public sealed class SubdermalImplantInserted { - public EntityUid Entity; + /// + /// Entity who implants + /// + public EntityUid User; + + /// + /// Entity being implanted + /// + public EntityUid Target; + public SubdermalImplantComponent Component; - public SubdermalImplantInserted(EntityUid entity, SubdermalImplantComponent component) + + public SubdermalImplantInserted(EntityUid user, EntityUid target, SubdermalImplantComponent component) { - Entity = entity; + User = user; + Target = target; Component = component; } } -public class SubdermalImplantRemoved +public sealed class SubdermalImplantRemoved { - public EntityUid Entity; + /// + /// Entity who removes implant + /// + public EntityUid User; + + /// + /// Entity which implant is removing + /// + public EntityUid Target; + public SubdermalImplantComponent Component; - public SubdermalImplantRemoved(EntityUid entity, SubdermalImplantComponent component) + + public SubdermalImplantRemoved(EntityUid user, EntityUid target, SubdermalImplantComponent component) { - Entity = entity; + User = user; + Target = target; Component = component; } } @@ -90,10 +111,11 @@ public abstract class SharedImplanterSystem : EntitySystem if (component.ImplanterSlot.ContainerSlot != null) _container.Remove(implant.Value, component.ImplanterSlot.ContainerSlot); + implantComp.ImplantedEntity = target; implantContainer.OccludesLight = false; _container.Insert(implant.Value, implantContainer); - RaiseLocalEvent(new SubdermalImplantInserted(implantComp.ImplantedEntity!.Value, implantComp)); //WD EDIT + RaiseLocalEvent(implant.Value, new SubdermalImplantInserted(user, target, implantComp)); //WD EDIT if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) DrawMode(implanter, component); @@ -103,7 +125,7 @@ public abstract class SharedImplanterSystem : EntitySystem var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; RaiseLocalEvent(target, ref ev); - Dirty(component); + Dirty(implanter, component); } public bool CanImplant( @@ -146,45 +168,47 @@ public abstract class SharedImplanterSystem : EntitySystem var permanentFound = false; - if (_container.TryGetContainer(target, ImplanterComponent.ImplantSlotId, out var implantContainer)) + if (!_container.TryGetContainer(target, ImplanterComponent.ImplantSlotId, out var implantContainer)) + return; + + var implantCompQuery = GetEntityQuery(); + + foreach (var implant in implantContainer.ContainedEntities) { - var implantCompQuery = GetEntityQuery(); + if (!implantCompQuery.TryGetComponent(implant, out var implantComp)) + continue; - foreach (var implant in implantContainer.ContainedEntities) + //Don't remove a permanent implant and look for the next that can be drawn + if (!_container.CanRemove(implant, implantContainer)) { - if (!implantCompQuery.TryGetComponent(implant, out var implantComp)) - continue; + var implantName = Identity.Entity(implant, EntityManager); + var targetName = Identity.Entity(target, EntityManager); + var failedPermanentMessage = Loc.GetString("implanter-draw-failed-permanent", + ("implant", implantName), ("target", targetName)); - //Don't remove a permanent implant and look for the next that can be drawn - if (!_container.CanRemove(implant, implantContainer)) - { - var implantName = Identity.Entity(implant, EntityManager); - var targetName = Identity.Entity(target, EntityManager); - var failedPermanentMessage = Loc.GetString("implanter-draw-failed-permanent", - ("implant", implantName), ("target", targetName)); - _popup.PopupEntity(failedPermanentMessage, target, user); - permanentFound = implantComp.Permanent; - continue; - } - - _container.Remove(implant, implantContainer); - RaiseLocalEvent(new SubdermalImplantRemoved(implantComp.ImplantedEntity!.Value, implantComp)); // WD EDIT - implantComp.ImplantedEntity = null; - _container.Insert(implant, implanterContainer); + _popup.PopupEntity(failedPermanentMessage, target, user); permanentFound = implantComp.Permanent; - - var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; - RaiseLocalEvent(target, ref ev); - - //Break so only one implant is drawn - break; + continue; } - if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound) - ImplantMode(implanter, component); + RaiseLocalEvent(implant, new SubdermalImplantRemoved(user, target, implantComp)); // WD EDIT + _container.Remove(implant, implantContainer); - Dirty(component); + implantComp.ImplantedEntity = null; + _container.Insert(implant, implanterContainer); + permanentFound = implantComp.Permanent; + + var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; + RaiseLocalEvent(target, ref ev); + + //Break so only one implant is drawn + break; } + + if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound) + ImplantMode(implanter, component); + + Dirty(implanter, component); } private void ImplantMode(EntityUid uid, ImplanterComponent component) @@ -204,26 +228,24 @@ public abstract class SharedImplanterSystem : EntitySystem if (!TryComp(uid, out var appearance)) return; - bool implantFound; + var implantFound = component.ImplanterSlot.HasItem; - if (component.ImplanterSlot.HasItem) - implantFound = true; - - else - implantFound = false; - - if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); - - else if (component.CurrentMode == ImplanterToggleMode.Inject && component.ImplantOnly) + switch (component.CurrentMode) { - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); - _appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, - appearance); - } + case ImplanterToggleMode.Inject when !component.ImplantOnly: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + case ImplanterToggleMode.Inject when component.ImplantOnly: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + _appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, + appearance); - else - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + case ImplanterToggleMode.Draw: + default: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + } } } diff --git a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs index ebe810546c..e5ba0a1961 100644 --- a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs +++ b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs @@ -136,7 +136,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem var implantContainer = implantedComp.ImplantContainer; component.ImplantedEntity = target; - RaiseLocalEvent(new SubdermalImplantInserted(target, component)); + RaiseLocalEvent(implant, new SubdermalImplantInserted(target, target, component)); _container.Insert(implant, implantContainer); } diff --git a/Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs b/Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs new file mode 100644 index 0000000000..48ec51b909 --- /dev/null +++ b/Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs @@ -0,0 +1,21 @@ +using Content.Shared.StatusIcon; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared._White.Implants.Mindslave.Components; + +[RegisterComponent, AutoGenerateComponentState, NetworkedComponent] +public sealed partial class MindSlaveComponent : Component +{ + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public List Slaves = new(); + + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public NetEntity Master; + + [DataField("slaveStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string SlaveStatusIcon = "SlaveMindslaveIcon"; + + [DataField("masterStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MasterStatusIcon = "MasterMindslaveIcon"; +} diff --git a/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs b/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs new file mode 100644 index 0000000000..fe1e266cf3 --- /dev/null +++ b/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs @@ -0,0 +1,54 @@ +using Content.Shared._White.Cult.Components; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.Implants; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Content.Shared.Mindshield.Components; +using Content.Shared.Popups; +using Content.Shared.Tag; + +namespace Content.Shared._White.Implants.Mindslave; + +public abstract class SharedMindslaveSystem : EntitySystem +{ + [Dependency] protected readonly TagSystem Tag = default!; + [Dependency] protected readonly SharedMindSystem Mind = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + + protected const string MindslaveTag = "MindSlave"; + + public override void Initialize() + { + SubscribeLocalEvent(OnTryInsertMindslave); + } + + private void OnTryInsertMindslave(Entity ent, ref AddImplantAttemptEvent args) + { + if (!Tag.HasTag(args.Implant, MindslaveTag)) + { + return; + } + + string message; + string wrappedMessage; + if (args.Target == args.User) + { + message = Loc.GetString("mindslave-target-self"); + wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + Popup.PopupClient(wrappedMessage, args.Implanter, args.User); + args.Cancel(); + return; + } + + if (HasComp(args.Target) || + HasComp(args.Target) || + HasComp(args.Target) || + HasComp(args.Target)) + { + message = Loc.GetString("mindslave-cant-insert"); + wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + Popup.PopupClient(wrappedMessage, args.Implanter, args.User); + args.Cancel(); + } + } +} diff --git a/Resources/Locale/ru-RU/_white/implants/mindslave.ftl b/Resources/Locale/ru-RU/_white/implants/mindslave.ftl new file mode 100644 index 0000000000..8d98357654 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/implants/mindslave.ftl @@ -0,0 +1,16 @@ +mindslave-briefing = Служите и защищайте {$player}, {$role}. Выполняйте каждый их приказ. Они для вас - абсолютная власть. +mindslave-chat-message = Перед вашим глазами в мгновение пролетают осколки ваших воспоминаний, после чего сознание застилает белая пелена. Во вспышке ярко-красного света вы вспоминаете свое предназначение - служить {$player}, {$role}. +mindslave-freed = Вы больше не служите {$player}! + +mindslave-target-self = Вы не можете сделать себя своим же рабом +mindslave-cant-insert = Разум данного существа уже на чем-то зациклен + +uplink-mind-slave = Имплант подчинения +uplink-mind-slave-desc = Захватите разум живого существа и прикажите ему закидать капитана взрывными пирогами. + +ent-MindSlaveImplanter = { ent-BaseImplanter } + .desc = { "" } + .suffix = майдслейв + +ent-MindslaveImplant = Имплант подчинения + .desc = Сделайте из кого-то свою личную куклу. diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl index eb9eff115c..bdac67fb6c 100644 --- a/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl +++ b/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl @@ -1,38 +1,28 @@ ent-EggSpider = яичный паук - .desc = Это драгоценный камень? Это яйцо? это выглядит дорого. + .desc = Это драгоценный камень? Это яйцо? это выглядит дорого. ent-LampInterrogator = лампа следователя - .desc = Ультраяркая лампа для плохого полицейского + .desc = Ультраяркая лампа для плохого полицейского ent-CultistCuffs = самодельные стяжки - .desc = Самодельные наручники из запасных тросов. + .desc = Самодельные наручники из запасных тросов. ent-ParamedicIDCard = ID карта парамедика - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-BrigmedicIDCard = ID карта бригмедика - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorEngineerIDCard = ID карта бригадира - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorResearcherIDCard = ID карта ведущего исследователя - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorPhysicianIDCard = ID карта медицинского офицера - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorOfficerIDCard = ID карта ветерана СБ - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorSalvageSpecialistIDCard = ID карта охотника карго - .desc = { ent-IDCardStandard.desc } -ent-BikeHornImplanter = имплантат велосипедного гудка - .desc = "" -ent-UplinkImplanter = имплантат аплинка - .desc = "" -ent-EmpImplanter = ЭМИ-имплантат - .desc = "" -ent-DnaScramblerImplanter = имплантат скремблера ДНК - .desc = "" -ent-DeathRattleImplanter = имплантат предсмертных хрипов - .desc = "" + .desc = { ent-IDCardStandard.desc } ent-ModularReceiver = модульный приемник - .desc = Жизненно важная часть, используемая в создании огнестрельного оружия. + .desc = Жизненно важная часть, используемая в создании огнестрельного оружия. ent-RifleStock = приклад - .desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия. + .desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия. ent-MedalCase = футляр для медали - .desc = Футляр с медалями. + .desc = Футляр с медалями. ent-SyndicateSpongeBox = коробка куба обезьяны - .desc = Обезьяньи кубики марки Drymate. Просто добавь воды! + .desc = Обезьяньи кубики марки Drymate. Просто добавь воды! diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl index 60c39f6356..e2a4dbb090 100644 --- a/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl +++ b/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl @@ -20,16 +20,6 @@ ent-SpiderWeb = паутина .desc = Она тягучая и липкая. ent-SpiderWebClown = клоунская паутина .desc = Она тягучая и липкая. -ent-BikeHornImplant = имплантат велосипедного гудка - .desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время. -ent-UplinkImplant = имплантат аплинка - .desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката. -ent-EmpImplant = ЭМИ-имплантат - .desc = Этот имплантат создает электромагнитный импульс при активации. -ent-DnaScramblerImplant = имплантат скремблера ДНК - .desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя. -ent-DeathRattleImplant = имплантат предсмертных хрипов - .desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет. ent-FloorTileItemFlesh = пол из плоти .desc = { ent-FloorTileItemBase.desc } ent-AmeJar = топливный бак ДАМ'а diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index 894d4165fb..07672cfe3b 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -1,33 +1,54 @@ ent-BaseImplanter = имплантер .desc = Специальный шприц, используемый только для имплантов. - .suffix = { "" } ent-Implanter = { ent-BaseImplanter } .desc = { ent-BaseImplanter.desc } - .suffix = { "" } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = Одноразовый имплантер. - .suffix = { "" } -ent-SadTromboneImplanter = имплантер Грустный тромбон - .desc = Одноразовый имплантер, содержащий имплант, который проигрывает грустную мелодию при смерти владельца. - .suffix = { "" } -ent-LightImplanter = имплантер Свет - .desc = Одноразовый имплантер, содержащий имплант, который излучает свет при активации. - .suffix = { "" } -ent-TrackingImplanter = имплантер Отслеживание - .desc = Одноразовый имплантер, содержащий имплант, постоянно передающий координаты владельца. - .suffix = { "" } -ent-StorageImplanter = имплантер Хранилище - .desc = Одноразовый имплантер, содержащий имплант, создающий хранилище в теле владельца. - .suffix = { "" } -ent-FreedomImplanter = имплантер Свобода - .desc = Одноразовый имплантер, содержащий имплант, позволяющий владельцу три раза освободиться от наручников и других ограничителей. - .suffix = { "" } -ent-MicroBombImplanter = имплантер Микробомба - .desc = Одноразовый имплантер, содержащий неизвлекаемый имплант, вызывающий небольшой взрыв при смерти владельца. - .suffix = { "" } -ent-MacroBombImplanter = имплантер Макробомба - .desc = Одноразовый имплантер, содержащий имплант, вызывающий мощный взрыв при смерти владельца по истечении заданного времени. - .suffix = { "" } -ent-MindshieldImplanter = имплантер Защиты Разума - .desc = Одноразовый имплантер, содержащий имплант защиты разума. - .suffix = { "" } +ent-SadTromboneImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = грустный тромбон +ent-LightImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = свет +ent-TrackingImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = отслеживание +ent-StorageImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = хранилище +ent-FreedomImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = свобода +ent-MicroBombImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = микробомба +ent-MacroBombImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = макробомба +ent-MindShieldImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = защита разума +ent-BikeHornImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = велосипедный гудок +ent-UplinkImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = аплинк +ent-EmpImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = ЭМИ +ent-DnaScramblerImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = скремблер ДНК +ent-DeathRattleImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = предсмертный хрип +ent-ScramImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = переброска +ent-DeathAcidifierImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = посмертный растворитель +ent-ImplanterAdmeme = { ent-BaseImplanter } + .desc = {""} + .suffix = адмемы diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl index 1931cab724..69213ef1f3 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl @@ -25,3 +25,13 @@ ent-MacroBombImplant = имплант Макробомба ent-MindShieldImplant = имплант Защиты Разума .desc = Маленький имплант, который защищает мозги носителя от промывки. .suffix = { "" } +ent-BikeHornImplant = имплант велосипедного гудка + .desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время. +ent-UplinkImplant = имплант аплинка + .desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката. +ent-EmpImplant = ЭМИ-имплант + .desc = Этот имплантат создает электромагнитный импульс при активации. +ent-DnaScramblerImplant = имплант скремблера ДНК + .desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя. +ent-DeathRattleImplant = имплант предсмертных хрипов + .desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет. diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index cd81a8a648..dcbed400e5 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -181,7 +181,7 @@ uplink-freedom-implanter-name = Имплант свободы uplink-freedom-implanter-desc = Убирайся подальше от этих мерзких офицеров с этим имплантатом! uplink-scram-implanter-name = Имплант переброски -uplink-scram-implanter-desc = Имплантат 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено. +uplink-scram-implanter-desc = Имплант 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено. uplink-dna-scrambler-implanter-name = Имплант скремблера ДНК uplink-dna-scrambler-implanter-desc = Одноразовый имплантат, который можно активировать, чтобы изменить вашу ДНК и придать вам совершенно новый вид, также имеет функцию отмены изменений. Невозможно зашифровать уже зашифрованную ДНК. @@ -198,10 +198,10 @@ uplink-uplink-implanter-desc = Незаметно заказывайте обо uplink-deathrattle-implant-name = Коробка имплантатов предсмертного хрипа uplink-deathrattle-implant-desc = Коробка с достаточным количеством предсмертных хрипов для всего отряда. Передает сообщение, содержащее вашу позицию, на канал синдиката, когда вы переходите в критическое состояние или умираете. -uplink-death-acidifier-implant-name = Имплантат расплавления +uplink-death-acidifier-implant-name = Имплантер расплавления uplink-death-acidifier-implant-desc = Полностью расплавляет пользователя и его снаряжение при использовании или смерти. -uplink-micro-bomb-implanter-name = Имплантатор микро-бомбы +uplink-micro-bomb-implanter-name = Имплантер микро-бомбы uplink-micro-bomb-implanter-desc = Взорвитесь при смерти или ручной активации с помощью этого имплантата. Уничтожает тело со всем снаряжением. # Bundles diff --git a/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl b/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl index 3e6d783a7a..421650fba6 100644 --- a/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl +++ b/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl @@ -1,13 +1,19 @@ hardlight-spear-pickup-failed = Вы не можете подобрать световое копьё. use-hardlight-spear-implant-action-name = Создать световое копьё. use-hardlight-spear-implant-action-description = Создает световое копьё в ваших руках. -uplink-hardlight-spear-implant-name = Имплантатор световое копьё +uplink-hardlight-spear-implant-name = Имплантер световое копьё uplink-hardlight-spear-implant-desc = Имплант, вводимый в тело и активируемый по желанию пользователя. Он вызывает копье из твердого света, с помощью которого пользователь может сеять хаос. ent-SpearHardlight = световое копьё .desc = Копьё из твердого света. -ent-HardlightSpearImplanter = имплантатор световое копьё +ent-HardlightSpearImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = световое копьё ent-HardlightSpearImplant = имплант световое копьё .desc = Этот имплант создаёт световое копьё в ваших руках. + +ent-SmokeImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = дым diff --git a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml index 4a7115c2d7..4d0e877290 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml @@ -124,24 +124,24 @@ - type: entity id: SadTromboneImplanter - name: sad trombone implanter parent: BaseImplantOnlyImplanter + suffix: sad trombone components: - type: Implanter implant: SadTromboneImplant - type: entity id: LightImplanter - name: light implanter parent: BaseImplantOnlyImplanter + suffix: light components: - type: Implanter implant: LightImplant - type: entity id: BikeHornImplanter - name: bike horn implanter parent: BaseImplantOnlyImplanter + suffix: bike horn components: - type: Implanter implant: BikeHornImplant @@ -150,8 +150,8 @@ - type: entity id: TrackingImplanter - name: tracking implanter parent: BaseImplantOnlyImplanter + suffix: tracking components: - type: Implanter implant: TrackingImplant @@ -160,24 +160,24 @@ - type: entity id: StorageImplanter - name: storage implanter parent: BaseImplantOnlyImplanterSyndi + suffix: storage components: - type: Implanter implant: StorageImplant - type: entity id: FreedomImplanter - name: freedom implanter parent: BaseImplantOnlyImplanterSyndi + suffix: freedom components: - type: Implanter implant: FreedomImplant - type: entity id: UplinkImplanter - name: uplink implanter parent: BaseImplantOnlyImplanterSyndi + suffix: uplink components: - type: Implanter implant: UplinkImplant @@ -185,24 +185,24 @@ - type: entity id: EmpImplanter - name: EMP implanter parent: BaseImplantOnlyImplanterSyndi + suffix: EMP components: - type: Implanter implant: EmpImplant - type: entity id: ScramImplanter - name: scram implanter parent: BaseImplantOnlyImplanterSyndi + suffix: scram components: - type: Implanter implant: ScramImplant - type: entity id: DnaScramblerImplanter - name: DNA scrambler implanter parent: BaseImplantOnlyImplanterSyndi + suffix: DNA scrambler components: - type: Implanter implant: DnaScramblerImplant @@ -211,32 +211,32 @@ - type: entity id: MicroBombImplanter - name: micro-bomb implanter parent: BaseImplantOnlyImplanterSyndi + suffix: micro-bomb components: - type: Implanter implant: MicroBombImplant - type: entity id: MacroBombImplanter - name: macro-bomb implanter parent: BaseImplantOnlyImplanterSyndi + suffix: macro-bomb components: - type: Implanter implant: MacroBombImplant - type: entity id: DeathRattleImplanter - name: death rattle implanter parent: BaseImplantOnlyImplanterSyndi + suffix: death rattle components: - type: Implanter implant: DeathRattleImplant - type: entity id: DeathAcidifierImplanter - name: death acidifier implanter parent: BaseImplantOnlyImplanterSyndi + suffix: death acidifier components: - type: Implanter implant: DeathAcidifierImplant @@ -245,8 +245,8 @@ - type: entity id: MindShieldImplanter - name: mind-shield implanter parent: BaseImplantOnlyImplanter + suffix: mind-shield components: - type: Implanter implant: MindShieldImplant diff --git a/Resources/Prototypes/White/Catalog/uplink.yml b/Resources/Prototypes/White/Catalog/uplink.yml index 9c6da52d4c..9bb495ac41 100644 --- a/Resources/Prototypes/White/Catalog/uplink.yml +++ b/Resources/Prototypes/White/Catalog/uplink.yml @@ -204,3 +204,13 @@ Telecrystal: 1 categories: - UplinkAmmo + +- type: listing + id: UplinkMindSlaveImplanter + name: uplink-mind-slave + description: uplink-mind-slave-desc + productEntity: MindSlaveImplanter + cost: + Telecrystal: 6 + categories: + - UplinkImplants diff --git a/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml index 4970be67b5..8bbbcf60e7 100644 --- a/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml @@ -1,15 +1,23 @@ - type: entity id: SmokeImplanter - name: имплант дыма parent: BaseImplantOnlyImplanterSyndi + suffix: smoke components: - - type: Implanter - implant: SmokeImplant + - type: Implanter + implant: SmokeImplant - type: entity id: HardlightSpearImplanter - name: hardlight spear implanter parent: BaseImplantOnlyImplanterSyndi + suffix: hardlight spear components: - - type: Implanter - implant: HardlightSpearImplant + - type: Implanter + implant: HardlightSpearImplant + +- type: entity + id: MindSlaveImplanter + parent: BaseImplantOnlyImplanterSyndi + suffix: mindslave + components: + - type: Implanter + implant: MindslaveImplant diff --git a/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml index 686d3b4283..b916ec534f 100644 --- a/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml @@ -23,3 +23,16 @@ components: - type: SubdermalImplant implantAction: ActivateHardlightSpearImplant + +- type: entity + parent: BaseSubdermalImplant + id: MindslaveImplant + name: mindslave implant + description: Make someone a proper doll for your use. + noSpawn: true + components: + - type: SubdermalImplant + - type: Tag + tags: + - MindSlave + diff --git a/Resources/Prototypes/White/tags.yml b/Resources/Prototypes/White/tags.yml index fc6f00c9af..466a1ddb17 100644 --- a/Resources/Prototypes/White/tags.yml +++ b/Resources/Prototypes/White/tags.yml @@ -51,3 +51,6 @@ - type: Tag id: WeldedKnife + +- type: Tag + id: MindSlave diff --git a/Resources/Prototypes/_White/StatusIcon/mindslave.yml b/Resources/Prototypes/_White/StatusIcon/mindslave.yml new file mode 100644 index 0000000000..9af545c195 --- /dev/null +++ b/Resources/Prototypes/_White/StatusIcon/mindslave.yml @@ -0,0 +1,15 @@ +- type: statusIcon + id: MasterMindslaveIcon + priority: 3 + locationPreference: Left + icon: + sprite: /Textures/White/Overlays/mindslave.rsi + state: master + +- type: statusIcon + id: SlaveMindslaveIcon + priority: 3 + locationPreference: Left + icon: + sprite: /Textures/White/Overlays/mindslave.rsi + state: slave diff --git a/Resources/Textures/White/Overlays/mindslave.rsi/master.png b/Resources/Textures/White/Overlays/mindslave.rsi/master.png new file mode 100644 index 0000000000000000000000000000000000000000..56416298ef956c274f9fccab0c49a7f9bc0e1046 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJjh-%!ArYL(TTH(EJKw-AW50i@ zV86-HARh%`r=v2GDL+*um-(J$O%{+=apOP0wCTx_^U^$1a}{~mroBtB*1jzvaclLp z3y162*aAf6*l&AmZ^h6l*d>>>LqLYrV1B#xGNT3qjsr(lByz?XJM7~r_Hg89*dTG& z=|EE~^Ba#R0u7xHOKn9}4o31!_s^Wmy7IxlKxH@Q1QQl)M4KZA1H%;t@5B4+>K+3f g&zBnEnda-upaoFVdQ&MBb@04V!W-2eap literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Overlays/mindslave.rsi/meta.json b/Resources/Textures/White/Overlays/mindslave.rsi/meta.json new file mode 100644 index 0000000000..3786e26e8d --- /dev/null +++ b/Resources/Textures/White/Overlays/mindslave.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "@JustNemo", + "states": [ + { + "name": "slave" + }, + { + "name": "master" + } + ] +} diff --git a/Resources/Textures/White/Overlays/mindslave.rsi/slave.png b/Resources/Textures/White/Overlays/mindslave.rsi/slave.png new file mode 100644 index 0000000000000000000000000000000000000000..3739880d22873569594c5ac942c696184debe43a GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6`n4RArYL(TTH(EJKw-AW50i@ zV86-HARPr^r=v2GGOtSmcy8aXXifaO`maXPmIn>844Y(96pa`<*PdIpmwAT6G^vPP z&2P6&Pf2G;OffWQZ)3T^sPH*aZ1LvI4D%Zq8<@|j`Xw67n$NtQ`v_a-Mdk+Ch8)W? zK{-hVmRXk`=(K5TU$Wv3x~#l7t+(w!21gGTg6FOP1H&Iqd9Adhh%}&^`BEc1(|mmy Yw18|5AO?X;!IMFhr>mdKI;Vst0IFA3U;qFB literal 0 HcmV?d00001 From e185a5d7b40166f4860747b3ed4912eb21a94455 Mon Sep 17 00:00:00 2001 From: RavmorganButOnCocaine Date: Sat, 2 Mar 2024 14:18:55 +0000 Subject: [PATCH 4/4] Automatic changelog update --- Resources/Changelog/ChangelogWhite.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/ChangelogWhite.yml b/Resources/Changelog/ChangelogWhite.yml index 9d80b68b7f..59a39228da 100644 --- a/Resources/Changelog/ChangelogWhite.yml +++ b/Resources/Changelog/ChangelogWhite.yml @@ -1906,3 +1906,11 @@ id: 176 time: '2024-03-02T14:16:27.0000000+00:00' url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/161 +- author: Remuchi + changes: + - message: "\u0418\u043C\u043F\u043B\u0430\u043D\u0442 \u043F\u043E\u0434\u0447\u0438\ + \u043D\u0435\u043D\u0438\u044F \u0432 \u0430\u043F\u043B\u0438\u043D\u043A." + type: Add + id: 177 + time: '2024-03-02T14:17:52.0000000+00:00' + url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/152