Hi,
I'm freshly learning the modding and haven't touched entities so far yet, but wanted to join discussion if you or someone figures this out.
I haven't used Harmony (and honestly I'm trying to avoid it as it seems it's quite delicate and would require higher level of maintenance between releases) - but perhaps using it would be the easiest way of doing this...
It depends on what you mean by
If there is additional logic to be added I think there is no way other than modifying AiTaskFleeEntity functions (as the logic of other AI stuff calls the flee behavior), but if just changing default parameters would be enough I did some digging:
The behavior/aitasks/fleeentity from json has some params. Unfortunately it seems that these are loaded as JSon objects per entity type (and that is read-only) and can't be modified on the fly. With this code in ModSystem I was able to get the list of all entities with flee behavior:
public override void AssetsFinalize(ICoreAPI api)
{
if (api.Side != EnumAppSide.Server)return;
foreach (EntityProperties ep in api.World.EntityTypes)
{
if(ep.Server.BehaviorsAsJsonObj != null)
{
for (int i = 0; i < ep.Server.BehaviorsAsJsonObj.Length; i++)
{
JsonObject jobj = ep.Server.BehaviorsAsJsonObj[i];
string code = jobj["code"].AsString();
if("taskai" == code)
{
if (null == jobj["aitasks"]) break; // I don't think this should happen, but guard just in case
JsonObject[] aitasks = jobj["aitasks"].AsArray();
Mod.Logger.Notification("Entity: {0}", ep.Code.ToString());
foreach (JsonObject _j in aitasks)
{
if ("fleeentity" == _j["code"].AsString())
{
Mod.Logger.Notification("Entity {0}", ep.Code.ToString());
Mod.Logger.Notification("Flee move speed: {0}", _j["movespeed"].AsFloat());
// _j is read-only and we can't "patch" it's default value :(
}
}
}
}
}
}
}
It seems that each the entity behavior has JSON-loaded default config. When entity spawns, this config is loaded and behavior list gets populated. This is problematic for modding without interference with original class, as it'd mean that we'd have to overwrite these values per entity per spawn in real time in game. The performance loss might be inconsequential, but it seems fishy. Patching every single json as you mentioned also feels like a wrong approach.
I'll continue to look at different angles for it, feel free to share any findings.
EDIT: Following on the just-existing-attributes topic, it seems quite simple with harmony to do the following:
[HarmonyPostfix]
[HarmonyPatch(typeof(AiTaskFleeEntity), nameof(AiTaskFleeEntity.LoadConfig))]
public static void AfterLoadConfig(ref float ___moveSpeed)
{
___moveSpeed = 2.0f;
}
This does not solve the issue of saving additional data within the class (not sure if this is possible), but it really depends on what you want to do. Existing fields seem to be easily accessible through postfix onLoadConfig harmony patch, and any change to behavior can be probably done by pre/postfixing appropriate methods within the behavior class.
Also, another approach that might be possible to experiment with is to just add additional custom behavior to entity from your own class, and harmony-patch functions that actually call the Flee behavior, to instead call your class instead.