Northstar Gloves (#16021)

* Added Gloves of North Star, no sprite or talking yet...

* Added sprites for the gloves of the north star...

* Replaced more placeholder sprites for northstar gloves...

* Added gloves of the north star to uplink...

* Added speech on hit, not yet configureable

* Not functional yet, but a step in the right direction I hope...

* IT WORKS!!

* Licensing and cleanup

* Reduced attack speed, changed from chat to popup, added some admin logging. It was causing too much adminlog spam otherwise

* Reorganized some files, final build??

* Changed the adminlog type from Verb to new type ItemConfigure

* More cleanup, fix sprite reference maybe

* Keronshb's suggestions, fixed some stuff, made hit sound use the meaty punch sfx

* Adds support for hiding speak/whisper/emote from adminlogs, makes northstar speak again!

* Some file shuffling, some of Keronshb's requests. Might appear a bit funky in github because vscode kept duplicating files for some reason and I had to delete them

* Made it work with the latest changes on Master

* Final? cleanup, upped dmg to 8, made ui not activate on activateinhand, instead you need to right click

* Set value to 0 credits, that's all

* Well that was much easier than I made it out to be. Now you can only activate the gloves with right click, no more mispredicts.

* Update MeleeWeaponSystem.cs

Iunno why this got changed in the first place, but I'm changin it back

* emptycommit

* emptycommit

* The tiny fixening
This commit is contained in:
HerCoyote23
2023-05-23 11:12:30 -07:00
committed by GitHub
parent 7ea1906c27
commit e45dd96af9
28 changed files with 383 additions and 47 deletions

View File

@@ -0,0 +1,56 @@
using Robust.Client.GameObjects;
using Content.Shared.Speech.Components;
namespace Content.Client.Weapons.Melee.UI;
/// <summary>
/// Initializes a <see cref="MeleeSpeechWindow"/> and updates it when new server messages are received.
/// </summary>
public sealed class MeleeSpeechBoundUserInterface : BoundUserInterface
{
private MeleeSpeechWindow? _window;
public MeleeSpeechBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new MeleeSpeechWindow();
if (State != null)
UpdateState(State);
_window.OpenCentered();
_window.OnClose += Close;
_window.OnBattlecryEntered += OnBattlecryChanged;
}
private void OnBattlecryChanged(string newBattlecry)
{
SendMessage(new MeleeSpeechBattlecryChangedMessage(newBattlecry));
}
/// <summary>
/// Update the UI state based on server-sent info
/// </summary>
/// <param name="state"></param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_window == null || state is not MeleeSpeechBoundUserInterfaceState cast)
return;
_window.SetCurrentBattlecry(cast.CurrentBattlecry);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}

View File

@@ -0,0 +1,8 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Loc north-star-menu-title}">
<BoxContainer Orientation="Vertical" SeparationOverride="4" MinWidth="150" >
<Label Name="CurrentBattlecry" Text="{Loc 'north-star-current-battlecry'}" />
<LineEdit Name="BattlecryLineEdit" />
</BoxContainer>
</DefaultWindow>

View File

@@ -0,0 +1,28 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Weapons.Melee.UI;
[GenerateTypedNameReferences]
public sealed partial class MeleeSpeechWindow : DefaultWindow
{
public event Action<string>? OnBattlecryEntered;
public MeleeSpeechWindow()
{
RobustXamlLoader.Load(this);
BattlecryLineEdit.OnTextEntered += e => OnBattlecryEntered?.Invoke(e.Text);
}
public void SetCurrentBattlecry(string battlecry)
{
BattlecryLineEdit.Text = battlecry;
}
}

View File

@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
return; return;
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>() IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Emote, ChatTransmitRange.Normal, shell, player); .TrySendInGameICMessage(playerEntity, message, InGameICChatType.Emote, ChatTransmitRange.Normal, false, shell, player);
} }
} }
} }

View File

@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
return; return;
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>() IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Speak, ChatTransmitRange.Normal, shell, player); .TrySendInGameICMessage(playerEntity, message, InGameICChatType.Speak, ChatTransmitRange.Normal, false, shell, player);
} }
} }
} }

View File

@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
return; return;
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>() IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Whisper, ChatTransmitRange.Normal, shell, player); .TrySendInGameICMessage(playerEntity, message, InGameICChatType.Whisper, ChatTransmitRange.Normal, false, shell, player);
} }
} }
} }

View File

@@ -52,13 +52,14 @@ public partial class ChatSystem
/// </summary> /// </summary>
/// <param name="source">The entity that is speaking</param> /// <param name="source">The entity that is speaking</param>
/// <param name="emoteId">The id of emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param> /// <param name="emoteId">The id of emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param> /// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param> /// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
public void TryEmoteWithChat(EntityUid source, string emoteId, ChatTransmitRange range = ChatTransmitRange.Normal, string? nameOverride = null) public void TryEmoteWithChat(EntityUid source, string emoteId, ChatTransmitRange range = ChatTransmitRange.Normal, bool hideLog = false, string? nameOverride = null)
{ {
if (!_prototypeManager.TryIndex<EmotePrototype>(emoteId, out var proto)) if (!_prototypeManager.TryIndex<EmotePrototype>(emoteId, out var proto))
return; return;
TryEmoteWithChat(source, proto, range, nameOverride); TryEmoteWithChat(source, proto, range, hideLog, nameOverride);
} }
/// <summary> /// <summary>
@@ -66,15 +67,17 @@ public partial class ChatSystem
/// </summary> /// </summary>
/// <param name="source">The entity that is speaking</param> /// <param name="source">The entity that is speaking</param>
/// <param name="emote">The emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param> /// <param name="emote">The emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param> /// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param> /// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
public void TryEmoteWithChat(EntityUid source, EmotePrototype emote, ChatTransmitRange range = ChatTransmitRange.Normal, string? nameOverride = null) public void TryEmoteWithChat(EntityUid source, EmotePrototype emote, ChatTransmitRange range = ChatTransmitRange.Normal, bool hideLog = false, string? nameOverride = null)
{ {
// check if proto has valid message for chat // check if proto has valid message for chat
if (emote.ChatMessages.Count != 0) if (emote.ChatMessages.Count != 0)
{ {
var action = _random.Pick(emote.ChatMessages); var action = _random.Pick(emote.ChatMessages);
SendEntityEmote(source, action, range, nameOverride, false); SendEntityEmote(source, action, range, nameOverride, false, hideLog);
} }
// do the rest of emote event logic here // do the rest of emote event logic here

View File

@@ -100,14 +100,14 @@ public sealed partial class ChatSystem : SharedChatSystem
private void OnGameChange(GameRunLevelChangedEvent ev) private void OnGameChange(GameRunLevelChangedEvent ev)
{ {
switch(ev.New) switch (ev.New)
{ {
case GameRunLevel.InRound: case GameRunLevel.InRound:
if(!_configurationManager.GetCVar(CCVars.OocEnableDuringRound)) if (!_configurationManager.GetCVar(CCVars.OocEnableDuringRound))
_configurationManager.SetCVar(CCVars.OocEnabled, false); _configurationManager.SetCVar(CCVars.OocEnabled, false);
break; break;
case GameRunLevel.PostRound: case GameRunLevel.PostRound:
if(!_configurationManager.GetCVar(CCVars.OocEnableDuringRound)) if (!_configurationManager.GetCVar(CCVars.OocEnableDuringRound))
_configurationManager.SetCVar(CCVars.OocEnabled, true); _configurationManager.SetCVar(CCVars.OocEnabled, true);
break; break;
} }
@@ -120,13 +120,14 @@ public sealed partial class ChatSystem : SharedChatSystem
/// <param name="message">The message being spoken or emoted</param> /// <param name="message">The message being spoken or emoted</param>
/// <param name="desiredType">The chat type</param> /// <param name="desiredType">The chat type</param>
/// <param name="hideChat">Whether or not this message should appear in the chat window</param> /// <param name="hideChat">Whether or not this message should appear in the chat window</param>
/// <param name="hideLog">Whether or not this message should appear in the adminlog window</param>
/// <param name="shell"></param> /// <param name="shell"></param>
/// <param name="player">The player doing the speaking</param> /// <param name="player">The player doing the speaking</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param> /// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, bool hideChat, public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, bool hideChat, bool hideLog = false,
IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true) IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true)
{ {
TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, shell, player, nameOverride, checkRadioPrefix); TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, hideLog, shell, player, nameOverride, checkRadioPrefix);
} }
/// <summary> /// <summary>
@@ -139,7 +140,7 @@ public sealed partial class ChatSystem : SharedChatSystem
/// <param name="shell"></param> /// <param name="shell"></param>
/// <param name="player">The player doing the speaking</param> /// <param name="player">The player doing the speaking</param>
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param> /// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, ChatTransmitRange range, public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, ChatTransmitRange range, bool hideLog = false,
IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true) IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true)
{ {
if (HasComp<GhostComponent>(source)) if (HasComp<GhostComponent>(source))
@@ -194,13 +195,13 @@ public sealed partial class ChatSystem : SharedChatSystem
switch (desiredType) switch (desiredType)
{ {
case InGameICChatType.Speak: case InGameICChatType.Speak:
SendEntitySpeak(source, message, range, nameOverride); SendEntitySpeak(source, message, range, nameOverride, hideLog);
break; break;
case InGameICChatType.Whisper: case InGameICChatType.Whisper:
SendEntityWhisper(source, message, range, null, nameOverride); SendEntityWhisper(source, message, range, null, nameOverride, hideLog);
break; break;
case InGameICChatType.Emote: case InGameICChatType.Emote:
SendEntityEmote(source, message, range, nameOverride); SendEntityEmote(source, message, range, nameOverride, hideLog);
break; break;
} }
} }
@@ -294,7 +295,7 @@ public sealed partial class ChatSystem : SharedChatSystem
#region Private API #region Private API
private void SendEntitySpeak(EntityUid source, string originalMessage, ChatTransmitRange range, string? nameOverride) private void SendEntitySpeak(EntityUid source, string originalMessage, ChatTransmitRange range, string? nameOverride, bool hideLog = false)
{ {
if (!_actionBlocker.CanSpeak(source)) if (!_actionBlocker.CanSpeak(source))
return; return;
@@ -326,7 +327,8 @@ public sealed partial class ChatSystem : SharedChatSystem
RaiseLocalEvent(source, ev, true); RaiseLocalEvent(source, ev, true);
// To avoid logging any messages sent by entities that are not players, like vendors, cloning, etc. // To avoid logging any messages sent by entities that are not players, like vendors, cloning, etc.
if (!HasComp<ActorComponent>(source)) // Also doesn't log if hideLog is true.
if (!HasComp<ActorComponent>(source) || hideLog == true)
return; return;
if (originalMessage == message) if (originalMessage == message)
@@ -347,7 +349,7 @@ public sealed partial class ChatSystem : SharedChatSystem
} }
} }
private void SendEntityWhisper(EntityUid source, string originalMessage, ChatTransmitRange range, RadioChannelPrototype? channel, string? nameOverride) private void SendEntityWhisper(EntityUid source, string originalMessage, ChatTransmitRange range, RadioChannelPrototype? channel, string? nameOverride, bool hideLog = false)
{ {
if (!_actionBlocker.CanSpeak(source)) if (!_actionBlocker.CanSpeak(source))
return; return;
@@ -399,7 +401,7 @@ public sealed partial class ChatSystem : SharedChatSystem
var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage); var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage);
RaiseLocalEvent(source, ev, true); RaiseLocalEvent(source, ev, true);
if (!hideLog)
if (originalMessage == message) if (originalMessage == message)
{ {
if (name != Name(source)) if (name != Name(source))
@@ -418,7 +420,7 @@ public sealed partial class ChatSystem : SharedChatSystem
} }
} }
private void SendEntityEmote(EntityUid source, string action, ChatTransmitRange range, string? nameOverride, bool checkEmote = true) private void SendEntityEmote(EntityUid source, string action, ChatTransmitRange range, string? nameOverride, bool hideLog = false, bool checkEmote = true)
{ {
if (!_actionBlocker.CanEmote(source)) return; if (!_actionBlocker.CanEmote(source)) return;
@@ -433,7 +435,7 @@ public sealed partial class ChatSystem : SharedChatSystem
if (checkEmote) if (checkEmote)
TryEmoteChatInput(source, action); TryEmoteChatInput(source, action);
SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, range); SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, range);
if (!hideLog)
if (name != Name(source)) if (name != Name(source))
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}"); _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}");
else else
@@ -714,7 +716,7 @@ public sealed class TransformSpeakerNameEvent : EntityEventArgs
} }
/// <summary> /// <summary>
/// Raised broadcast in order to transform speech. /// Raised broadcast in order to transform speech.transmit
/// </summary> /// </summary>
public sealed class TransformSpeechEvent : EntityEventArgs public sealed class TransformSpeechEvent : EntityEventArgs
{ {

View File

@@ -0,0 +1,66 @@
using Content.Server.Administration.Logs;
using Content.Shared.Speech.Components;
using Content.Shared.Weapons.Melee;
using Content.Shared.Database;
namespace Content.Server.Speech.EntitySystems;
public sealed class MeleeSpeechSystem : SharedMeleeSpeechSystem
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MeleeSpeechComponent, MeleeSpeechBattlecryChangedMessage>(OnBattlecryChanged);
}
private void OnBattlecryChanged(EntityUid uid, MeleeSpeechComponent comp, MeleeSpeechBattlecryChangedMessage args)
{
if (!TryComp<MeleeSpeechComponent>(uid, out var meleeSpeechUser))
return;
TryChangeBattlecry(uid, args.Battlecry, meleeSpeechUser);
}
/// <summary>
/// Attempts to change the battlecry of an entity.
/// Returns true/false.
/// </summary>
/// <remarks>
/// If provided with a player's EntityUid to the player parameter, adds the change to the admin logs.
/// </remarks>
public bool TryChangeBattlecry(EntityUid uid, string? battlecry, MeleeSpeechComponent? meleeSpeechComp = null)
{
if (!Resolve(uid, ref meleeSpeechComp))
return false;
if (!string.IsNullOrWhiteSpace(battlecry))
{
battlecry = battlecry.Trim();
}
else
{
battlecry = null;
}
if (meleeSpeechComp.Battlecry == battlecry)
return true;
meleeSpeechComp.Battlecry = battlecry;
Dirty(meleeSpeechComp);
_adminLogger.Add(LogType.ItemConfigure, LogImpact.Medium, $" {ToPrettyString(uid):entity}'s battlecry has been changed to {battlecry}");
return true;
}
}

View File

@@ -42,6 +42,13 @@ namespace Content.Server.UserInterface
[DataField("requireHands")] [DataField("requireHands")]
public bool RequireHands = true; public bool RequireHands = true;
/// <summary>
/// Whether you can activate this ui with activateinhand or not
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("rightClickOnly")]
public bool rightClickOnly = false;
/// <summary> /// <summary>
/// Whether spectators (non-admin ghosts) should be allowed to view this UI. /// Whether spectators (non-admin ghosts) should be allowed to view this UI.
/// </summary> /// </summary>

View File

@@ -91,6 +91,7 @@ public sealed partial class ActivatableUISystem : EntitySystem
private void OnUseInHand(EntityUid uid, ActivatableUIComponent component, UseInHandEvent args) private void OnUseInHand(EntityUid uid, ActivatableUIComponent component, UseInHandEvent args)
{ {
if (args.Handled) return; if (args.Handled) return;
if (component.rightClickOnly) return;
args.Handled = InteractUI(args.User, component); args.Handled = InteractUI(args.User, component);
} }

View File

@@ -1,14 +1,16 @@
using System.Linq; using System.Linq;
using Content.Server.Body.Components; using Content.Server.Body.Components;
using Content.Server.Body.Systems; using Content.Server.Body.Systems;
using Content.Server.Chat.Systems;
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.CombatMode.Disarm; using Content.Server.CombatMode.Disarm;
using Content.Server.Contests; using Content.Server.Contests;
using Content.Server.Examine; using Content.Server.Examine;
using Content.Server.Movement.Systems; using Content.Server.Movement.Systems;
using Content.Shared.Actions.Events; using Content.Server.Popups;
using Content.Shared.Administration.Components; using Content.Shared.Administration.Components;
using Content.Shared.Actions.Events;
using Content.Shared.CombatMode; using Content.Shared.CombatMode;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Database; using Content.Shared.Database;
@@ -17,6 +19,7 @@ using Content.Shared.Hands.Components;
using Content.Shared.IdentityManagement; using Content.Shared.IdentityManagement;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Speech.Components;
using Content.Shared.StatusEffect; using Content.Shared.StatusEffect;
using Content.Shared.Tag; using Content.Shared.Tag;
using Content.Shared.Verbs; using Content.Shared.Verbs;
@@ -42,11 +45,15 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
[Dependency] private readonly LagCompensationSystem _lag = default!; [Dependency] private readonly LagCompensationSystem _lag = default!;
[Dependency] private readonly SolutionContainerSystem _solutions = default!; [Dependency] private readonly SolutionContainerSystem _solutions = default!;
[Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(OnChemicalInjectorHit); SubscribeLocalEvent<MeleeChemicalInjectorComponent, MeleeHitEvent>(OnChemicalInjectorHit);
SubscribeLocalEvent<MeleeSpeechComponent, MeleeHitEvent>(OnSpeechHit);
SubscribeLocalEvent<MeleeWeaponComponent, GetVerbsEvent<ExamineVerb>>(OnMeleeExaminableVerb); SubscribeLocalEvent<MeleeWeaponComponent, GetVerbsEvent<ExamineVerb>>(OnMeleeExaminableVerb);
} }
@@ -79,7 +86,7 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
Text = Loc.GetString("damage-examinable-verb-text"), Text = Loc.GetString("damage-examinable-verb-text"),
Message = Loc.GetString("damage-examinable-verb-message"), Message = Loc.GetString("damage-examinable-verb-message"),
Category = VerbCategory.Examine, Category = VerbCategory.Examine,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
}; };
args.Verbs.Add(verb); args.Verbs.Add(verb);
@@ -200,7 +207,7 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
var eventArgs = new DisarmedEvent { Target = target, Source = user, PushProbability = 1 - chance }; var eventArgs = new DisarmedEvent { Target = target, Source = user, PushProbability = 1 - chance };
RaiseLocalEvent(target, eventArgs); RaiseLocalEvent(target, eventArgs);
RaiseNetworkEvent(new DamageEffectEvent(Color.Aqua, new List<EntityUid>() {target})); RaiseNetworkEvent(new DamageEffectEvent(Color.Aqua, new List<EntityUid>() { target }));
return true; return true;
} }
@@ -265,6 +272,21 @@ public sealed class MeleeWeaponSystem : SharedMeleeWeaponSystem
RaiseNetworkEvent(new MeleeLungeEvent(user, angle, localPos, animation), filter); RaiseNetworkEvent(new MeleeLungeEvent(user, angle, localPos, animation), filter);
} }
private void OnSpeechHit(EntityUid owner, MeleeSpeechComponent comp, MeleeHitEvent args)
{
if (!args.IsHit ||
!args.HitEntities.Any())
{
return;
}
if (comp.Battlecry != null)//If the battlecry is set to empty, doesn't speak
{
_chat.TrySendInGameICMessage(args.User, comp.Battlecry, InGameICChatType.Speak, true, true); //Speech that isn't sent to chat or adminlogs
}
}
private void OnChemicalInjectorHit(EntityUid owner, MeleeChemicalInjectorComponent comp, MeleeHitEvent args) private void OnChemicalInjectorHit(EntityUid owner, MeleeChemicalInjectorComponent comp, MeleeHitEvent args)
{ {
if (!args.IsHit || if (!args.IsHit ||

View File

@@ -86,4 +86,5 @@ public enum LogType
Teleport = 81, Teleport = 81,
EntityDelete = 82, EntityDelete = 82,
Vote = 83, Vote = 83,
ItemConfigure = 84,
} }

View File

@@ -1,4 +1,4 @@
using Content.Shared.Clothing.EntitySystems; using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Inventory; using Content.Shared.Inventory;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -55,7 +55,7 @@ public sealed class ChameleonBoundUserInterfaceState : BoundUserInterfaceState
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class ChameleonPrototypeSelectedMessage: BoundUserInterfaceMessage public sealed class ChameleonPrototypeSelectedMessage : BoundUserInterfaceMessage
{ {
public readonly string SelectedId; public readonly string SelectedId;

View File

@@ -0,0 +1,51 @@
using Content.Shared.Speech.EntitySystems;
using Robust.Shared.Serialization;
namespace Content.Shared.Speech.Components;
[RegisterComponent]
[AutoGenerateComponentState]
[Access(typeof(SharedMeleeSpeechSystem), Other = AccessPermissions.ReadWrite)]
public sealed partial class MeleeSpeechComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("Battlecry")]
[AutoNetworkedField]
[Access(typeof(SharedMeleeSpeechSystem), Other = AccessPermissions.ReadWrite)]
public string? Battlecry;
}
/// <summary>
/// Key representing which <see cref="BoundUserInterface"/> is currently open.
/// Useful when there are multiple UI for an object. Here it's future-proofing only.
/// </summary>
[Serializable, NetSerializable]
public enum MeleeSpeechUiKey : byte
{
Key,
}
/// <summary>
/// Represents an <see cref="MeleeSpeechComponent"/> state that can be sent to the client
/// </summary>
[Serializable, NetSerializable]
public sealed class MeleeSpeechBoundUserInterfaceState : BoundUserInterfaceState
{
public string CurrentBattlecry { get; }
public MeleeSpeechBoundUserInterfaceState(string currentBattlecry)
{
CurrentBattlecry = currentBattlecry;
}
}
[Serializable, NetSerializable]
public sealed class MeleeSpeechBattlecryChangedMessage : BoundUserInterfaceMessage
{
public string Battlecry { get; }
public MeleeSpeechBattlecryChangedMessage(string battlecry)
{
Battlecry = battlecry;
}
}

View File

@@ -0,0 +1,7 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Weapons.Melee;
public abstract class SharedMeleeSpeechSystem : EntitySystem
{
}

View File

@@ -1,4 +1,4 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.Speech namespace Content.Shared.Speech

View File

@@ -54,6 +54,7 @@ public sealed class MeleeWeaponComponent : Component
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public bool Attacking = false; public bool Attacking = false;
/// <summary> /// <summary>
/// When did we start a heavy attack. /// When did we start a heavy attack.
/// </summary> /// </summary>

View File

@@ -0,0 +1,7 @@
using Robust.Shared.Serialization;
namespace Content.Shared.Speech.EntitySystems;
public abstract class SharedMeleeSpeechSystem : EntitySystem
{
}

View File

@@ -0,0 +1,2 @@
north-star-current-battlecry = Battlecry:
north-star-menu-title = Set Battlecry

View File

@@ -20,6 +20,9 @@ uplink-edagger-desc = A small energy blade conveniently disguised in the form of
uplink-fire-axe-flaming-name = Fire Axe uplink-fire-axe-flaming-name = Fire Axe
uplink-fire-axe-flaming-desc = A classic-style weapon infused with advanced atmos technology to allow it to set targets on fire. uplink-fire-axe-flaming-desc = A classic-style weapon infused with advanced atmos technology to allow it to set targets on fire.
uplink-gloves-north-star-name = Gloves of the North Star
uplink-gloves-north-star-desc = A pair of gloves that reduce your punching cooldown drastically, allowing you to beat people to death in a flurry of punches.
# Explosives # Explosives
uplink-explosive-grenade-name = Explosive Grenade uplink-explosive-grenade-name = Explosive Grenade
uplink-explosive-grenade-desc = Grenade that creates a small but devastating explosion. uplink-explosive-grenade-desc = Grenade that creates a small but devastating explosion.

View File

@@ -75,6 +75,16 @@
categories: categories:
- UplinkWeapons - UplinkWeapons
- type: listing
id: UplinkGlovesNorthStar
name: uplink-gloves-north-star-name
description: uplink-gloves-north-star-desc
productEntity: ClothingHandsGlovesNorthStar
cost:
Telecrystal: 8
categories:
- UplinkWeapons
# Explosives # Explosives
- type: listing - type: listing

View File

@@ -293,6 +293,40 @@
components: components:
- type: Unremoveable - type: Unremoveable
- type: entity
parent: ClothingHandsBase
id: ClothingHandsGlovesNorthStar
name: gloves of the north star
description: These gloves allow you to punch incredibly fast
components:
- type: Sprite
sprite: Clothing/Hands/Gloves/northstar.rsi
- type: Clothing
sprite: Clothing/Hands/Gloves/northstar.rsi
- type: MeleeWeapon
attackRate: 4
damage:
types:
Blunt: 8
soundHit:
collection: Punch
animation: WeaponArcFist
- type: Fiber
fiberMaterial: fibers-leather
fiberColor: fibers-blue
- type: FingerprintMask
- type: MeleeSpeech
- type: ActivatableUI
key: enum.MeleeSpeechUiKey.Key
closeOnHandDeselect: false
rightClickOnly: true
- type: UserInterface
interfaces:
- key: enum.MeleeSpeechUiKey.Key
type: MeleeSpeechBoundUserInterface
- type: StaticPrice
price: 0
- type: entity - type: entity
parent: ClothingHandsBase parent: ClothingHandsBase
id: ForensicGloves id: ForensicGloves
@@ -304,3 +338,4 @@
- type: Clothing - type: Clothing
sprite: Clothing/Hands/Gloves/forensic.rsi sprite: Clothing/Hands/Gloves/forensic.rsi
- type: FingerprintMask - type: FingerprintMask

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

View File

@@ -0,0 +1,26 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/pull/37864/commits/efdef3f1f997d1c0575c36cd31a5db575d1df0ca#diff-a4eb7c89f7231f0aaf0c2f69d730dea56383019f2aa5c6a1d91a82c781b528e6. Modified by hercoyote23 (github) for SS14",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "equipped-HAND",
"directions": 4
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}