diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index 9e594260f3..767e7ac325 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -1,16 +1,13 @@ using System.IO; using System.Linq; -using Content.Client.Popups; using Content.Shared.Actions; using Content.Shared.Actions.ActionTypes; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Player; -using Robust.Shared.Audio; using Robust.Shared.ContentPack; using Robust.Shared.GameStates; using Robust.Shared.Input.Binding; -using Robust.Shared.Player; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Markdown; using Robust.Shared.Serialization.Markdown.Mapping; @@ -28,9 +25,6 @@ namespace Content.Client.Actions [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IResourceManager _resources = default!; [Dependency] private readonly ISerializationManager _serialization = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - - [Dependency] private readonly PopupSystem _popupSystem = default!; public event Action? ActionAdded; public event Action? ActionRemoved; diff --git a/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs b/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs index 06a7792f38..472ad49a3f 100644 --- a/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs +++ b/Content.Client/UserInterface/Systems/Actions/ActionUIController.cs @@ -20,7 +20,6 @@ using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controllers; using Robust.Client.UserInterface.Controls; -using Robust.Client.Utility; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Timing; @@ -39,7 +38,6 @@ namespace Content.Client.UserInterface.Systems.Actions; public sealed class ActionUIController : UIController, IOnStateChanged, IOnSystemChanged { - [Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IOverlayManager _overlays = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; @@ -47,6 +45,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged /// Action slot we are currently selecting a target for. /// - public TargetedAction? SelectingTargetFor { get; private set; } = null; + public TargetedAction? SelectingTargetFor { get; private set; } public ActionUIController() { @@ -190,15 +189,15 @@ public sealed class ActionUIController : UIController, IOnStateChanged _timing.CurTime) { // The user is targeting with this action, but it is not valid. Maybe mark this click as @@ -247,7 +246,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged action.Enabled, - Filters.Item => action.Provider != null && action.Provider != _actionsSystem?.PlayerActions?.Owner, - Filters.Innate => action.Provider == null || action.Provider == _actionsSystem?.PlayerActions?.Owner, + Filters.Item => action.Provider != null && action.Provider != _playerManager.LocalPlayer?.ControlledEntity, + Filters.Innate => action.Provider == null || action.Provider == _playerManager.LocalPlayer?.ControlledEntity, Filters.Instant => action is InstantAction, Filters.Targeted => action is TargetedAction, _ => throw new ArgumentOutOfRangeException(nameof(filter), filter, null) @@ -582,10 +589,10 @@ public sealed class ActionUIController : UIController, IOnStateChanged(action.Provider.Value).EntityName; + var name = EntityManager.GetComponent(action.Provider.Value).EntityName; return name.Contains(search, StringComparison.OrdinalIgnoreCase); }); @@ -731,12 +738,12 @@ public sealed class ActionUIController : UIController, IOnStateChanged(action.EntityIcon.Value).Icon? + _dragShadow.Texture = EntityManager.GetComponent(action.EntityIcon.Value).Icon? .GetFrame(RSI.State.Direction.South, 0); } else if (action.Icon != null) { - _dragShadow.Texture = action.Icon!.Frame0(); + _dragShadow.Texture = _spriteSystem.Frame0(action.Icon); } else { @@ -761,13 +768,7 @@ public sealed class ActionUIController : UIController, IOnStateChanged - public void ToggleTargeting(TargetedAction action) + private void ToggleTargeting(TargetedAction action) { if (SelectingTargetFor == action) { @@ -935,9 +936,9 @@ public sealed class ActionUIController : UIController, IOnStateChanged /// Switch out of targeting mode if currently selecting target for an action /// - public void StopTargeting() + private void StopTargeting() { if (SelectingTargetFor == null) return; diff --git a/Content.Server/Magic/Components/SpellbookComponent.cs b/Content.Server/Magic/Components/SpellbookComponent.cs index 0432336dfd..db6c717061 100644 --- a/Content.Server/Magic/Components/SpellbookComponent.cs +++ b/Content.Server/Magic/Components/SpellbookComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.Actions.ActionTypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; -namespace Content.Server.Magic; +namespace Content.Server.Magic.Components; /// /// Spellbooks for having an entity learn spells as long as they've read the book and it's in their hand. @@ -19,14 +19,25 @@ public sealed class SpellbookComponent : Component /// The three fields below is just used for initialization. /// [DataField("worldSpells", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] + [ViewVariables(VVAccess.ReadWrite)] public readonly Dictionary WorldSpells = new(); [DataField("entitySpells", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] + [ViewVariables(VVAccess.ReadWrite)] public readonly Dictionary EntitySpells = new(); [DataField("instantSpells", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] + [ViewVariables(VVAccess.ReadWrite)] public readonly Dictionary InstantSpells = new(); [DataField("learnTime")] + [ViewVariables(VVAccess.ReadWrite)] public float LearnTime = .75f; + + /// + /// If true, the spell action stays even after the book is removed + /// + [DataField("learnPermanently")] + [ViewVariables(VVAccess.ReadWrite)] + public bool LearnPermanently; } diff --git a/Content.Server/Magic/MagicSystem.cs b/Content.Server/Magic/MagicSystem.cs index c692433762..48b6a5b8da 100644 --- a/Content.Server/Magic/MagicSystem.cs +++ b/Content.Server/Magic/MagicSystem.cs @@ -3,6 +3,7 @@ using Content.Server.Body.Systems; using Content.Server.Chat.Systems; using Content.Server.Coordinates.Helpers; using Content.Server.Doors.Systems; +using Content.Server.Magic.Components; using Content.Server.Magic.Events; using Content.Server.Weapons.Ranged.Systems; using Content.Shared.Actions; @@ -72,7 +73,7 @@ public sealed class MagicSystem : EntitySystem if (args.Handled || args.Cancelled) return; - _actionsSystem.AddActions(args.Args.User, component.Spells, uid); + _actionsSystem.AddActions(args.Args.User, component.Spells, component.LearnPermanently ? null : uid); args.Handled = true; } @@ -166,12 +167,14 @@ public sealed class MagicSystem : EntitySystem { // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map. var mapPos = pos.ToMap(EntityManager); - EntityCoordinates spawnCoords = _mapManager.TryFindGridAt(mapPos, out var grid) + var spawnCoords = _mapManager.TryFindGridAt(mapPos, out var grid) ? pos.WithEntityId(grid.Owner, EntityManager) : new(_mapManager.GetMapEntityId(mapPos.MapId), mapPos.Position); var ent = Spawn(ev.Prototype, spawnCoords); - _gunSystem.ShootProjectile(ent, ev.Target.Position - mapPos.Position, userVelocity, ev.Performer); + var direction = ev.Target.ToMapPos(EntityManager, _transformSystem) - + spawnCoords.ToMapPos(EntityManager, _transformSystem); + _gunSystem.ShootProjectile(ent, direction, userVelocity, ev.Performer); } } diff --git a/Content.Shared/Actions/ActionsComponent.cs b/Content.Shared/Actions/ActionsComponent.cs index 646dac9d73..ba2aedb6da 100644 --- a/Content.Shared/Actions/ActionsComponent.cs +++ b/Content.Shared/Actions/ActionsComponent.cs @@ -10,7 +10,8 @@ namespace Content.Shared.Actions; public sealed class ActionsComponent : Component { [ViewVariables] - [Access(typeof(SharedActionsSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + [Access(typeof(SharedActionsSystem), Other = AccessPermissions.ReadExecute)] + // FIXME Friends public SortedSet Actions = new(); public override bool SendOnlyToOwner => true; diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 324c260a1e..a6c82c217e 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -5,12 +5,9 @@ using Content.Shared.Database; using Content.Shared.Hands; using Content.Shared.Interaction; using Content.Shared.Inventory.Events; -using Content.Shared.Popups; -using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Map; -using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using System.Linq; @@ -25,8 +22,8 @@ public abstract class SharedActionsSystem : EntitySystem [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedTransformSystem _transformSystem = default!; public override void Initialize() { @@ -98,7 +95,7 @@ public abstract class SharedActionsSystem : EntitySystem /// private void OnActionRequest(RequestPerformActionEvent ev, EntitySessionEventArgs args) { - if (args.SenderSession.AttachedEntity is not EntityUid user) + if (args.SenderSession.AttachedEntity is not { } user) return; if (!TryComp(user, out ActionsComponent? component)) @@ -134,7 +131,8 @@ public abstract class SharedActionsSystem : EntitySystem return; } - _rotateToFaceSystem.TryFaceCoordinates(user, Transform(entityTarget).WorldPosition); + var targetWorldPos = _transformSystem.GetWorldPosition(entityTarget); + _rotateToFaceSystem.TryFaceCoordinates(user, targetWorldPos); if (!ValidateEntityTarget(user, entityTarget, entityAction)) return; @@ -156,7 +154,7 @@ public abstract class SharedActionsSystem : EntitySystem case WorldTargetAction worldAction: - if (ev.EntityCoordinatesTarget is not EntityCoordinates entityCoordinatesTarget) + if (ev.EntityCoordinatesTarget is not { } entityCoordinatesTarget) { Logger.Error($"Attempted to perform a world-targeted action without a target! Action: {worldAction.DisplayName}"); return; @@ -231,7 +229,8 @@ public abstract class SharedActionsSystem : EntitySystem if (action.Range <= 0) return true; - return (xform.WorldPosition - targetXform.WorldPosition).Length <= action.Range; + var distance = (_transformSystem.GetWorldPosition(xform) - _transformSystem.GetWorldPosition(targetXform)).Length; + return distance <= action.Range; } if (_interactionSystem.InRangeUnobstructed(user, target, range: action.Range) @@ -259,7 +258,7 @@ public abstract class SharedActionsSystem : EntitySystem if (action.Range <= 0) return true; - return coords.InRange(EntityManager, Transform(user).Coordinates, action.Range); + return coords.InRange(EntityManager, _transformSystem, Transform(user).Coordinates, action.Range); } return _interactionSystem.InRangeUnobstructed(user, coords, range: action.Range); @@ -354,7 +353,7 @@ public abstract class SharedActionsSystem : EntitySystem { comp ??= EnsureComp(uid); - bool allClientExclusive = true; + var allClientExclusive = true; foreach (var action in actions) { @@ -400,7 +399,7 @@ public abstract class SharedActionsSystem : EntitySystem private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args) { var ev = new GetItemActionsEvent(args.SlotFlags); - RaiseLocalEvent(args.Equipment, ev, false); + RaiseLocalEvent(args.Equipment, ev); if (ev.Actions.Count == 0) return; @@ -411,7 +410,7 @@ public abstract class SharedActionsSystem : EntitySystem private void OnHandEquipped(EntityUid uid, ActionsComponent component, DidEquipHandEvent args) { var ev = new GetItemActionsEvent(); - RaiseLocalEvent(args.Equipped, ev, false); + RaiseLocalEvent(args.Equipped, ev); if (ev.Actions.Count == 0) return; diff --git a/Resources/Prototypes/Entities/Objects/Magic/books.yml b/Resources/Prototypes/Entities/Objects/Magic/books.yml index 7b4dc5d535..b9208dc669 100644 --- a/Resources/Prototypes/Entities/Objects/Magic/books.yml +++ b/Resources/Prototypes/Entities/Objects/Magic/books.yml @@ -107,4 +107,4 @@ FlashRune: -1 ExplosionRune: -1 IgniteRune: -1 - StunRune: -1 \ No newline at end of file + StunRune: -1