Revert "Refactor Damage to use Protoypes (#4262)"

This reverts commit 20bf5739a9.
This commit is contained in:
Silver
2021-08-24 00:50:39 -06:00
committed by Silver
parent 20bf5739a9
commit e708091518
121 changed files with 711 additions and 10237 deletions

View File

@@ -1,94 +0,0 @@
#nullable enable annotations
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Observer;
using Content.Server.Interfaces.GameTicking;
using Content.Server.Mobs;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.Preferences;
using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Network;
namespace Content.Server.GameTicking
{
/// <summary>
/// A round-start setup preset, such as which antagonists to spawn.
/// </summary>
public abstract class GamePreset
{
public abstract bool Start(IReadOnlyList<IPlayerSession> readyPlayers, bool force = false);
public virtual string ModeTitle => "Sandbox";
public virtual string Description => "Secret!";
public virtual bool DisallowLateJoin => false;
public Dictionary<NetUserId, HumanoidCharacterProfile> ReadyProfiles = new();
public virtual void OnGameStarted() { }
/// <summary>
/// Called when a player is spawned in (this includes, but is not limited to, before Start)
/// </summary>
public virtual void OnSpawnPlayerCompleted(IPlayerSession session, IEntity mob, bool lateJoin) { }
/// <summary>
/// Called when a player attempts to ghost.
/// </summary>
public virtual bool OnGhostAttempt(Mind mind, bool canReturnGlobal)
{
var playerEntity = mind.OwnedEntity;
if (playerEntity != null && playerEntity.HasComponent<GhostComponent>())
return false;
if (mind.VisitingEntity != null)
{
mind.UnVisit();
}
var position = playerEntity?.Transform.Coordinates ?? IoCManager.Resolve<IGameTicker>().GetObserverSpawnPoint();
var canReturn = false;
if (playerEntity != null && canReturnGlobal && playerEntity.TryGetComponent(out IMobStateComponent? mobState))
{
if (mobState.IsDead())
{
canReturn = true;
}
else if (mobState.IsCritical())
{
canReturn = true;
if (playerEntity.TryGetComponent(out IDamageableComponent? damageable))
{
//todo: what if they dont breathe lol
//cry deeply
damageable.SetDamage(damageable.GetDamageType("Asphyxiation"), 200, playerEntity);
}
}
else
{
canReturn = false;
}
}
var entityManager = IoCManager.Resolve<IEntityManager>();
var ghost = entityManager.SpawnEntity("MobObserver", position);
ghost.Name = mind.CharacterName ?? string.Empty;
var ghostComponent = ghost.GetComponent<GhostComponent>();
ghostComponent.CanReturnToBody = canReturn;
if (canReturn)
mind.Visit(ghost);
else
mind.TransferTo(ghost);
return true;
}
public virtual string GetRoundEndDescription() => "";
}
}

View File

@@ -1,233 +0,0 @@
using System;
using System.Collections.Generic;
using Content.Server.Atmos;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Markers;
using Content.Server.GameObjects.Components.PDA;
using Content.Server.GameObjects.Components.TraitorDeathMatch;
using Content.Server.GameTicking.GameRules;
using Content.Server.Interfaces.Chat;
using Content.Server.Interfaces.GameTicking;
using Content.Server.Mobs;
using Content.Server.Mobs.Roles.Traitor;
using Content.Server.Players;
using Content.Shared;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.Components.PDA;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Random;
namespace Content.Server.GameTicking.GamePresets
{
[GamePreset("traitordm", "traitordeathmatch")]
public sealed class PresetTraitorDeathMatch : GamePreset
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IGameTicker _gameTicker = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
public string PDAPrototypeName => "CaptainPDA";
public string BeltPrototypeName => "ClothingBeltJanitorFilled";
public string BackpackPrototypeName => "ClothingBackpackFilled";
private RuleMaxTimeRestart _restarter = default!;
private bool _safeToEndRound = false;
private Dictionary<UplinkAccount, string> _allOriginalNames = new();
public override bool Start(IReadOnlyList<IPlayerSession> readyPlayers, bool force = false)
{
_gameTicker.AddGameRule<RuleTraitorDeathMatch>();
_restarter = _gameTicker.AddGameRule<RuleMaxTimeRestart>();
_restarter.RoundMaxTime = TimeSpan.FromMinutes(30);
_restarter.RestartTimer();
_safeToEndRound = true;
return true;
}
public override void OnSpawnPlayerCompleted(IPlayerSession session, IEntity mob, bool lateJoin)
{
var startingBalance = _cfg.GetCVar(CCVars.TraitorDeathMatchStartingBalance);
// Yup, they're a traitor
var mind = session.Data.ContentData()?.Mind;
if (mind == null)
{
Logger.ErrorS("preset", "Failed getting mind for TDM player.");
return;
}
var traitorRole = new TraitorRole(mind);
mind.AddRole(traitorRole);
// Delete anything that may contain "dangerous" role-specific items.
// (This includes the PDA, as everybody gets the captain PDA in this mode for true-all-access reasons.)
if (mind.OwnedEntity != null && mind.OwnedEntity.TryGetComponent(out InventoryComponent? inventory))
{
var victimSlots = new[] {EquipmentSlotDefines.Slots.IDCARD, EquipmentSlotDefines.Slots.BELT, EquipmentSlotDefines.Slots.BACKPACK};
foreach (var slot in victimSlots)
{
if (inventory.TryGetSlotItem(slot, out ItemComponent? vItem))
vItem.Owner.Delete();
}
// Replace their items:
// pda
var newPDA = _entityManager.SpawnEntity(PDAPrototypeName, mind.OwnedEntity.Transform.Coordinates);
inventory.Equip(EquipmentSlotDefines.Slots.IDCARD, newPDA.GetComponent<ItemComponent>());
// belt
var newTmp = _entityManager.SpawnEntity(BeltPrototypeName, mind.OwnedEntity.Transform.Coordinates);
inventory.Equip(EquipmentSlotDefines.Slots.BELT, newTmp.GetComponent<ItemComponent>());
// backpack
newTmp = _entityManager.SpawnEntity(BackpackPrototypeName, mind.OwnedEntity.Transform.Coordinates);
inventory.Equip(EquipmentSlotDefines.Slots.BACKPACK, newTmp.GetComponent<ItemComponent>());
// Like normal traitors, they need access to a traitor account.
var uplinkAccount = new UplinkAccount(mind.OwnedEntity.Uid, startingBalance);
var pdaComponent = newPDA.GetComponent<PDAComponent>();
pdaComponent.InitUplinkAccount(uplinkAccount);
_allOriginalNames[uplinkAccount] = mind.OwnedEntity.Name;
// The PDA needs to be marked with the correct owner.
pdaComponent.SetPDAOwner(mind.OwnedEntity.Name);
newPDA.AddComponent<TraitorDeathMatchReliableOwnerTagComponent>().UserId = mind.UserId;
}
// Finally, it would be preferrable if they spawned as far away from other players as reasonably possible.
if (mind.OwnedEntity != null && FindAnyIsolatedSpawnLocation(mind, out var bestTarget))
{
mind.OwnedEntity.Transform.Coordinates = bestTarget;
}
else
{
// The station is too drained of air to safely continue.
if (_safeToEndRound)
{
_chatManager.DispatchServerAnnouncement(Loc.GetString("The station is too unsafe to continue. You have one minute."));
_restarter.RoundMaxTime = TimeSpan.FromMinutes(1);
_restarter.RestartTimer();
_safeToEndRound = false;
}
}
}
// It would be nice if this function were moved to some generic helpers class.
private bool FindAnyIsolatedSpawnLocation(Mind ignoreMe, out EntityCoordinates bestTarget)
{
// Collate people to avoid...
var existingPlayerPoints = new List<EntityCoordinates>();
foreach (var player in _playerManager.GetAllPlayers())
{
var avoidMeMind = player.Data.ContentData()?.Mind;
if ((avoidMeMind == null) || (avoidMeMind == ignoreMe))
continue;
var avoidMeEntity = avoidMeMind.OwnedEntity;
if (avoidMeEntity == null)
continue;
if (avoidMeEntity.TryGetComponent(out IMobStateComponent? mobState))
{
// Does have mob state component; if critical or dead, they don't really matter for spawn checks
if (mobState.IsCritical() || mobState.IsDead())
continue;
}
else
{
// Doesn't have mob state component. Assume something interesting is going on and don't count this as someone to avoid.
continue;
}
existingPlayerPoints.Add(avoidMeEntity.Transform.Coordinates);
}
// Iterate over each possible spawn point, comparing to the existing player points.
// On failure, the returned target is the location that we're already at.
var bestTargetDistanceFromNearest = -1.0f;
// Need the random shuffle or it stuffs the first person into Atmospherics pretty reliably
var ents = new List<IEntity>(_entityManager.GetEntities(new TypeEntityQuery(typeof(SpawnPointComponent))));
_robustRandom.Shuffle(ents);
var foundATarget = false;
bestTarget = EntityCoordinates.Invalid;
foreach (var entity in ents)
{
if (!entity.Transform.Coordinates.IsTileAirProbablySafe())
continue;
var distanceFromNearest = float.PositiveInfinity;
foreach (var existing in existingPlayerPoints)
{
if (entity.Transform.Coordinates.TryDistance(_entityManager, existing, out var dist))
distanceFromNearest = Math.Min(distanceFromNearest, dist);
}
if (bestTargetDistanceFromNearest < distanceFromNearest)
{
bestTarget = entity.Transform.Coordinates;
bestTargetDistanceFromNearest = distanceFromNearest;
foundATarget = true;
}
}
return foundATarget;
}
public override bool OnGhostAttempt(Mind mind, bool canReturnGlobal)
{
var entity = mind.OwnedEntity;
if ((entity != null) && (entity.TryGetComponent(out IMobStateComponent? mobState)))
{
if (mobState.IsCritical())
{
// TODO: This is copy/pasted from ghost code. Really, IDamagableComponent needs a method to reliably kill the target.
if (entity.TryGetComponent(out IDamageableComponent? damageable))
{
//todo: what if they dont breathe lol
damageable.ChangeDamage(damageable.GetDamageType("Asphyxiation"), 100, true);
}
}
else if (!mobState.IsDead())
{
if (entity.HasComponent<HandsComponent>())
{
return false;
}
}
}
var session = mind.Session;
if (session == null)
return false;
_gameTicker.Respawn(session);
return true;
}
public override string GetRoundEndDescription()
{
var lines = new List<string>();
lines.Add("The PDAs recovered afterwards...");
foreach (var entity in _entityManager.GetEntities(new TypeEntityQuery(typeof(PDAComponent))))
{
var pda = entity.GetComponent<PDAComponent>();
var uplink = pda.SyndicateUplinkAccount;
if ((uplink != null) && _allOriginalNames.ContainsKey(uplink))
{
lines.Add(Loc.GetString("{0}'s PDA, with {1} TC", _allOriginalNames[uplink], uplink.Balance));
}
}
return string.Join('\n', lines);
}
public override string ModeTitle => "Traitor Deathmatch";
public override string Description => Loc.GetString("Everyone's a traitor. Everyone wants each other dead.");
}
}

View File

@@ -10,7 +10,6 @@ using Robust.Server.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
namespace Content.Server.GameTicking.Presets
{
@@ -67,17 +66,7 @@ namespace Content.Server.GameTicking.Presets
if (playerEntity.TryGetComponent(out IDamageableComponent? damageable))
{
//todo: what if they dont breathe lol
<<<<<<< HEAD
<<<<<<< refs/remotes/origin/master
damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity);
=======
//cry deeply
damageable.TrySetDamage(IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("Asphyxiation"), 200);
>>>>>>> Refactor damageablecomponent update (#4406)
=======
//cry deeply
damageable.TrySetDamage(IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("Asphyxiation"), 200);
>>>>>>> refactor-damageablecomponent
}
}
}

View File

@@ -23,7 +23,6 @@ using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Map;
@@ -39,7 +38,6 @@ namespace Content.Server.GameTicking.Presets
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string PDAPrototypeName => "CaptainPDA";
public string BeltPrototypeName => "ClothingBeltJanitorFilled";
@@ -194,19 +192,11 @@ namespace Content.Server.GameTicking.Presets
{
if (mobState.IsCritical())
{
// TODO: This is copy/pasted from ghost code. Really, IDamageableComponent needs a method to reliably kill the target.
// TODO: This is copy/pasted from ghost code. Really, IDamagableComponent needs a method to reliably kill the target.
if (entity.TryGetComponent(out IDamageableComponent? damageable))
{
//todo: what if they dont breathe lol
<<<<<<< HEAD
<<<<<<< refs/remotes/origin/master
damageable.ChangeDamage(DamageType.Asphyxiation, 100, true);
=======
damageable.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>("Asphyxiation"), 100, true);
>>>>>>> Refactor damageablecomponent update (#4406)
=======
damageable.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>("Asphyxiation"), 100, true);
>>>>>>> refactor-damageablecomponent
}
}
else if (!mobState.IsDead())