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:
metalgearsloth
2021-02-21 10:27:17 +11:00
committed by GitHub
parent df8a69d5cd
commit e0eaef1aa9
4 changed files with 108 additions and 29 deletions

View File

@@ -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>());
}
}
}

View File

@@ -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,
}
}

View File

@@ -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,
}
}

View 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