You can now return to a brain. Also, clean up terrible console misuse. (#4092)
* You can now return to a brain. Also, clean up terrible console misuse. * Get rid of Obsolete attribute on Ghost.Execute
This commit is contained in:
@@ -7,6 +7,7 @@ using Content.Server.GameObjects.Components.GUI;
|
|||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.Interfaces.Chat;
|
using Content.Server.Interfaces.Chat;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
@@ -69,8 +70,10 @@ namespace Content.Server.Commands.Chat
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var chat = IoCManager.Resolve<IChatManager>();
|
var chat = IoCManager.Resolve<IChatManager>();
|
||||||
var owner = player.ContentData()?.Mind?.OwnedComponent?.Owner;
|
var mind = player.ContentData()?.Mind;
|
||||||
|
var owner = mind?.OwnedComponent?.Owner;
|
||||||
|
|
||||||
|
// This check also proves mind not-null for at the end when the mob is ghosted.
|
||||||
if (owner == null)
|
if (owner == null)
|
||||||
{
|
{
|
||||||
shell.WriteLine("You don't have a mind!");
|
shell.WriteLine("You don't have a mind!");
|
||||||
@@ -121,9 +124,9 @@ namespace Content.Server.Commands.Chat
|
|||||||
|
|
||||||
dmgComponent.SetDamage(DamageType.Piercing, 200, owner);
|
dmgComponent.SetDamage(DamageType.Piercing, 200, owner);
|
||||||
|
|
||||||
// Prevent the player from returning to the body. Yes, this is an ugly hack.
|
// Prevent the player from returning to the body.
|
||||||
var ghost = new Ghost(){CanReturn = false};
|
// Note that mind cannot be null because otherwise owner would be null.
|
||||||
ghost.Execute(shell, argStr, Array.Empty<string>());
|
IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind!, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Interfaces.GameTicking;
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Server.Players;
|
using Content.Server.Players;
|
||||||
@@ -14,7 +15,6 @@ namespace Content.Server.Commands.Observer
|
|||||||
public string Command => "ghost";
|
public string Command => "ghost";
|
||||||
public string Description => "Give up on life and become a ghost.";
|
public string Description => "Give up on life and become a ghost.";
|
||||||
public string Help => "ghost";
|
public string Help => "ghost";
|
||||||
public bool CanReturn { get; set; } = true;
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||||
{
|
{
|
||||||
@@ -32,7 +32,7 @@ namespace Content.Server.Commands.Observer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind, CanReturn))
|
if (!IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind, true))
|
||||||
{
|
{
|
||||||
shell?.WriteLine("You can't ghost right now.");
|
shell?.WriteLine("You can't ghost right now.");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Server.Commands.Observer;
|
using Content.Server.Commands.Observer;
|
||||||
using Content.Server.GameObjects.Components.Observer;
|
using Content.Server.GameObjects.Components.Observer;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.Components.Body.Part;
|
using Content.Shared.GameObjects.Components.Body.Part;
|
||||||
@@ -28,6 +30,7 @@ namespace Content.Server.GameObjects.Components.Body
|
|||||||
public class BodyComponent : SharedBodyComponent, IRelayMoveInput, IGhostOnMove
|
public class BodyComponent : SharedBodyComponent, IRelayMoveInput, IGhostOnMove
|
||||||
{
|
{
|
||||||
private Container _partContainer = default!;
|
private Container _partContainer = default!;
|
||||||
|
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||||
|
|
||||||
protected override bool CanAddPart(string slotId, IBodyPart part)
|
protected override bool CanAddPart(string slotId, IBodyPart part)
|
||||||
{
|
{
|
||||||
@@ -92,11 +95,11 @@ namespace Content.Server.GameObjects.Components.Body
|
|||||||
void IRelayMoveInput.MoveInputPressed(ICommonSession session)
|
void IRelayMoveInput.MoveInputPressed(ICommonSession session)
|
||||||
{
|
{
|
||||||
if (Owner.TryGetComponent(out IMobStateComponent? mobState) &&
|
if (Owner.TryGetComponent(out IMobStateComponent? mobState) &&
|
||||||
mobState.IsDead())
|
mobState.IsDead() &&
|
||||||
|
Owner.TryGetComponent(out MindComponent? mind) &&
|
||||||
|
mind.HasMind)
|
||||||
{
|
{
|
||||||
var host = IoCManager.Resolve<IServerConsoleHost>();
|
_gameTicker.OnGhostAttempt(mind.Mind!, true);
|
||||||
|
|
||||||
new Ghost().Execute(new ConsoleShell(host, session), string.Empty, Array.Empty<string>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using Content.Server.Commands.Observer;
|
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.Interfaces.GameTicking;
|
||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
using Robust.Server.Console;
|
using Robust.Server.Console;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
@@ -17,6 +17,7 @@ namespace Content.Server.GameObjects.Components.Observer
|
|||||||
public class GhostOnMoveComponent : Component, IRelayMoveInput, IGhostOnMove
|
public class GhostOnMoveComponent : Component, IRelayMoveInput, IGhostOnMove
|
||||||
{
|
{
|
||||||
public override string Name => "GhostOnMove";
|
public override string Name => "GhostOnMove";
|
||||||
|
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||||
|
|
||||||
[DataField("canReturn")] public bool CanReturn { get; set; } = true;
|
[DataField("canReturn")] public bool CanReturn { get; set; } = true;
|
||||||
|
|
||||||
@@ -26,8 +27,7 @@ namespace Content.Server.GameObjects.Components.Observer
|
|||||||
if (Owner.HasComponent<VisitingMindComponent>()) return;
|
if (Owner.HasComponent<VisitingMindComponent>()) return;
|
||||||
if (!Owner.TryGetComponent(out MindComponent? mind) || !mind.HasMind || mind.Mind!.IsVisitingEntity) return;
|
if (!Owner.TryGetComponent(out MindComponent? mind) || !mind.HasMind || mind.Mind!.IsVisitingEntity) return;
|
||||||
|
|
||||||
var host = IoCManager.Resolve<IServerConsoleHost>();
|
_gameTicker.OnGhostAttempt(mind.Mind!, CanReturn);
|
||||||
new Ghost().Execute(new ConsoleShell(host, session), string.Empty, Array.Empty<string>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,15 +48,19 @@ namespace Content.Server.GameTicking
|
|||||||
}
|
}
|
||||||
|
|
||||||
var position = playerEntity?.Transform.Coordinates ?? IoCManager.Resolve<IGameTicker>().GetObserverSpawnPoint();
|
var position = playerEntity?.Transform.Coordinates ?? IoCManager.Resolve<IGameTicker>().GetObserverSpawnPoint();
|
||||||
var canReturn = false;
|
// Ok, so, this is the master place for the logic for if ghosting is "too cheaty" to allow returning.
|
||||||
|
// There's no reason at this time to move it to any other place, especially given that the 'side effects required' situations would also have to be moved.
|
||||||
|
// + If CharacterDeadPhysically applies, we're physically dead. Therefore, ghosting OK, and we can return (this is critical for gibbing)
|
||||||
|
// Note that we could theoretically be ICly dead and still physically alive and vice versa.
|
||||||
|
// (For example, a zombie could be dead ICly, but may retain memories and is definitely physically active)
|
||||||
|
// + If we're in a mob that is critical, and we're supposed to be able to return if possible,
|
||||||
|
/// we're succumbing - the mob is killed. Therefore, character is dead. Ghosting OK.
|
||||||
|
// (If the mob survives, that's a bug. Ghosting is kept regardless.)
|
||||||
|
var canReturn = canReturnGlobal && mind.CharacterDeadPhysically;
|
||||||
|
|
||||||
if (playerEntity != null && canReturnGlobal && playerEntity.TryGetComponent(out IMobStateComponent? mobState))
|
if (playerEntity != null && canReturnGlobal && playerEntity.TryGetComponent(out IMobStateComponent? mobState))
|
||||||
{
|
{
|
||||||
if (mobState.IsDead())
|
if (mobState.IsCritical())
|
||||||
{
|
|
||||||
canReturn = true;
|
|
||||||
}
|
|
||||||
else if (mobState.IsCritical())
|
|
||||||
{
|
{
|
||||||
canReturn = true;
|
canReturn = true;
|
||||||
|
|
||||||
@@ -66,10 +70,6 @@ namespace Content.Server.GameTicking
|
|||||||
damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity);
|
damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
canReturn = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||||
|
|||||||
@@ -114,7 +114,13 @@ namespace Content.Server.Mobs
|
|||||||
/// (Maybe you were looking for the action blocker system?)
|
/// (Maybe you were looking for the action blocker system?)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool CharacterDeadIC
|
public bool CharacterDeadIC => CharacterDeadPhysically;
|
||||||
|
/// <summary>
|
||||||
|
/// True if the OwnedEntity of this mind is physically dead.
|
||||||
|
/// This specific definition, as opposed to CharacterDeadIC, is used to determine if ghosting should allow return.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public bool CharacterDeadPhysically
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user