+++ /dev/null
-using Content.Client.ContextMenu.UI;
-using Content.Client.Verbs;
-using Content.Shared.CombatMode;
-using Content.Shared.Targeting;
-using Robust.Client.Player;
-using Robust.Client.UserInterface;
-
-namespace Content.Client.CombatMode
-{
- [RegisterComponent]
- [ComponentReference(typeof(SharedCombatModeComponent))]
- public sealed class CombatModeComponent : SharedCombatModeComponent
- {
- [Dependency] private readonly IPlayerManager _playerManager = default!;
-
- public override bool IsInCombatMode
- {
- get => base.IsInCombatMode;
- set
- {
- base.IsInCombatMode = value;
- UpdateHud();
- }
- }
-
- public override TargetingZone ActiveZone
- {
- get => base.ActiveZone;
- set
- {
- base.ActiveZone = value;
- UpdateHud();
- }
- }
-
- private void UpdateHud()
- {
- if (Owner != _playerManager.LocalPlayer?.ControlledEntity)
- {
- return;
- }
-
- IoCManager.Resolve<IUserInterfaceManager>().GetUIController<ContextMenuUIController>().Close();
- }
- }
-}
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
+ public event Action? LocalPlayerCombatModeUpdated;
+
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<SharedCombatModeComponent, ComponentHandleState>(OnHandleState);
+ SubscribeLocalEvent<CombatModeComponent, ComponentHandleState>(OnHandleState);
}
- private void OnHandleState(EntityUid uid, SharedCombatModeComponent component, ref ComponentHandleState args)
+ private void OnHandleState(EntityUid uid, CombatModeComponent component, ref ComponentHandleState args)
{
if (args.Current is not CombatModeComponentState state)
return;
component.IsInCombatMode = state.IsInCombatMode;
component.ActiveZone = state.TargetingZone;
+ UpdateHud(uid);
}
+
public override void Shutdown()
{
CommandBinds.Unregister<CombatModeSystem>();
base.Shutdown();
}
+ private void OnTargetingZoneChanged(TargetingZone obj)
+ {
+ EntityManager.RaisePredictiveEvent(new CombatModeSystemMessages.SetTargetZoneMessage(obj));
+ }
+
public bool IsInCombatMode()
{
var entity = _playerManager.LocalPlayer?.ControlledEntity;
return IsInCombatMode(entity.Value);
}
- private void OnTargetingZoneChanged(TargetingZone obj)
+ public override void SetInCombatMode(EntityUid entity, bool inCombatMode, CombatModeComponent? component = null)
{
- EntityManager.RaisePredictiveEvent(new CombatModeSystemMessages.SetTargetZoneMessage(obj));
+ base.SetInCombatMode(entity, inCombatMode, component);
+ UpdateHud(entity);
+ }
+
+ public override void SetActiveZone(EntityUid entity, TargetingZone zone, CombatModeComponent? component = null)
+ {
+ base.SetActiveZone(entity, zone, component);
+ UpdateHud(entity);
+ }
+
+ private void UpdateHud(EntityUid entity)
+ {
+ if (entity != _playerManager.LocalPlayer?.ControlledEntity)
+ {
+ return;
+ }
+
+ LocalPlayerCombatModeUpdated?.Invoke();
}
}
}
using System.Threading;
+using Content.Client.CombatMode;
using Content.Client.Gameplay;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;
using Timer = Robust.Shared.Timing.Timer;
+
namespace Content.Client.ContextMenu.UI
{
/// <summary>
/// <remarks>
/// This largely involves setting up timers to open and close sub-menus when hovering over other menu elements.
/// </remarks>
- public sealed class ContextMenuUIController : UIController, IOnStateEntered<GameplayState>, IOnStateExited<GameplayState>
+ public sealed class ContextMenuUIController : UIController, IOnStateEntered<GameplayState>, IOnStateExited<GameplayState>, IOnSystemChanged<CombatModeSystem>
{
public static readonly TimeSpan HoverDelay = TimeSpan.FromSeconds(0.2);
menu.InvalidateMeasure();
}
+
+ private void OnCombatModeUpdated()
+ {
+ Close();
+ }
+
+ public void OnSystemLoaded(CombatModeSystem system)
+ {
+ system.LocalPlayerCombatModeUpdated += OnCombatModeUpdated;
+ }
+
+ public void OnSystemUnloaded(CombatModeSystem system)
+ {
+ system.LocalPlayerCombatModeUpdated -= OnCombatModeUpdated;
+ }
}
}
-using Content.Client.CombatMode;
using Content.Client.Gameplay;
+using Content.Shared.CombatMode;
using Content.Shared.Hands.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.StatusEffect;
+++ /dev/null
-using Content.Shared.CombatMode;
-
-namespace Content.Server.CombatMode
-{
- /// <summary>
- /// Stores whether an entity is in "combat mode"
- /// This is used to differentiate between regular item interactions or
- /// using *everything* as a weapon.
- /// </summary>
- [RegisterComponent]
- [ComponentReference(typeof(SharedCombatModeComponent))]
- public sealed class CombatModeComponent : SharedCombatModeComponent
- {
- }
-}
{
base.Initialize();
- SubscribeLocalEvent<SharedCombatModeComponent, ComponentGetState>(OnGetState);
+ SubscribeLocalEvent<CombatModeComponent, ComponentGetState>(OnGetState);
}
- private void OnGetState(EntityUid uid, SharedCombatModeComponent component, ref ComponentGetState args)
+ private void OnGetState(EntityUid uid, CombatModeComponent component, ref ComponentGetState args)
{
args.State = new CombatModeComponentState(component.IsInCombatMode, component.ActiveZone);
}
-using Content.Server.CombatMode;
using Content.Server.NPC.Components;
using Content.Server.NPC.Events;
+using Content.Shared.CombatMode;
using Content.Shared.NPC;
using Content.Shared.Weapons.Melee;
using Robust.Shared.Map;
{
if (TryComp<CombatModeComponent>(uid, out var combatMode))
{
- combatMode.IsInCombatMode = false;
+ _combat.SetInCombatMode(uid, false, combatMode);
}
_steering.Unregister(component.Owner);
{
if (TryComp<CombatModeComponent>(uid, out var combatMode))
{
- combatMode.IsInCombatMode = true;
+ _combat.SetInCombatMode(uid, true, combatMode);
}
// TODO: Cleanup later, just looking for parity for now.
public sealed partial class NPCCombatSystem
{
+ [Dependency] private readonly SharedCombatModeSystem _combat = default!;
[Dependency] private readonly RotateToFaceSystem _rotate = default!;
// TODO: Don't predict for hitscan
private void OnRangedStartup(EntityUid uid, NPCRangedCombatComponent component, ComponentStartup args)
{
- if (TryComp<SharedCombatModeComponent>(uid, out var combat))
+ if (TryComp<CombatModeComponent>(uid, out var combat))
{
- combat.IsInCombatMode = true;
+ _combat.SetInCombatMode(uid, true, combat);
}
else
{
private void OnRangedShutdown(EntityUid uid, NPCRangedCombatComponent component, ComponentShutdown args)
{
- if (TryComp<SharedCombatModeComponent>(uid, out var combat))
+ if (TryComp<CombatModeComponent>(uid, out var combat))
{
- combat.IsInCombatMode = false;
+ _combat.SetInCombatMode(uid, false, combat);
}
}
{
var bodyQuery = GetEntityQuery<PhysicsComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
- var combatQuery = GetEntityQuery<SharedCombatModeComponent>();
+ var combatQuery = GetEntityQuery<CombatModeComponent>();
var query = EntityQueryEnumerator<NPCRangedCombatComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var comp, out var xform))
if (combatQuery.TryGetComponent(uid, out var combatMode))
{
- combatMode.IsInCombatMode = true;
+ _combat.SetInCombatMode(uid, true, combatMode);
}
if (!_gun.TryGetGun(uid, out var gunUid, out var gun))
-using Content.Server.CombatMode;
using Content.Server.Destructible;
using Content.Server.NPC.Components;
using Content.Server.NPC.Pathfinding;
+using Content.Shared.CombatMode;
using Content.Shared.Doors.Components;
using Content.Shared.NPC;
using Robust.Shared.Physics;
{
if (_melee.TryGetWeapon(uid, out var meleeUid, out var meleeWeapon) && meleeWeapon.NextAttack <= _timing.CurTime && TryComp<CombatModeComponent>(uid, out var combatMode))
{
- combatMode.IsInCombatMode = true;
+ _combat.SetInCombatMode(uid, true, combatMode);
var destructibleQuery = GetEntityQuery<DestructibleComponent>();
// TODO: This is a hack around grilles and windows.
}
}
- combatMode.IsInCombatMode = false;
+ _combat.SetInCombatMode(uid, false, combatMode);
if (obstacleEnts.Count == 0)
return SteeringObstacleStatus.Completed;
using Content.Server.NPC.Events;
using Content.Server.NPC.Pathfinding;
using Content.Shared.CCVar;
+using Content.Shared.CombatMode;
using Content.Shared.Interaction;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Systems;
[Dependency] private readonly SharedMoverController _mover = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedCombatModeSystem _combat = default!;
/// <summary>
/// Enabled antistuck detection so if an NPC is in the same spot for a while it will re-path.
{
base.StartOpeningStripper(user, component, openInCombat);
- if (TryComp<SharedCombatModeComponent>(user, out var mode) && mode.IsInCombatMode && !openInCombat)
+ if (TryComp<CombatModeComponent>(user, out var mode) && mode.IsInCombatMode && !openInCombat)
return;
if (TryComp<ActorComponent>(user, out var actor))
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.EntitySystems;
-using Content.Server.CombatMode;
using Content.Server.CombatMode.Disarm;
using Content.Server.Contests;
using Content.Server.Examine;
RaiseNetworkEvent(new DamageEffectEvent(Color.Red, targets), filter);
}
- private float CalculateDisarmChance(EntityUid disarmer, EntityUid disarmed, EntityUid? inTargetHand, SharedCombatModeComponent disarmerComp)
+ private float CalculateDisarmChance(EntityUid disarmer, EntityUid disarmed, EntityUid? inTargetHand, CombatModeComponent disarmerComp)
{
if (HasComp<DisarmProneComponent>(disarmer))
return 1.0f;
using Content.Server.Chat;
using Content.Server.Chat.Managers;
using Content.Server.Chat.Systems;
-using Content.Server.CombatMode;
using Content.Server.Disease.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Humanoid;
using Content.Server.Speech.Components;
using Content.Server.Temperature.Components;
using Content.Server.Traitor;
+using Content.Shared.CombatMode;
using Content.Shared.Damage;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
[Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!;
+ [Dependency] private readonly SharedCombatModeSystem _combat = default!;
[Dependency] private readonly IChatManager _chatMan = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
//in an attempt to make an entity not attack. This is the easiest way to do it.
RemComp<CombatModeComponent>(target);
var combat = AddComp<CombatModeComponent>(target);
- combat.IsInCombatMode = true;
+ _combat.SetInCombatMode(target, true, combat);
//This is the actual damage of the zombie. We assign the visual appearance
//and range here because of stuff we'll find out later
using Content.Shared.Actions;
using Content.Shared.Actions.ActionTypes;
using Content.Shared.Targeting;
-using Content.Shared.Verbs;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-using Robust.Shared.Utility;
namespace Content.Shared.CombatMode
{
- [NetworkedComponent()]
- public abstract class SharedCombatModeComponent : Component
+ /// <summary>
+ /// Stores whether an entity is in "combat mode"
+ /// This is used to differentiate between regular item interactions or
+ /// using *everything* as a weapon.
+ /// </summary>
+ [RegisterComponent, NetworkedComponent]
+ [Access(typeof(SharedCombatModeSystem))]
+ public sealed class CombatModeComponent : Component
{
#region Disarm
public InstantAction? CombatToggleAction;
[ViewVariables(VVAccess.ReadWrite)]
- public virtual bool IsInCombatMode
+ public bool IsInCombatMode
{
get => _isInCombatMode;
set
}
[ViewVariables(VVAccess.ReadWrite)]
- public virtual TargetingZone ActiveZone
+ public TargetingZone ActiveZone
{
get => _activeZone;
set
public sealed class PacificationSystem : EntitySystem
{
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
+ [Dependency] private readonly SharedCombatModeSystem _combatSystem = default!;
public override void Initialize()
{
private void OnStartup(EntityUid uid, PacifiedComponent component, ComponentStartup args)
{
- if (!TryComp<SharedCombatModeComponent>(uid, out var combatMode))
+ if (!TryComp<CombatModeComponent>(uid, out var combatMode))
return;
if (combatMode.CanDisarm != null)
- combatMode.CanDisarm = false;
+ _combatSystem.SetCanDisarm(uid, false, combatMode);
- combatMode.IsInCombatMode = false;
+ _combatSystem.SetInCombatMode(uid, false, combatMode);
if (combatMode.CombatToggleAction != null)
{
private void OnShutdown(EntityUid uid, PacifiedComponent component, ComponentShutdown args)
{
- if (!TryComp<SharedCombatModeComponent>(uid, out var combatMode))
+ if (!TryComp<CombatModeComponent>(uid, out var combatMode))
return;
if (combatMode.CanDisarm != null)
- combatMode.CanDisarm = true;
+ _combatSystem.SetCanDisarm(uid, true, combatMode);
if (combatMode.CombatToggleAction != null)
_actionsSystem.SetEnabled(combatMode.CombatToggleAction, true);
{
base.Initialize();
- SubscribeLocalEvent<SharedCombatModeComponent, ComponentStartup>(OnStartup);
- SubscribeLocalEvent<SharedCombatModeComponent, ComponentShutdown>(OnShutdown);
- SubscribeLocalEvent<SharedCombatModeComponent, ToggleCombatActionEvent>(OnActionPerform);
+ SubscribeLocalEvent<CombatModeComponent, ComponentStartup>(OnStartup);
+ SubscribeLocalEvent<CombatModeComponent, ComponentShutdown>(OnShutdown);
+ SubscribeLocalEvent<CombatModeComponent, ToggleCombatActionEvent>(OnActionPerform);
}
- private void OnStartup(EntityUid uid, SharedCombatModeComponent component, ComponentStartup args)
+ private void OnStartup(EntityUid uid, CombatModeComponent component, ComponentStartup args)
{
if (component.CombatToggleAction == null
&& _protoMan.TryIndex(component.CombatToggleActionId, out InstantActionPrototype? toggleProto))
_actionsSystem.AddAction(uid, component.CombatToggleAction, null);
}
- private void OnShutdown(EntityUid uid, SharedCombatModeComponent component, ComponentShutdown args)
+ private void OnShutdown(EntityUid uid, CombatModeComponent component, ComponentShutdown args)
{
if (component.CombatToggleAction != null)
_actionsSystem.RemoveAction(uid, component.CombatToggleAction);
}
- public bool IsInCombatMode(EntityUid? entity, SharedCombatModeComponent? component = null)
+ private void OnActionPerform(EntityUid uid, CombatModeComponent component, ToggleCombatActionEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ SetInCombatMode(uid, !component.IsInCombatMode, component);
+ args.Handled = true;
+ }
+
+ public void SetCanDisarm(EntityUid entity, bool canDisarm, CombatModeComponent? component = null)
+ {
+ if (!Resolve(entity, ref component))
+ return;
+
+ component.CanDisarm = canDisarm;
+ }
+
+ public bool IsInCombatMode(EntityUid? entity, CombatModeComponent? component = null)
{
return entity != null && Resolve(entity.Value, ref component, false) && component.IsInCombatMode;
}
- private void OnActionPerform(EntityUid uid, SharedCombatModeComponent component, ToggleCombatActionEvent args)
+ public virtual void SetInCombatMode(EntityUid entity, bool inCombatMode,
+ CombatModeComponent? component = null)
{
- if (args.Handled)
+ if (!Resolve(entity, ref component))
return;
- component.IsInCombatMode = !component.IsInCombatMode;
- args.Handled = true;
+ component.IsInCombatMode = inCombatMode;
+ }
+
+ public virtual void SetActiveZone(EntityUid entity, TargetingZone zone,
+ CombatModeComponent? component = null)
+ {
+ if (!Resolve(entity, ref component))
+ return;
+
+ component.ActiveZone = zone;
}
[Serializable, NetSerializable]
if (target != null && Deleted(target.Value))
return;
- if (!altInteract && TryComp(user, out SharedCombatModeComponent? combatMode) && combatMode.IsInCombatMode)
+ if (!altInteract && TryComp(user, out CombatModeComponent? combatMode) && combatMode.IsInCombatMode)
{
// Eat the input
return;
description: Nice to have, but you can't build a civilization on a foundation of honey alone.
components:
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MovementSpeedModifier
baseWalkSpeed : 7
baseSprintSpeed : 7
description: How nice a bee. Oh no, it looks angry and wants my pizza.
components:
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MeleeWeapon
hidden: true
angle: 0
description: A large marsupial herbivore. It has powerful hind legs and... boxing gloves?
components:
- type: CombatMode
- disarm: null
- type: Sprite
drawdepth: Mobs
layers:
description: New church of neo-darwinists actually believe that EVERY animal evolved from a monkey. Tastes like pork, and killing them is both fun and relaxing.
components:
- type: CombatMode
- disarm: null
- type: NameIdentifier
group: Monkey
- type: SentienceTarget
enabled: false
autoPopulate: false
name: action-name-combat
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: Bloodstream
bloodMaxVolume: 50
- type: DiseaseCarrier #The other class lab animal and disease vector
- id: FoodMeatSpider
amount: 2
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MobThresholds
thresholds:
0: Alive
types:
Blunt: 0.1
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MeleeWeapon
hidden: true
soundHit:
bloodMaxVolume: 300
bloodReagent: Cryoxadone
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: Temperature
heatDamageThreshold: 500
coldDamageThreshold: 0
- map: [ "enum.DamageStateVisualLayers.Base" ]
state: base
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: Physics
- type: Fixtures
fixtures:
- type: Bloodstream
bloodMaxVolume: 100
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MeleeWeapon
hidden: true
soundHit:
- type: Bloodstream
bloodMaxVolume: 50
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MeleeWeapon
hidden: true
soundHit:
- type: DiseaseProtection
protection: 1
- type: CombatMode
- disarm: null
- type: InputMover
- type: MobMover
- type: HTN
- Dragon
- type: Speech
- type: CombatMode
- disarmAction:
- enabled: false
- autoPopulate: false
- name: action-name-disarm
- type: MobMover
- type: InputMover
- type: MovementSpeedModifier
id: MobDwarf
components:
- type: CombatMode
- disarm: null
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic
id: MobHuman
components:
- type: CombatMode
- disarm: null
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic
id: MobReptilian
components:
- type: CombatMode
- disarm: null
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic
id: MobSlimePerson
components:
- type: CombatMode
- disarm: null
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic
id: MobVox
components:
- type: CombatMode
- disarm: null
- type: InteractionPopup
successChance: 1
interactSuccessString: hugging-success-generic