diff --git a/Content.Client/Language/LanguageMenuWindow.xaml.cs b/Content.Client/Language/LanguageMenuWindow.xaml.cs index e6744b5770a..d338bf4c419 100644 --- a/Content.Client/Language/LanguageMenuWindow.xaml.cs +++ b/Content.Client/Language/LanguageMenuWindow.xaml.cs @@ -7,6 +7,7 @@ using Robust.Client.UserInterface.XAML; using Robust.Shared.Console; using Robust.Shared.Utility; +using Serilog; using static Content.Shared.Language.Systems.SharedLanguageSystem; namespace Content.Client.Language; @@ -23,6 +24,15 @@ public LanguageMenuWindow() _clientLanguageSystem = IoCManager.Resolve().GetEntitySystem(); } + protected override void Opened() + { + // Refresh the window when it gets opened. + // This actually causes two refreshes: one immediately, and one after the server sends a state message. + UpdateState(_clientLanguageSystem.CurrentLanguage, _clientLanguageSystem.SpokenLanguages); + _clientLanguageSystem.RequestStateUpdate(); + } + + public void UpdateState(string currentLanguage, List spokenLanguages) { var langName = Loc.GetString($"language-{currentLanguage}-name"); @@ -46,55 +56,55 @@ public void UpdateState(string currentLanguage, List spokenLanguages) private void AddLanguageEntry(string language) { - var proto = _clientLanguageSystem.GetLanguage(language); + var proto = _clientLanguageSystem.GetLanguagePrototype(language); var state = new EntryState { language = language }; - var container = new BoxContainer(); - container.Orientation = BoxContainer.LayoutOrientation.Vertical; + var container = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Vertical }; - // Create and add a header with the name and the button to select the language + #region Header + var header = new BoxContainer { - var header = new BoxContainer(); - header.Orientation = BoxContainer.LayoutOrientation.Horizontal; + Orientation = BoxContainer.LayoutOrientation.Horizontal, + HorizontalExpand = true, + SeparationOverride = 2 + }; - header.Orientation = BoxContainer.LayoutOrientation.Horizontal; - header.HorizontalExpand = true; - header.SeparationOverride = 2; + var name = new Label + { + Text = proto?.Name ?? Loc.GetString("generic-error"), + MinWidth = 50, + HorizontalExpand = true + }; - var name = new Label(); - name.Text = proto?.Name ?? ""; - name.MinWidth = 50; - name.HorizontalExpand = true; + var button = new Button { Text = "Choose" }; + button.OnPressed += _ => OnLanguageChosen(language); + state.button = button; - var button = new Button(); - button.Text = "Choose"; - button.OnPressed += _ => OnLanguageChosen(language); - state.button = button; + header.AddChild(name); + header.AddChild(button); - header.AddChild(name); - header.AddChild(button); + container.AddChild(header); + #endregion - container.AddChild(header); - } - - // Create and add a collapsible description + #region Collapsible description + var body = new CollapsibleBody { - var body = new CollapsibleBody(); - body.HorizontalExpand = true; - body.Margin = new Thickness(4f, 4f); + HorizontalExpand = true, + Margin = new Thickness(4f, 4f) + }; - var description = new RichTextLabel(); - description.SetMessage(proto?.Description ?? ""); - description.HorizontalExpand = true; + var description = new RichTextLabel { HorizontalExpand = true }; + description.SetMessage(proto?.Description ?? Loc.GetString("generic-error")); + body.AddChild(description); - body.AddChild(description); + var collapser = new Collapsible(Loc.GetString("language-menu-description-header"), body) + { + Orientation = BoxContainer.LayoutOrientation.Vertical, + HorizontalExpand = true + }; - var collapser = new Collapsible(Loc.GetString("language-menu-description-header"), body); - collapser.Orientation = BoxContainer.LayoutOrientation.Vertical; - collapser.HorizontalExpand = true; - - container.AddChild(collapser); - } + container.AddChild(collapser); + #endregion // Before adding, wrap the new container in a PanelContainer to give it a distinct look var wrapper = new PanelContainer(); @@ -106,9 +116,10 @@ private void AddLanguageEntry(string language) _entries.Add(state); } + private void OnLanguageChosen(string id) { - var proto = _clientLanguageSystem.GetLanguage(id); + var proto = _clientLanguageSystem.GetLanguagePrototype(id); if (proto != null) _clientLanguageSystem.RequestSetLanguage(proto); } diff --git a/Content.Client/Language/Systems/LanguageSystem.cs b/Content.Client/Language/Systems/LanguageSystem.cs index 3254297b0c2..9714078b2c5 100644 --- a/Content.Client/Language/Systems/LanguageSystem.cs +++ b/Content.Client/Language/Systems/LanguageSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Language; using Content.Shared.Language.Events; using Content.Shared.Language.Systems; +using Robust.Client; using Robust.Shared.Console; namespace Content.Client.Language.Systems; @@ -14,6 +15,8 @@ namespace Content.Client.Language.Systems; /// public sealed class LanguageSystem : SharedLanguageSystem { + [Dependency] private readonly IBaseClient _client = default!; + /// /// The current language of the entity currently possessed by the player. /// @@ -27,11 +30,26 @@ public sealed class LanguageSystem : SharedLanguageSystem /// public List UnderstoodLanguages { get; private set; } = new(); - [Dependency] private readonly IConsoleHost _consoleHost = default!; - public override void Initialize() { + base.Initialize(); + SubscribeNetworkEvent(OnLanguagesUpdated); + _client.RunLevelChanged += OnRunLevelChanged; + } + + private void OnLanguagesUpdated(LanguagesUpdatedMessage message) + { + CurrentLanguage = message.CurrentLanguage; + SpokenLanguages = message.Spoken; + UnderstoodLanguages = message.Understood; + } + + private void OnRunLevelChanged(object? sender, RunLevelChangedEventArgs args) + { + // Request an update when entering a game + if (args.NewLevel == ClientRunLevel.InGame) + RequestStateUpdate(); } /// @@ -45,23 +63,14 @@ public void RequestStateUpdate() public void RequestSetLanguage(LanguagePrototype language) { - // May cause some minor desync... if (language.ID == CurrentLanguage) return; - // (This is dumb. This is very dumb. It should be a message instead.) - // TODO Change this, soonish - _consoleHost.ExecuteCommand("languageselect " + language.ID); + RaiseNetworkEvent(new LanguagesSetMessage(language.ID)); + // May cause some minor desync... // So to reduce the probability of desync, we replicate the change locally too if (SpokenLanguages.Contains(language.ID)) CurrentLanguage = language.ID; } - - private void OnLanguagesUpdated(LanguagesUpdatedMessage message) - { - CurrentLanguage = message.CurrentLanguage; - SpokenLanguages = message.Spoken; - UnderstoodLanguages = message.Understood; - } } diff --git a/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs b/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs index b2f3747728f..f36521ce819 100644 --- a/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs +++ b/Content.Client/UserInterface/Systems/Language/LanguageMenuUIController.cs @@ -15,30 +15,32 @@ namespace Content.Client.UserInterface.Systems.Language; [UsedImplicitly] public sealed class LanguageMenuUIController : UIController, IOnStateEntered, IOnStateExited { - public LanguageMenuWindow? _languageWindow; + public LanguageMenuWindow? LanguageWindow; private MenuButton? LanguageButton => UIManager.GetActiveUIWidgetOrNull()?.LanguageButton; public override void Initialize() { - SubscribeNetworkEvent((LanguagesUpdatedMessage message, EntitySessionEventArgs args) => _languageWindow?.UpdateState(message.CurrentLanguage, message.Spoken)); + SubscribeNetworkEvent((LanguagesUpdatedMessage message, EntitySessionEventArgs _) => + LanguageWindow?.UpdateState(message.CurrentLanguage, message.Spoken)); } public void OnStateEntered(GameplayState state) { - DebugTools.Assert(_languageWindow == null); + DebugTools.Assert(LanguageWindow == null); - _languageWindow = UIManager.CreateWindow(); - LayoutContainer.SetAnchorPreset(_languageWindow, LayoutContainer.LayoutPreset.CenterTop); + LanguageWindow = UIManager.CreateWindow(); + LayoutContainer.SetAnchorPreset(LanguageWindow, LayoutContainer.LayoutPreset.CenterTop); - CommandBinds.Builder.Bind(ContentKeyFunctions.OpenLanguageMenu, InputCmdHandler.FromDelegate(_ => ToggleWindow())).Register(); + CommandBinds.Builder.Bind(ContentKeyFunctions.OpenLanguageMenu, + InputCmdHandler.FromDelegate(_ => ToggleWindow())).Register(); } public void OnStateExited(GameplayState state) { - if (_languageWindow != null) + if (LanguageWindow != null) { - _languageWindow.Dispose(); - _languageWindow = null; + LanguageWindow.Dispose(); + LanguageWindow = null; } CommandBinds.Unregister(); @@ -47,9 +49,7 @@ public void OnStateExited(GameplayState state) public void UnloadButton() { if (LanguageButton == null) - { return; - } LanguageButton.OnPressed -= LanguageButtonPressed; } @@ -57,51 +57,33 @@ public void UnloadButton() public void LoadButton() { if (LanguageButton == null) - { return; - } LanguageButton.OnPressed += LanguageButtonPressed; - if (_languageWindow == null) - { + if (LanguageWindow == null) return; - } - _languageWindow.OnClose += DeactivateButton; - _languageWindow.OnOpen += ActivateButton; + LanguageWindow.OnClose += () => LanguageButton.Pressed = false; + LanguageWindow.OnOpen += () => LanguageButton.Pressed = true; } - private void DeactivateButton() => LanguageButton!.Pressed = false; - private void ActivateButton() => LanguageButton!.Pressed = true; - private void LanguageButtonPressed(ButtonEventArgs args) { ToggleWindow(); } - private void CloseWindow() - { - _languageWindow?.Close(); - } - private void ToggleWindow() { - if (_languageWindow == null) + if (LanguageWindow == null) return; if (LanguageButton != null) - { - LanguageButton.SetClickPressed(!_languageWindow.IsOpen); - } + LanguageButton.SetClickPressed(!LanguageWindow.IsOpen); - if (_languageWindow.IsOpen) - { - CloseWindow(); - } + if (LanguageWindow.IsOpen) + LanguageWindow.Close(); else - { - _languageWindow.Open(); - } + LanguageWindow.Open(); } } diff --git a/Content.Server/Abilities/Mime/MimePowersComponent.cs b/Content.Server/Abilities/Mime/MimePowersComponent.cs index fd4fc2c2af9..757528a9cbc 100644 --- a/Content.Server/Abilities/Mime/MimePowersComponent.cs +++ b/Content.Server/Abilities/Mime/MimePowersComponent.cs @@ -47,5 +47,17 @@ public sealed partial class MimePowersComponent : Component /// [DataField("vowCooldown")] public TimeSpan VowCooldown = TimeSpan.FromMinutes(5); + + /// + [DataField("mimeFeedback")] + public string MimeFeedback = "mime-feedback"; + + /// + [DataField("mimeBrokenFeedback")] + public string MimeBrokenFeedback = "mime-broken-feedback"; } } diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index b3bd3392434..9c108c4bcf2 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -1,5 +1,4 @@ using Content.Server.Popups; -using Content.Server.Speech.Muting; using Content.Shared.Actions; using Content.Shared.Actions.Events; using Content.Shared.Alert; @@ -58,14 +57,21 @@ private void OnComponentInit(EntityUid uid, MimePowersComponent component, Compo EnsureComp(uid); _alertsSystem.ShowAlert(uid, AlertType.VowOfSilence); _actionsSystem.AddAction(uid, ref component.InvisibleWallActionEntity, component.InvisibleWallAction, uid); - //Nyano - Summary: Add Psionic Ability to Mime. - if (TryComp(uid, out var psionic) && psionic.PsionicAbility == null) - psionic.PsionicAbility = component.InvisibleWallActionEntity; + + // Mimes gain their power from a special Vow, but this vow extends to Telepathic speech. + if (EnsureComp(uid, out var psionic)) + { + psionic.TelepathicMute = true; + psionic.ActivePowers.Add(component); + psionic.PsychicFeedback.Add(component.MimeFeedback); + psionic.Dampening += 1f; + } } /// /// Creates an invisible wall in a free space after some checks. /// + // TODO: Consider separating this out from the Mime entirely, and make a standalone "Telekinetic Barricade" power. private void OnInvisibleWall(EntityUid uid, MimePowersComponent component, InvisibleWallActionEvent args) { if (!component.Enabled) @@ -98,9 +104,11 @@ private void OnInvisibleWall(EntityUid uid, MimePowersComponent component, Invis return; } } - // Begin Nyano-code: mime powers are psionic. - _psionics.LogPowerUsed(uid, "invisible wall"); - // End Nyano-code. + if (TryComp(uid, out var psionic)) + _psionics.LogPowerUsed(uid, "invisible wall", + (int) Math.Round(4 * psionic.Amplification - psionic.Dampening), + (int) Math.Round(6 * psionic.Amplification - psionic.Dampening)); + _popupSystem.PopupEntity(Loc.GetString("mime-invisible-wall-popup", ("mime", uid)), uid); // Make sure we set the invisible wall to despawn properly Spawn(component.WallPrototype, _turf.GetTileCenter(tile.Value)); @@ -126,6 +134,14 @@ public void BreakVow(EntityUid uid, MimePowersComponent? mimePowers = null) _alertsSystem.ClearAlert(uid, AlertType.VowOfSilence); _alertsSystem.ShowAlert(uid, AlertType.VowBroken); _actionsSystem.RemoveAction(uid, mimePowers.InvisibleWallActionEntity); + if (TryComp(uid, out var psionic)) + { + psionic.TelepathicMute = false; + psionic.ActivePowers.Remove(mimePowers); + psionic.PsychicFeedback.Remove(mimePowers.MimeFeedback); + psionic.PsychicFeedback.Add(mimePowers.MimeBrokenFeedback); + psionic.Dampening -= 1f; + } } /// @@ -149,6 +165,14 @@ public void RetakeVow(EntityUid uid, MimePowersComponent? mimePowers = null) _alertsSystem.ClearAlert(uid, AlertType.VowBroken); _alertsSystem.ShowAlert(uid, AlertType.VowOfSilence); _actionsSystem.AddAction(uid, ref mimePowers.InvisibleWallActionEntity, mimePowers.InvisibleWallAction, uid); + if (TryComp(uid, out var psionic)) + { + psionic.TelepathicMute = true; + psionic.ActivePowers.Add(mimePowers); + psionic.PsychicFeedback.Add(mimePowers.MimeFeedback); + psionic.PsychicFeedback.Remove(mimePowers.MimeBrokenFeedback); + psionic.Dampening += 1f; + } } } } diff --git a/Content.Server/Arachne/ArachneSystem.cs b/Content.Server/Arachne/ArachneSystem.cs new file mode 100644 index 00000000000..9cdefb441be --- /dev/null +++ b/Content.Server/Arachne/ArachneSystem.cs @@ -0,0 +1,231 @@ +using Content.Shared.Arachne; +using Content.Shared.Actions; +using Content.Shared.IdentityManagement; +using Content.Shared.Verbs; +using Content.Shared.Buckle.Components; +using Content.Shared.DoAfter; +using Content.Shared.Stunnable; +using Content.Shared.Eye.Blinding.Systems; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Damage; +using Content.Shared.Inventory; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Humanoid; +using Content.Shared.Nutrition.EntitySystems; +using Content.Server.Buckle.Systems; +using Content.Server.Popups; +using Content.Server.DoAfter; +using Content.Server.Body.Components; +using Content.Server.Vampiric; +using Content.Server.Speech.Components; +using Robust.Shared.Physics.Components; +using Robust.Shared.Containers; +using Robust.Shared.Map; +using Robust.Shared.Utility; +using Robust.Server.Console; + +namespace Content.Server.Arachne +{ + public sealed class ArachneSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly BuckleSystem _buckleSystem = default!; + [Dependency] private readonly ItemSlotsSystem _itemSlots = default!; + [Dependency] private readonly BlindableSystem _blindableSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + + [Dependency] private readonly IServerConsoleHost _host = default!; + [Dependency] private readonly BloodSuckerSystem _bloodSuckerSystem = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + + private const string BodySlot = "body_slot"; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(AddCocoonVerb); + + SubscribeLocalEvent(OnCocEntInserted); + SubscribeLocalEvent(OnCocEntRemoved); + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent>(AddSuccVerb); + SubscribeLocalEvent(OnCocoonDoAfter); + } + + private void AddCocoonVerb(EntityUid uid, ArachneComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (args.Target == uid) + return; + + if (!TryComp(args.Target, out var bloodstream)) + return; + + if (bloodstream.BloodReagent != component.WebBloodReagent) + return; + + InnateVerb verb = new() + { + Act = () => + { + StartCocooning(uid, component, args.Target); + }, + Text = Loc.GetString("cocoon"), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnCocEntInserted(EntityUid uid, CocoonComponent component, EntInsertedIntoContainerMessage args) + { + _blindableSystem.UpdateIsBlind(args.Entity); + EnsureComp(args.Entity); + + if (TryComp(args.Entity, out var currentAccent)) + { + component.WasReplacementAccent = true; + component.OldAccent = currentAccent.Accent; + currentAccent.Accent = "mumble"; + } else + { + component.WasReplacementAccent = false; + var replacement = EnsureComp(args.Entity); + replacement.Accent = "mumble"; + } + } + + private void OnCocEntRemoved(EntityUid uid, CocoonComponent component, EntRemovedFromContainerMessage args) + { + if (component.WasReplacementAccent && TryComp(args.Entity, out var replacement)) + { + replacement.Accent = component.OldAccent; + } else + { + RemComp(args.Entity); + } + + RemComp(args.Entity); + _blindableSystem.UpdateIsBlind(args.Entity); + } + + private void OnDamageChanged(EntityUid uid, CocoonComponent component, DamageChangedEvent args) + { + if (!args.DamageIncreased) + return; + + if (args.DamageDelta == null) + return; + + var body = _itemSlots.GetItemOrNull(uid, BodySlot); + + if (body == null) + return; + + var damage = args.DamageDelta * component.DamagePassthrough; + _damageableSystem.TryChangeDamage(body, damage); + } + + private void AddSuccVerb(EntityUid uid, CocoonComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (!TryComp(args.User, out var sucker)) + return; + + if (!sucker.WebRequired) + return; + + var victim = _itemSlots.GetItemOrNull(uid, BodySlot); + + if (victim == null) + return; + + if (!TryComp(victim, out var stream)) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + _bloodSuckerSystem.StartSuccDoAfter(args.User, victim.Value, sucker, stream, false); // start doafter + }, + Text = Loc.GetString("action-name-suck-blood"), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Nyanotrasen/Icons/verbiconfangs.png")), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnEntRemoved(EntityUid uid, WebComponent web, EntRemovedFromContainerMessage args) + { + if (!TryComp(uid, out var strap)) + return; + + if (HasComp(args.Entity)) + _buckleSystem.StrapSetEnabled(uid, false, strap); + } + + private void StartCocooning(EntityUid uid, ArachneComponent component, EntityUid target) + { + _popupSystem.PopupEntity(Loc.GetString("cocoon-start-third-person", ("target", Identity.Entity(target, EntityManager)), ("spider", Identity.Entity(uid, EntityManager))), uid, + Shared.Popups.PopupType.MediumCaution); + + _popupSystem.PopupEntity(Loc.GetString("cocoon-start-second-person", ("target", Identity.Entity(target, EntityManager))), uid, uid, Shared.Popups.PopupType.Medium); + + var delay = component.CocoonDelay; + + if (HasComp(target)) + delay *= component.CocoonKnockdownMultiplier; + + // Is it good practice to use empty data just to disambiguate doafters + // Who knows, there's no docs! + var ev = new ArachneCocoonDoAfterEvent(); + + var args = new DoAfterArgs(EntityManager, uid, delay, ev, uid, target: target) + { + BreakOnUserMove = true, + BreakOnTargetMove = true, + }; + + _doAfter.TryStartDoAfter(args); + } + + private void OnCocoonDoAfter(EntityUid uid, ArachneComponent component, ArachneCocoonDoAfterEvent args) + { + if (args.Handled || args.Cancelled || args.Args.Target == null) + return; + + var spawnProto = HasComp(args.Args.Target) ? "CocoonedHumanoid" : "CocoonSmall"; + Transform(args.Args.Target.Value).AttachToGridOrMap(); + var cocoon = Spawn(spawnProto, Transform(args.Args.Target.Value).Coordinates); + + if (!TryComp(cocoon, out var slots)) + return; + + // todo: our species should use scale visuals probably... + // TODO: We need a client-accessible notion of scale influence here. + /* if (spawnProto == "CocoonedHumanoid" && TryComp(args.Args.Target.Value, out var sprite)) */ + /* { */ + /* // why the fuck is this only available as a console command. */ + /* _host.ExecuteCommand(null, "scale " + cocoon + " " + sprite.Scale.Y); */ + if (TryComp(args.Args.Target.Value, out var physics)) + { + var scale = Math.Clamp(1 / (35 / physics.FixturesMass), 0.35, 2.5); + _host.ExecuteCommand(null, "scale " + cocoon + " " + scale); + } + _itemSlots.SetLock(cocoon, BodySlot, false, slots); + _itemSlots.TryInsert(cocoon, BodySlot, args.Args.Target.Value, args.Args.User); + _itemSlots.SetLock(cocoon, BodySlot, true, slots); + + var impact = (spawnProto == "CocoonedHumanoid") ? LogImpact.High : LogImpact.Medium; + + _adminLogger.Add(LogType.Action, impact, $"{ToPrettyString(args.Args.User):player} cocooned {ToPrettyString(args.Args.Target.Value):target}"); + args.Handled = true; + } + } +} diff --git a/Content.Server/Arachne/CocoonComponent.cs b/Content.Server/Arachne/CocoonComponent.cs new file mode 100644 index 00000000000..42ecf27971a --- /dev/null +++ b/Content.Server/Arachne/CocoonComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Server.Arachne +{ + [RegisterComponent] + public sealed partial class CocoonComponent : Component + { + public bool WasReplacementAccent = false; + + public string OldAccent = ""; + + [DataField("damagePassthrough")] + public float DamagePassthrough = 0.5f; + } +} diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index d34aac48e04..7190b94e141 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -72,7 +72,7 @@ public sealed partial class ChatSystem : SharedChatSystem public const int WhisperClearRange = 2; // how far whisper goes while still being understandable, in world units public const int WhisperMuffledRange = 5; // how far whisper goes at all, in world units public const string DefaultAnnouncementSound = "/Audio/Announcements/announce.ogg"; - public const float DefaultObfuscationFactor = 0.2f; // Einstein Engines - percentage of symbols in a whispered message that can be seen even by "far" listeners + public const float DefaultObfuscationFactor = 0.2f; // Percentage of symbols in a whispered message that can be seen even by "far" listeners private bool _loocEnabled = true; private bool _deadLoocEnabled; @@ -425,7 +425,7 @@ private void SendEntitySpeak( // The chat message wrapped in a "x says y" string var wrappedMessage = WrapPublicMessage(source, name, message); // The chat message obfuscated via language obfuscation - var obfuscated = _language.ObfuscateSpeech(message, language); + var obfuscated = SanitizeInGameICMessage(source, _language.ObfuscateSpeech(message, language), out var emoteStr, true, _configurationManager.GetCVar(CCVars.ChatPunctuation), (!CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Parent.Name == "en") || (CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Name == "en")); // The language-obfuscated message wrapped in a "x says y" string var wrappedObfuscated = WrapPublicMessage(source, name, obfuscated); @@ -492,7 +492,7 @@ private void SendEntityWhisper( name = FormattedMessage.EscapeText(name); var language = languageOverride ?? _language.GetLanguage(source); - var languageObfuscatedMessage = _language.ObfuscateSpeech(message, language); + var languageObfuscatedMessage = SanitizeInGameICMessage(source, _language.ObfuscateSpeech(message, language), out var emoteStr, true, _configurationManager.GetCVar(CCVars.ChatPunctuation), (!CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Parent.Name == "en") || (CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Name == "en")); foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange)) { diff --git a/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs b/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs index faee26ffee8..da16529d515 100644 --- a/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs +++ b/Content.Server/Chemistry/ReagentEffects/MakeSentient.cs @@ -7,8 +7,8 @@ using Content.Shared.Mind.Components; using Robust.Shared.Prototypes; using Content.Server.Psionics; //Nyano - Summary: pulls in the ability for the sentient creature to become psionic. -using Content.Shared.Humanoid; -using Content.Shared.Language.Events; //Delta-V - Banning humanoids from becoming ghost roles. +using Content.Shared.Humanoid; //Delta-V - Banning humanoids from becoming ghost roles. +using Content.Shared.Language.Events; namespace Content.Server.Chemistry.ReagentEffects; @@ -38,10 +38,10 @@ public override void Effect(ReagentEffectArgs args) { speaker.CurrentLanguage = fallback; speaker.SpokenLanguages.Add(fallback); - - args.EntityManager.EventBus.RaiseLocalEvent(uid, new LanguagesUpdateEvent(), true); } + args.EntityManager.EventBus.RaiseLocalEvent(uid, new LanguagesUpdateEvent(), true); + // Stops from adding a ghost role to things like people who already have a mind if (entityManager.TryGetComponent(uid, out var mindContainer) && mindContainer.HasMind) { diff --git a/Content.Server/Language/Commands/ListLanguagesCommand.cs b/Content.Server/Language/Commands/ListLanguagesCommand.cs index 2d55e3b36d8..6698e1b6453 100644 --- a/Content.Server/Language/Commands/ListLanguagesCommand.cs +++ b/Content.Server/Language/Commands/ListLanguagesCommand.cs @@ -16,7 +16,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { if (shell.Player is not { } player) { - shell.WriteError("This command cannot be run from the server."); + shell.WriteError(Loc.GetString("shell-cannot-run-command-from-server")); return; } @@ -25,7 +25,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (player.AttachedEntity is not {} playerEntity) { - shell.WriteError("You don't have an entity!"); + shell.WriteError(Loc.GetString("shell-must-be-attached-to-entity")); return; } diff --git a/Content.Server/Language/Commands/SayLanguageCommand.cs b/Content.Server/Language/Commands/SayLanguageCommand.cs index ec321617f14..2e4a27b1dcc 100644 --- a/Content.Server/Language/Commands/SayLanguageCommand.cs +++ b/Content.Server/Language/Commands/SayLanguageCommand.cs @@ -16,7 +16,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { if (shell.Player is not { } player) { - shell.WriteError("This command cannot be run from the server."); + shell.WriteError(Loc.GetString("shell-cannot-run-command-from-server")); return; } @@ -25,7 +25,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (player.AttachedEntity is not {} playerEntity) { - shell.WriteError("You don't have an entity!"); + shell.WriteError(Loc.GetString("shell-must-be-attached-to-entity")); return; } @@ -41,7 +41,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languages = IoCManager.Resolve().GetEntitySystem(); var chats = IoCManager.Resolve().GetEntitySystem(); - var language = languages.GetLanguage(languageId); + var language = languages.GetLanguagePrototype(languageId); if (language == null || !languages.CanSpeak(playerEntity, language.ID)) { shell.WriteError($"Language {languageId} is invalid or you cannot speak it!"); diff --git a/Content.Server/Language/Commands/SelectLanguageCommand.cs b/Content.Server/Language/Commands/SelectLanguageCommand.cs index a7f6751fe16..e3363846539 100644 --- a/Content.Server/Language/Commands/SelectLanguageCommand.cs +++ b/Content.Server/Language/Commands/SelectLanguageCommand.cs @@ -16,7 +16,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) { if (shell.Player is not { } player) { - shell.WriteError("This command cannot be run from the server."); + shell.WriteError(Loc.GetString("shell-cannot-run-command-from-server")); return; } @@ -25,7 +25,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) if (player.AttachedEntity is not { } playerEntity) { - shell.WriteError("You don't have an entity!"); + shell.WriteError(Loc.GetString("shell-must-be-attached-to-entity")); return; } @@ -36,7 +36,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) var languages = IoCManager.Resolve().GetEntitySystem(); - var language = languages.GetLanguage(languageId); + var language = languages.GetLanguagePrototype(languageId); if (language == null || !languages.CanSpeak(playerEntity, language.ID)) { shell.WriteError($"Language {languageId} is invalid or you cannot speak it!"); diff --git a/Content.Server/Language/LanguageSystem.Networking.cs b/Content.Server/Language/LanguageSystem.Networking.cs index 94f7c19f500..00a3a2269c9 100644 --- a/Content.Server/Language/LanguageSystem.Networking.cs +++ b/Content.Server/Language/LanguageSystem.Networking.cs @@ -1,13 +1,17 @@ using Content.Server.Mind; using Content.Shared.Language; using Content.Shared.Language.Events; -using Content.Shared.Language.Systems; using Content.Shared.Mind; using Content.Shared.Mind.Components; using Robust.Shared.Player; namespace Content.Server.Language; +/// +/// LanguageSystem Networking +/// This is used to update client state when mind change entity. +/// + public sealed partial class LanguageSystem { [Dependency] private readonly MindSystem _mind = default!; @@ -26,10 +30,11 @@ public void InitializeNet() SubscribeNetworkEvent((_, session) => SendLanguageStateToClient(session.SenderSession)); } + private void SendLanguageStateToClient(EntityUid uid, LanguageSpeakerComponent? comp = null) { // Try to find a mind inside the entity and notify its session - if (!_mind.TryGetMind(uid, out var mind, out var mindComp) || mindComp.Session == null) + if (!_mind.TryGetMind(uid, out _, out var mindComp) || mindComp.Session == null) return; SendLanguageStateToClient(uid, mindComp.Session, comp); @@ -47,9 +52,6 @@ private void SendLanguageStateToClient(ICommonSession session, LanguageSpeakerCo private void SendLanguageStateToClient(EntityUid uid, ICommonSession session, LanguageSpeakerComponent? component = null) { var langs = GetLanguages(uid, component); - if (langs == null) - return; - var message = new LanguagesUpdatedMessage(langs.CurrentLanguage, langs.SpokenLanguages, langs.UnderstoodLanguages); RaiseNetworkEvent(message, session); } diff --git a/Content.Server/Language/LanguageSystem.cs b/Content.Server/Language/LanguageSystem.cs index 26b46e63cd3..75a89f66027 100644 --- a/Content.Server/Language/LanguageSystem.cs +++ b/Content.Server/Language/LanguageSystem.cs @@ -26,15 +26,17 @@ public override void Initialize() { base.Initialize(); + SubscribeNetworkEvent(OnClientSetLanguage); SubscribeLocalEvent(OnInitLanguageSpeaker); SubscribeLocalEvent(_ => RandomRoundSeed = _random.Next()); InitializeNet(); } + #region public api /// - /// Obfuscate the speech of the given entity using its default language. + /// Obfuscate a message using an entity's default language. /// public string ObfuscateSpeech(EntityUid source, string message) { @@ -49,13 +51,9 @@ public string ObfuscateSpeech(string message, LanguagePrototype language) { var builder = new StringBuilder(); if (language.ObfuscateSyllables) - { ObfuscateSyllables(builder, message, language); - } else - { ObfuscatePhrases(builder, message, language); - } return builder.ToString(); } @@ -79,9 +77,10 @@ public bool CanSpeak(EntityUid speaker, string language, LanguageSpeakerComponen return langs?.Contains(language, StringComparer.Ordinal) ?? false; } - // - // Returns the current language of the given entity. Assumes Universal if not specified. - // + /// + /// Returns the current language of the given entity. + /// Assumes Universal if not specified. + /// public LanguagePrototype GetLanguage(EntityUid speaker, LanguageSpeakerComponent? languageComp = null) { var id = GetLanguages(speaker, languageComp)?.CurrentLanguage; @@ -93,9 +92,6 @@ public LanguagePrototype GetLanguage(EntityUid speaker, LanguageSpeakerComponent return proto ?? Universal; } - // - // Set the CurrentLanguage of the given entity. - // public void SetLanguage(EntityUid speaker, string language, LanguageSpeakerComponent? languageComp = null) { if (!CanSpeak(speaker, language) || HasComp(speaker)) @@ -126,9 +122,6 @@ public void AddLanguage(LanguageSpeakerComponent comp, string language, bool add RaiseLocalEvent(comp.Owner, new LanguagesUpdateEvent(), true); } - /// - /// Returns a pair of (spoken, understood) languages of the given entity. - /// public (List spoken, List understood) GetAllLanguages(EntityUid speaker) { var languages = GetLanguages(speaker); @@ -158,9 +151,7 @@ public void EnsureValidLanguage(EntityUid entity, LanguageSpeakerComponent? comp private void OnInitLanguageSpeaker(EntityUid uid, LanguageSpeakerComponent component, ComponentInit args) { if (string.IsNullOrEmpty(component.CurrentLanguage)) - { component.CurrentLanguage = component.SpokenLanguages.FirstOrDefault(UniversalPrototype); - } } #endregion @@ -195,9 +186,7 @@ private void ObfuscateSyllables(StringBuilder builder, string message, LanguageP wordBeginIndex = i + 1; } else - { hashCode = hashCode * 31 + ch; - } } } @@ -239,11 +228,13 @@ private static bool IsSentenceEnd(char ch) #region internal api - misc /// /// Dynamically resolves the current language of the entity and the list of all languages it speaks. - /// The returned event is reused and thus must not be held as a reference anywhere but inside the caller function. /// /// If the entity is not a language speaker, or is a universal language speaker, then it's assumed to speak Universal, /// aka all languages at once and none at the same time. /// + /// + /// The returned event is reused and thus must not be held as a reference anywhere but inside the caller function. + /// private DetermineEntityLanguagesEvent GetLanguages(EntityUid speaker, LanguageSpeakerComponent? comp = null) { // This is a shortcut for ghosts and entities that should not speak normally (admemes) @@ -266,15 +257,32 @@ private DetermineEntityLanguagesEvent GetLanguages(EntityUid speaker, LanguageSp } /// - /// Generates a stable pseudo-random number in the range [min, max) for the given seed. Each input seed corresponds to exactly one random number. + /// Generates a stable pseudo-random number in the range (min, max) for the given seed. + /// Each input seed corresponds to exactly one random number. /// private int PseudoRandomNumber(int seed, int min, int max) { - // This is not a uniform distribution, but it shouldn't matter: given there's 2^31 possible random numbers, - // The bias of this function should be so tiny it will never be noticed. + // This is not a uniform distribution, but it shouldn't matter given there's 2^31 possible random numbers, + // the bias of this function should be so tiny it will never be noticed. seed += RandomRoundSeed; var random = ((seed * 1103515245) + 12345) & 0x7fffffff; // Source: http://cs.uccs.edu/~cs591/bufferOverflow/glibc-2.2.4/stdlib/random_r.c return random % (max - min) + min; } + + /// + /// Set CurrentLanguage of the client, the client must be able to Understand the language requested. + /// + private void OnClientSetLanguage(LanguagesSetMessage message, EntitySessionEventArgs args) + { + if (args.SenderSession.AttachedEntity is not {Valid: true} speaker) + return; + + var language = GetLanguagePrototype(message.CurrentLanguage); + + if (language == null || !CanSpeak(speaker, language.ID)) + return; + + SetLanguage(speaker, language.ID); + } #endregion } diff --git a/Content.Server/Language/TranslatorImplanterSystem.cs b/Content.Server/Language/TranslatorImplanterSystem.cs index cdc0cd7f8e7..1e0c13375e4 100644 --- a/Content.Server/Language/TranslatorImplanterSystem.cs +++ b/Content.Server/Language/TranslatorImplanterSystem.cs @@ -18,12 +18,15 @@ public sealed class TranslatorImplanterSystem : SharedTranslatorImplanterSystem [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly LanguageSystem _language = default!; + public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnImplant); } + private void OnImplant(EntityUid implanter, TranslatorImplanterComponent component, AfterInteractEvent args) { if (component.Used || !args.CanReach || args.Target is not { Valid: true } target) @@ -41,7 +44,8 @@ private void OnImplant(EntityUid implanter, TranslatorImplanterComponent compone var understood = _language.GetAllLanguages(target).understood; if (component.RequiredLanguages.Count > 0 && !component.RequiredLanguages.Any(lang => understood.Contains(lang))) { - RefusesPopup(implanter, target); + _popup.PopupEntity(Loc.GetString("translator-implanter-refuse", + ("implanter", implanter), ("target", target)), implanter); return; } @@ -55,7 +59,8 @@ private void OnImplant(EntityUid implanter, TranslatorImplanterComponent compone intrinsic.UnderstoodLanguages.Add(lang); component.Used = true; - SuccessPopup(implanter, target); + _popup.PopupEntity(Loc.GetString("translator-implanter-success", + ("implanter", implanter), ("target", target)), implanter); _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.User):player} used {ToPrettyString(implanter):implanter} to give {ToPrettyString(target):target} the following languages:" @@ -64,18 +69,4 @@ private void OnImplant(EntityUid implanter, TranslatorImplanterComponent compone OnAppearanceChange(implanter, component); RaiseLocalEvent(target, new LanguagesUpdateEvent(), true); } - - private void RefusesPopup(EntityUid implanter, EntityUid target) - { - _popup.PopupEntity( - Loc.GetString("translator-implanter-refuse", ("implanter", implanter), ("target", target)), - implanter); - } - - private void SuccessPopup(EntityUid implanter, EntityUid target) - { - _popup.PopupEntity( - Loc.GetString("translator-implanter-success", ("implanter", implanter), ("target", target)), - implanter); - } } diff --git a/Content.Server/Language/TranslatorSystem.cs b/Content.Server/Language/TranslatorSystem.cs index d918d024298..3b7704b9a71 100644 --- a/Content.Server/Language/TranslatorSystem.cs +++ b/Content.Server/Language/TranslatorSystem.cs @@ -11,20 +11,17 @@ namespace Content.Server.Language; -// this does not support holding multiple translators at once yet. -// that should not be an issue for now, but it better get fixed later. +// This does not support holding multiple translators at once. +// That shouldn't be an issue for now, but it needs to be fixed later. public sealed class TranslatorSystem : SharedTranslatorSystem { [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly LanguageSystem _language = default!; [Dependency] private readonly PowerCellSystem _powerCell = default!; - private ISawmill _sawmill = default!; - public override void Initialize() { base.Initialize(); - _sawmill = Logger.GetSawmill("translator"); // I wanna die. But my death won't help us discover polymorphism. SubscribeLocalEvent(OnDetermineLanguages); @@ -83,23 +80,15 @@ private void OnDetermineLanguages(EntityUid uid, IntrinsicTranslatorComponent co if (addSpoken) { foreach (var language in component.SpokenLanguages) - { AddIfNotExists(ev.SpokenLanguages, language); - } - if (component.CurrentSpeechLanguage != null && ev.CurrentLanguage.Length == 0) - { - ev.CurrentLanguage = component.CurrentSpeechLanguage; - } + if (component.DefaultLanguageOverride != null && ev.CurrentLanguage.Length == 0) + ev.CurrentLanguage = component.DefaultLanguageOverride; } if (addUnderstood) - { foreach (var language in component.UnderstoodLanguages) - { AddIfNotExists(ev.UnderstoodLanguages, language); - } - } } private void OnTranslatorInteract( EntityUid translator, HandheldTranslatorComponent component, InteractHandEvent args) @@ -111,7 +100,7 @@ private void OnTranslatorInteract( EntityUid translator, HandheldTranslatorCompo var intrinsic = EnsureComp(holder); UpdateBoundIntrinsicComp(component, intrinsic, component.Enabled); - UpdatedLanguages(holder); + RaiseLocalEvent(holder, new LanguagesUpdateEvent(), true); } private void OnTranslatorDropped(EntityUid translator, HandheldTranslatorComponent component, DroppedEvent args) @@ -122,14 +111,13 @@ private void OnTranslatorDropped(EntityUid translator, HandheldTranslatorCompone if (intrinsic.Issuer == component) { - intrinsic.Enabled = false; RemCompDeferred(holder, intrinsic); } _language.EnsureValidLanguage(holder); - UpdatedLanguages(holder); + RaiseLocalEvent(holder, new LanguagesUpdateEvent(), true); } private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponent component, ActivateInWorldEvent args) @@ -139,9 +127,11 @@ private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponen var hasPower = _powerCell.HasDrawCharge(translator); - if (Transform(args.Target).ParentUid is { Valid: true } holder && EntityManager.HasComponent(holder)) + if (Transform(args.Target).ParentUid is { Valid: true } holder + && EntityManager.HasComponent(holder)) { - // This translator is held by a language speaker and thus has an intrinsic counterpart bound to it. Make sure it's up-to-date. + // This translator is held by a language speaker and thus has an intrinsic counterpart bound to it. + // Make sure it's up-to-date. var intrinsic = EnsureComp(holder); var isEnabled = !component.Enabled; if (intrinsic.Issuer != component) @@ -158,11 +148,11 @@ private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponen _powerCell.SetPowerCellDrawEnabled(translator, isEnabled); _language.EnsureValidLanguage(holder); - UpdatedLanguages(holder); + RaiseLocalEvent(holder, new LanguagesUpdateEvent(), true); } else { - // This is a standalone translator (e.g. lying on the ground). Simply toggle its state. + // This is a standalone translator (e.g. lying on the ground), toggle its state. component.Enabled = !component.Enabled && hasPower; _powerCell.SetPowerCellDrawEnabled(translator, !component.Enabled && hasPower); } @@ -172,8 +162,11 @@ private void OnTranslatorToggle(EntityUid translator, HandheldTranslatorComponen // HasPower shows a popup when there's no power, so we do not proceed in that case if (hasPower) { - var message = - Loc.GetString(component.Enabled ? "translator-component-turnon" : "translator-component-shutoff", ("translator", component.Owner)); + var message = Loc.GetString( + component.Enabled + ? "translator-component-turnon" + : "translator-component-shutoff", + ("translator", component.Owner)); _popup.PopupEntity(message, component.Owner, args.User); } } @@ -184,7 +177,8 @@ private void OnPowerCellSlotEmpty(EntityUid translator, HandheldTranslatorCompon _powerCell.SetPowerCellDrawEnabled(translator, false); OnAppearanceChange(translator, component); - if (Transform(translator).ParentUid is { Valid: true } holder && EntityManager.HasComponent(holder)) + if (Transform(translator).ParentUid is { Valid: true } holder + && EntityManager.HasComponent(holder)) { if (!EntityManager.TryGetComponent(holder, out var intrinsic)) return; @@ -196,12 +190,12 @@ private void OnPowerCellSlotEmpty(EntityUid translator, HandheldTranslatorCompon } _language.EnsureValidLanguage(holder); - UpdatedLanguages(holder); + RaiseLocalEvent(holder, new LanguagesUpdateEvent(), true); } } /// - /// Copies the state from the handheld [comp] to the [intrinsic] comp, using [isEnabled] as the enabled state. + /// Copies the state from the handheld to the intrinsic component /// private void UpdateBoundIntrinsicComp(HandheldTranslatorComponent comp, HoldsTranslatorComponent intrinsic, bool isEnabled) { @@ -209,13 +203,13 @@ private void UpdateBoundIntrinsicComp(HandheldTranslatorComponent comp, HoldsTra { intrinsic.SpokenLanguages = new List(comp.SpokenLanguages); intrinsic.UnderstoodLanguages = new List(comp.UnderstoodLanguages); - intrinsic.CurrentSpeechLanguage = comp.CurrentSpeechLanguage; + intrinsic.DefaultLanguageOverride = comp.DefaultLanguageOverride; } else { intrinsic.SpokenLanguages.Clear(); intrinsic.UnderstoodLanguages.Clear(); - intrinsic.CurrentSpeechLanguage = null; + intrinsic.DefaultLanguageOverride = null; } intrinsic.Enabled = isEnabled; @@ -228,9 +222,4 @@ private static void AddIfNotExists(List list, string item) return; list.Add(item); } - - private void UpdatedLanguages(EntityUid uid) - { - RaiseLocalEvent(uid, new LanguagesUpdateEvent(), true); - } } diff --git a/Content.Server/Mind/Commands/MakeSentientCommand.cs b/Content.Server/Mind/Commands/MakeSentientCommand.cs index ecd04b3b2b0..cacd499ab8d 100644 --- a/Content.Server/Mind/Commands/MakeSentientCommand.cs +++ b/Content.Server/Mind/Commands/MakeSentientCommand.cs @@ -61,7 +61,8 @@ public static void MakeSentient(EntityUid uid, IEntityManager entityManager, boo var language = IoCManager.Resolve().GetEntitySystem(); var speaker = entityManager.EnsureComponent(uid); - // The logic is simple, if the speaker knows any language (like monkey or robot), it should keep speaking that language + // If the speaker knows any language (like monkey or robot), they keep those + // Otherwise, we give them the fallback if (speaker.SpokenLanguages.Count == 0) language.AddLanguage(speaker, SharedLanguageSystem.FallbackLanguagePrototype); } diff --git a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs b/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs index 24459d29e22..3a0e912c08a 100644 --- a/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs +++ b/Content.Server/Nyanotrasen/Research/Oracle/OracleSystem.cs @@ -8,13 +8,11 @@ using Content.Shared.Psionics.Abilities; using Content.Shared.Chat; using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Reagent; using Content.Shared.Interaction; using Content.Shared.Mobs.Components; using Content.Shared.Psionics.Glimmer; using Content.Shared.Research.Prototypes; -using Robust.Server.GameObjects; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; diff --git a/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs b/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs index 98d79d3d9a0..dac38290f22 100644 --- a/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/MetapsionicPowerSystem.cs @@ -2,16 +2,12 @@ using Content.Shared.Actions.Events; using Content.Shared.Psionics.Abilities; using Content.Shared.DoAfter; -using Content.Shared.Examine; -using static Content.Shared.Examine.ExamineSystemShared; using Content.Shared.Popups; using Robust.Server.Audio; using Robust.Shared.Audio; using Robust.Shared.Timing; -using Robust.Shared.Player; using Content.Server.DoAfter; using Content.Shared.Psionics.Events; -using Content.Server.Psionics; namespace Content.Server.Psionics.Abilities { @@ -170,14 +166,13 @@ private void OnDoAfter(EntityUid uid, MetapsionicPowerComponent component, Focus return; } - if (!TryComp(args.Target, out var psychic)) - return; - - foreach (var psychicFeedback in psychic.PsychicFeedback) + if (TryComp(args.Target, out var psychic)) { - _popups.PopupEntity(Loc.GetString(psychicFeedback, ("entity", args.Target)), uid, uid, PopupType.LargeCaution); + foreach (var psychicFeedback in psychic.PsychicFeedback) + { + _popups.PopupEntity(Loc.GetString(psychicFeedback, ("entity", args.Target)), uid, uid, PopupType.LargeCaution); + } } - } } } diff --git a/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs b/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs index 1e50a586b4f..b0e27027ad5 100644 --- a/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/MindSwapPowerSystem.cs @@ -9,7 +9,6 @@ using Content.Server.Mind; using Content.Shared.Mobs.Systems; using Content.Server.Popups; -using Content.Server.Psionics; using Content.Server.GameTicking; using Content.Shared.Mind; using Content.Shared.Actions.Events; diff --git a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs index c81d3d7a0b0..480cf561001 100644 --- a/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs +++ b/Content.Server/Psionics/Abilities/PsionicAbilitiesSystem.cs @@ -6,10 +6,7 @@ using Content.Shared.StatusEffect; using Robust.Shared.Random; using Robust.Shared.Prototypes; -using Robust.Shared.Player; -using Content.Shared.Examine; using Content.Shared.Popups; -using static Content.Shared.Examine.ExamineSystemShared; namespace Content.Server.Psionics.Abilities { diff --git a/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs b/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs index 893d1bc4cfa..715774ae1c7 100644 --- a/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PsionicRegenerationPowerSystem.cs @@ -1,5 +1,4 @@ using Robust.Shared.Audio; -using Robust.Shared.Player; using Content.Server.Body.Components; using Content.Server.Body.Systems; using Content.Server.DoAfter; @@ -11,8 +10,6 @@ using Content.Shared.Mobs; using Content.Shared.Popups; using Content.Shared.Psionics.Events; -using Content.Shared.Examine; -using static Content.Shared.Examine.ExamineSystemShared; using Robust.Shared.Timing; using Content.Shared.Actions.Events; using Robust.Server.Audio; diff --git a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs index 77075dab206..e488aac7879 100644 --- a/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/PyrokinesisPowerSystem.cs @@ -5,7 +5,6 @@ using Robust.Server.GameObjects; using Content.Shared.Actions.Events; using Content.Server.Explosion.Components; -using Content.Shared.Mobs.Components; using Robust.Shared.Map; namespace Content.Server.Psionics.Abilities @@ -16,8 +15,6 @@ public sealed class PyrokinesisPowerSystem : EntitySystem [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!; [Dependency] private readonly GunSystem _gunSystem = default!; - [Dependency] private readonly SharedTransformSystem _transformSystem = default!; - [Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly IMapManager _mapManager = default!; public override void Initialize() { diff --git a/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs b/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs index 2e0431832af..be435d1acc5 100644 --- a/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs +++ b/Content.Server/Psionics/Abilities/RegenerativeStasisPowerSystem.cs @@ -2,11 +2,7 @@ using Content.Server.Body.Components; using Content.Shared.Actions; using Content.Shared.Chemistry.Components; -using Content.Shared.Bed.Sleep; using Content.Shared.Psionics.Abilities; -using Robust.Shared.Prototypes; -using Robust.Shared.Timing; -using Content.Shared.Mind; using Content.Shared.Actions.Events; using Content.Shared.FixedPoint; @@ -61,10 +57,9 @@ private void OnPowerUsed(EntityUid uid, RegenerativeStasisPowerComponent compone && TryComp(args.Target, out var stream)) { var solution = new Solution(); - var amount = FixedPoint2.New(MathF.Min(2.5f * psionic.Amplification + psionic.Dampening, 15f)); - solution.AddReagent("PsionicRegenerationEssence", amount); - solution.AddReagent("Epinephrine", amount); - solution.AddReagent("Nocturine", amount * 2); + solution.AddReagent("PsionicRegenerationEssence", FixedPoint2.New(MathF.Min(2.5f * psionic.Amplification + psionic.Dampening, 15f))); + solution.AddReagent("Epinephrine", FixedPoint2.New(MathF.Min(2.5f * psionic.Dampening + psionic.Amplification, 15f))); + solution.AddReagent("Nocturine", 10f + (1 * psionic.Amplification + psionic.Dampening)); _bloodstreamSystem.TryAddToChemicals(args.Target, solution, stream); _psionics.LogPowerUsed(uid, "regenerative stasis", diff --git a/Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs b/Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs index 9583f45fdc9..c21444139d1 100644 --- a/Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs +++ b/Content.Server/Psionics/Invisibility/PsionicInvisibilitySystem.cs @@ -1,6 +1,5 @@ using Content.Shared.Psionics.Abilities; using Content.Shared.Psionics; -using Content.Server.Psionics.Abilities; using Content.Shared.Eye; using Content.Server.NPC.Systems; using Robust.Shared.Containers; @@ -89,6 +88,7 @@ private void OnInvisInit(EntityUid uid, PsionicallyInvisibleComponent component, _visibilitySystem.AddLayer(uid, visibility, (int) VisibilityFlags.PsionicInvisibility, false); _visibilitySystem.RemoveLayer(uid, visibility, (int) VisibilityFlags.Normal, false); _visibilitySystem.RefreshVisibility(uid, visibility); + SetCanSeePsionicInvisiblity(uid, true); } @@ -99,6 +99,7 @@ private void OnInvisShutdown(EntityUid uid, PsionicallyInvisibleComponent compon _visibilitySystem.RemoveLayer(uid, visibility, (int) VisibilityFlags.PsionicInvisibility, false); _visibilitySystem.AddLayer(uid, visibility, (int) VisibilityFlags.Normal, false); _visibilitySystem.RefreshVisibility(uid, visibility); + SetCanSeePsionicInvisiblity(uid, false); } } diff --git a/Content.Server/Psionics/PsionicsCommands.cs b/Content.Server/Psionics/PsionicsCommands.cs index 3f9ee794b38..76c9022151e 100644 --- a/Content.Server/Psionics/PsionicsCommands.cs +++ b/Content.Server/Psionics/PsionicsCommands.cs @@ -1,7 +1,6 @@ using Content.Server.Administration; using Content.Shared.Administration; using Content.Shared.Psionics.Abilities; -using Content.Shared.Mobs.Components; using Robust.Shared.Console; using Content.Shared.Actions; using Robust.Shared.Player; diff --git a/Content.Server/Psionics/PsionicsSystem.cs b/Content.Server/Psionics/PsionicsSystem.cs index bf829477609..7e97af34b80 100644 --- a/Content.Server/Psionics/PsionicsSystem.cs +++ b/Content.Server/Psionics/PsionicsSystem.cs @@ -134,12 +134,10 @@ public void RollPsionics(EntityUid uid, PotentialPsionicComponent component, boo return; var chance = component.Chance; - var warn = true; if (TryComp(uid, out var bonus)) { chance *= bonus.Multiplier; chance += bonus.FlatBonus; - warn = bonus.Warn; } if (applyGlimmer) diff --git a/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs b/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs index ad49075e65a..2c6b93e2542 100644 --- a/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs +++ b/Content.Server/Psionics/Telepathy/TelepathyChatSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Administration.Managers; using Content.Server.Chat.Managers; using Content.Server.Chat.Systems; +using Content.Server.Popups; using Content.Shared.Psionics.Abilities; using Content.Shared.Bed.Sleep; using Content.Shared.Chat; @@ -30,6 +31,7 @@ public sealed class NyanoChatSystem : EntitySystem [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly GlimmerSystem _glimmerSystem = default!; [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; private IEnumerable GetPsionicChatClients() { return Filter.Empty() @@ -74,6 +76,12 @@ public void SendTelepathicChat(EntityUid source, string message, bool hideChat) if (!IsEligibleForTelepathy(source)) return; + if (TryComp(source, out var psionic) && psionic.TelepathicMute) + { + _popupSystem.PopupEntity(Loc.GetString("telepathic-mute-message"), source, source); + return; + } + var clients = GetPsionicChatClients(); var admins = GetAdminClients(); string messageWrap; diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index c3ab28b80a3..60aa7c2f4fb 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -61,9 +61,7 @@ private void OnIntrinsicReceive(EntityUid uid, IntrinsicRadioReceiverComponent c var listener = component.Owner; var msg = args.OriginalChatMsg; if (listener != null && !_language.CanUnderstand(listener, args.Language)) - { msg = args.LanguageObfuscatedChatMsg; - } _netMan.ServerSendMessage(new MsgChatMessage { Message = msg}, actor.PlayerSession.Channel); } diff --git a/Content.Server/Vampire/BloodSuckedComponent.cs b/Content.Server/Vampire/BloodSuckedComponent.cs new file mode 100644 index 00000000000..d7e402cd98a --- /dev/null +++ b/Content.Server/Vampire/BloodSuckedComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Vampiric +{ + /// + /// For entities who have been succed. + /// + [RegisterComponent] + public sealed partial class BloodSuckedComponent : Component + {} +} diff --git a/Content.Server/Vampire/BloodSuckerComponent.cs b/Content.Server/Vampire/BloodSuckerComponent.cs new file mode 100644 index 00000000000..f5619d1cb49 --- /dev/null +++ b/Content.Server/Vampire/BloodSuckerComponent.cs @@ -0,0 +1,44 @@ +namespace Content.Server.Vampiric +{ + [RegisterComponent] + public sealed partial class BloodSuckerComponent : Component + { + /// + /// How much to succ each time we succ. + /// + [DataField("unitsToSucc")] + public float UnitsToSucc = 20f; + + /// + /// The time (in seconds) that it takes to succ an entity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan Delay = TimeSpan.FromSeconds(4); + + // ***INJECT WHEN SUCC*** + + /// + /// Whether to inject chems into a chemstream when we suck something. + /// + [DataField("injectWhenSucc")] + public bool InjectWhenSucc = false; + + /// + /// How many units of our injected chem to inject. + /// + [DataField("unitsToInject")] + public float UnitsToInject = 5; + + /// + /// Which reagent to inject. + /// + [DataField("injectReagent")] + public string InjectReagent = ""; + + /// + /// Whether we need to web the thing up first... + /// + [DataField("webRequired")] + public bool WebRequired = false; + } +} diff --git a/Content.Server/Vampire/BloodSuckerSystem.cs b/Content.Server/Vampire/BloodSuckerSystem.cs new file mode 100644 index 00000000000..a63334a8943 --- /dev/null +++ b/Content.Server/Vampire/BloodSuckerSystem.cs @@ -0,0 +1,213 @@ +using Content.Shared.Verbs; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Interaction; +using Content.Shared.Inventory; +using Content.Shared.Administration.Logs; +using Content.Shared.Vampiric; +using Content.Server.Atmos.Components; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Shared.Chemistry.EntitySystems; +using Content.Server.Popups; +using Content.Server.HealthExaminable; +using Content.Server.DoAfter; +using Content.Server.Nutrition.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Utility; + +namespace Content.Server.Vampiric +{ + public sealed class BloodSuckerSystem : EntitySystem + { + [Dependency] private readonly BodySystem _bodySystem = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!; + [Dependency] private readonly PopupSystem _popups = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly StomachSystem _stomachSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent>(AddSuccVerb); + SubscribeLocalEvent(OnHealthExamined); + SubscribeLocalEvent(OnDamageChanged); + SubscribeLocalEvent(OnDoAfter); + } + + private void AddSuccVerb(EntityUid uid, BloodSuckerComponent component, GetVerbsEvent args) + { + if (args.User == args.Target) + return; + if (component.WebRequired) + return; // handled elsewhere + if (!TryComp(args.Target, out var bloodstream)) + return; + if (!args.CanAccess) + return; + + InnateVerb verb = new() + { + Act = () => + { + StartSuccDoAfter(uid, args.Target, component, bloodstream); // start doafter + }, + Text = Loc.GetString("action-name-suck-blood"), + Icon = new SpriteSpecifier.Texture(new ("/Textures/Nyanotrasen/Icons/verbiconfangs.png")), + Priority = 2 + }; + args.Verbs.Add(verb); + } + + private void OnHealthExamined(EntityUid uid, BloodSuckedComponent component, HealthBeingExaminedEvent args) + { + args.Message.PushNewline(); + args.Message.AddMarkup(Loc.GetString("bloodsucked-health-examine", ("target", uid))); + } + + private void OnDamageChanged(EntityUid uid, BloodSuckedComponent component, DamageChangedEvent args) + { + if (args.DamageIncreased) + return; + + if (_prototypeManager.TryIndex("Brute", out var brute) && args.Damageable.Damage.TryGetDamageInGroup(brute, out var bruteTotal) + && _prototypeManager.TryIndex("Airloss", out var airloss) && args.Damageable.Damage.TryGetDamageInGroup(airloss, out var airlossTotal)) + { + if (bruteTotal == 0 && airlossTotal == 0) + RemComp(uid); + } + } + + private void OnDoAfter(EntityUid uid, BloodSuckerComponent component, BloodSuckDoAfterEvent args) + { + if (args.Cancelled || args.Handled || args.Args.Target == null) + return; + + args.Handled = TrySucc(uid, args.Args.Target.Value); + } + + public void StartSuccDoAfter(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodSuckerComponent = null, BloodstreamComponent? stream = null, bool doChecks = true) + { + if (!Resolve(bloodsucker, ref bloodSuckerComponent)) + return; + + if (!Resolve(victim, ref stream)) + return; + + if (doChecks) + { + if (!_interactionSystem.InRangeUnobstructed(bloodsucker, victim)) + { + return; + } + + if (_inventorySystem.TryGetSlotEntity(victim, "head", out var headUid) && HasComp(headUid)) + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-helmet", ("helmet", headUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + + if (_inventorySystem.TryGetSlotEntity(bloodsucker, "mask", out var maskUid) && + EntityManager.TryGetComponent(maskUid, out var blocker) && + blocker.Enabled) + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-mask", ("mask", maskUid)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + } + + if (stream.BloodReagent != "Blood") + { + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-not-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + return; + } + + if (_solutionSystem.PercentFull(stream.Owner) != 0) + _popups.PopupEntity(Loc.GetString("bloodsucker-fail-no-blood", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + + _popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start-victim", ("sucker", bloodsucker)), victim, victim, Shared.Popups.PopupType.LargeCaution); + _popups.PopupEntity(Loc.GetString("bloodsucker-doafter-start", ("target", victim)), victim, bloodsucker, Shared.Popups.PopupType.Medium); + + var ev = new BloodSuckDoAfterEvent(); + var args = new DoAfterArgs(EntityManager, bloodsucker, bloodSuckerComponent.Delay, ev, bloodsucker, target: victim) + { + BreakOnTargetMove = true, + BreakOnUserMove = false, + DistanceThreshold = 2f, + NeedHand = false + }; + + _doAfter.TryStartDoAfter(args); + } + + public bool TrySucc(EntityUid bloodsucker, EntityUid victim, BloodSuckerComponent? bloodsuckerComp = null) + { + // Is bloodsucker a bloodsucker? + if (!Resolve(bloodsucker, ref bloodsuckerComp)) + return false; + + // Does victim have a bloodstream? + if (!TryComp(victim, out var bloodstream)) + return false; + + // No blood left, yikes. + if (_bloodstreamSystem.GetBloodLevelPercentage(victim, bloodstream) == 0.0f) + return false; + + // Does bloodsucker have a stomach? + var stomachList = _bodySystem.GetBodyOrganComponents(bloodsucker); + if (stomachList.Count == 0) + return false; + + if (!_solutionSystem.TryGetSolution(stomachList[0].Comp.Owner, StomachSystem.DefaultSolutionName, out var stomachSolution)) + return false; + + // Are we too full? + + if (_solutionSystem.PercentFull(bloodsucker) >= 1) + { + _popups.PopupEntity(Loc.GetString("drink-component-try-use-drink-had-enough"), bloodsucker, bloodsucker, Shared.Popups.PopupType.MediumCaution); + return false; + } + + _adminLogger.Add(Shared.Database.LogType.MeleeHit, Shared.Database.LogImpact.Medium, $"{ToPrettyString(bloodsucker):player} sucked blood from {ToPrettyString(victim):target}"); + + // All good, succ time. + _audio.PlayPvs("/Audio/Items/drink.ogg", bloodsucker); + _popups.PopupEntity(Loc.GetString("bloodsucker-blood-sucked-victim", ("sucker", bloodsucker)), victim, victim, Shared.Popups.PopupType.LargeCaution); + _popups.PopupEntity(Loc.GetString("bloodsucker-blood-sucked", ("target", victim)), bloodsucker, bloodsucker, Shared.Popups.PopupType.Medium); + EnsureComp(victim); + + // Make everything actually ingest. + if (bloodstream.BloodSolution == null) + return false; + + var temp = _solutionSystem.SplitSolution(bloodstream.BloodSolution.Value, bloodsuckerComp.UnitsToSucc); + _stomachSystem.TryTransferSolution(stomachList[0].Comp.Owner, temp, stomachList[0].Comp); + + // Add a little pierce + DamageSpecifier damage = new(); + damage.DamageDict.Add("Piercing", 1); // Slowly accumulate enough to gib after like half an hour + + _damageableSystem.TryChangeDamage(victim, damage, true, true); + + //I'm not porting the nocturine gland, this code is deprecated, and will be reworked at a later date. + //if (bloodsuckerComp.InjectWhenSucc && _solutionSystem.TryGetInjectableSolution(victim, out var injectable)) + //{ + // _solutionSystem.TryAddReagent(victim, injectable, bloodsuckerComp.InjectReagent, bloodsuckerComp.UnitsToInject, out var acceptedQuantity); + //} + return true; + } + + private record struct BloodSuckData() + {} + } +} diff --git a/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs new file mode 100644 index 00000000000..1a3c9b1588a --- /dev/null +++ b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorComponent.cs @@ -0,0 +1,23 @@ +namespace Content.Server.Vampiric +{ + [RegisterComponent] + /// + /// Item that gives a bloodsucker injection glands (for poison, usually) + /// + public sealed partial class BloodSuckerGlandInjectorComponent : Component + { + public bool Used = false; + + /// + /// How many units of our injected chem to inject. + /// + [DataField("unitsToInject")] + public float UnitsToInject = 5; + + /// + /// Which reagent to inject. + /// + [DataField("injectReagent")] + public string InjectReagent = ""; + } +} diff --git a/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs new file mode 100644 index 00000000000..d2a92f24be6 --- /dev/null +++ b/Content.Server/Vampire/Injector/BloodSuckerGlandInjectorSystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Popups; +using Content.Shared.Interaction; + +namespace Content.Server.Vampiric +{ + public sealed class BloodSuckerGlandInjectorSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAfterInteract); + } + + private void OnAfterInteract(EntityUid uid, BloodSuckerGlandInjectorComponent component, AfterInteractEvent args) + { + if (component.Used) + return; + + if (!args.CanReach) + return; + + if (!TryComp(args.Target, out var bloodSuckerComponent)) + return; + + // They already have one. + if (bloodSuckerComponent.InjectWhenSucc) + return; + + bloodSuckerComponent.InjectWhenSucc = true; + bloodSuckerComponent.InjectReagent = component.InjectReagent; + bloodSuckerComponent.UnitsToInject = component.UnitsToInject; + component.Used = true; + QueueDel(uid); + + _popupSystem.PopupEntity(Loc.GetString("bloodsucker-glands-throb"), args.Target.Value, args.Target.Value); + } + } +} diff --git a/Content.Shared/Arachne/ArachneComponent.cs b/Content.Shared/Arachne/ArachneComponent.cs new file mode 100644 index 00000000000..04c369cc456 --- /dev/null +++ b/Content.Shared/Arachne/ArachneComponent.cs @@ -0,0 +1,21 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Arachne +{ + [RegisterComponent, NetworkedComponent] + public sealed partial class ArachneComponent : Component + { + [DataField("cocoonDelay")] + public float CocoonDelay = 12f; + + [DataField("cocoonKnockdownMultiplier")] + public float CocoonKnockdownMultiplier = 0.5f; + + /// + /// Blood reagent required to web up a mob. + /// + + [DataField("webBloodReagent")] + public string WebBloodReagent = "Blood"; + } +} diff --git a/Content.Shared/Arachne/Events.cs b/Content.Shared/Arachne/Events.cs new file mode 100644 index 00000000000..02001286ac6 --- /dev/null +++ b/Content.Shared/Arachne/Events.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Map; +using Robust.Shared.Serialization; +using Content.Shared.DoAfter; + +namespace Content.Shared.Arachne +{ + [Serializable, NetSerializable] + public sealed partial class ArachneCocoonDoAfterEvent : SimpleDoAfterEvent + { + } +} diff --git a/Content.Shared/Arachne/WebComponent.cs b/Content.Shared/Arachne/WebComponent.cs new file mode 100644 index 00000000000..c8284f39434 --- /dev/null +++ b/Content.Shared/Arachne/WebComponent.cs @@ -0,0 +1,8 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Arachne +{ + [RegisterComponent, NetworkedComponent] + public sealed partial class WebComponent : Component + {} +} diff --git a/Content.Shared/Language/Components/LanguageSpeakerComponent.cs b/Content.Shared/Language/Components/LanguageSpeakerComponent.cs index c6610c69d99..95232ffe6ff 100644 --- a/Content.Shared/Language/Components/LanguageSpeakerComponent.cs +++ b/Content.Shared/Language/Components/LanguageSpeakerComponent.cs @@ -6,8 +6,8 @@ namespace Content.Shared.Language; public sealed partial class LanguageSpeakerComponent : Component { /// - /// The current language the entity may use to speak. - /// Other listeners will hear the entity speak in this language. + /// The current language the entity may use to speak. + /// Other listeners will hear the entity speak in this language. /// [ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] diff --git a/Content.Shared/Language/Components/TranslatorImplanterComponent.cs b/Content.Shared/Language/Components/TranslatorImplanterComponent.cs index a2bdc8eeba0..401e8a8b8aa 100644 --- a/Content.Shared/Language/Components/TranslatorImplanterComponent.cs +++ b/Content.Shared/Language/Components/TranslatorImplanterComponent.cs @@ -8,27 +8,28 @@ namespace Content.Shared.Language.Components; [RegisterComponent] public sealed partial class TranslatorImplanterComponent : Component { - [DataField("spoken", customTypeSerializer: typeof(PrototypeIdListSerializer)), ViewVariables] + [DataField("spoken", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List SpokenLanguages = new(); - [DataField("understood", customTypeSerializer: typeof(PrototypeIdListSerializer)), ViewVariables] + [DataField("understood", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List UnderstoodLanguages = new(); /// /// The list of languages the mob must understand in order for this translator to have effect. /// Knowing one language is enough. /// - [DataField("requires", customTypeSerializer: typeof(PrototypeIdListSerializer)), ViewVariables] + [DataField("requires", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List RequiredLanguages = new(); /// /// If true, only allows to use this implanter on mobs. /// - [DataField("mobsOnly")] + [DataField] public bool MobsOnly = true; /// /// Whether this implant has been used already. /// + [DataField] public bool Used = false; } diff --git a/Content.Shared/Language/Components/Translators/BaseTranslatorComponent.cs b/Content.Shared/Language/Components/Translators/BaseTranslatorComponent.cs index 13a7c6ad634..a66c9be082e 100644 --- a/Content.Shared/Language/Components/Translators/BaseTranslatorComponent.cs +++ b/Content.Shared/Language/Components/Translators/BaseTranslatorComponent.cs @@ -4,13 +4,14 @@ namespace Content.Shared.Language.Components.Translators; public abstract partial class BaseTranslatorComponent : Component { + // TODO may need to be removed completely, it's a part of legacy code that never ended up being used. /// /// The language this translator changes the speaker's language to when they don't specify one. /// If null, does not modify the default language. /// - [DataField("default-language")] + [DataField("defaultLanguage")] [ViewVariables(VVAccess.ReadWrite)] - public string? CurrentSpeechLanguage = null; + public string? DefaultLanguageOverride = null; /// /// The list of additional languages this translator allows the wielder to speak. @@ -37,7 +38,7 @@ public abstract partial class BaseTranslatorComponent : Component /// /// Otherwise, at least one language must be known (or the list must be empty). /// - [DataField("requires-all")] + [DataField("requiresAll")] [ViewVariables(VVAccess.ReadWrite)] public bool RequiresAllLanguages = false; diff --git a/Content.Shared/Language/Events/LanguagesSetMessage.cs b/Content.Shared/Language/Events/LanguagesSetMessage.cs new file mode 100644 index 00000000000..f7a78210aaf --- /dev/null +++ b/Content.Shared/Language/Events/LanguagesSetMessage.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Language.Events; + +/// +/// Sent from the client to the server when it needs to want to set his currentLangauge. +/// Yeah im using this instead of ExecuteCommand... Better right? +/// +[Serializable, NetSerializable] +public sealed class LanguagesSetMessage(string currentLanguage) : EntityEventArgs +{ + public string CurrentLanguage = currentLanguage; +} diff --git a/Content.Shared/Language/Events/LanguagesUpdatedMessage.cs b/Content.Shared/Language/Events/LanguagesUpdatedMessage.cs index 273659b86d3..563f036df6d 100644 --- a/Content.Shared/Language/Events/LanguagesUpdatedMessage.cs +++ b/Content.Shared/Language/Events/LanguagesUpdatedMessage.cs @@ -3,7 +3,8 @@ namespace Content.Shared.Language.Events; /// -/// Sent to the client when its list of languages changes. The client should in turn update its HUD and relevant systems. +/// Sent to the client when its list of languages changes. +/// The client should in turn update its HUD and relevant systems. /// [Serializable, NetSerializable] public sealed class LanguagesUpdatedMessage(string currentLanguage, List spoken, List understood) : EntityEventArgs diff --git a/Content.Shared/Language/LanguagePrototype.cs b/Content.Shared/Language/LanguagePrototype.cs index 2dccf393cbe..801ab8a393b 100644 --- a/Content.Shared/Language/LanguagePrototype.cs +++ b/Content.Shared/Language/LanguagePrototype.cs @@ -9,17 +9,17 @@ public sealed class LanguagePrototype : IPrototype [IdDataField] public string ID { get; private set; } = default!; - // - // If true, obfuscated phrases of creatures speaking this language will have their syllables replaced with "replacement" syllables. - // Otherwise entire sentences will be replaced. - // + /// + /// If true, obfuscated phrases of creatures speaking this language will have their syllables replaced with "replacement" syllables. + /// Otherwise entire sentences will be replaced. + /// [DataField(required: true)] public bool ObfuscateSyllables; - // - // Lists all syllables that are used to obfuscate a message a listener cannot understand if obfuscateSyllables is true, - // Otherwise uses all possible phrases the creature can make when trying to say anything. - // + /// + /// Lists all syllables that are used to obfuscate a message a listener cannot understand if obfuscateSyllables is true. + /// Otherwise uses all possible phrases the creature can make when trying to say anything. + /// [DataField(required: true)] public List Replacement = []; diff --git a/Content.Shared/Language/Systems/SharedLanguageSystem.cs b/Content.Shared/Language/Systems/SharedLanguageSystem.cs index 55cf5980461..fd301d7ecb3 100644 --- a/Content.Shared/Language/Systems/SharedLanguageSystem.cs +++ b/Content.Shared/Language/Systems/SharedLanguageSystem.cs @@ -30,7 +30,7 @@ public override void Initialize() Universal = _prototype.Index("Universal"); } - public LanguagePrototype? GetLanguage(string id) + public LanguagePrototype? GetLanguagePrototype(string id) { _prototype.TryIndex(id, out var proto); return proto; diff --git a/Content.Server/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs similarity index 87% rename from Content.Server/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs index c52aaf241c8..29ee615dd49 100644 --- a/Content.Server/Psionics/Abilities/PsionicInvisibilityPowerSystem.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityPowerSystem.cs @@ -1,6 +1,4 @@ -using Content.Server.DoAfter; using Content.Shared.Actions; -using Content.Shared.Psionics.Abilities; using Content.Shared.Damage; using Content.Shared.DoAfter; using Content.Shared.Stunnable; @@ -13,9 +11,8 @@ using Content.Shared.Weapons.Ranged.Events; using Content.Shared.Throwing; using Robust.Shared.Timing; -using Content.Shared.Psionics; -namespace Content.Server.Psionics.Abilities +namespace Content.Shared.Psionics.Abilities { public sealed class PsionicInvisibilityPowerSystem : EntitySystem { @@ -25,7 +22,7 @@ public sealed class PsionicInvisibilityPowerSystem : EntitySystem [Dependency] private readonly SharedStealthSystem _stealth = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; public override void Initialize() { @@ -80,14 +77,20 @@ private void OnPowerUsed(EntityUid uid, PsionicInvisibilityPowerComponent compon var ev = new PsionicInvisibilityTimerEvent(_gameTiming.CurTime); var doAfterArgs = new DoAfterArgs(EntityManager, uid, component.UseTimer, ev, uid) { Hidden = true }; - _doAfterSystem.TryStartDoAfter(doAfterArgs); - - ToggleInvisibility(args.Performer); - - _psionics.LogPowerUsed(uid, "psionic invisibility", - (int) MathF.Round(8 * psionic.Amplification - 2 * psionic.Dampening), - (int) MathF.Round(12 * psionic.Amplification - 2 * psionic.Dampening)); - args.Handled = true; + if (_doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId)) + { + ToggleInvisibility(args.Performer); + if (TryComp(uid, out var invis)) + { + _actions.AddAction(uid, ref invis.PsionicInvisibilityUsedActionEntity, invis.PsionicInvisibilityUsedActionId); + invis.DoAfter = doAfterId; + } + + _psionics.LogPowerUsed(uid, "psionic invisibility", + (int) MathF.Round(8 * psionic.Amplification - 2 * psionic.Dampening), + (int) MathF.Round(12 * psionic.Amplification - 2 * psionic.Dampening)); + args.Handled = true; + } } private void OnPowerOff(RemovePsionicInvisibilityOffPowerActionEvent args) @@ -110,6 +113,7 @@ private void OnEnd(EntityUid uid, PsionicInvisibilityUsedComponent component, Co if (Terminating(uid)) return; + _doAfterSystem.Cancel(component.DoAfter); RemComp(uid); RemComp(uid); _audio.PlayPvs("/Audio/Effects/toss.ogg", uid); @@ -155,7 +159,8 @@ public void ToggleInvisibility(EntityUid uid) public void OnDoAfter(EntityUid uid, PsionicInvisibilityPowerComponent component, PsionicInvisibilityTimerEvent args) { - RemComp(uid); + if (!args.Cancelled) + RemComp(uid); } private void OnInsulated(EntityUid uid, PsionicInvisibilityUsedComponent component, PsionicInsulationEvent args) diff --git a/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs index 2a9dd7642ba..22d1b928553 100644 --- a/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibilityUsedComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.DoAfter; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -6,13 +7,13 @@ namespace Content.Shared.Psionics.Abilities [RegisterComponent] public sealed partial class PsionicInvisibilityUsedComponent : Component { - [ValidatePrototypeId] - public const string PsionicInvisibilityUsedActionPrototype = "ActionPsionicInvisibilityUsed"; - [DataField("psionicInvisibilityUsedActionId", + [DataField("psionicInvisibilityActionId", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? PsionicInvisibilityUsedActionId = "ActionPsionicInvisibilityUsed"; [DataField("psionicInvisibilityUsedActionEntity")] public EntityUid? PsionicInvisibilityUsedActionEntity; + + public DoAfterId? DoAfter; } } diff --git a/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsComponent.cs similarity index 93% rename from Content.Server/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsComponent.cs index 268deddf6d9..376414eedce 100644 --- a/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsComponent.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsComponent.cs @@ -1,6 +1,6 @@ using Content.Shared.Whitelist; -namespace Content.Server.Psionics +namespace Content.Shared.Psionics { [RegisterComponent] public sealed partial class PsionicInvisibleContactsComponent : Component diff --git a/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsSystem.cs similarity index 98% rename from Content.Server/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsSystem.cs index 403e0592617..f71605238ae 100644 --- a/Content.Server/Psionics/Invisibility/PsionicInvisibleContactsSystem.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicInvisibleContactsSystem.cs @@ -3,7 +3,7 @@ using Robust.Shared.Physics.Events; using Robust.Shared.Physics.Systems; -namespace Content.Server.Psionics +namespace Content.Shared.Psionics { /// /// Allows an entity to become psionically invisible when touching certain entities. diff --git a/Content.Server/Psionics/Invisibility/PsionicallyInvisibleComponent.cs b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicallyInvisibleComponent.cs similarity index 76% rename from Content.Server/Psionics/Invisibility/PsionicallyInvisibleComponent.cs rename to Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicallyInvisibleComponent.cs index 5352f5737f2..87d3f250b1e 100644 --- a/Content.Server/Psionics/Invisibility/PsionicallyInvisibleComponent.cs +++ b/Content.Shared/Psionics/Abilities/PsionicInvisibility/PsionicallyInvisibleComponent.cs @@ -1,4 +1,4 @@ -namespace Content.Server.Psionics +namespace Content.Shared.Psionics { [RegisterComponent] public sealed partial class PsionicallyInvisibleComponent : Component diff --git a/Content.Shared/Psionics/Abilities/RegenerativeStasis/RegenerativeStasisPowerComponent.cs b/Content.Shared/Psionics/Abilities/RegenerativeStasis/RegenerativeStasisPowerComponent.cs index 27a0903e224..7caa6100806 100644 --- a/Content.Shared/Psionics/Abilities/RegenerativeStasis/RegenerativeStasisPowerComponent.cs +++ b/Content.Shared/Psionics/Abilities/RegenerativeStasis/RegenerativeStasisPowerComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Actions; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; diff --git a/Content.Shared/Psionics/PsionicComponent.cs b/Content.Shared/Psionics/PsionicComponent.cs index 9a06e54cb31..c955626c53d 100644 --- a/Content.Shared/Psionics/PsionicComponent.cs +++ b/Content.Shared/Psionics/PsionicComponent.cs @@ -24,7 +24,8 @@ public sealed partial class PsionicComponent : Component [DataField("dampening")] public float Dampening = 0.1f; - public bool Telepath = false; + public bool Telepath = true; + public bool TelepathicMute = false; public bool InnatePsiChecked = false; } } diff --git a/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs b/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs new file mode 100644 index 00000000000..6aadc258d73 --- /dev/null +++ b/Content.Shared/Vampiric/BloodSuckDoAfterEvent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.Serialization; +using Content.Shared.DoAfter; + +namespace Content.Shared.Vampiric +{ + [Serializable, NetSerializable] + public sealed partial class BloodSuckDoAfterEvent : SimpleDoAfterEvent + { + } +} diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8c0eef855cc..89dcd2f5822 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4118,3 +4118,51 @@ Entries: message: New Tools Sprites! id: 6115 time: '2024-05-29T01:06:42.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Tweak + message: Resprited gas canisters + - type: Tweak + message: Resprited gas tanks + id: 6116 + time: '2024-05-31T00:13:45.0000000+00:00' +- author: LovelyLophi + changes: + - type: Add + message: Added five new coats + - type: Add + message: Added loadouts + - type: Fix + message: Fixed the coat handhole + id: 6117 + time: '2024-06-02T00:36:59.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Tweak + message: Floors Looks Updated/Resprited. + id: 6118 + time: '2024-06-03T19:23:51.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Add + message: All species can now bring their own cultures and languages + id: 6119 + time: '2024-06-10T20:48:48.0000000+00:00' +- author: FoxxoTrystan + changes: + - type: Tweak + message: Rust Walls Sprites. + - type: Tweak + message: Armor, Bulletproof, Riot Suit Resprites. + - type: Tweak + message: New Banners Sprites. + - type: Tweak + message: Stunbaton, Fire Extinguisher New Sprites. + - type: Tweak + message: Rack/WallScreen resprites. + - type: Tweak + message: Stock Parts new sprites! + - type: Tweak + message: Radiation Collector has now a new sprite! + id: 6120 + time: '2024-06-11T00:34:02.0000000+00:00' diff --git a/Resources/Locale/en-US/abilities/arachne.ftl b/Resources/Locale/en-US/abilities/arachne.ftl new file mode 100644 index 00000000000..6f6348d7212 --- /dev/null +++ b/Resources/Locale/en-US/abilities/arachne.ftl @@ -0,0 +1,13 @@ +action-name-spin-web = Spin Web +action-desc-spin-web = Use your spinnerets to make a spider web in the current tile. Makes you hungrier and thirstier. +action-name-spin-web-space = You can't spin a web in space! +action-name-spin-web-blocked = There's no room for a web here. +spin-web-action-hungry = You're too hungry to spin a web! +spin-web-action-thirsty = You're too thirsty to spin a web! +spin-web-start-second-person = You start spinning a web. +spin-web-start-third-person = {CAPITALIZE(THE($spider))} starts spinning a web! +cocoon-start-second-person = You start cocooning {THE($target)}. +cocoon-start-third-person = {CAPITALIZE(THE($spider))} starts cocooning {THE($target)}. +spun-web-second-person = You spin up a web. +spun-web-third-person = {CAPITALIZE(THE($spider))} spins up a web! +cocoon = Cocoon diff --git a/Resources/Locale/en-US/abilities/bloodsucker.ftl b/Resources/Locale/en-US/abilities/bloodsucker.ftl new file mode 100644 index 00000000000..d956eaff84e --- /dev/null +++ b/Resources/Locale/en-US/abilities/bloodsucker.ftl @@ -0,0 +1,19 @@ +action-name-suck-blood = Suck Blood +action-description-suck-blood = Suck the blood of the victim in your hand. + +bloodsucker-fail-helmet = You'd need to remove {THE($helmet)}. +bloodsucker-fail-mask = You'd need to remove your mask! + +bloodsucker-fail-not-blood = { CAPITALIZE(SUBJECT($target)) } doesn't have delicious, nourishing mortal blood. +bloodsucker-fail-no-blood = { CAPITALIZE(SUBJECT($target)) } has no blood in { POSS-ADJ($target) } body. +bloodsucker-fail-no-blood-bloodsucked = { CAPITALIZE(SUBJECT($target)) } has been sucked dry. + +bloodsucker-blood-sucked = You suck some blood from {$target}. +bloodsucker-doafter-start = You try to suck blood from {$target}. + +bloodsucker-doafter-start-victim = {CAPITALIZE(THE($sucker))} is trying to bite your neck! +bloodsucker-blood-sucked-victim = {CAPITALIZE(THE($sucker))} sucks some of your blood! + +bloodsucked-health-examine = [color=red]{ CAPITALIZE(SUBJECT($target)) } { CONJUGATE-HAVE($target) } bite marks on { POSS-ADJ($target) } neck.[/color] + +bloodsucker-glands-throb = The glands behind your fangs feel a bit sore. diff --git a/Resources/Locale/en-US/language/languages.ftl b/Resources/Locale/en-US/language/languages.ftl index 8b8fb8ac665..69c5d0a4a76 100644 --- a/Resources/Locale/en-US/language/languages.ftl +++ b/Resources/Locale/en-US/language/languages.ftl @@ -5,13 +5,13 @@ language-GalacticCommon-name = Galactic common language-GalacticCommon-description = The standard Galatic language, most commonly used for inter-species communications and legal work. language-Bubblish-name = Bubblish -language-Bubblish-description = The language of Slimes. Being a mixture of bubbling noises and pops it's very difficult to speak for huamns without the use of mechanical aids. +language-Bubblish-description = The language of Slimes. Being a mixture of bubbling noises and pops it's very difficult to speak for humans without the use of mechanical aids. language-RootSpeak-name = Rootspeak language-RootSpeak-description = The strange whistling-style language spoken by the Diona. language-Nekomimetic-name = Nekomimetic -language-Nekomimetic-description = To the casual observer, this langauge is an incomprehensible mess of broken Japanese. To the felinids, it's somehow comprehensible. +language-Nekomimetic-description = To the casual observer, this language is an incomprehensible mess of broken Japanese. To the felinids, it's somehow comprehensible. language-Draconic-name = Draconic language-Draconic-description = The common language of lizard-people, composed of sibilant hisses and rattles. diff --git a/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl b/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl index 5b368e822f1..d46a05e9c98 100644 --- a/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl +++ b/Resources/Locale/en-US/nyanotrasen/abilities/psionic.ftl @@ -26,13 +26,10 @@ accept-psionics-window-prompt-text-part = You rolled a psionic power! Do you still wish to be psionic? action-name-psionic-invisibility = Psionic Invisibility -action-description-psionic-invisibility = Render yourself invisible to any entity that could potentially be psychic. Borgs, animals, and so on are not affected. - -action-name-psionic-invisibility = Psionic Invisibility -action-description-psionic-invisibility = Render yourself invisible to any entity that could potentially be psychic. Borgs, animals, and so on are not affected. +action-description-psionic-invisibility = Telepathically remove yourself from the vision of anyone not psionically insulated. action-name-psionic-invisibility-off = Turn Off Psionic Invisibility -action-description-psionic-invisibility-off = Return to visibility, and receive a stun. +action-description-psionic-invisibility-off = End your invisibility early. action-name-mind-swap = Mind Swap action-description-mind-swap = Swap minds with the target. Either can change back after 20 seconds. diff --git a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl index baa8fc27d9e..4af3ae267b3 100644 --- a/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl +++ b/Resources/Locale/en-US/nyanotrasen/psionics/psychic-feedback.ftl @@ -10,15 +10,38 @@ noospheric-zap-feedback = {CAPITALIZE($entity)}'s soul writhes with thunder from pyrokinesis-feedback = The Secret of Fire dwells within {CAPITALIZE($entity)} invisibility-feedback = {CAPITALIZE($entity)}'s wyrd seeks to hide from thine gaze telegnosis-feedback = {CAPITALIZE($entity)}'s soul travels across bridges composed of dreamlight -sophic-grammateus-feedback = SEEKER, YOU NEED ONLY ASK FOR MY WISDOM. -oracle-feedback = WHY DO YOU BOTHER ME SEEKER? HAVE I NOT MADE MY DESIRES CLEAR? metempsychotic-machine-feedback = The sea of fate flows through this machine +regeneration-feedback = {CAPITALIZE($entity)} possesses an overwhelming will to live +regenerative-stasis-feedback = {CAPITALIZE($entity)} possesses an overwhelming will such that others may live +mime-feedback = A servant of the Silent Dreamer, {CAPITALIZE($entity)} bears His power in exchange for a vow of silence +mime-broken-feedback = TREASONOUS VERMIN! {CAPITALIZE($entity)} HAS BETRAYED THEIR VOW! THE SILENT DREAMER DEMANDS THEIR HEAD! + +# Entity Feedback Messages ifrit-feedback = A spirit of Gehenna, bound by the will of a powerful psychic -regeneration-feedback = {CAPITALIZE($entity)} demonstrates an overwhelming will to live -regenerative-stasis-feedback = {CAPITALIZE($entity)} holds the life of others within their hands prober-feedback = A mirror into the end of time, the screaming of dead stars emanates from this machine +drain-feedback = A mirror into a realm where the stars sit still forever, a cold and distant malevolence stares back +sophic-grammateus-feedback = SEEKER, YOU NEED ONLY ASK FOR MY WISDOM. +oracle-feedback = WHY DO YOU BOTHER ME SEEKER? HAVE I NOT MADE MY DESIRES CLEAR? +orecrab-feedback = Heralds of the Lord of Earth, summoned to this realm from Grome's kingdom +reagent-slime-feedback = Heralds of the Lord of Water, summoned to this realm from Straasha's kingdom. +flesh-golem-feedback = Abominations pulled from dead realms, twisted amalgamations of those fallen to the influence of primordial Chaos + +# Anomaly Feedback Messages +anomaly-pyroclastic-feedback = A small mirror to the plane of Gehenna, truth lies within the Secret of Fire +anomaly-gravity-feedback = Violet and crimson, blue of blue, impossibly dark yet greater than the whitest of white, a black star shines weakly at the end of it all +anomaly-electricity-feedback = A mirror to a realm tiled by silicon, the lifeblood of artificial thought flows from it +anomaly-flesh-feedback = From within it comes the suffering of damned mutants howling for all eternity +anomaly-bluespace-feedback = A bridge of dreamlight, crossing into the space between realms of the multiverse +anomaly-ice-feedback = Walls of blackened stone, ruin and famine wait for those who fall within +anomaly-rock-feedback = A vast old oak dwells high over a plane of stone, it turns to stare back +anomaly-flora-feedback = Musical notes drift around you, playfully beckoning, they wish to feast +anomaly-liquid-feedback = A realm of twisting currents. Its placidity is a lie. The eyes within stare hungrilly +anomaly-shadow-feedback = At the end of time, when all suns have set forever, there amidst the void stands a monument to past sins. # Power PVS Messages focused-metapsionic-pulse-begin = The air around {CAPITALIZE($entity)} begins to shimmer faintly psionic-regeneration-self-revive = {CAPITALIZE($entity)} begins to visibly regenerate mindbreaking-feedback = The light of life vanishes from {CAPITALIZE($entity)}'s eyes, leaving behind a husk pretending at sapience + +# Misc Psionic Messages +telepathic-mute-message = You strain, but are unable to send your thoughts to the Noosphere diff --git a/Resources/Locale/en-US/species/species.ftl b/Resources/Locale/en-US/species/species.ftl index 64ee7a65548..63cde37974c 100644 --- a/Resources/Locale/en-US/species/species.ftl +++ b/Resources/Locale/en-US/species/species.ftl @@ -6,6 +6,7 @@ species-name-reptilian = Unathi species-name-slime = Slime Person species-name-diona = Diona species-name-arachnid = Arachnid +species-name-arachne = Arachne species-name-moth = Nian species-name-skeleton = Skeleton species-name-vox = Vox diff --git a/Resources/Prototypes/Chemistry/metabolizer_types.yml b/Resources/Prototypes/Chemistry/metabolizer_types.yml index c26cb2b8ca9..4987bd89c62 100644 --- a/Resources/Prototypes/Chemistry/metabolizer_types.yml +++ b/Resources/Prototypes/Chemistry/metabolizer_types.yml @@ -1,4 +1,4 @@ -ļ»æ# If your species wants to metabolize stuff differently, +# If your species wants to metabolize stuff differently, # you'll likely have to tag its metabolizers with something other than Human. - type: metabolizerType @@ -47,4 +47,8 @@ - type: metabolizerType id: IPC - name: ipc \ No newline at end of file + name: ipc + +- type: metabolizerType + id: Vampiric + name: vampiric diff --git a/Resources/Prototypes/Damage/containers.yml b/Resources/Prototypes/Damage/containers.yml index fb40e9b658f..b01d22df3b7 100644 --- a/Resources/Prototypes/Damage/containers.yml +++ b/Resources/Prototypes/Damage/containers.yml @@ -52,3 +52,13 @@ id: ShadowHaze supportedTypes: - Heat + +- type: damageContainer + id: HalfSpirit + supportedGroups: + - Burn + - Brute + - Airloss + - Immaterial + supportedTypes: + - Poison diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index dea15dfd940..e1b882815c3 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -354,3 +354,16 @@ flatReductions: # can't punch the endoskeleton to death Blunt: 5 + +- type: damageModifierSet + id: HalfSpirit + coefficients: + Cold: 0.5 + Shock: 0.75 + Blunt: 0.75 + Slash: 0.75 + Piercing: 0.75 + Heat: 1.25 + Holy: 1.5 + flatReductions: + Cold: 3 diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index fdaee45ccc8..fb9ebacf92f 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -138,6 +138,9 @@ Radiation: 0 Caustic: 0.75 - type: GroupExamine + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterArmorHeavy @@ -260,6 +263,9 @@ - type: ExplosionResistance damageCoefficient: 0.5 - type: GroupExamine + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBaseLarge diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index 13524efa9e6..6dcdeffdd4a 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -93,6 +93,7 @@ - Hardsuit - WhitelistChameleon - HidesHarpyWings #DeltaV: Used by harpies to help render their hardsuit sprites + - FullBodyOuter - type: entity abstract: true diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index 96a97be87ec..bc1a61b0323 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -22,6 +22,7 @@ tags: - Hardsuit - WhitelistChameleon + - FullBodyOuter - type: entity parent: ClothingOuterBaseLarge @@ -44,6 +45,7 @@ tags: - Hardsuit - WhitelistChameleon + - FullBodyOuter - type: entity parent: ClothingOuterBaseLarge @@ -97,6 +99,9 @@ sprintModifier: 0.8 - type: HeldSpeedModifier - type: GroupExamine + - type: Tag + tags: + - FullBodyOuter - type: entity parent: [ClothingOuterBaseLarge, GeigerCounterClothing] @@ -120,7 +125,10 @@ - type: ContainerContainer containers: toggleable-clothing: !type:ContainerSlot {} - + - type: Tag + tags: + - FullBodyOuter + - type: entity parent: ClothingOuterBaseLarge id: ClothingOuterSuitSpaceNinja @@ -171,6 +179,9 @@ sprite: Clothing/OuterClothing/Suits/chicken.rsi - type: Clothing sprite: Clothing/OuterClothing/Suits/chicken.rsi + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBase @@ -196,6 +207,9 @@ - type: ContainerContainer containers: toggleable-clothing: !type:ContainerSlot {} + - type: Tag + tags: + - FullBodyOuter - type: entity parent: ClothingOuterBase diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index adba2cabc1d..24ae121f6db 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1371,7 +1371,6 @@ - type: LanguageSpeaker speaks: - Kobold - - Monkey understands: - Kobold - Monkey @@ -1931,6 +1930,11 @@ path: /Audio/Animals/parrot_raught.ogg - type: Bloodstream bloodMaxVolume: 50 + - type: LanguageSpeaker + speaks: + - GalacticCommon + understands: + - GalacticCommon - type: entity name: penguin diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index 01fce382e37..fda467cb32d 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -101,6 +101,12 @@ - SimpleHostile - type: Damageable damageContainer: StructuralInorganic + - type: PotentialPsionic + - type: Psionic + removable: false + dampening: 1 + psychicFeedback: + - "orecrab-feedback" - type: entity parent: MobOreCrab @@ -292,6 +298,12 @@ solution: bloodstream - type: DrainableSolution solution: bloodstream + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 1 + psychicFeedback: + - "reagent-slime-feedback" - type: entity name: Reagent Slime Spawner @@ -529,3 +541,20 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive color: "#3e901c" + +- type: entity + id: ReagentSlimeLoto + parent: ReagentSlime + suffix: LotophagoiOil + components: + - type: Bloodstream + bloodReagent: LotophagoiOil + - type: PointLight + color: "#ffbf00" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#ffbf00" diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml index 06ab02dedc9..93081d382a2 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/flesh.yml @@ -54,6 +54,11 @@ Slash: 6 - type: ReplacementAccent accent: genericAggressive + - type: Psionic + removable: false + amplification: 1 + psychicFeedback: + - "flesh-golem-feedback" - type: entity parent: BaseMobFlesh diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index 624d07bbd56..50fe3b6765e 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -118,6 +118,7 @@ - type: Grammar attributes: gender: male + - type: PotentialPsionic # Nyano - type: LanguageSpeaker speaks: - GalacticCommon diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index ec1ed3a58f6..1316aefc50b 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -97,6 +97,7 @@ - RevenantTheme - type: Speech speechVerb: Ghost + - type: UniversalLanguageSpeaker - type: Tag tags: - NoPaint diff --git a/Resources/Prototypes/Entities/Mobs/Player/arachne.yml b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml new file mode 100644 index 00000000000..bebf42f31ba --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Player/arachne.yml @@ -0,0 +1,35 @@ +- type: entity + save: false + name: Urist McArachne + parent: MobArachneBase + id: MobArachne + components: + - type: CombatMode + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-generic + interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-generic-others + - type: MindContainer + showExamineInfo: true + - type: Input + context: "human" + - type: MobMover + - type: InputMover + - type: Respirator + damage: + types: + Asphyxiation: 1.0 + damageRecovery: + types: + Asphyxiation: -1.0 + - type: Alerts + - type: Actions + - type: Eye + - type: CameraRecoil + - type: Examiner + - type: CanHostGuardian + - type: NpcFactionMember + factions: + - NanoTrasen + - type: PotentialPsionic diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachne.yml b/Resources/Prototypes/Entities/Mobs/Species/arachne.yml new file mode 100644 index 00000000000..991668e444f --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Species/arachne.yml @@ -0,0 +1,223 @@ +- type: entity + save: false + name: Urist McArachne + parent: BaseMobHuman + id: MobArachneBase + abstract: true + components: + - type: Sprite + # Arachne are one of the species that needs a manual visual layers setup. + layers: + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body_front + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Species/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_arm + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/anytaur_masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + state: bald + sprite: Mobs/Customization/human_hair.rsi + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: none + visible: false + - map: [ "clownedon" ] # Dynamically generated + sprite: "Effects/creampie.rsi" + state: "creampie_human" + visible: false + - type: HumanoidAppearance + species: Arachne + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + fix1: + shape: + !type:PhysShapeCircle + radius: 0.40 + density: 140 + restitution: 0.0 + mask: + - MobMask + layer: + - MobLayer + - type: Body + prototype: Arachne + requiredLegs: 8 + - type: Damageable + damageContainer: HalfSpirit + damageModifierSet: HalfSpirit + - type: Speech + speechSounds: Alto + - type: Inventory + templateId: anytaur + - type: Tag + tags: + - CanPilot + - ShoesRequiredStepTriggerImmune + - DoorBumpOpener + - type: Bloodstream + bloodReagent: DemonsBlood + - type: BloodSucker + webRequired: true + - type: Arachne + - type: DamageVisuals + thresholds: [ 20, 40, 100 ] + targetLayers: + - "enum.HumanoidVisualLayers.Chest" + - "enum.HumanoidVisualLayers.Head" + - "enum.HumanoidVisualLayers.LArm" + - "enum.HumanoidVisualLayers.RArm" + - type: MovedByPressure + pressureResistance: 4 + - type: Barotrauma + damage: + types: + Blunt: 0.05 #per second, scales with pressure and other constants. Reduced Damage. This allows medicine to heal faster than damage. + - type: MovementAlwaysTouching + - type: MovementSpeedModifier + baseWalkSpeed : 3.0 + baseSprintSpeed : 5.0 + - type: FireVisuals + sprite: Mobs/Effects/onfire.rsi + normalState: Generic_mob_burning + alternateState: arachne_standing + fireStackAlternateState: 3 + - type: Spider + - type: IgnoreSpiderWeb + +- type: entity + save: false + name: Urist McHands + parent: MobHumanDummy + id: MobArachneDummy + noSpawn: true + description: A dummy arachne meant to be used in character setup. + components: + - type: Sprite + layers: + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body + - map: [ "enum.HumanoidVisualLayers.Chest" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: torso_m + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + sprite: Mobs/Species/arachne.rsi + state: spider_body_front + - map: [ "enum.HumanoidVisualLayers.Head" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: head_m + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + color: "#008800" + sprite: Mobs/Species/eyes.rsi + state: eyes + - map: [ "enum.HumanoidVisualLayers.RArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_arm + - map: [ "enum.HumanoidVisualLayers.LArm" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_arm + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: [ "enum.HumanoidVisualLayers.StencilMask" ] + sprite: Mobs/Customization/anytaur_masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: l_hand + - map: [ "enum.HumanoidVisualLayers.RHand" ] + color: "#e8b59b" + sprite: Mobs/Species/Human/parts.rsi + state: r_hand + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + state: bald + sprite: Mobs/Customization/human_hair.rsi + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + sprite: Mobs/Customization/masking_helpers.rsi + state: none + visible: false + - type: Inventory + templateId: anytaur + - type: HumanoidAppearance + species: Arachne diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 5a9917d9747..3f18e22a961 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -219,6 +219,11 @@ price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. - type: CanEscapeInventory # Carrying system from nyanotrasen. + - type: LanguageSpeaker # This is here so all with no LanguageSpeaker at least spawn with the default languages. + speaks: + - GalacticCommon + understands: + - GalacticCommon - type: Tag tags: - CanPilot diff --git a/Resources/Prototypes/Entities/Objects/Devices/translator_implants.yml b/Resources/Prototypes/Entities/Objects/Devices/translator_implants.yml index 972c8f1234d..fc947efe9a3 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/translator_implants.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/translator_implants.yml @@ -2,8 +2,8 @@ abstract: true id: BaseTranslatorImplanter parent: [ BaseItem ] - name: Basic translator implant - description: "Translates speech." + name: basic translator implant + description: Translates speech. components: - type: Sprite sprite: Objects/Specific/Medical/implanter.rsi @@ -28,8 +28,8 @@ - type: entity id: BasicGalaticCommonTranslatorImplanter parent: [ BaseTranslatorImplanter ] - name: Basic Galatic Common translator implant - description: "An implant giving the ability to understand Galatic Common." + name: basic Galactic Common translator implant + description: An implant giving the ability to understand Galactic Common. components: - type: TranslatorImplanter understood: @@ -38,8 +38,8 @@ - type: entity id: AdvancedGalaticCommonTranslatorImplanter parent: [ BaseTranslatorImplanter ] - name: Advanced Galactic Common translator implant - description: "An implant giving the ability to understand and speak Galactic Common." + name: advanced Galactic Common translator implant + description: An implant giving the ability to understand and speak Galactic Common. components: - type: TranslatorImplanter spoken: @@ -51,7 +51,7 @@ id: BubblishTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: Bubblish translator implant - description: "An implant giving the ability to understand and speak Bubblish." + description: An implant giving the ability to understand and speak Bubblish. components: - type: TranslatorImplanter spoken: @@ -63,7 +63,7 @@ id: NekomimeticTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: Nekomimetic translator implant - description: "An implant giving the ability to understand and speak Nekomimetic, Nya~!" + description: An implant giving the ability to understand and speak Nekomimetic. Nya~! components: - type: TranslatorImplanter spoken: @@ -75,7 +75,7 @@ id: DraconicTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: Draconic translator implant - description: "An implant giving the ability to understand and speak Draconic." + description: An implant giving the ability to understand and speak Draconic. components: - type: TranslatorImplanter spoken: @@ -87,7 +87,7 @@ id: CanilunztTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: Canilunzt translator implant - description: "An implant giving the ability to understand and speak Canilunzt, Yeeps!" + description: An implant giving the ability to understand and speak Canilunzt. Yeeps! components: - type: TranslatorImplanter spoken: @@ -99,7 +99,7 @@ id: SolCommonTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: SolCommon translator implant - description: "An implant giving the ability to understand and speak SolCommon, raaagh!" + description: An implant giving the ability to understand and speak SolCommon. Raaagh! components: - type: TranslatorImplanter spoken: @@ -111,7 +111,7 @@ id: RootSpeakTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: RootSpeak translator implant - description: "An implant giving the ability to understand and speak RootSpeak." + description: An implant giving the ability to understand and speak RootSpeak. components: - type: TranslatorImplanter spoken: @@ -123,7 +123,7 @@ id: MofficTranslatorImplanter parent: [ BaseTranslatorImplanter ] name: Moffic translator implant - description: "An implant giving the ability to understand and speak Moffic." + description: An implant giving the ability to understand and speak Moffic. components: - type: TranslatorImplanter spoken: diff --git a/Resources/Prototypes/Entities/Objects/Devices/translators.yml b/Resources/Prototypes/Entities/Objects/Devices/translators.yml index 7093acf77d9..e5ad824c5d9 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/translators.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/translators.yml @@ -2,8 +2,8 @@ abstract: true id: TranslatorUnpowered parent: [ BaseItem ] - name: Translator - description: "Translates speech." + name: translator + description: Translates speech. components: - type: Sprite sprite: Objects/Devices/translator.rsi @@ -35,7 +35,7 @@ - type: entity abstract: true - id: TranslatorEmtpy + id: TranslatorEmpty parent: [ Translator ] suffix: Empty components: @@ -44,14 +44,14 @@ cell_slot: name: power-cell-slot-component-slot-name-default + - type: entity id: CanilunztTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Canilunzt translator - description: "Translates speech between Canilunzt and Galactic Common." + description: Translates speech between Canilunzt and Galactic Common. components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Canilunzt @@ -61,16 +61,14 @@ requires: - GalacticCommon - Canilunzt - requires-all: false - type: entity id: BubblishTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Bubblish translator - description: "Translates speech between Bubblish and Galactic Common." + description: Translates speech between Bubblish and Galactic Common. components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Bubblish @@ -80,16 +78,14 @@ requires: - GalacticCommon - Bubblish - requires-all: false - type: entity id: NekomimeticTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Nekomimetic translator - description: "Translates speech between Nekomimetic and Galactic Common. Why would you want that?" + description: Translates speech between Nekomimetic and Galactic Common. Why would you want that? components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Nekomimetic @@ -99,16 +95,14 @@ requires: - GalacticCommon - Nekomimetic - requires-all: false - type: entity id: DraconicTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Draconic translator - description: "Translates speech between Draconic and Galactic Common." + description: Translates speech between Draconic and Galactic Common. components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Draconic @@ -118,16 +112,14 @@ requires: - GalacticCommon - Draconic - requires-all: false - type: entity id: SolCommonTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Sol Common translator - description: "Translates speech between Sol Common and Galactic Common. Like a true Earthman!" + description: Translates speech between Sol Common and Galactic Common. Like a true Earthman! components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - SolCommon @@ -137,16 +129,14 @@ requires: - GalacticCommon - SolCommon - requires-all: false - type: entity id: RootSpeakTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: RootSpeak translator - description: "Translates speech between RootSpeak and Galactic Common. Like a true plant?" + description: Translates speech between RootSpeak and Galactic Common. Like a true plant? components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - RootSpeak @@ -156,16 +146,14 @@ requires: - GalacticCommon - RootSpeak - requires-all: false - type: entity id: MofficTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Moffic translator - description: "Translates speech between Moffic and Galactic Common. Like a true moth... or bug?" + description: Translates speech between Moffic and Galactic Common. Like a true moth... or bug? components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Moffic @@ -175,16 +163,14 @@ requires: - GalacticCommon - Moffic - requires-all: false - type: entity id: XenoTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Xeno translator - description: "Translates speech between Xeno and Galactic Common. Not sure if that will help." + description: Translates speech between Xeno and Galactic Common. Not sure if that will help. components: - type: HandheldTranslator - default-language: GalacticCommon spoken: - GalacticCommon - Xeno @@ -196,9 +182,9 @@ - type: entity id: AnimalTranslator - parent: [ TranslatorEmtpy ] + parent: [ TranslatorEmpty ] name: Animal translator - description: "Translates all the cutes nosies that animals make into a more understandable form!" + description: Translates all the cutes noises that animals make into a more understandable form! components: - type: HandheldTranslator understood: @@ -217,4 +203,3 @@ - Kobold requires: - GalacticCommon - requires-all: false diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml index 43c0bdce12f..9a2bd4af69f 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml @@ -48,7 +48,7 @@ sound: path: /Audio/Effects/teleport_arrival.ogg - type: Psionic #Nyano - Summary: makes psionic on creation. - - type: GlimmerSource #Nyano - Summary: makes this a potential source of Glimmer. + - type: GlimmerSource #Nyano - Summary: makes this a potential source of Glimmer. active: false - type: entity @@ -99,6 +99,12 @@ - type: IgniteOnCollide fixtureId: fix1 fireStacks: 1 + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-pyroclastic-feedback" - type: entity id: AnomalyGravity @@ -131,6 +137,12 @@ - type: SingularityDistortion intensity: 1000 falloffPower: 2.7 + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-gravity-feedback" - type: entity id: AnomalyElectricity @@ -154,6 +166,12 @@ castShadows: false - type: ElectricityAnomaly - type: Electrified + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-electricity-feedback" - type: entity id: AnomalyFlesh @@ -245,6 +263,12 @@ - MobFleshClamp - MobFleshLover - FleshKudzu + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-flesh-feedback" - type: entity id: AnomalyBluespace @@ -295,6 +319,12 @@ anomalyContactDamage: types: Radiation: 10 + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-bluespace-feedback" - type: entity id: AnomalyIce @@ -344,6 +374,12 @@ releasedGas: 8 # Frezon. Please replace if there is a better way to specify this releaseOnMaxSeverity: true spawnRadius: 0 + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-ice-feedback" - type: entity id: AnomalyRockBase @@ -380,6 +416,12 @@ maxAmount: 50 maxRange: 12 floor: FloorAsteroidTile + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-rock-feedback" - type: entity id: AnomalyRockUranium @@ -637,6 +679,12 @@ maxRange: 6 spawns: - KudzuFlowerAngry + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-flora-feedback" - type: entity id: AnomalyFloraBulb @@ -795,6 +843,12 @@ solution: anomaly - type: InjectableSolution solution: beaker + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-liquid-feedback" - type: entity id: AnomalyShadow @@ -849,3 +903,9 @@ - type: Tag tags: - SpookyFog + - type: PotentialPsionic + - type: Psionic + removable: false + amplification: 5 + psychicFeedback: + - "anomaly-shadow-feedback" diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index c9af55042e9..e6561b2ba63 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -395,6 +395,22 @@ # - id: MobClownSpider # prob: 0.05 +- type: entity + id: OneirophageSpawn + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + id: VentCritters + earliestStart: 15 + minimumPlayers: 15 + weight: 4 + duration: 60 + - type: VentCrittersRule + entries: + - id: MobGiantSpiderVampireAngry + prob: 0.01 + - type: entity id: ZombieOutbreak parent: BaseGameRule diff --git a/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml b/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml new file mode 100644 index 00000000000..0dd5961aef3 --- /dev/null +++ b/Resources/Prototypes/InventoryTemplates/anytaur_inventory_template.yml @@ -0,0 +1,112 @@ +- type: inventoryTemplate + id: anytaur + slots: + - name: jumpsuit + slotTexture: uniform + slotFlags: INNERCLOTHING + stripTime: 5 + uiWindowPos: 0,2 + strippingWindowPos: 0,2 + displayName: Jumpsuit + - name: outerClothing + slotTexture: suit + slotFlags: OUTERCLOTHING + slotGroup: MainHotbar + stripTime: 6 + uiWindowPos: 1,2 + strippingWindowPos: 1,2 + displayName: Suit + blacklist: + tags: + - FullBodyOuter + - name: gloves + slotTexture: gloves + slotFlags: GLOVES + uiWindowPos: 2,2 + strippingWindowPos: 2,2 + displayName: Gloves + - name: neck + slotTexture: neck + slotFlags: NECK + uiWindowPos: 0,1 + strippingWindowPos: 0,1 + displayName: Neck + - name: mask + slotTexture: mask + slotFlags: MASK + uiWindowPos: 1,1 + strippingWindowPos: 1,1 + displayName: Mask + - name: eyes + slotTexture: glasses + slotFlags: EYES + stripTime: 2 + uiWindowPos: 0,0 + strippingWindowPos: 0,0 + displayName: Eyes + - name: ears + slotTexture: ears + slotFlags: EARS + stripTime: 2 + uiWindowPos: 2,0 + strippingWindowPos: 2,1 + displayName: Ears + - name: head + slotTexture: head + slotFlags: HEAD + uiWindowPos: 1,0 + strippingWindowPos: 1,0 + displayName: Head + - name: pocket1 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 2 + uiWindowPos: 0,3 + strippingWindowPos: 0,3 + dependsOn: jumpsuit + displayName: Pocket 1 + stripHidden: true + - name: pocket2 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 2 + uiWindowPos: 2,3 + strippingWindowPos: 2,3 + dependsOn: jumpsuit + displayName: Pocket 2 + stripHidden: true + - name: suitstorage + slotTexture: suit_storage + slotFlags: SUITSTORAGE + stripTime: 2 + uiWindowPos: 2,0 + strippingWindowPos: 2,0 + dependsOn: outerClothing + displayName: Suit Storage + - name: id + slotTexture: id + slotFlags: IDCARD + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 2,1 + strippingWindowPos: 2,4 + dependsOn: jumpsuit + displayName: ID + - name: belt + slotTexture: belt + slotFlags: BELT + slotGroup: SecondHotbar + stripTime: 5 + uiWindowPos: 3,1 + strippingWindowPos: 1,3 + displayName: Belt + - name: back + slotTexture: back + slotFlags: BACK + slotGroup: SecondHotbar + stripTime: 5 + uiWindowPos: 3,0 + strippingWindowPos: 0,4 + displayName: Back diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml new file mode 100644 index 00000000000..23934b3ebcc --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Mechanisms/vampiric.yml @@ -0,0 +1,22 @@ +- type: entity + id: OrganVampiricHumanoidStomach + parent: OrganHumanStomach + components: + - type: Metabolizer + # mm yummy + maxReagents: 3 + metabolizerTypes: [Vampiric] + groups: + - id: Food + - id: Drink + +- type: entity + id: OrganVampiricStomach + parent: OrganAnimalStomach + components: + - type: Metabolizer + maxReagents: 3 + metabolizerTypes: [Vampiric] + groups: + - id: Food + - id: Drink diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml index a900f7524e7..7e71227dbcb 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Parts/spider.yml @@ -24,13 +24,33 @@ - ReagentId: DemonsBlood Quantity: 10 +- type: entity + id: ThoraxSpider + name: "spider thorax" #for arachne, actual spiders should get a cephalothorax that combines with head. + parent: PartSpider + components: + - type: Sprite + sprite: Mobs/Species/Moth/parts.rsi # placeholder sprite + state: "torso_m" + - type: Icon + sprite: Mobs/Species/Moth/parts.rsi + state: "torso_m" + - type: BodyPart #"Other" type + - type: Extractable + juiceSolution: + reagents: + - ReagentId: Fat + Quantity: 10 + - ReagentId: DemonsBlood + Quantity: 20 + - type: entity id: RightLegSpider name: "right spider leg" parent: PartSpider components: - type: Sprite - sprite: Objects/Consumable/Food/meat.rsi + sprite: Objects/Consumable/Food/meat.rsi # placeholder sprite state: spiderleg - type: Icon sprite: Objects/Consumable/Food/meat.rsi @@ -48,7 +68,7 @@ parent: PartSpider components: - type: Sprite - sprite: Objects/Consumable/Food/meat.rsi + sprite: Objects/Consumable/Food/meat.rsi # placeholder sprite state: spiderleg - type: Icon sprite: Objects/Consumable/Food/meat.rsi diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml new file mode 100644 index 00000000000..553391484e2 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/arachne.yml @@ -0,0 +1,63 @@ +- type: body + id: Arachne + name: "arachne" + root: torso + slots: + head: + part: HeadHuman + connections: + - torso + organs: + brain: OrganHumanBrain + eyes: OrganHumanEyes + torso: + part: TorsoHuman + connections: + - left arm + - right arm + - thorax + organs: + heart: OrganHumanHeart + lungs: OrganHumanLungs + stomach: OrganVampiricHumanoidStomach + liver: OrganHumanLiver + kidneys: OrganHumanKidneys + right arm: + part: RightArmHuman + connections: + - right hand + left arm: + part: LeftArmHuman + connections: + - left hand + right hand: + part: RightHandHuman + left hand: + part: LeftHandHuman + thorax: + part: ThoraxSpider + connections: + - left foreleg + - left second leg + - left third leg + - left hind leg + - right foreleg + - right second leg + - right third leg + - right hind leg + left foreleg: + part: LeftLegSpider + left second leg: + part: LeftLegSpider + left third leg: + part: LeftLegSpider + left hind leg: + part: LeftLegSpider + right foreleg: + part: RightLegSpider + right second leg: + part: RightLegSpider + right third leg: + part: RightLegSpider + right hind leg: + part: RightLegSpider diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml new file mode 100644 index 00000000000..3f4cdb06de1 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/vampiricanimal.yml @@ -0,0 +1,43 @@ +- type: body + id: VampiricAnimal + name: "vampiric animal" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - legs + organs: + lungs: OrganAnimalLungs + stomach: OrganVampiricStomach + liver: OrganAnimalLiver + heart: OrganAnimalHeart + kidneys: OrganAnimalKidneys + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal + +- type: body + id: VampiricAnimalLarge + name: "large vampiric animal" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - legs + organs: + lungs: OrganAnimalLungs + stomach: OrganVampiricHumanoidStomach + liver: OrganAnimalLiver + heart: OrganAnimalHeart + kidneys: OrganAnimalKidneys + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml index 2652a89127e..046a324e6f6 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Markers/Spawners/ghost_roles.yml @@ -51,23 +51,23 @@ - state: prisoner # - type: MidRoundAntagSpawnLocation # When MidRoundAntag? -# - type: entity -# id: SpawnPointGhostVampSpider -# name: ghost role spawn point -# suffix: Vampire spider -# parent: MarkerBase -# noSpawn: true -# components: -# - type: GhostRoleMobSpawner -# prototype: MobGiantSpiderVampireAngry -# - type: GhostRole -# makeSentient: true -# name: ghost-role-information-giant-spider-vampire-name -# description: ghost-role-information-giant-spider-vampire-description -# rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. -# - type: Sprite -# sprite: Markers/jobs.rsi -# layers: -# - state: green -# - sprite: Mobs/Animals/bat.rsi -# state: bat +- type: entity + id: SpawnPointGhostVampSpider + name: ghost role spawn point + suffix: Vampire spider + parent: MarkerBase + noSpawn: true + components: + - type: GhostRoleMobSpawner + prototype: MobGiantSpiderVampireAngry + - type: GhostRole + makeSentient: true + name: ghost-role-information-giant-spider-vampire-name + description: ghost-role-information-giant-spider-vampire-description + rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. + - type: Sprite + sprite: Markers/jobs.rsi + layers: + - state: green + - sprite: Mobs/Animals/bat.rsi + state: bat diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml index 5daf2e15e56..2a385341806 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/NPCs/mutants.yml @@ -70,143 +70,131 @@ - type: Produce - type: NoSlip -# - type: entity -# name: oneirophage -# parent: SimpleMobBase -# id: MobGiantSpiderVampire -# description: The 'dream-eater' spider, rumored to be one of the potential genetic sources for arachne. -# components: -# - type: Sprite -# drawdepth: Mobs -# layers: -# - map: ["enum.DamageStateVisualLayers.Base"] -# state: viper -# sprite: Mobs/Animals/spider.rsi -# - type: Physics -# - type: Fixtures -# fixtures: -# fix1: -# shape: -# !type:PhysShapeCircle -# radius: 0.35 -# density: 130 -# mask: -# - SmallMobMask -# layer: -# - SmallMobLayer -# - type: Appearance -# - type: DamageStateVisuals -# states: -# Alive: -# Base: viper -# Critical: -# Base: viper_dead -# Dead: -# Base: viper_dead -# - type: Butcherable -# spawned: -# - id: FoodMeatSpider -# amount: 2 -# - type: CombatMode -# - type: ReplacementAccent -# accent: xeno -# - type: InteractionPopup -# successChance: 0.5 -# interactSuccessString: petting-success-tarantula -# interactFailureString: petting-failure-generic -# - type: Puller -# needsHands: false -# - type: Arachne -# cocoonDelay: 8 -# - type: SolutionContainerManager -# solutions: -# melee: -# reagents: -# - ReagentId: Nocturine -# Quantity: 20 -# - type: MeleeChemicalInjector -# solution: melee -# transferAmount: 3.5 -# - type: SolutionRegeneration -# solution: melee -# generated: -# reagents: -# - ReagentId: Nocturine -# Quantity: 0.15 -# - type: BloodSucker -# unitsToSucc: 35 -# injectWhenSucc: true -# injectReagent: Cryptobiolin -# unitsToInject: 10 -# webRequired: true -# - type: Bloodstream -# bloodReagent: DemonsBlood -# - type: Body -# prototype: VampiricAnimalLarge -# - type: PotentialPsionic -# - type: Psionic -# removable: false -# - type: MetapsionicPower -# - type: MeleeWeapon -# hidden: true -# angle: 0 -# animation: WeaponArcBite -# damage: -# types: -# Piercing: 8 -# - type: AntiPsionicWeapon -# punish: false -# modifiers: -# coefficients: -# Piercing: 2.25 -# - type: Damageable -# damageContainer: HalfSpirit -# damageModifierSet: HalfSpirit -# - type: StatusEffects -# allowed: -# - Stun -# - KnockedDown -# - SlowedDown -# - Stutter -# - SeeingRainbows -# - Electrocution -# - Drunk -# - SlurredSpeech -# - PressureImmunity -# - Muted -# - ForcedSleep -# - TemporaryBlindness -# - Pacified -# - PsionicsDisabled -# - PsionicallyInsulated -# - type: Tag -# tags: -# - Oneirophage -# - type: MovementAlwaysTouching -# - type: PsionicInvisibleContacts -# whitelist: -# tags: -# - ArachneWeb +- type: entity + name: oneirophage + parent: MobGiantSpider + id: MobGiantSpiderVampire + description: The 'dream-eater' spider, rumored to be one of the potential genetic sources for arachne. + components: + - type: Sprite + drawdepth: Mobs + layers: + - map: ["enum.DamageStateVisualLayers.Base", "movement"] + state: viper + sprite: Mobs/Animals/spider.rsi + - type: SpriteMovement + movementLayers: + movement: + state: viper-moving + noMovementLayers: + movement: + state: viper + - type: Appearance + - type: DamageStateVisuals + states: + Alive: + Base: viper + Critical: + Base: viper_dead + Dead: + Base: viper_dead + - type: ReplacementAccent + accent: xeno + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-tarantula + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/snake_hiss.ogg + - type: Puller + needsHands: false + - type: Arachne + cocoonDelay: 8 + - type: SolutionContainerManager + solutions: + melee: + reagents: + - ReagentId: Nocturine + Quantity: 20 + - type: MeleeChemicalInjector + solution: melee + transferAmount: 3.5 + - type: SolutionRegeneration + solution: melee + generated: + reagents: + - ReagentId: Nocturine + Quantity: 0.15 + - type: BloodSucker + unitsToSucc: 35 + injectWhenSucc: true + injectReagent: Cryptobiolin + unitsToInject: 10 + webRequired: true + - type: Bloodstream + bloodReagent: DemonsBlood + - type: Body + prototype: VampiricAnimalLarge + - type: PotentialPsionic + - type: Psionic + removable: false + - type: MetapsionicPower + - type: PsionicInvisibilityPower + - type: AntiPsionicWeapon + punish: false + modifiers: + coefficients: + Piercing: 2.25 + - type: Damageable + damageContainer: HalfSpirit + damageModifierSet: HalfSpirit + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - SeeingRainbows + - Electrocution + - Drunk + - SlurredSpeech + - PressureImmunity + - Muted + - ForcedSleep + - TemporaryBlindness + - Pacified + - PsionicsDisabled + - PsionicallyInsulated + - type: Tag + tags: + - Oneirophage + - type: MovementAlwaysTouching + - type: PsionicInvisibleContacts + whitelist: + tags: + - ArachneWeb -# - type: entity -# name: oneirophage -# parent: MobGiantSpiderVampire -# id: MobGiantSpiderVampireAngry -# suffix: Angry -# components: -# - type: NpcFactionMember -# factions: -# - SimpleHostile -# - type: InputMover -# - type: MobMover -# - type: HTN -# rootTask: SimpleHostileCompound -# - type: GhostRole -# makeSentient: true -# name: ghost-role-information-giant-spider-vampire-name -# description: ghost-role-information-giant-spider-vampire-description -# rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. -# - type: GhostTakeoverAvailable +- type: entity + name: oneirophage + parent: MobGiantSpiderVampire + id: MobGiantSpiderVampireAngry + suffix: Angry + components: + - type: NpcFactionMember + factions: + - SimpleHostile + - type: InputMover + - type: MobMover + - type: HTN + rootTask: + task: SimpleHostileCompound + - type: GhostRole + makeSentient: true + name: ghost-role-information-giant-spider-vampire-name + description: ghost-role-information-giant-spider-vampire-description + rules: No antagonist restrictions. Just don't talk in emote; you have telepathic chat. + - type: GhostTakeoverAvailable - type: entity parent: SimpleMobBase diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml index 951e75183b6..eca5b5e3758 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Research/glimmer_prober.yml @@ -4,7 +4,10 @@ name: glimmer prober description: Probes the noƶsphere to generate research points. Might be worth turning off if glimmer is a problem. components: + - type: PotentialPsionic - type: Psionic + removable: false + amplification: 10 psychicFeedback: - "prober-feedback" - type: GlimmerSource @@ -92,7 +95,12 @@ name: glimmer drain description: Uses electricity to try and sort out the noƶsphere, reducing its level of entropy. components: + - type: PotentialPsionic - type: Psionic + removable: false + dampening: 10 + psychicFeedback: + - "drain-feedback" - type: GlimmerSource addToGlimmer: false - type: Construction diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml new file mode 100644 index 00000000000..e483ea5da71 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Structures/Webbing/webs.yml @@ -0,0 +1,93 @@ +- type: entity + id: CocoonedHumanoid + name: cocooned humanoid + description: Unlucky. + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: Sprite + layers: + - sprite: Nyanotrasen/Structures/cocoon.rsi + state: cocoon_large1 + map: [ "enum.DamageStateVisualLayers.Base" ] + - type: RandomSprite + available: + - enum.DamageStateVisualLayers.Base: + cocoon_large1: "" + - enum.DamageStateVisualLayers.Base: #your guess for why randomsprite requires an arbitrary layer is as good as mine friend + cocoon_large2: "" + - enum.DamageStateVisualLayers.Base: + cocoon_large3: "" + - type: Cocoon + - type: Clickable + - type: InteractionOutline + - type: Transform + noRot: true + - type: Damageable + damageModifierSet: Web + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 40 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.4,0.25,0.1" + density: 20 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: Physics + bodyType: Dynamic + - type: Pullable + - type: AntiRottingContainer + - type: ItemSlots + slots: + body_slot: + name: Body + locked: true + ejectOnBreak: true + - type: Butcherable + butcheringType: Knife + butcherDelay: 12 + spawned: + - id: MaterialCloth1 + amount: 1 + prob: 0.5 #This doesn't cost hunger so should at least make it not worth it time-wise + - type: Appearance + - type: ContainerContainer + containers: + body_slot: !type:ContainerSlot + +- type: entity + id: CocoonSmall + parent: CocoonedHumanoid + name: cocoon + description: What could be inside...? + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: Sprite + layers: + - sprite: Nyanotrasen/Structures/cocoon.rsi + state: cocoon1 + map: [ "enum.DamageStateVisualLayers.Base" ] + - type: RandomSprite + available: + - enum.DamageStateVisualLayers.Base: + cocoon1: "" + - enum.DamageStateVisualLayers.Base: #your guess for why randomsprite requires an arbitrary layer is as good as mine friend + cocoon2: "" + - enum.DamageStateVisualLayers.Base: + cocoon3: "" diff --git a/Resources/Prototypes/Nyanotrasen/psionicPowers.yml b/Resources/Prototypes/Nyanotrasen/psionicPowers.yml index d90fe9a820e..ca1764e204c 100644 --- a/Resources/Prototypes/Nyanotrasen/psionicPowers.yml +++ b/Resources/Prototypes/Nyanotrasen/psionicPowers.yml @@ -6,7 +6,7 @@ TelegnosisPower: 1 PsionicRegenerationPower: 1 RegenerativeStasisPower: 0.3 - #PsionicInvisibilityPower: 0.15 #Temporarily disabled, engine update broke it + PsionicInvisibilityPower: 0.15 MindSwapPower: 0.15 NoosphericZapPower: 0.15 PyrokinesisPower: 0.15 diff --git a/Resources/Prototypes/Reagents/biological.yml b/Resources/Prototypes/Reagents/biological.yml index c24c073f037..f3c57dccb9e 100644 --- a/Resources/Prototypes/Reagents/biological.yml +++ b/Resources/Prototypes/Reagents/biological.yml @@ -23,6 +23,29 @@ - !type:OrganType type: Human shouldHave: false + - !type:SatiateHunger + factor: 0.5 + conditions: + - !type:OrganType + type: Vampiric + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Water + amount: 0.15 + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Protein + amount: 0.15 + - !type:AdjustReagent + conditions: + - !type:OrganType + type: Vampiric + reagent: Omnizine + amount: 0.2 Food: effects: - !type:AdjustReagent diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml index 129ae6c2adc..aa26dbf41f6 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml @@ -16,6 +16,7 @@ special: - !type:AddComponentSpecial components: + - type: PotentialPsionic - type: Psionic # Nyano - Summary: Makes the mime psionic. - type: MimePowers - type: FrenchAccent diff --git a/Resources/Prototypes/Species/arachne.yml b/Resources/Prototypes/Species/arachne.yml new file mode 100644 index 00000000000..ed494c37cc8 --- /dev/null +++ b/Resources/Prototypes/Species/arachne.yml @@ -0,0 +1,50 @@ +- type: species + id: Arachne + name: species-name-arachne + roundStart: true + prototype: MobArachne + sprites: MobArachneSprites + markingLimits: MobArachneMarkingLimits + dollPrototype: MobArachneDummy + skinColoration: HumanToned + sexes: + - Female + minAge: 60 + youngAge: 150 + oldAge: 400 + maxAge: 666 + +- type: markingPoints + id: MobArachneMarkingLimits + points: + Hair: + points: 1 + required: false + Tail: + points: 1 + required: false + Chest: + points: 1 + required: false + Arms: + points: 2 + required: false + + +- type: speciesBaseSprites + id: MobArachneSprites + sprites: + Head: MobHumanHead + Hair: MobHumanoidAnyMarking + Chest: MobHumanTorso + Eyes: MobArachneEyes + LArm: MobHumanLArm + RArm: MobHumanRArm + LHand: MobHumanLHand + RHand: MobHumanRHand + +- type: humanoidBaseSprite + id: MobArachneEyes + baseSprite: + sprite: Mobs/Species/eyes.rsi + state: eyes diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 62772b23482..9170a2076db 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -16,6 +16,9 @@ - type: Tag id: AppraisalTool +- type: Tag + id: ArachneWeb + - type: Tag id: ArtifactFragment @@ -575,6 +578,9 @@ - type: Tag id: Fruit +- type: Tag + id: FullBodyOuter + - type: Tag id: Galaxythistle @@ -889,6 +895,9 @@ - type: Tag id: Ointment +- type: Tag + id: Oneirophage + - type: Tag id: Ore diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/equipped-OUTERCLOTHING.png index 81512185135..78f7cd2453e 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/equipped-OUTERCLOTHING.png and b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/icon.png b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/icon.png index 2c2e17abe25..b1405b8b062 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/icon.png and b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/meta.json index 3f816376c7e..9ae7fc3f93a 100644 --- a/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/meta.json +++ b/Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken/modified by Taral from tgstation at commit https://github.com/tgstation/tgstation/commit/dbc2435fa562f4ef130a7112d2a4cc9c80099894", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/equipped-OUTERCLOTHING.png index fdbed82bd34..45ba5b9a32f 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/equipped-OUTERCLOTHING.png and b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/icon.png b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/icon.png index bb2e517bde2..fde6c90e2ca 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/icon.png and b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/meta.json index 30607d47eaa..afdd4120b55 100644 --- a/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/meta.json +++ b/Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from TGstation github https://github.com/tgstation/tgstation/commit/fed2ddeb54d0fb8bb97cb0a899a088b7d7423bbb", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise", "size": { "x": 32, "y": 32 @@ -23,4 +23,4 @@ "directions": 4 } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/equipped-OUTERCLOTHING.png index 427c203b198..0063e8cda06 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/equipped-OUTERCLOTHING.png and b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/icon.png b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/icon.png index e70741f1ff9..a92566d3087 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/icon.png and b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json index e482264df5f..afdd4120b55 100644 --- a/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json +++ b/Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/4f6190e2895e09116663ef282d3ce1d8b35c032e", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/equipped-OUTERCLOTHING.png index fb4087b662b..59d6ea3b487 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/equipped-OUTERCLOTHING.png and b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/icon.png b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/icon.png index f2b15dd82f3..23bb26f648e 100644 Binary files a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/icon.png and b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/meta.json index e0d437b8ece..afdd4120b55 100644 --- a/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/meta.json +++ b/Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/6665eec76c98a4f3f89bebcd10b34b47dcc0b8ae", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png new file mode 100644 index 00000000000..acb96562e73 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_full.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_none.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png new file mode 100644 index 00000000000..acb96562e73 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/female_top.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/full.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_full.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_none.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/male_top.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json new file mode 100644 index 00000000000..b44be570c4f --- /dev/null +++ b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/meta.json @@ -0,0 +1,59 @@ +{ + "version": 1, + "copyright": "Rane", + "license": "CC-BY-SA-3.0", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "female_none", + "directions": 4 + }, + { + "name": "female_full", + "directions": 4 + }, + { + "name": "female_top", + "directions": 4 + }, + { + "name": "male_none", + "directions": 4 + }, + { + "name": "male_full", + "directions": 4 + }, + { + "name": "male_top", + "directions": 4 + }, + { + "name": "full", + "directions": 4 + }, + { + "name": "none", + "directions": 4 + }, + { + "name": "top", + "directions": 4 + }, + { + "name": "unisex_full", + "directions": 4 + }, + { + "name": "unisex_none", + "directions": 4 + }, + { + "name": "unisex_top", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/none.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/top.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_full.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_none.png differ diff --git a/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png new file mode 100644 index 00000000000..20ccfaa8db4 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/anytaur_masking_helpers.rsi/unisex_top.png differ diff --git a/Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png b/Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png new file mode 100644 index 00000000000..0f253476944 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/spidereyes.rsi/eyes.png differ diff --git a/Resources/Textures/Mobs/Customization/spidereyes.rsi/meta.json b/Resources/Textures/Mobs/Customization/spidereyes.rsi/meta.json new file mode 100644 index 00000000000..0eb61ec1dde --- /dev/null +++ b/Resources/Textures/Mobs/Customization/spidereyes.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "copyright" : "@Rane#7518", + "license" : "CC-BY-SA-3.0", + "size" : { + "x" : 32, + "y" : 32 + }, + "states" : [ + { + "directions" : 4, + "name" : "eyes" + } + ], + "version" : 1 +} diff --git a/Resources/Textures/Mobs/Species/arachne.rsi/meta.json b/Resources/Textures/Mobs/Species/arachne.rsi/meta.json new file mode 100644 index 00000000000..a985b24cca3 --- /dev/null +++ b/Resources/Textures/Mobs/Species/arachne.rsi/meta.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "license": "CC-BY-4.0", + "copyright": "Created by @kes#0001, colored by Woods#1999", + "size": { + "x": 64, + "y": 64 + }, + "states": [ + { + "name": "spider_body", + "directions": 4 + }, + { + "name": "spider_body_front", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Species/arachne.rsi/spider_body.png b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body.png new file mode 100644 index 00000000000..d1432cc3fd6 Binary files /dev/null and b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body.png differ diff --git a/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png new file mode 100644 index 00000000000..0171f16fe38 Binary files /dev/null and b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png differ diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png b/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png new file mode 100644 index 00000000000..b6250e22b38 Binary files /dev/null and b/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png differ diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/meta.json b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json new file mode 100644 index 00000000000..a98aba406f1 --- /dev/null +++ b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by @Rane#7518", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "eyes", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png new file mode 100644 index 00000000000..27741fdf314 Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon2.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon2.png new file mode 100644 index 00000000000..252be2398af Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon2.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon3.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon3.png new file mode 100644 index 00000000000..ca9cbb79bbe Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon3.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png new file mode 100644 index 00000000000..f9431f64285 Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large2.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large2.png new file mode 100644 index 00000000000..885bb7b3c93 Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large2.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png new file mode 100644 index 00000000000..9a033961ffa Binary files /dev/null and b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png differ diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/meta.json b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/meta.json new file mode 100644 index 00000000000..08cfb264df9 --- /dev/null +++ b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "copyright" : "Taken from https://github.com/tgstation/tgstation", + "license" : "CC-BY-SA-3.0", + "size" : { + "x" : 32, + "y" : 32 + }, + "states" : [ + { + "directions" : 1, + "name" : "cocoon1" + }, + { + "directions" : 1, + "name" : "cocoon2" + }, + { + "directions" : 1, + "name" : "cocoon3" + }, + { + "directions" : 1, + "name" : "cocoon_large1" + }, + { + "directions" : 1, + "name" : "cocoon_large2" + }, + { + "directions" : 1, + "name" : "cocoon_large3" + } + ], + "version" : 1 +} diff --git a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_closed.png b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_closed.png index 7c99615ffec..b84389a06bd 100644 Binary files a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_closed.png and b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_closed.png differ diff --git a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_open.png b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_open.png index 7909d14f269..0cf52827fca 100644 Binary files a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_open.png and b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/fire_extinguisher_open.png differ diff --git a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/meta.json b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/meta.json index 990bbf93567..2e60d4f4041 100644 --- a/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/meta.json +++ b/Resources/Textures/Objects/Misc/fire_extinguisher.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/tgstation/tgstation at commit 9bebd81ae0b0a7f952b59886a765c681205de31f", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise // Hand Sprites taken from https://github.com/tgstation/tgstation at commit 9bebd81ae0b0a7f952b59886a765c681205de31f", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_capacitor.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_capacitor.png index 039817e37b9..2be12b48a64 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_capacitor.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_capacitor.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_scan_module.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_scan_module.png index 1871b477b63..0ee37e653da 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_scan_module.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/adv_scan_module.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/advanced_matter_bin.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/advanced_matter_bin.png index 819275417ba..7533331b835 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/advanced_matter_bin.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/advanced_matter_bin.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/bluespace_matter_bin.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/bluespace_matter_bin.png index ba244f3f297..56d1aa2a36a 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/bluespace_matter_bin.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/bluespace_matter_bin.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/capacitor.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/capacitor.png index 305087c37b6..242f217e4af 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/capacitor.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/capacitor.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/femto_mani.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/femto_mani.png index f7e231248e5..04057ffa822 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/femto_mani.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/femto_mani.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/high_micro_laser.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/high_micro_laser.png index 2bd8d3837da..c23c941e150 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/high_micro_laser.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/high_micro_laser.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/matter_bin.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/matter_bin.png index c4603632dff..494582986fd 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/matter_bin.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/matter_bin.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/meta.json b/Resources/Textures/Objects/Misc/stock_parts.rsi/meta.json index fac73084019..50a7fd96d53 100644 --- a/Resources/Textures/Objects/Misc/stock_parts.rsi/meta.json +++ b/Resources/Textures/Objects/Misc/stock_parts.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/tgstation/tgstation at 0d9c9a8233dfc3fc55edc538955a761a6328bee0, micro_mani by EmoGarbage404 (github)", + "copyright": "Taken from https://github.com/tgstation/tgstation at 0d9c9a8233dfc3fc55edc538955a761a6328bee0 // Taken from https://github.com/ParadiseSS13/Paradise/", "states": [ { "name": "adv_capacitor" @@ -27,6 +27,7 @@ 0.1, 0.1, 0.1, + 0.1, 0.1 ] ] @@ -53,7 +54,13 @@ "name": "bluespace_matter_bin", "delays": [ [ - 0.3, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, 0.1, 0.1, 0.1 @@ -146,15 +153,7 @@ ] }, { - "name": "femto_mani", - "delays": [ - [ - 0.3, - 0.1, - 0.1, - 0.1 - ] - ] + "name": "femto_mani" }, { "name": "hdd1" @@ -184,24 +183,10 @@ "name": "pico_mani" }, { - "name": "quadratic_capacitor", - "delays": [ - [ - 0.3, - 0.1, - 0.1, - 0.1 - ] - ] + "name": "quadratic_capacitor" }, { - "name": "quadultra_micro_laser", - "delays": [ - [ - 0.1, - 0.1 - ] - ] + "name": "quadultra_micro_laser" }, { "name": "rom1" @@ -222,7 +207,6 @@ 0.1, 0.1, 0.1, - 0.1, 0.1 ] ] @@ -260,7 +244,15 @@ "name": "super_matter_bin" }, { - "name": "super_scan_module" + "name": "super_scan_module", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] }, { "name": "treatment_disk" diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_laser.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_laser.png index c23eea56f85..0bf4296e9b3 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_laser.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_laser.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_mani.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_mani.png index 8dca252f688..c63b141f11d 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_mani.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/micro_mani.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/nano_mani.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/nano_mani.png index 93b2d06f098..0c3defdefa4 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/nano_mani.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/nano_mani.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/pico_mani.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/pico_mani.png index f3d1ff54dc9..2da4e416464 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/pico_mani.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/pico_mani.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/quadratic_capacitor.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/quadratic_capacitor.png index 11633f753de..0cb5de4a3fd 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/quadratic_capacitor.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/quadratic_capacitor.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/quadultra_micro_laser.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/quadultra_micro_laser.png index cc907fa5e26..b3bbe275e15 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/quadultra_micro_laser.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/quadultra_micro_laser.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/scan_module.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/scan_module.png index b95b803d8f7..a05d626eea0 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/scan_module.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/scan_module.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_capacitor.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_capacitor.png index d6d1f9d555a..054299f6d7a 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_capacitor.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_capacitor.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_matter_bin.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_matter_bin.png index 54678e59150..b56c920f7be 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_matter_bin.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_matter_bin.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_scan_module.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_scan_module.png index 240ab514d76..7fa4ceedfbd 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/super_scan_module.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/super_scan_module.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/triphasic_scan_module.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/triphasic_scan_module.png index d3e7d72b57d..e2fd4e6fbff 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/triphasic_scan_module.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/triphasic_scan_module.png differ diff --git a/Resources/Textures/Objects/Misc/stock_parts.rsi/ultra_high_micro_laser.png b/Resources/Textures/Objects/Misc/stock_parts.rsi/ultra_high_micro_laser.png index 3e65d639a5e..6aec80e9dd5 100644 Binary files a/Resources/Textures/Objects/Misc/stock_parts.rsi/ultra_high_micro_laser.png and b/Resources/Textures/Objects/Misc/stock_parts.rsi/ultra_high_micro_laser.png differ diff --git a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/meta.json index fc15bfadef2..d75e46fbf42 100644 --- a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from vgstation at https://github.com/vgstation-coders/vgstation13/commit/1cdfb0230cc96d0ba751fa002d04f8aa2f25ad7d", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/ // Hands sprites taken from vgstation at https://github.com/vgstation-coders/vgstation13/commit/1cdfb0230cc96d0ba751fa002d04f8aa2f25ad7d", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_nocell.png b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_nocell.png index 8c4fbac7fdb..bf08ef9cc76 100644 Binary files a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_nocell.png and b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_nocell.png differ diff --git a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png index 59940f44ca4..8704ab6bcfc 100644 Binary files a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png and b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png differ diff --git a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_on.png b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_on.png index 2132190ad45..2adbe76e9e1 100644 Binary files a/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_on.png and b/Resources/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_on.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner.png index 8daa67ae23e..8db1e80fdd1 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_cargo.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_cargo.png index ff808bbc8bb..899c8d6e4cb 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_cargo.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_cargo.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_engineering.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_engineering.png index da76b044c1e..e45b9e35303 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_engineering.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_engineering.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_medical.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_medical.png index 5bbd100773c..c2dc11d21bf 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_medical.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_medical.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_science.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_science.png index 8ae607cdcd4..1da59b8a315 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_science.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_science.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_security.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_security.png index 42114c515b2..cfd18620e04 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_security.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_security.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/banner_syndicate.png b/Resources/Textures/Structures/Decoration/banner.rsi/banner_syndicate.png index c8424057d02..6b39694e7a7 100644 Binary files a/Resources/Textures/Structures/Decoration/banner.rsi/banner_syndicate.png and b/Resources/Textures/Structures/Decoration/banner.rsi/banner_syndicate.png differ diff --git a/Resources/Textures/Structures/Decoration/banner.rsi/meta.json b/Resources/Textures/Structures/Decoration/banner.rsi/meta.json index 2de33ea0290..2df45b016ce 100644 --- a/Resources/Textures/Structures/Decoration/banner.rsi/meta.json +++ b/Resources/Textures/Structures/Decoration/banner.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "https://github.com/tgstation/tgstation/commit/fa9e44d937026d5a2ba72615afccf2f18a87c485 | banner_syndicate sprited by mureixlol (Discord)", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise // banner_revolution, banner-red, banner-blue, banner-yellow, banner-green Taken from https://github.com/tgstation/tgstation/commit/fa9e44d937026d5a2ba72615afccf2f18a87c485", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Furniture/furniture.rsi/meta.json b/Resources/Textures/Structures/Furniture/furniture.rsi/meta.json index 1f7049dfbe1..5afc1b2b0f1 100644 --- a/Resources/Textures/Structures/Furniture/furniture.rsi/meta.json +++ b/Resources/Textures/Structures/Furniture/furniture.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d5cb4288ec5f7cb9fb5b6f6e798f4c64cd82cd09, Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/9d7ff729b6b89eee0b3d750327f9fbaff4aeb045", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d5cb4288ec5f7cb9fb5b6f6e798f4c64cd82cd09, Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/9d7ff729b6b89eee0b3d750327f9fbaff4aeb045, Taken from https://github.com/ParadiseSS13/Paradise", "size": { "x": 32, "y": 32 @@ -29,4 +29,4 @@ "name": "dresser" } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Structures/Furniture/furniture.rsi/rack.png b/Resources/Textures/Structures/Furniture/furniture.rsi/rack.png index b299cc49e14..cb146b54125 100644 Binary files a/Resources/Textures/Structures/Furniture/furniture.rsi/rack.png and b/Resources/Textures/Structures/Furniture/furniture.rsi/rack.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o0.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o0.png index 5eefb01db6a..2cf968a8c32 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o0.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o0.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o1.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o1.png index 1902bbd8b96..3d461d60296 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o1.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o1.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o2.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o2.png index 57a1eaa3abf..ef543a5e09e 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o2.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o2.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o3.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o3.png index 3522af81e5c..4e1dc10c29a 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o3.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-o3.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-tank.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-tank.png index 4d5049f7b4e..a48466d3b46 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-tank.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca-tank.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_active.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_active.png index 134c51bccb0..184b8801124 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_active.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_active.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_deactive.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_deactive.png index e40e276e040..420179558ca 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_deactive.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_deactive.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_off.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_off.png index a3cac04acb3..9da9ba51a10 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_off.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_off.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_on.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_on.png index b9a49e1ec98..eb8cbc1f818 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_on.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/ca_on.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/cu.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/cu.png index 896c844149d..9da9ba51a10 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/cu.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/cu.png differ diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/meta.json b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/meta.json index 1da3a0a7336..1c8714a8dbe 100644 --- a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/meta.json +++ b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from goonstation at https://github.com/goonstation/goonstation/commit/cbe076402ed43b1cd861295bbcb95608c453de7a. Edited by chromiumboy", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/. Edited by FoxxoTrystan", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/static.png b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/static.png index 6097982ee26..7d8c7a8c49c 100644 Binary files a/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/static.png and b/Resources/Textures/Structures/Power/Generation/Singularity/collector.rsi/static.png differ diff --git a/Resources/Textures/Structures/Wallmounts/screen.rsi/meta.json b/Resources/Textures/Structures/Wallmounts/screen.rsi/meta.json index a4c3148aa8e..25f0d7f1981 100644 --- a/Resources/Textures/Structures/Wallmounts/screen.rsi/meta.json +++ b/Resources/Textures/Structures/Wallmounts/screen.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "From vgstation: https://github.com/vgstation-coders/vgstation13/commit/a7290010020e541ed6b57817a07023ca6bef26fe#diff-20395160138bed693d15eee6f16d671531b5fa533ec52c50e8df6d52370dbecd", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Wallmounts/screen.rsi/screen.png b/Resources/Textures/Structures/Wallmounts/screen.rsi/screen.png index a3e7a3fe55a..6b6329e83d0 100644 Binary files a/Resources/Textures/Structures/Wallmounts/screen.rsi/screen.png and b/Resources/Textures/Structures/Wallmounts/screen.rsi/screen.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/full.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/full.png index bac03f82f18..31911eddb81 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/full.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/full.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/meta.json b/Resources/Textures/Structures/Walls/solid_rust.rsi/meta.json index af5ebe04cf7..3b1da2fdae0 100644 --- a/Resources/Textures/Structures/Walls/solid_rust.rsi/meta.json +++ b/Resources/Textures/Structures/Walls/solid_rust.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/tgstation/tgstation/commit/67a5373b4649937dd63dd94153e05e8506f40a5d and modified.", + "copyright": "Taken from https://github.com/ParadiseSS13/Paradise/ and modified by FoxxoTrystan.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-0.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-0.png index 3af17740393..81f7b75d7bb 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-0.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-0.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-1.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-1.png index 57f9a29657b..69acb771155 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-1.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-1.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-2.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-2.png index 122fb413982..63c1502b8a7 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-2.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-2.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-3.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-3.png index 2e7be27dd05..ad5094443b9 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-3.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-3.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-4.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-4.png index 48a07386adb..50b465c63be 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-4.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-4.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-5.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-5.png index 0969ca3ecd7..c6d8dacab13 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-5.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_construct-5.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over0.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over0.png index 89314482b3a..ce5adc65b5d 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over0.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over0.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over1.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over1.png index 79fb38bd6ac..dd8b232de26 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over1.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over1.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over2.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over2.png index 89314482b3a..ce5adc65b5d 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over2.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over2.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over3.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over3.png index 79fb38bd6ac..dd8b232de26 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over3.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over3.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over4.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over4.png index 3fd3d1f3a26..e6c25bf9542 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over4.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over4.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over5.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over5.png index a9d7e717378..d0384e6f2b4 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over5.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over5.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over6.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over6.png index 3fd3d1f3a26..e6c25bf9542 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over6.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over6.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over7.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over7.png index 970ef1f1f5d..45a43655f63 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over7.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/reinf_over7.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/rgeneric.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/rgeneric.png index 02a1c5c63bb..81f7b75d7bb 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/rgeneric.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/rgeneric.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid0.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid0.png index b6720ad5a32..a82cf053371 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid0.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid0.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid1.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid1.png index 9d1da43e6f0..88c852b3963 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid1.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid1.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid2.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid2.png index b6720ad5a32..a82cf053371 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid2.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid2.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid3.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid3.png index 9d1da43e6f0..88c852b3963 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid3.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid3.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid4.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid4.png index f31f3a6bc98..ba6ac0281f9 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid4.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid4.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid5.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid5.png index 7c18f9c11a7..d0384e6f2b4 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid5.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid5.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid6.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid6.png index 8737894cbf0..ba6ac0281f9 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid6.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid6.png differ diff --git a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid7.png b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid7.png index 15f74bcaeed..45a43655f63 100644 Binary files a/Resources/Textures/Structures/Walls/solid_rust.rsi/solid7.png and b/Resources/Textures/Structures/Walls/solid_rust.rsi/solid7.png differ diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 8ad5e4071f9..24da641a078 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -186,7 +186,7 @@ binds: key: C - function: OpenLanguageMenu type: State - key: M + key: L - function: TextCursorSelect # TextCursorSelect HAS to be above ExamineEntity # So that LineEdit receives it correctly.