Revert "Gamerule Entities" (#15724)
This commit is contained in:
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Preferences.Managers;
|
||||
using Content.Server.Spawners.Components;
|
||||
using Content.Server.Station.Components;
|
||||
@@ -26,7 +25,7 @@ namespace Content.Server.GameTicking.Rules;
|
||||
/// <summary>
|
||||
/// This handles the Pirates minor antag, which is designed to coincide with other modes on occasion.
|
||||
/// </summary>
|
||||
public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
||||
public sealed class PiratesRuleSystem : GameRuleSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
@@ -40,6 +39,17 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
||||
[Dependency] private readonly MapLoaderSystem _map = default!;
|
||||
[Dependency] private readonly NamingSystem _namingSystem = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private List<Mind.Mind> _pirates = new();
|
||||
[ViewVariables]
|
||||
private EntityUid _pirateShip = EntityUid.Invalid;
|
||||
[ViewVariables]
|
||||
private HashSet<EntityUid> _initialItems = new();
|
||||
[ViewVariables]
|
||||
private double _initialShipValue;
|
||||
|
||||
public override string Prototype => "Pirates";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -47,186 +57,178 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
||||
|
||||
SubscribeLocalEvent<RulePlayerSpawningEvent>(OnPlayerSpawningEvent);
|
||||
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndTextEvent);
|
||||
SubscribeLocalEvent<RoundStartAttemptEvent>(OnStartAttempt);
|
||||
}
|
||||
|
||||
private void OnRoundEndTextEvent(RoundEndTextAppendEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<PiratesRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var pirates, out var gameRule))
|
||||
if (!RuleAdded)
|
||||
return;
|
||||
|
||||
if (Deleted(_pirateShip))
|
||||
{
|
||||
if (Deleted(pirates.PirateShip))
|
||||
// Major loss, the ship somehow got annihilated.
|
||||
ev.AddLine(Loc.GetString("pirates-no-ship"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
List<(double, EntityUid)> mostValuableThefts = new();
|
||||
|
||||
var finalValue = _pricingSystem.AppraiseGrid(_pirateShip, uid =>
|
||||
{
|
||||
// Major loss, the ship somehow got annihilated.
|
||||
ev.AddLine(Loc.GetString("pirates-no-ship"));
|
||||
}
|
||||
else
|
||||
foreach (var mind in _pirates)
|
||||
{
|
||||
if (mind.CurrentEntity == uid)
|
||||
return false; // Don't appraise the pirates twice, we count them in separately.
|
||||
}
|
||||
return true;
|
||||
}, (uid, price) =>
|
||||
{
|
||||
if (_initialItems.Contains(uid))
|
||||
return;
|
||||
|
||||
List<(double, EntityUid)> mostValuableThefts = new();
|
||||
mostValuableThefts.Add((price, uid));
|
||||
mostValuableThefts.Sort((i1, i2) => i2.Item1.CompareTo(i1.Item1));
|
||||
if (mostValuableThefts.Count > 5)
|
||||
mostValuableThefts.Pop();
|
||||
});
|
||||
|
||||
var comp1 = pirates;
|
||||
var finalValue = _pricingSystem.AppraiseGrid(pirates.PirateShip, uid =>
|
||||
{
|
||||
foreach (var mind in comp1.Pirates)
|
||||
{
|
||||
if (mind.CurrentEntity == uid)
|
||||
return false; // Don't appraise the pirates twice, we count them in separately.
|
||||
}
|
||||
|
||||
return true;
|
||||
}, (uid, price) =>
|
||||
{
|
||||
if (comp1.InitialItems.Contains(uid))
|
||||
return;
|
||||
|
||||
mostValuableThefts.Add((price, uid));
|
||||
mostValuableThefts.Sort((i1, i2) => i2.Item1.CompareTo(i1.Item1));
|
||||
if (mostValuableThefts.Count > 5)
|
||||
mostValuableThefts.Pop();
|
||||
});
|
||||
|
||||
foreach (var mind in pirates.Pirates)
|
||||
{
|
||||
if (mind.CurrentEntity is not null)
|
||||
finalValue += _pricingSystem.GetPrice(mind.CurrentEntity.Value);
|
||||
}
|
||||
|
||||
var score = finalValue - pirates.InitialShipValue;
|
||||
|
||||
ev.AddLine(Loc.GetString("pirates-final-score", ("score", $"{score:F2}")));
|
||||
ev.AddLine(Loc.GetString("pirates-final-score-2", ("finalPrice", $"{finalValue:F2}")));
|
||||
|
||||
ev.AddLine("");
|
||||
ev.AddLine(Loc.GetString("pirates-most-valuable"));
|
||||
|
||||
foreach (var (price, obj) in mostValuableThefts)
|
||||
{
|
||||
ev.AddLine(Loc.GetString("pirates-stolen-item-entry", ("entity", obj), ("credits", $"{price:F2}")));
|
||||
}
|
||||
|
||||
if (mostValuableThefts.Count == 0)
|
||||
ev.AddLine(Loc.GetString("pirates-stole-nothing"));
|
||||
foreach (var mind in _pirates)
|
||||
{
|
||||
if (mind.CurrentEntity is not null)
|
||||
finalValue += _pricingSystem.GetPrice(mind.CurrentEntity.Value);
|
||||
}
|
||||
|
||||
var score = finalValue - _initialShipValue;
|
||||
|
||||
ev.AddLine(Loc.GetString("pirates-final-score", ("score", $"{score:F2}")));
|
||||
ev.AddLine(Loc.GetString("pirates-final-score-2", ("finalPrice", $"{finalValue:F2}")));
|
||||
|
||||
ev.AddLine("");
|
||||
ev.AddLine(Loc.GetString("pirates-list-start"));
|
||||
foreach (var pirate in pirates.Pirates)
|
||||
ev.AddLine(Loc.GetString("pirates-most-valuable"));
|
||||
|
||||
foreach (var (price, obj) in mostValuableThefts)
|
||||
{
|
||||
ev.AddLine($"- {pirate.CharacterName} ({pirate.Session?.Name})");
|
||||
ev.AddLine(Loc.GetString("pirates-stolen-item-entry", ("entity", obj), ("credits", $"{price:F2}")));
|
||||
}
|
||||
|
||||
if (mostValuableThefts.Count == 0)
|
||||
ev.AddLine(Loc.GetString("pirates-stole-nothing"));
|
||||
}
|
||||
|
||||
ev.AddLine("");
|
||||
ev.AddLine(Loc.GetString("pirates-list-start"));
|
||||
foreach (var pirates in _pirates)
|
||||
{
|
||||
ev.AddLine($"- {pirates.CharacterName} ({pirates.Session?.Name})");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Started() { }
|
||||
|
||||
public override void Ended() { }
|
||||
|
||||
private void OnPlayerSpawningEvent(RulePlayerSpawningEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<PiratesRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var pirates, out var gameRule))
|
||||
// Forgive me for copy-pasting nukies.
|
||||
if (!RuleAdded)
|
||||
{
|
||||
// Forgive me for copy-pasting nukies.
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
return;
|
||||
|
||||
pirates.Pirates.Clear();
|
||||
pirates.InitialItems.Clear();
|
||||
|
||||
// Between 1 and <max pirate count>: needs at least n players per op.
|
||||
var numOps = Math.Max(1,
|
||||
(int) Math.Min(
|
||||
Math.Floor((double) ev.PlayerPool.Count / _cfg.GetCVar(CCVars.PiratesPlayersPerOp)),
|
||||
_cfg.GetCVar(CCVars.PiratesMaxOps)));
|
||||
var ops = new IPlayerSession[numOps];
|
||||
for (var i = 0; i < numOps; i++)
|
||||
{
|
||||
ops[i] = _random.PickAndTake(ev.PlayerPool);
|
||||
}
|
||||
|
||||
var map = "/Maps/Shuttles/pirate.yml";
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
|
||||
var aabbs = _stationSystem.Stations.SelectMany(x =>
|
||||
Comp<StationDataComponent>(x).Grids.Select(x =>
|
||||
xformQuery.GetComponent(x).WorldMatrix.TransformBox(_mapManager.GetGridComp(x).LocalAABB)))
|
||||
.ToArray();
|
||||
|
||||
var aabb = aabbs[0];
|
||||
|
||||
for (var i = 1; i < aabbs.Length; i++)
|
||||
{
|
||||
aabb.Union(aabbs[i]);
|
||||
}
|
||||
|
||||
var gridId = _map.LoadGrid(GameTicker.DefaultMap, map, new MapLoadOptions
|
||||
{
|
||||
Offset = aabb.Center + MathF.Max(aabb.Height / 2f, aabb.Width / 2f) * 2.5f
|
||||
});
|
||||
|
||||
if (!gridId.HasValue)
|
||||
{
|
||||
Logger.ErrorS("pirates", $"Gridid was null when loading \"{map}\", aborting.");
|
||||
foreach (var session in ops)
|
||||
{
|
||||
ev.PlayerPool.Add(session);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pirates.PirateShip = gridId.Value;
|
||||
|
||||
// TODO: Loot table or something
|
||||
var pirateGear = _prototypeManager.Index<StartingGearPrototype>("PirateGear"); // YARRR
|
||||
|
||||
var spawns = new List<EntityCoordinates>();
|
||||
|
||||
// Forgive me for hardcoding prototypes
|
||||
foreach (var (_, meta, xform) in
|
||||
EntityQuery<SpawnPointComponent, MetaDataComponent, TransformComponent>(true))
|
||||
{
|
||||
if (meta.EntityPrototype?.ID != "SpawnPointPirates" || xform.ParentUid != pirates.PirateShip)
|
||||
continue;
|
||||
|
||||
spawns.Add(xform.Coordinates);
|
||||
}
|
||||
|
||||
if (spawns.Count == 0)
|
||||
{
|
||||
spawns.Add(Transform(pirates.PirateShip).Coordinates);
|
||||
Logger.WarningS("pirates", $"Fell back to default spawn for pirates!");
|
||||
}
|
||||
|
||||
for (var i = 0; i < ops.Length; i++)
|
||||
{
|
||||
var sex = _random.Prob(0.5f) ? Sex.Male : Sex.Female;
|
||||
var gender = sex == Sex.Male ? Gender.Male : Gender.Female;
|
||||
|
||||
var name = _namingSystem.GetName("Human", gender);
|
||||
|
||||
var session = ops[i];
|
||||
var newMind = new Mind.Mind(session.UserId)
|
||||
{
|
||||
CharacterName = name
|
||||
};
|
||||
newMind.ChangeOwningPlayer(session.UserId);
|
||||
|
||||
var mob = Spawn("MobHuman", _random.Pick(spawns));
|
||||
MetaData(mob).EntityName = name;
|
||||
|
||||
newMind.TransferTo(mob);
|
||||
var profile = _prefs.GetPreferences(session.UserId).SelectedCharacter as HumanoidCharacterProfile;
|
||||
_stationSpawningSystem.EquipStartingGear(mob, pirateGear, profile);
|
||||
|
||||
pirates.Pirates.Add(newMind);
|
||||
|
||||
GameTicker.PlayerJoinGame(session);
|
||||
}
|
||||
|
||||
pirates.InitialShipValue = _pricingSystem.AppraiseGrid(pirates.PirateShip, uid =>
|
||||
{
|
||||
pirates.InitialItems.Add(uid);
|
||||
return true;
|
||||
}); // Include the players in the appraisal.
|
||||
return;
|
||||
}
|
||||
|
||||
_pirates.Clear();
|
||||
_initialItems.Clear();
|
||||
|
||||
// Between 1 and <max pirate count>: needs at least n players per op.
|
||||
var numOps = Math.Max(1,
|
||||
(int)Math.Min(
|
||||
Math.Floor((double)ev.PlayerPool.Count / _cfg.GetCVar(CCVars.PiratesPlayersPerOp)), _cfg.GetCVar(CCVars.PiratesMaxOps)));
|
||||
var ops = new IPlayerSession[numOps];
|
||||
for (var i = 0; i < numOps; i++)
|
||||
{
|
||||
ops[i] = _random.PickAndTake(ev.PlayerPool);
|
||||
}
|
||||
|
||||
var map = "/Maps/Shuttles/pirate.yml";
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
|
||||
var aabbs = _stationSystem.Stations.SelectMany(x =>
|
||||
Comp<StationDataComponent>(x).Grids.Select(x => xformQuery.GetComponent(x).WorldMatrix.TransformBox(_mapManager.GetGridComp(x).LocalAABB))).ToArray();
|
||||
|
||||
var aabb = aabbs[0];
|
||||
|
||||
for (var i = 1; i < aabbs.Length; i++)
|
||||
{
|
||||
aabb.Union(aabbs[i]);
|
||||
}
|
||||
|
||||
var gridId = _map.LoadGrid(GameTicker.DefaultMap, map, new MapLoadOptions
|
||||
{
|
||||
Offset = aabb.Center + MathF.Max(aabb.Height / 2f, aabb.Width / 2f) * 2.5f
|
||||
});
|
||||
|
||||
if (!gridId.HasValue)
|
||||
{
|
||||
Logger.ErrorS("pirates", $"Gridid was null when loading \"{map}\", aborting.");
|
||||
foreach (var session in ops)
|
||||
{
|
||||
ev.PlayerPool.Add(session);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_pirateShip = gridId.Value;
|
||||
|
||||
// TODO: Loot table or something
|
||||
var pirateGear = _prototypeManager.Index<StartingGearPrototype>("PirateGear"); // YARRR
|
||||
|
||||
var spawns = new List<EntityCoordinates>();
|
||||
|
||||
// Forgive me for hardcoding prototypes
|
||||
foreach (var (_, meta, xform) in EntityQuery<SpawnPointComponent, MetaDataComponent, TransformComponent>(true))
|
||||
{
|
||||
if (meta.EntityPrototype?.ID != "SpawnPointPirates" || xform.ParentUid != _pirateShip) continue;
|
||||
|
||||
spawns.Add(xform.Coordinates);
|
||||
}
|
||||
|
||||
if (spawns.Count == 0)
|
||||
{
|
||||
spawns.Add(Transform(_pirateShip).Coordinates);
|
||||
Logger.WarningS("pirates", $"Fell back to default spawn for pirates!");
|
||||
}
|
||||
|
||||
for (var i = 0; i < ops.Length; i++)
|
||||
{
|
||||
var sex = _random.Prob(0.5f) ? Sex.Male : Sex.Female;
|
||||
var gender = sex == Sex.Male ? Gender.Male : Gender.Female;
|
||||
|
||||
var name = _namingSystem.GetName("Human", gender);
|
||||
|
||||
var session = ops[i];
|
||||
var newMind = new Mind.Mind(session.UserId)
|
||||
{
|
||||
CharacterName = name
|
||||
};
|
||||
newMind.ChangeOwningPlayer(session.UserId);
|
||||
|
||||
var mob = Spawn("MobHuman", _random.Pick(spawns));
|
||||
MetaData(mob).EntityName = name;
|
||||
|
||||
newMind.TransferTo(mob);
|
||||
var profile = _prefs.GetPreferences(session.UserId).SelectedCharacter as HumanoidCharacterProfile;
|
||||
_stationSpawningSystem.EquipStartingGear(mob, pirateGear, profile);
|
||||
|
||||
_pirates.Add(newMind);
|
||||
|
||||
GameTicker.PlayerJoinGame(session);
|
||||
}
|
||||
|
||||
_initialShipValue = _pricingSystem.AppraiseGrid(_pirateShip, uid =>
|
||||
{
|
||||
_initialItems.Add(uid);
|
||||
return true;
|
||||
}); // Include the players in the appraisal.
|
||||
}
|
||||
|
||||
//Forcing one player to be a pirate.
|
||||
@@ -239,26 +241,21 @@ public sealed class PiratesRuleSystem : GameRuleSystem<PiratesRuleComponent>
|
||||
|
||||
private void OnStartAttempt(RoundStartAttemptEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<PiratesRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var pirates, out var gameRule))
|
||||
if (!RuleAdded)
|
||||
return;
|
||||
|
||||
var minPlayers = _cfg.GetCVar(CCVars.PiratesMinPlayers);
|
||||
if (!ev.Forced && ev.Players.Length < minPlayers)
|
||||
{
|
||||
if (!GameTicker.IsGameRuleActive(uid, gameRule))
|
||||
return;
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("nukeops-not-enough-ready-players", ("readyPlayersCount", ev.Players.Length), ("minimumPlayers", minPlayers)));
|
||||
ev.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
var minPlayers = _cfg.GetCVar(CCVars.PiratesMinPlayers);
|
||||
if (!ev.Forced && ev.Players.Length < minPlayers)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("nukeops-not-enough-ready-players",
|
||||
("readyPlayersCount", ev.Players.Length), ("minimumPlayers", minPlayers)));
|
||||
ev.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.Players.Length == 0)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("nukeops-no-one-ready"));
|
||||
ev.Cancel();
|
||||
}
|
||||
if (ev.Players.Length == 0)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("nukeops-no-one-ready"));
|
||||
ev.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user