Data-driven NPC factions (#3249)
* Data-driven NPC factions * Minor re-factor so it's settable via yaml instead. Any changes made during runtime aren't saved back. * Still uses enums given bitmasks go BRRT * private setters whoops * nullables Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.AI
|
||||
{
|
||||
[Prototype("aiFaction")]
|
||||
public class AiFactionPrototype : IIndexedPrototype, IPrototype
|
||||
{
|
||||
// These are immutable so any dynamic changes aren't saved back over.
|
||||
// AiFactionSystem will just read these and then store them.
|
||||
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
public IReadOnlyList<string> Hostile { get; private set; } = default!;
|
||||
|
||||
public void LoadFrom(YamlMappingNode mapping)
|
||||
{
|
||||
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||
|
||||
serializer.DataField(this, x => x.ID, "id", string.Empty);
|
||||
serializer.DataField(this, x => x.Hostile, "hostile", new List<string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.EntitySystems.AI;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
@@ -35,15 +37,4 @@ namespace Content.Server.GameObjects.Components.AI
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Faction
|
||||
{
|
||||
None = 0,
|
||||
NanoTrasen = 1 << 0,
|
||||
SimpleHostile = 1 << 1,
|
||||
SimpleNeutral = 1 << 2,
|
||||
Syndicate = 1 << 3,
|
||||
Xeno = 1 << 4,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.AI;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
{
|
||||
@@ -14,27 +19,44 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
* This may change where specified friendly factions are listed. (e.g. to get number of friendlies in area).
|
||||
*/
|
||||
|
||||
private readonly Dictionary<Faction, Faction> _hostileFactions = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
var protoManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
|
||||
foreach (var faction in protoManager.EnumeratePrototypes<AiFactionPrototype>())
|
||||
{
|
||||
if (Enum.TryParse(faction.ID, out Faction @enum))
|
||||
{
|
||||
var parsedFaction = Faction.None;
|
||||
|
||||
foreach (var hostile in faction.Hostile)
|
||||
{
|
||||
if (Enum.TryParse(hostile, out Faction parsedHostile))
|
||||
{
|
||||
parsedFaction |= parsedHostile;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Unable to parse hostile faction {hostile} for {faction.ID}");
|
||||
}
|
||||
}
|
||||
|
||||
_hostileFactions[@enum] = parsedFaction;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Unable to parse AI faction {faction.ID}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Faction GetHostileFactions(Faction faction) => _hostileFactions.TryGetValue(faction, out var hostiles) ? hostiles : Faction.None;
|
||||
|
||||
private readonly Dictionary<Faction, Faction> _hostileFactions = new()
|
||||
{
|
||||
{Faction.NanoTrasen,
|
||||
Faction.SimpleHostile | Faction.Syndicate | Faction.Xeno},
|
||||
{Faction.SimpleHostile,
|
||||
Faction.NanoTrasen | Faction.Syndicate
|
||||
},
|
||||
// What makes a man turn neutral?
|
||||
{Faction.SimpleNeutral,
|
||||
Faction.None
|
||||
},
|
||||
{Faction.Syndicate,
|
||||
Faction.NanoTrasen | Faction.SimpleHostile | Faction.Xeno},
|
||||
{Faction.Xeno,
|
||||
Faction.NanoTrasen | Faction.Syndicate},
|
||||
};
|
||||
|
||||
public Faction GetFactions(IEntity entity) =>
|
||||
entity.TryGetComponent(out AiFactionTagComponent factionTags)
|
||||
entity.TryGetComponent(out AiFactionTagComponent? factionTags)
|
||||
? factionTags.Factions
|
||||
: Faction.None;
|
||||
|
||||
@@ -83,4 +105,15 @@ namespace Content.Server.GameObjects.EntitySystems.AI
|
||||
_hostileFactions[source] = hostileFactions;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Faction
|
||||
{
|
||||
None = 0,
|
||||
NanoTrasen = 1 << 0,
|
||||
SimpleHostile = 1 << 1,
|
||||
SimpleNeutral = 1 << 2,
|
||||
Syndicate = 1 << 3,
|
||||
Xeno = 1 << 4,
|
||||
}
|
||||
}
|
||||
|
||||
28
Resources/Prototypes/ai_factions.yml
Normal file
28
Resources/Prototypes/ai_factions.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
- type: aiFaction
|
||||
id: NanoTrasen
|
||||
hostile:
|
||||
- SimpleHostile
|
||||
- Syndicate
|
||||
- Xeno
|
||||
|
||||
- type: aiFaction
|
||||
id: SimpleHostile
|
||||
hostile:
|
||||
- NanoTrasen
|
||||
- Syndicate
|
||||
|
||||
- type: aiFaction
|
||||
id: SimpleNeutral
|
||||
|
||||
- type: aiFaction
|
||||
id: Syndicate
|
||||
hostile:
|
||||
- NanoTrasen
|
||||
- SimpleHostile
|
||||
- Xeno
|
||||
|
||||
- type: aiFaction
|
||||
id: Xeno
|
||||
hostile:
|
||||
- NanoTrasen
|
||||
- Syndicate
|
||||
Reference in New Issue
Block a user