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.Interfaces.Chat;
|
||||
using Content.Server.Interfaces.GameObjects;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Utility;
|
||||
using Content.Shared.Damage;
|
||||
@@ -69,8 +70,10 @@ namespace Content.Server.Commands.Chat
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
shell.WriteLine("You don't have a mind!");
|
||||
@@ -121,9 +124,9 @@ namespace Content.Server.Commands.Chat
|
||||
|
||||
dmgComponent.SetDamage(DamageType.Piercing, 200, owner);
|
||||
|
||||
// Prevent the player from returning to the body. Yes, this is an ugly hack.
|
||||
var ghost = new Ghost(){CanReturn = false};
|
||||
ghost.Execute(shell, argStr, Array.Empty<string>());
|
||||
// Prevent the player from returning to the body.
|
||||
// Note that mind cannot be null because otherwise owner would be null.
|
||||
IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind!, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Server.Players;
|
||||
@@ -14,7 +15,6 @@ namespace Content.Server.Commands.Observer
|
||||
public string Command => "ghost";
|
||||
public string Description => "Give up on life and become a ghost.";
|
||||
public string Help => "ghost";
|
||||
public bool CanReturn { get; set; } = true;
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace Content.Server.Commands.Observer
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind, CanReturn))
|
||||
if (!IoCManager.Resolve<IGameTicker>().OnGhostAttempt(mind, true))
|
||||
{
|
||||
shell?.WriteLine("You can't ghost right now.");
|
||||
return;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System;
|
||||
using Content.Server.Commands.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.GameObjects.Components.Body;
|
||||
using Content.Shared.GameObjects.Components.Body.Part;
|
||||
@@ -28,6 +30,7 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
public class BodyComponent : SharedBodyComponent, IRelayMoveInput, IGhostOnMove
|
||||
{
|
||||
private Container _partContainer = default!;
|
||||
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||
|
||||
protected override bool CanAddPart(string slotId, IBodyPart part)
|
||||
{
|
||||
@@ -92,11 +95,11 @@ namespace Content.Server.GameObjects.Components.Body
|
||||
void IRelayMoveInput.MoveInputPressed(ICommonSession session)
|
||||
{
|
||||
if (Owner.TryGetComponent(out IMobStateComponent? mobState) &&
|
||||
mobState.IsDead())
|
||||
mobState.IsDead() &&
|
||||
Owner.TryGetComponent(out MindComponent? mind) &&
|
||||
mind.HasMind)
|
||||
{
|
||||
var host = IoCManager.Resolve<IServerConsoleHost>();
|
||||
|
||||
new Ghost().Execute(new ConsoleShell(host, session), string.Empty, Array.Empty<string>());
|
||||
_gameTicker.OnGhostAttempt(mind.Mind!, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Content.Server.Commands.Observer;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.Interfaces.GameTicking;
|
||||
using Content.Shared.GameObjects.Components.Movement;
|
||||
using Robust.Server.Console;
|
||||
using Robust.Shared.Console;
|
||||
@@ -17,6 +17,7 @@ namespace Content.Server.GameObjects.Components.Observer
|
||||
public class GhostOnMoveComponent : Component, IRelayMoveInput, IGhostOnMove
|
||||
{
|
||||
public override string Name => "GhostOnMove";
|
||||
[Dependency] private readonly IGameTicker _gameTicker = default!;
|
||||
|
||||
[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.TryGetComponent(out MindComponent? mind) || !mind.HasMind || mind.Mind!.IsVisitingEntity) return;
|
||||
|
||||
var host = IoCManager.Resolve<IServerConsoleHost>();
|
||||
new Ghost().Execute(new ConsoleShell(host, session), string.Empty, Array.Empty<string>());
|
||||
_gameTicker.OnGhostAttempt(mind.Mind!, CanReturn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,19 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
|
||||
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 (mobState.IsDead())
|
||||
{
|
||||
canReturn = true;
|
||||
}
|
||||
else if (mobState.IsCritical())
|
||||
if (mobState.IsCritical())
|
||||
{
|
||||
canReturn = true;
|
||||
|
||||
@@ -66,10 +70,6 @@ namespace Content.Server.GameTicking
|
||||
damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
canReturn = false;
|
||||
}
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
@@ -114,7 +114,13 @@ namespace Content.Server.Mobs
|
||||
/// (Maybe you were looking for the action blocker system?)
|
||||
/// </summary>
|
||||
[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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user