From 3ee1f1f810691c713d637731f47921c88a6c2307 Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> Date: Tue, 26 Apr 2022 16:57:24 +0200 Subject: [PATCH] Suspicion rework (#7723) * Deprecate suspicion spawn markers. * Add suspicion loot table. * Add suspicion item tag component. * Suspicion rule now spawns items randomly around the station on start. Also cleans them up when it ends. * Fix build huh, that API changed quickly-- --- .../GameTicking/Rules/SuspicionRuleSystem.cs | 76 ++++++- .../Suspicion/SuspicionItemComponent.cs | 9 + .../Spawners/Conditional/suspicion.yml | 20 ++ .../LootTables/suspicion_loot_table.yml | 211 ++++++++++++++++++ 4 files changed, 304 insertions(+), 12 deletions(-) create mode 100644 Content.Server/Suspicion/SuspicionItemComponent.cs create mode 100644 Resources/Prototypes/LootTables/suspicion_loot_table.yml diff --git a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs index cf939eb755..c4261eb9c7 100644 --- a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs @@ -1,18 +1,20 @@ -using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using Content.Server.Chat.Managers; using Content.Server.Players; using Content.Server.Roles; +using Content.Server.Station; using Content.Server.Suspicion; using Content.Server.Suspicion.Roles; using Content.Server.Traitor.Uplink; using Content.Server.Traitor.Uplink.Account; using Content.Shared.CCVar; using Content.Shared.Doors.Systems; +using Content.Shared.EntityList; using Content.Shared.GameTicking; +using Content.Shared.Maps; using Content.Shared.MobState.Components; +using Content.Shared.Random.Helpers; using Content.Shared.Roles; using Content.Shared.Sound; using Content.Shared.Suspicion; @@ -22,15 +24,10 @@ using Robust.Server.Player; using Robust.Shared.Audio; using Robust.Shared.Configuration; using Robust.Shared.Enums; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Localization; -using Robust.Shared.Log; -using Robust.Shared.Maths; +using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Timing; using Robust.Shared.Utility; using Timer = Robust.Shared.Timing.Timer; @@ -42,14 +39,16 @@ namespace Content.Server.GameTicking.Rules; /// public sealed class SuspicionRuleSystem : GameRuleSystem { + [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefMan = default!; [Dependency] private readonly SharedDoorSystem _doorSystem = default!; + [Dependency] private readonly EntityLookupSystem _lookupSystem = default!; public override string Prototype => "Suspicion"; @@ -79,6 +78,7 @@ public sealed class SuspicionRuleSystem : GameRuleSystem private const string TraitorID = "SuspicionTraitor"; private const string InnocentID = "SuspicionInnocent"; + private const string SuspicionLootTable = "SuspicionRule"; public override void Initialize() { @@ -140,8 +140,9 @@ public sealed class SuspicionRuleSystem : GameRuleSystem attached.EnsureComponent(); } + // Max is players-1 so there's always at least one innocent. var numTraitors = MathHelper.Clamp(ev.Players.Length / playersPerTraitor, - minTraitors, ev.Players.Length); + minTraitors, ev.Players.Length-1); var traitors = new List(); @@ -219,6 +220,51 @@ public sealed class SuspicionRuleSystem : GameRuleSystem _doorSystem.AccessType = SharedDoorSystem.AccessTypes.AllowAllNoExternal; + var susLoot = _prototypeManager.Index(SuspicionLootTable); + + foreach (var (_, mapGrid) in EntityManager.EntityQuery(true)) + { + // I'm so sorry. + var tiles = mapGrid.Grid.GetAllTiles().ToArray(); + Logger.Info($"TILES: {tiles.Length}"); + + var spawn = susLoot.GetSpawns(); + var count = spawn.Count; + + // Try to scale spawned amount by station size... + if (tiles.Length < 1000) + { + count = Math.Min(count, tiles.Length / 10); + + // Shuffle so we pick items at random. + _random.Shuffle(spawn); + } + + for (var i = 0; i < count; i++) + { + var item = spawn[i]; + + // Maximum number of attempts for trying to find a suitable empty tile. + // We do this because we don't want to hang the server when a devious map has literally no free tiles. + const int maxTries = 100; + + for (var j = 0; j < maxTries; j++) + { + var tile = _random.Pick(tiles); + + // Let's not spawn things on top of walls. + if (tile.IsBlockedTurf(false, _lookupSystem) || tile.IsSpace(_tileDefMan)) + continue; + + var uid = Spawn(item, tile.GridPosition(_mapManager)); + + // Keep track of all suspicion-spawned weapons so we can clean them up once the rule ends. + EnsureComp(uid); + break; + } + } + } + _checkTimerCancel = new CancellationTokenSource(); Timer.SpawnRepeating(DeadCheckDelay, CheckWinConditions, _checkTimerCancel.Token); } @@ -231,6 +277,12 @@ public sealed class SuspicionRuleSystem : GameRuleSystem _playerManager.PlayerStatusChanged -= PlayerManagerOnPlayerStatusChanged; + // Clean up all items we spawned before... + foreach (var item in EntityManager.EntityQuery(true)) + { + Del(item.Owner); + } + _checkTimerCancel.Cancel(); } @@ -245,8 +297,8 @@ public sealed class SuspicionRuleSystem : GameRuleSystem foreach (var playerSession in _playerManager.ServerSessions) { if (playerSession.AttachedEntity is not {Valid: true} playerEntity - || !_entities.TryGetComponent(playerEntity, out MobStateComponent? mobState) - || !_entities.HasComponent(playerEntity)) + || !TryComp(playerEntity, out MobStateComponent? mobState) + || !HasComp(playerEntity)) { continue; } diff --git a/Content.Server/Suspicion/SuspicionItemComponent.cs b/Content.Server/Suspicion/SuspicionItemComponent.cs new file mode 100644 index 0000000000..cca978d25f --- /dev/null +++ b/Content.Server/Suspicion/SuspicionItemComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Suspicion; + +/// +/// Tag component meant for bookkeeping items spawned by the suspicion rule. +/// +[RegisterComponent] +public sealed class SuspicionItemComponent : Component +{ +} diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Conditional/suspicion.yml b/Resources/Prototypes/Entities/Markers/Spawners/Conditional/suspicion.yml index 61a9e44b68..c0f9519f6e 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Conditional/suspicion.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Conditional/suspicion.yml @@ -1,7 +1,13 @@ +# -- WARNING -- +# These spawners are all deprecated. +# Please edit the suspicion loot table instead. Thanks. +# -- WARNING -- + - type: entity name: Suspicion Rifle Spawner id: SuspicionRifleSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -25,6 +31,7 @@ name: Suspicion Pistol Spawner id: SuspicionPistolSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -51,6 +58,7 @@ name: Suspicion Melee Spawner id: SuspicionMeleeSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -72,6 +80,7 @@ name: Suspicion Revolver Spawner id: SuspicionRevolverSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -90,6 +99,7 @@ name: Suspicion Shotgun Spawner id: SuspicionShotgunSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -112,6 +122,7 @@ name: Suspicion SMG Spawner id: SuspicionSMGSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -132,6 +143,7 @@ name: Suspicion Sniper Spawner id: SuspicionSniperSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -150,6 +162,7 @@ name: Suspicion Hitscan Spawner id: SuspicionHitscanSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -172,6 +185,7 @@ name: Suspicion Launchers Spawner id: SuspicionLaunchersSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -189,6 +203,7 @@ name: Suspicion Grenades Spawner id: SuspicionGrenadesSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -212,6 +227,7 @@ name: Suspicion Rifle Ammo Spawner id: SuspicionRifleMagazineSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -233,6 +249,7 @@ name: Suspicion Shotgun Ammo Spawner id: SuspicionShotgunMagazineSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -249,6 +266,7 @@ name: Suspicion Pistol Ammo Spawner id: SuspicionPistolMagazineSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -266,6 +284,7 @@ name: Suspicion Magnum Ammo Spawner id: SuspicionMagnumMagazineSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: @@ -283,6 +302,7 @@ name: Suspicion Launcher Ammo Spawner id: SuspicionLauncherAmmoSpawner parent: MarkerBase + noSpawn: true components: - type: Sprite layers: diff --git a/Resources/Prototypes/LootTables/suspicion_loot_table.yml b/Resources/Prototypes/LootTables/suspicion_loot_table.yml new file mode 100644 index 0000000000..2c40f90e92 --- /dev/null +++ b/Resources/Prototypes/LootTables/suspicion_loot_table.yml @@ -0,0 +1,211 @@ +# These will be spawned randomly around the station +- type: entityLootTable + id: SuspicionRule + entries: + - id: RifleAk + amount: 0 + maxAmount: 5 + - id: RifleBlackAk + amount: 0 + maxAmount: 5 + - id: RifleCarbine + amount: 0 + maxAmount: 5 + - id: RifleDallas + amount: 0 + maxAmount: 5 + - id: RifleSTS + amount: 0 + maxAmount: 5 + - id: RifleVintorez + amount: 0 + maxAmount: 5 + - id: RifleWintermute + amount: 0 + maxAmount: 5 + - id: RifleCalico + amount: 0 + maxAmount: 5 + + - id: PistolClarissa + amount: 0 + maxAmount: 5 + - id: PistolColt + amount: 0 + maxAmount: 5 + - id: PistolGiskard + amount: 0 + maxAmount: 5 + - id: PistolHMPistol + amount: 0 + maxAmount: 5 + - id: PistolLamia + amount: 0 + maxAmount: 5 + - id: PistolMandella + amount: 0 + maxAmount: 5 + - id: PistolMk58 + amount: 0 + maxAmount: 5 + - id: PistolMk58Wood + amount: 0 + maxAmount: 5 + - id: PistolMolly + amount: 0 + maxAmount: 5 + - id: PistolOlivaw + amount: 0 + maxAmount: 5 + - id: PistolPaco + amount: 0 + maxAmount: 5 + + - id: ButchCleaver + maxAmount: 5 + - id: Pickaxe + maxAmount: 5 + - id: Spear + maxAmount: 5 + - id: ToolboxEmergency + maxAmount: 5 + - id: CrowbarRed + maxAmount: 5 + - id: Stunbaton + maxAmount: 10 + + - id: RevolverDeckard + amount: 0 + maxAmount: 5 + - id: RevolverInspector + amount: 0 + maxAmount: 5 + - id: RevolverMateba + amount: 0 + maxAmount: 5 + + - id: ShotgunBojevic + amount: 0 + maxAmount: 5 + - id: ShotgunDB + amount: 0 + maxAmount: 5 + - id: ShotgunBull + amount: 0 + maxAmount: 5 + - id: ShotgunGladstone + amount: 0 + maxAmount: 5 + - id: ShotgunRegulator + amount: 0 + maxAmount: 5 + - id: ShotgunPump + amount: 0 + maxAmount: 5 + - id: ShotgunSawn + amount: 0 + maxAmount: 5 + + - id: SmgAtreides + amount: 0 + maxAmount: 5 + - id: SmgC20r + amount: 0 + maxAmount: 5 + - id: SmgDrozd + amount: 0 + maxAmount: 5 + - id: SmgWt550 + amount: 0 + maxAmount: 5 + - id: SmgZoric + amount: 0 + maxAmount: 5 + + - id: SniperBoltGun + amount: 0 + maxAmount: 5 + - id: SniperBoltGunWood + amount: 0 + maxAmount: 5 + - id: SniperHeavy + amount: 0 + maxAmount: 5 + + - id: RedLaser + amount: 0 + maxAmount: 5 + - id: RedHeavyLaser + amount: 0 + maxAmount: 1 + - id: XrayLaser + amount: 0 + maxAmount: 1 + - id: LaserGun + amount: 0 + maxAmount: 1 + - id: LaserCannon + amount: 0 + maxAmount: 1 + - id: XrayCannon + amount: 0 + maxAmount: 2 + - id: TaserGun + amount: 0 + maxAmount: 4 + + - id: LauncherChinaLake + prob: 0.30 + maxAmount: 3 + + - id: LauncherRocket + prob: 0.20 + maxAmount: 3 + + - id: ExGrenade + prob: 0.10 + amount: 0 + maxAmount: 2 + + - id: GrenadeFlashBang + - id: SyndieMiniBomb + prob: 0.05 + amount: 0 + maxAmount: 5 + + - id: GrenadeFlash + - id: GrenadeBlast + - id: GrenadeFrag + - id: GrenadeBaton + - id: SoapSyndie + amount: 0 + maxAmount: 3 + + + # Spawn a bunch of ammo around! + - id: MagazineSRifle + maxAmount: 15 + - id: MagazineClRifle + maxAmount: 15 + - id: MagazineClRifle10x24 + maxAmount: 15 + - id: MagazineClRiflePistol + maxAmount: 15 + - id: MagazineLRifle + maxAmount: 15 + - id: MagazinePistolCalicoTopMounted + maxAmount: 15 + - id: MagazineShotgun + maxAmount: 15 + - id: MagazinePistol + maxAmount: 15 + - id: MagazineHCPistol + maxAmount: 15 + - id: MagazineMagnum + maxAmount: 15 + - id: MagazineMagnumSmg + maxAmount: 15 + - id: RocketAmmo + maxAmount: 15 + - id: GrenadeFrag + maxAmount: 15