diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index 26a22fa8b8df..7b13233bab5c 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -51,6 +51,29 @@ public override void Initialize() SubscribeLocalEvent(OnEntityWorldTargetHandleState); } + public override void FrameUpdate(float frameTime) + { + base.FrameUpdate(frameTime); + + var worldActionQuery = EntityQueryEnumerator(); + while (worldActionQuery.MoveNext(out var uid, out var action)) + { + UpdateAction(uid, action); + } + + var instantActionQuery = EntityQueryEnumerator(); + while (instantActionQuery.MoveNext(out var uid, out var action)) + { + UpdateAction(uid, action); + } + + var entityActionQuery = EntityQueryEnumerator(); + while (entityActionQuery.MoveNext(out var uid, out var action)) + { + UpdateAction(uid, action); + } + } + private void OnInstantHandleState(EntityUid uid, InstantActionComponent component, ref ComponentHandleState args) { if (args.Current is not InstantActionComponentState state) @@ -95,6 +118,8 @@ private void BaseHandleState(EntityUid uid, BaseActionComponent component, Ba component.Icon = state.Icon; component.IconOn = state.IconOn; component.IconColor = state.IconColor; + component.OriginalIconColor = state.OriginalIconColor; + component.DisabledIconColor = state.DisabledIconColor; component.Keywords.Clear(); component.Keywords.UnionWith(state.Keywords); component.Enabled = state.Enabled; @@ -125,6 +150,8 @@ public override void UpdateAction(EntityUid? actionId, BaseActionComponent? acti if (!ResolveActionData(actionId, ref action)) return; + action.IconColor = action.Charges < 1 ? action.DisabledIconColor : action.OriginalIconColor; + base.UpdateAction(actionId, action); if (_playerManager.LocalEntity != action.AttachedEntity) return; diff --git a/Content.Server/Access/Systems/AgentIDCardSystem.cs b/Content.Server/Access/Systems/AgentIDCardSystem.cs index 8f1d0d4f820a..4de908bc3019 100644 --- a/Content.Server/Access/Systems/AgentIDCardSystem.cs +++ b/Content.Server/Access/Systems/AgentIDCardSystem.cs @@ -32,7 +32,7 @@ public override void Initialize() private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args) { - if (!TryComp(args.Target, out var targetAccess) || !HasComp(args.Target) || args.Target == null) + if (args.Target == null || !args.CanReach || !TryComp(args.Target, out var targetAccess) || !HasComp(args.Target)) return; if (!TryComp(uid, out var access) || !HasComp(uid)) diff --git a/Content.Server/VendingMachines/VendingMachineContrabandWireAction.cs b/Content.Server/VendingMachines/VendingMachineContrabandWireAction.cs index 22a0341fcbea..39231fbe8349 100644 --- a/Content.Server/VendingMachines/VendingMachineContrabandWireAction.cs +++ b/Content.Server/VendingMachines/VendingMachineContrabandWireAction.cs @@ -7,11 +7,20 @@ namespace Content.Server.VendingMachines; [DataDefinition] public sealed partial class VendingMachineContrabandWireAction : BaseToggleWireAction { + private VendingMachineSystem _vendingMachineSystem = default!; + public override Color Color { get; set; } = Color.Green; public override string Name { get; set; } = "wire-name-vending-contraband"; public override object? StatusKey { get; } = ContrabandWireKey.StatusKey; public override object? TimeoutKey { get; } = ContrabandWireKey.TimeoutKey; + public override void Initialize() + { + base.Initialize(); + + _vendingMachineSystem = EntityManager.System(); + } + public override StatusLightState? GetLightState(Wire wire) { if (EntityManager.TryGetComponent(wire.Owner, out VendingMachineComponent? vending)) @@ -28,7 +37,7 @@ public override void ToggleValue(EntityUid owner, bool setting) { if (EntityManager.TryGetComponent(owner, out VendingMachineComponent? vending)) { - vending.Contraband = !setting; + _vendingMachineSystem.SetContraband(owner, !vending.Contraband, vending); } } diff --git a/Content.Server/VendingMachines/VendingMachineSystem.cs b/Content.Server/VendingMachines/VendingMachineSystem.cs index 38407a98c729..90fe4cb7d8ae 100644 --- a/Content.Server/VendingMachines/VendingMachineSystem.cs +++ b/Content.Server/VendingMachines/VendingMachineSystem.cs @@ -192,6 +192,18 @@ public void SetShooting(EntityUid uid, bool canShoot, VendingMachineComponent? c component.CanShoot = canShoot; } + /// + /// Sets the property of the vending machine. + /// + public void SetContraband(EntityUid uid, bool contraband, VendingMachineComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + component.Contraband = contraband; + Dirty(uid, component); + } + public void Deny(EntityUid uid, VendingMachineComponent? vendComponent = null) { if (!Resolve(uid, ref vendComponent)) diff --git a/Content.Shared/Actions/BaseActionComponent.cs b/Content.Shared/Actions/BaseActionComponent.cs index 9156f747f5c9..01452bdc72e0 100644 --- a/Content.Shared/Actions/BaseActionComponent.cs +++ b/Content.Shared/Actions/BaseActionComponent.cs @@ -40,6 +40,16 @@ public abstract partial class BaseActionComponent : Component /// [DataField("iconColor")] public Color IconColor = Color.White; + /// + /// The original this action was. + /// + [DataField] public Color OriginalIconColor; + + /// + /// The color the action should turn to when disabled + /// + [DataField] public Color DisabledIconColor = Color.DimGray; + /// /// Keywords that can be used to search for this action in the action menu. /// @@ -179,6 +189,8 @@ public abstract class BaseActionComponentState : ComponentState public SpriteSpecifier? Icon; public SpriteSpecifier? IconOn; public Color IconColor; + public Color OriginalIconColor; + public Color DisabledIconColor; public HashSet Keywords; public bool Enabled; public bool Toggled; @@ -209,6 +221,8 @@ protected BaseActionComponentState(BaseActionComponent component, IEntityManager Icon = component.Icon; IconOn = component.IconOn; IconColor = component.IconColor; + OriginalIconColor = component.OriginalIconColor; + DisabledIconColor = component.DisabledIconColor; Keywords = component.Keywords; Enabled = component.Enabled; Toggled = component.Toggled; diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 275634542825..76b8a1b081b4 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -69,8 +69,42 @@ public override void Initialize() SubscribeAllEvent(OnActionRequest); } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var worldActionQuery = EntityQueryEnumerator(); + while (worldActionQuery.MoveNext(out var uid, out var action)) + { + if (IsCooldownActive(action) || !ShouldResetCharges(action)) + continue; + + ResetCharges(uid, dirty: true); + } + + var instantActionQuery = EntityQueryEnumerator(); + while (instantActionQuery.MoveNext(out var uid, out var action)) + { + if (IsCooldownActive(action) || !ShouldResetCharges(action)) + continue; + + ResetCharges(uid, dirty: true); + } + + var entityActionQuery = EntityQueryEnumerator(); + while (entityActionQuery.MoveNext(out var uid, out var action)) + { + if (IsCooldownActive(action) || !ShouldResetCharges(action)) + continue; + + ResetCharges(uid, dirty: true); + } + } + private void OnActionMapInit(EntityUid uid, BaseActionComponent component, MapInitEvent args) { + component.OriginalIconColor = component.IconColor; + if (component.Charges == null) return; @@ -326,14 +360,18 @@ public void RemoveCharges(EntityUid? actionId, int? removeCharges) Dirty(actionId.Value, action); } - public void ResetCharges(EntityUid? actionId) + public void ResetCharges(EntityUid? actionId, bool update = false, bool dirty = false) { if (!TryGetActionData(actionId, out var action)) return; action.Charges = action.MaxCharges; - UpdateAction(actionId, action); - Dirty(actionId.Value, action); + + if (update) + UpdateAction(actionId, action); + + if (dirty) + Dirty(actionId.Value, action); } private void OnActionsGetState(EntityUid uid, ActionsComponent component, ref ComponentGetState args) @@ -386,13 +424,12 @@ private void OnActionRequest(RequestPerformActionEvent ev, EntitySessionEventArg return; var curTime = GameTiming.CurTime; - // TODO: Check for charge recovery timer - if (action.Cooldown.HasValue && action.Cooldown.Value.End > curTime) + if (IsCooldownActive(action, curTime)) return; // TODO: Replace with individual charge recovery when we have the visuals to aid it if (action is { Charges: < 1, RenewCharges: true }) - ResetCharges(actionEnt); + ResetCharges(actionEnt, true, true); BaseActionEvent? performEvent = null; @@ -1072,4 +1109,19 @@ public void SetEntityIcon(EntityUid uid, EntityUid? icon, BaseActionComponent? a action.EntityIcon = icon; Dirty(uid, action); } + + /// + /// Checks if the action has a cooldown and if it's still active + /// + protected bool IsCooldownActive(BaseActionComponent action, TimeSpan? curTime = null) + { + curTime ??= GameTiming.CurTime; + // TODO: Check for charge recovery timer + return action.Cooldown.HasValue && action.Cooldown.Value.End > curTime; + } + + protected bool ShouldResetCharges(BaseActionComponent action) + { + return action is { Charges: < 1, RenewCharges: true }; + } } diff --git a/Content.Shared/VendingMachines/VendingMachineComponent.cs b/Content.Shared/VendingMachines/VendingMachineComponent.cs index a3c7949600a1..50023a023ab1 100644 --- a/Content.Shared/VendingMachines/VendingMachineComponent.cs +++ b/Content.Shared/VendingMachines/VendingMachineComponent.cs @@ -41,6 +41,7 @@ public sealed partial class VendingMachineComponent : Component [DataField, AutoNetworkedField] public Dictionary ContrabandInventory = new(); + [DataField, AutoNetworkedField] public bool Contraband; public bool Ejecting; diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a31711b81609..f010f4808bab 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,41 +1,4 @@ Entries: -- author: deepdarkdepths - changes: - - message: Removed the description about geras in the Slime guidebook section. - type: Remove - id: 6935 - time: '2024-07-19T09:04:43.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30140 -- author: Blackern5000 - changes: - - message: Nuclear operatives are now able to purchase durable armor which is NOT - space-proof. - type: Add - id: 6936 - time: '2024-07-19T09:38:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29845 -- author: Plykiya, slarticodefast - changes: - - message: Explosive pens now correctly embed into their target. - type: Fix - id: 6937 - time: '2024-07-19T09:42:58.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30112 -- author: ThatOneEnby1337 - changes: - - message: News Reporters are now able to use markup tags in their reports without - bricking the PDAs of readers - type: Fix - id: 6938 - time: '2024-07-19T14:18:39.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30169 -- author: themias - changes: - - message: Mailing units are functional again - type: Fix - id: 6939 - time: '2024-07-20T02:31:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30174 - author: Ghagliiarghii changes: - message: Nuclear Operatives' Reinforcements now have a PDA! @@ -3928,3 +3891,39 @@ id: 7434 time: '2024-09-24T21:58:46.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32343 +- author: goet + changes: + - message: Vending machines can be hacked again. + type: Fix + id: 7435 + time: '2024-09-25T05:21:24.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32431 +- author: themias + changes: + - message: Agent ID card can now only copy access within interaction range. + type: Fix + id: 7436 + time: '2024-09-25T15:41:34.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32445 +- author: Myra + changes: + - message: Silicon with no laws will not have binary channel access. + type: Remove + id: 7437 + time: '2024-09-25T16:49:43.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32385 +- author: august-sun + changes: + - message: Rolling pins are now craftable. + type: Tweak + id: 7438 + time: '2024-09-25T17:27:30.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32285 +- author: BramvanZijp + changes: + - message: Fixed an issue that caused Doctors Delight to metabolize twice the normal + speed, which also halved its effectiveness. + type: Fix + id: 7439 + time: '2024-09-25T17:39:49.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32297 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index aaf21345d89b..ff21ae7dbd0c 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -32,12 +32,8 @@ factions: - SimpleNeutral - type: IntrinsicRadioReceiver - - type: IntrinsicRadioTransmitter - channels: - - Binary - type: ActiveRadio channels: - - Binary - Common - type: HealthExaminable examinableTypes: @@ -418,6 +414,5 @@ - Bot - type: ActiveRadio channels: - - Binary - Common - Supply diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 4695f1c125d2..ff662c2186aa 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -44,12 +44,8 @@ stopSearchVerbPopup: pai-system-stopped-searching - type: Examiner - type: IntrinsicRadioReceiver - - type: IntrinsicRadioTransmitter - channels: - - Binary - type: ActiveRadio channels: - - Binary - Common - type: DoAfter - type: Actions diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index d985560ac2da..41d167352f29 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -514,3 +514,6 @@ - type: Tag tags: - RollingPin + - type: Construction + graph: WoodenRollingPin + node: rollingpin diff --git a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml index 99879cfbc945..e047614ac246 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml @@ -79,12 +79,8 @@ speechVerb: Robotic speechSounds: Vending - type: IntrinsicRadioReceiver - - type: IntrinsicRadioTransmitter - channels: - - Binary - type: ActiveRadio channels: - - Binary - Common - type: DoAfter - type: Electrified diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml index a1c20cb28315..96b9c173498c 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml @@ -875,8 +875,6 @@ - !type:AdjustReagent reagent: Ethanol amount: 0.05 - Medicine: - effects: - !type:HealthChange damage: groups: diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/rolling_pin.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/rolling_pin.yml new file mode 100644 index 000000000000..caa9ebbea91a --- /dev/null +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/rolling_pin.yml @@ -0,0 +1,15 @@ +- type: constructionGraph + id: WoodenRollingPin + start: start + graph: + - node: start + edges: + - to: rollingpin + steps: + - material: WoodPlank + amount: 2 + - material: MetalRod + amount: 1 + doAfter: 2 + - node: rollingpin + entity: RollingPin diff --git a/Resources/Prototypes/Recipes/Crafting/improvised.yml b/Resources/Prototypes/Recipes/Crafting/improvised.yml index 7dbac11b8887..ba3634822562 100644 --- a/Resources/Prototypes/Recipes/Crafting/improvised.yml +++ b/Resources/Prototypes/Recipes/Crafting/improvised.yml @@ -158,7 +158,7 @@ targetNode: shell category: construction-category-weapons objectType: Item - description: A homemade shotgun shell that shoots painful glass shrapnel. The spread is so wide that it couldn't hit the broad side of a Barn + description: A homemade shotgun shell that shoots painful glass shrapnel. The spread is so wide that it couldn't hit the broad side of a barn. icon: sprite: Objects/Weapons/Guns/Ammunition/Casings/shotgun_shell.rsi state: improvised @@ -254,6 +254,19 @@ sprite: Objects/Weapons/Bombs/pipebomb.rsi state: icon +- type: construction + name: rolling pin + id: rollingpin + graph: WoodenRollingPin + startNode: start + targetNode: rollingpin + category: construction-category-tools + objectType: Item + description: A rolling pin, used for cooking and defending the kitchen. + icon: + sprite: Objects/Tools/rolling_pin.rsi + state: icon + - type: construction name: yarn noodles id: yarnnoodles diff --git a/Resources/Textures/Clothing/Head/Helmets/bone_helmet.rsi/meta.json b/Resources/Textures/Clothing/Head/Helmets/bone_helmet.rsi/meta.json index bbb0aac66482..a470e0094432 100644 --- a/Resources/Textures/Clothing/Head/Helmets/bone_helmet.rsi/meta.json +++ b/Resources/Textures/Clothing/Head/Helmets/bone_helmet.rsi/meta.json @@ -20,7 +20,7 @@ }, { "name": "inhand-right", - "direction": 4 + "directions": 4 } ] }