From affcc2278481572f012407c278c055077f02bff0 Mon Sep 17 00:00:00 2001 From: qwerltaz <69696513+qwerltaz@users.noreply.github.com> Date: Thu, 17 Jul 2025 18:34:00 +0200 Subject: [PATCH] =?UTF-8?q?NPC=20spiders=20sometimes=20spin=20webs=20?= =?UTF-8?q?=F0=9F=95=B7=EF=B8=8F=F0=9F=95=B8=EF=B8=8F=20(#38319)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * NPC spiders now spin webs * oops * move logic to always update next spawn, to prevent rare web spam * WebSpawnCooldown is timespan * remove vv * add web spawn method, no sus action event method call * dont spin web immediately at spawn * move NextWebSpawn value init to update * oop * remove unused game timing * web spawn cooldown to 45 --- Content.Server/Spider/SpiderSystem.cs | 82 +++++++++++++------ Content.Shared/Spider/SpiderComponent.cs | 18 ++++ .../Prototypes/Entities/Mobs/NPCs/pets.yml | 2 + 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/Content.Server/Spider/SpiderSystem.cs b/Content.Server/Spider/SpiderSystem.cs index e6a7dd7806..33142b19b1 100644 --- a/Content.Server/Spider/SpiderSystem.cs +++ b/Content.Server/Spider/SpiderSystem.cs @@ -2,8 +2,11 @@ using System.Linq; using Content.Server.Popups; using Content.Shared.Spider; using Content.Shared.Maps; +using Content.Shared.Mobs.Systems; using Robust.Server.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Timing; namespace Content.Server.Spider; @@ -11,6 +14,8 @@ public sealed class SpiderSystem : SharedSpiderSystem { [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly TurfSystem _turf = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; /// /// A recycled hashset used to check turfs for spiderwebs. @@ -23,6 +28,30 @@ public sealed class SpiderSystem : SharedSpiderSystem SubscribeLocalEvent(OnSpawnNet); } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var spider)) + { + spider.NextWebSpawn ??= _timing.CurTime + spider.WebSpawnCooldown; + + if (_timing.CurTime < spider.NextWebSpawn) + continue; + + spider.NextWebSpawn += spider.WebSpawnCooldown; + + if (HasComp(uid) + || _mobState.IsDead(uid) + || !spider.SpawnsWebsAsNonPlayer) + continue; + + var transform = Transform(uid); + SpawnWeb((uid, spider), transform.Coordinates); + } + } + private void OnSpawnNet(EntityUid uid, SpiderComponent component, SpiderWebActionEvent args) { if (args.Handled) @@ -36,30 +65,7 @@ public sealed class SpiderSystem : SharedSpiderSystem return; } - var coords = transform.Coordinates; - - // TODO generic way to get certain coordinates - - var result = false; - // Spawn web in center - if (!IsTileBlockedByWeb(coords)) - { - Spawn(component.WebPrototype, coords); - result = true; - } - - // Spawn web in other directions - for (var i = 0; i < 4; i++) - { - var direction = (DirectionFlag) (1 << i); - coords = transform.Coordinates.Offset(direction.AsDir().ToVec()); - - if (!IsTileBlockedByWeb(coords)) - { - Spawn(component.WebPrototype, coords); - result = true; - } - } + var result = SpawnWeb((uid, component), transform.Coordinates); if (result) { @@ -70,6 +76,33 @@ public sealed class SpiderSystem : SharedSpiderSystem _popup.PopupEntity(Loc.GetString("spider-web-action-fail"), args.Performer, args.Performer); } + private bool SpawnWeb(Entity ent, EntityCoordinates coords) + { + var result = false; + + // Spawn web in center + if (!IsTileBlockedByWeb(coords)) + { + Spawn(ent.Comp.WebPrototype, coords); + result = true; + } + + // Spawn web in other directions + for (var i = 0; i < 4; i++) + { + var direction = (DirectionFlag)(1 << i); + var outerSpawnCoordinates = coords.Offset(direction.AsDir().ToVec()); + + if (IsTileBlockedByWeb(outerSpawnCoordinates)) + continue; + + Spawn(ent.Comp.WebPrototype, outerSpawnCoordinates); + result = true; + } + + return result; + } + private bool IsTileBlockedByWeb(EntityCoordinates coords) { _webs.Clear(); @@ -82,4 +115,3 @@ public sealed class SpiderSystem : SharedSpiderSystem return false; } } - diff --git a/Content.Shared/Spider/SpiderComponent.cs b/Content.Shared/Spider/SpiderComponent.cs index 42213adcb1..3a1612fed0 100644 --- a/Content.Shared/Spider/SpiderComponent.cs +++ b/Content.Shared/Spider/SpiderComponent.cs @@ -18,6 +18,24 @@ public sealed partial class SpiderComponent : Component public string WebAction = "ActionSpiderWeb"; [DataField] public EntityUid? Action; + + /// + /// Whether the spider will spawn webs when not controlled by a player. + /// + [DataField] + public bool SpawnsWebsAsNonPlayer = true; + + /// + /// The cooldown in seconds between web spawns when not controlled by a player. + /// + [DataField] + public TimeSpan WebSpawnCooldown = TimeSpan.FromSeconds(45f); + + /// + /// The next time the spider can spawn a web when not controlled by a player. + /// + [DataField] + public TimeSpan? NextWebSpawn; } public sealed partial class SpiderWebActionEvent : InstantActionEvent { } diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index be0ed00172..75aacadd35 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -712,6 +712,8 @@ types: Piercing: 8 Poison: 8 + - type: Spider + spawnsWebsAsNonPlayer: false - type: Grammar attributes: proper: true