Merge remote-tracking branch 'upstream/master' into 20-10-30-admins
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using Content.Server.Commands;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Robust.Server.Interfaces.Console;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Players;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedAlertsComponent))]
|
||||
public sealed class ServerAlertsComponent : SharedAlertsComponent
|
||||
{
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
if (EntitySystem.TryGet<WeightlessSystem>(out var weightlessSystem))
|
||||
{
|
||||
weightlessSystem.AddAlert(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WarningS("alert", "weightlesssystem not found");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
if (EntitySystem.TryGet<WeightlessSystem>(out var weightlessSystem))
|
||||
{
|
||||
weightlessSystem.RemoveAlert(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WarningS("alert", "weightlesssystem not found");
|
||||
}
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new AlertsComponentState(CreateAlertStatesArray());
|
||||
}
|
||||
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||
{
|
||||
base.HandleNetworkMessage(message, netChannel, session);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(session));
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case ClickAlertMessage msg:
|
||||
{
|
||||
var player = session.AttachedEntity;
|
||||
|
||||
if (player != Owner)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Implement clicking other status effects in the HUD
|
||||
if (AlertManager.TryDecode(msg.EncodedAlert, out var alert))
|
||||
{
|
||||
PerformAlertClickCallback(alert, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WarningS("alert", "unrecognized encoded alert {0}", msg.EncodedAlert);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ShowAlert : IClientCommand
|
||||
{
|
||||
public string Command => "showalert";
|
||||
public string Description => "Shows an alert for a player, defaulting to current player";
|
||||
public string Help => "showalert <alertType> <severity, -1 if no severity> <name or userID, omit for current player>";
|
||||
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
|
||||
{
|
||||
var attachedEntity = player.AttachedEntity;
|
||||
if (args.Length > 2)
|
||||
{
|
||||
var target = args[2];
|
||||
if (!Commands.CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return;
|
||||
}
|
||||
|
||||
if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return;
|
||||
|
||||
|
||||
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent))
|
||||
{
|
||||
shell.SendText(player, "user has no alerts component");
|
||||
return;
|
||||
}
|
||||
|
||||
var alertType = args[0];
|
||||
var severity = args[1];
|
||||
var alertMgr = IoCManager.Resolve<AlertManager>();
|
||||
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
|
||||
{
|
||||
shell.SendText(player, "unrecognized alertType " + alertType);
|
||||
return;
|
||||
}
|
||||
if (!short.TryParse(severity, out var sevint))
|
||||
{
|
||||
shell.SendText(player, "invalid severity " + sevint);
|
||||
return;
|
||||
}
|
||||
alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ClearAlert : IClientCommand
|
||||
{
|
||||
public string Command => "clearalert";
|
||||
public string Description => "Clears an alert for a player, defaulting to current player";
|
||||
public string Help => "clearalert <alertType> <name or userID, omit for current player>";
|
||||
|
||||
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args)
|
||||
{
|
||||
var attachedEntity = player.AttachedEntity;
|
||||
if (args.Length > 1)
|
||||
{
|
||||
var target = args[1];
|
||||
if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return;
|
||||
}
|
||||
|
||||
if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return;
|
||||
|
||||
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent))
|
||||
{
|
||||
shell.SendText(player, "user has no alerts component");
|
||||
return;
|
||||
}
|
||||
|
||||
var alertType = args[0];
|
||||
var alertMgr = IoCManager.Resolve<AlertManager>();
|
||||
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
|
||||
{
|
||||
shell.SendText(player, "unrecognized alertType " + alertType);
|
||||
return;
|
||||
}
|
||||
|
||||
alertsComponent.ClearAlert(alert.AlertType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.Atmos;
|
||||
using Content.Server.GameObjects.Components.Buckle;
|
||||
using Content.Server.GameObjects.Components.Movement;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Pulling;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Mobs
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(SharedStatusEffectsComponent))]
|
||||
public sealed class ServerStatusEffectsComponent : SharedStatusEffectsComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<StatusEffect, StatusEffectStatus> _statusEffects = new Dictionary<StatusEffect, StatusEffectStatus>();
|
||||
|
||||
public override IReadOnlyDictionary<StatusEffect, StatusEffectStatus> Statuses => _statusEffects;
|
||||
|
||||
protected override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
EntitySystem.Get<WeightlessSystem>().AddStatus(this);
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
EntitySystem.Get<WeightlessSystem>().RemoveStatus(this);
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new StatusEffectComponentState(_statusEffects);
|
||||
}
|
||||
|
||||
public override void ChangeStatusEffectIcon(StatusEffect effect, string icon)
|
||||
{
|
||||
if (_statusEffects.TryGetValue(effect, out var value) && value.Icon == icon)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_statusEffects[effect] = new StatusEffectStatus()
|
||||
{Icon = icon, Cooldown = value.Cooldown};
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public void ChangeStatusEffectCooldown(StatusEffect effect, ValueTuple<TimeSpan, TimeSpan> cooldown)
|
||||
{
|
||||
if (_statusEffects.TryGetValue(effect, out var value)
|
||||
&& value.Cooldown == cooldown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_statusEffects[effect] = new StatusEffectStatus()
|
||||
{
|
||||
Icon = value.Icon, Cooldown = cooldown
|
||||
};
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public override void ChangeStatusEffect(StatusEffect effect, string icon, ValueTuple<TimeSpan, TimeSpan>? cooldown)
|
||||
{
|
||||
_statusEffects[effect] = new StatusEffectStatus()
|
||||
{Icon = icon, Cooldown = cooldown};
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public override void RemoveStatusEffect(StatusEffect effect)
|
||||
{
|
||||
if (!_statusEffects.Remove(effect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dirty();
|
||||
}
|
||||
|
||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||
{
|
||||
base.HandleNetworkMessage(message, netChannel, session);
|
||||
|
||||
if (session == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(session));
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case ClickStatusMessage msg:
|
||||
{
|
||||
var player = session.AttachedEntity;
|
||||
|
||||
if (player != Owner)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Implement clicking other status effects in the HUD
|
||||
switch (msg.Effect)
|
||||
{
|
||||
case StatusEffect.Buckled:
|
||||
if (!player.TryGetComponent(out BuckleComponent buckle))
|
||||
break;
|
||||
|
||||
buckle.TryUnbuckle(player);
|
||||
break;
|
||||
case StatusEffect.Piloting:
|
||||
if (!player.TryGetComponent(out ShuttleControllerComponent controller))
|
||||
break;
|
||||
|
||||
controller.RemoveController();
|
||||
break;
|
||||
case StatusEffect.Pulling:
|
||||
EntitySystem
|
||||
.Get<SharedPullingSystem>()
|
||||
.GetPulled(player)?
|
||||
.GetComponentOrNull<SharedPullableComponent>()?
|
||||
.TryStopPull();
|
||||
|
||||
break;
|
||||
case StatusEffect.Fire:
|
||||
if (!player.TryGetComponent(out FlammableComponent flammable))
|
||||
break;
|
||||
|
||||
flammable.Resist();
|
||||
break;
|
||||
default:
|
||||
player.PopupMessage(msg.Effect.ToString());
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
@@ -17,10 +18,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
appearance.SetData(DamageStateVisuals.State, DamageState.Critical);
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||
if (entity.TryGetComponent(out ServerAlertsComponent status))
|
||||
{
|
||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||
"/Textures/Interface/StatusEffects/Human/humancrit-0.png"); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it
|
||||
status.ShowAlert(AlertType.HumanCrit); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
@@ -18,10 +19,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
appearance.SetData(DamageStateVisuals.State, DamageState.Dead);
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||
if (entity.TryGetComponent(out ServerAlertsComponent status))
|
||||
{
|
||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||
"/Textures/Interface/StatusEffects/Human/humandead.png");
|
||||
status.ShowAlert(AlertType.HumanDead);
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayComponent))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
@@ -51,9 +52,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
// TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used
|
||||
base.OnRemove();
|
||||
|
||||
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||
if (Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||
{
|
||||
status.RemoveStatusEffect(StatusEffect.Health);
|
||||
status.ClearAlert(AlertType.HumanHealth);
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.GameObjects.Components.Damage;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Mobs.State;
|
||||
@@ -27,15 +28,14 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
|
||||
public override void UpdateState(IEntity entity)
|
||||
{
|
||||
if (!entity.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||
if (!entity.TryGetComponent(out ServerAlertsComponent status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entity.TryGetComponent(out IDamageableComponent damageable))
|
||||
{
|
||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||
"/Textures/Interface/StatusEffects/Human/human0.png");
|
||||
status.ShowAlert(AlertType.HumanHealth, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,10 +49,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
return;
|
||||
}
|
||||
|
||||
var modifier = (int) (ruinable.TotalDamage / (threshold / 7f));
|
||||
var modifier = (short) (ruinable.TotalDamage / (threshold / 7f));
|
||||
|
||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
||||
status.ShowAlert(AlertType.HumanHealth, modifier);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -63,10 +62,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State
|
||||
return;
|
||||
}
|
||||
|
||||
var modifier = (int) (damageable.TotalDamage / (threshold / 7f));
|
||||
var modifier = (short) (damageable.TotalDamage / (threshold / 7f));
|
||||
|
||||
status.ChangeStatusEffectIcon(StatusEffect.Health,
|
||||
"/Textures/Interface/StatusEffects/Human/human" + modifier + ".png");
|
||||
status.ShowAlert(AlertType.HumanHealth, modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
@@ -89,7 +90,7 @@ namespace Content.Server.GameObjects.Components.Mobs
|
||||
}
|
||||
|
||||
if (!StunStart.HasValue || !StunEnd.HasValue ||
|
||||
!Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||
!Owner.TryGetComponent(out ServerAlertsComponent status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -102,7 +103,7 @@ namespace Content.Server.GameObjects.Components.Mobs
|
||||
|
||||
if (progress >= length)
|
||||
{
|
||||
Owner.SpawnTimer(250, () => status.RemoveStatusEffect(StatusEffect.Stun), StatusRemoveCancellation.Token);
|
||||
Owner.SpawnTimer(250, () => status.ClearAlert(AlertType.Stun), StatusRemoveCancellation.Token);
|
||||
LastStun = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user