fish-station/Content.Server/NPC/Systems/NPCSystem.cs
Vigers Ray 95b86d7a4b Merge remote-tracking branch 'space-wizards/master'
# Conflicts:
#	Content.Client/Construction/UI/ConstructionMenu.xaml
#	Content.Client/Construction/UI/ConstructionMenu.xaml.cs
#	Content.Client/Construction/UI/ConstructionMenuPresenter.cs
#	Content.Server/Warps/WarpPointSystem.cs
#	Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs
#	Content.Server/Weapons/Ranged/Systems/GunSystem.cs
#	Content.Shared/Construction/Steps/ArbitraryInsertConstructionGraphStep.cs
#	Content.Shared/Construction/Steps/MaterialConstructionGraphStep.cs
#	Content.Shared/Humanoid/SharedHumanoidAppearanceSystem.cs
#	Content.Shared/Inventory/InventorySystem.Relay.cs
#	Content.Shared/Weapons/Reflect/ReflectSystem.cs
#	Resources/Locale/en-US/_strings/plants/mutations.ftl
#	Resources/Locale/en-US/_strings/stack/stacks.ftl
#	Resources/Locale/en-US/_strings/teleportation/teleportation-menu-gui.ftl
#	Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/heads.yml
#	Resources/Prototypes/Catalog/VendingMachines/Inventories/winterdrobe.yml
#	Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml
#	Resources/Prototypes/Entities/Objects/Power/powercells.yml
#	Resources/Prototypes/Entities/Objects/Specific/Cargo/cargo_pallet.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
#	Resources/Prototypes/Entities/Stations/base.yml
#	Resources/Prototypes/Entities/Structures/Machines/nuke.yml
#	Resources/Prototypes/Reagents/toxins.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/clothing/clown_banana.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/machines/computer.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/mechs/hamtr_construction.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/mechs/honker_construction.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/mechs/ripley_construction.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/mechs/vim_construction.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/airlock.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/airlock_clockwork.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/blast_door.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/conveyor.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/firelock.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/glassbox.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/secretdoor.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/shutter.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/shuttle.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/structures/windoor.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/APC.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/air_alarms.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/disposal_machines.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/intercom.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/lighting.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/solarpanel.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/station_maps.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_generator.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_substation.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/bladed_hats.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/bola.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/improvised_arrow.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/modular_grenade.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/modular_mine.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/shiv.yml
#	Resources/Prototypes/Recipes/Construction/Graphs/weapons/spear.yml
#	Resources/Prototypes/Recipes/Construction/structures.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/cleanbot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/firebot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/honkbot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/medibot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/mimebot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/bots/supplybot.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/firebomb.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/improvised_shotgun.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/improvised_shotgun_shell.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/makeshiftstunprod.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/pipebomb.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/pneumatic_cannon.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/storage/cratefreezer.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/storage/tallbox.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/strawhat.yml
#	Resources/Prototypes/Recipes/Crafting/Graphs/toys.yml
#	Resources/Prototypes/Recipes/Crafting/improvised.yml
#	Resources/Prototypes/Recipes/Reactions/medicine.yml
#	Resources/Prototypes/Roles/Jobs/CentComm/official.yml
#	Resources/Textures/Clothing/Neck/mantles/cemantle.rsi/equipped-NECK.png
#	Resources/Textures/Clothing/Neck/mantles/cemantle.rsi/icon.png
#	Resources/Textures/Clothing/Neck/mantles/cemantle.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/mime.rsi/equipped-INNERCLOTHING.png
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/mime.rsi/icon.png
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/mime.rsi/inhand-left.png
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/mime.rsi/inhand-right.png
#	Resources/Textures/Clothing/Uniforms/Jumpskirt/mime.rsi/meta.json
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/mime.rsi/equipped-INNERCLOTHING.png
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/mime.rsi/icon.png
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/mime.rsi/inhand-left.png
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/mime.rsi/inhand-right.png
#	Resources/Textures/Clothing/Uniforms/Jumpsuit/mime.rsi/meta.json
2025-05-04 23:13:12 +03:00

157 lines
4.8 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Content.Server.NPC.Components;
using Content.Server.NPC.HTN;
using Content.Shared.CCVar;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;
using Content.Shared.NPC;
using Robust.Shared.Configuration;
using Robust.Shared.Player;
namespace Content.Server.NPC.Systems
{
/// <summary>
/// Handles NPCs running every tick.
/// </summary>
public sealed partial class NPCSystem : EntitySystem
{
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly HTNSystem _htn = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
/// <summary>
/// Whether any NPCs are allowed to run at all.
/// </summary>
public bool Enabled { get; set; } = true;
private int _maxUpdates;
private int _count;
/// <inheritdoc />
public override void Initialize()
{
base.Initialize();
Subs.CVar(_configurationManager, CCVars.NPCEnabled, value => Enabled = value, true);
Subs.CVar(_configurationManager, CCVars.NPCMaxUpdates, obj => _maxUpdates = obj, true);
}
public void OnPlayerNPCAttach(EntityUid uid, HTNComponent component, PlayerAttachedEvent args)
{
SleepNPC(uid, component);
}
public void OnPlayerNPCDetach(EntityUid uid, HTNComponent component, PlayerDetachedEvent args)
{
if (_mobState.IsIncapacitated(uid) || TerminatingOrDeleted(uid))
return;
// This NPC has an attached mind, so it should not wake up.
if (TryComp<MindContainerComponent>(uid, out var mindContainer) && mindContainer.HasMind)
return;
WakeNPC(uid, component);
}
public void OnNPCMapInit(EntityUid uid, HTNComponent component, MapInitEvent args)
{
component.Blackboard.SetValue(NPCBlackboard.Owner, uid);
WakeNPC(uid, component);
}
public void OnNPCShutdown(EntityUid uid, HTNComponent component, ComponentShutdown args)
{
SleepNPC(uid, component);
}
/// <summary>
/// Is the NPC awake and updating?
/// </summary>
public bool IsAwake(EntityUid uid, HTNComponent component, ActiveNPCComponent? active = null)
{
return Resolve(uid, ref active, false);
}
public bool TryGetNpc(EntityUid uid, [NotNullWhen(true)] out NPCComponent? component)
{
// If you add your own NPC components then add them here.
if (TryComp<HTNComponent>(uid, out var htn))
{
component = htn;
return true;
}
component = null;
return false;
}
/// <summary>
/// Allows the NPC to actively be updated.
/// </summary>
public void WakeNPC(EntityUid uid, HTNComponent? component = null)
{
if (!Resolve(uid, ref component, false))
{
return;
}
Log.Debug($"Waking {ToPrettyString(uid)}");
EnsureComp<ActiveNPCComponent>(uid);
}
public void SleepNPC(EntityUid uid, HTNComponent? component = null)
{
if (!Resolve(uid, ref component, false))
{
return;
}
// Don't bother with an event
if (TryComp<HTNComponent>(uid, out var htn))
{
if (htn.Plan != null)
{
var currentOperator = htn.Plan.CurrentOperator;
_htn.ShutdownTask(currentOperator, htn.Blackboard, HTNOperatorStatus.Failed);
_htn.ShutdownPlan(htn);
htn.Plan = null;
}
}
Log.Debug($"Sleeping {ToPrettyString(uid)}");
RemComp<ActiveNPCComponent>(uid);
}
/// <inheritdoc />
public override void Update(float frameTime)
{
base.Update(frameTime);
if (!Enabled)
return;
// Add your system here.
_htn.UpdateNPC(ref _count, _maxUpdates, frameTime);
}
public void OnMobStateChange(EntityUid uid, HTNComponent component, MobStateChangedEvent args)
{
if (HasComp<ActorComponent>(uid))
return;
switch (args.NewMobState)
{
case MobState.Alive:
WakeNPC(uid, component);
break;
case MobState.Critical:
case MobState.Dead:
SleepNPC(uid, component);
break;
}
}
}
}