Suggestion General Ability to attach custom observers to simulated battles

Currently viewing this thread:

Retsam

Recruit
The goal

The goal is to have a mod be able to track the results of a simulated battle as it progresses - similar to how a mod might use MissionBehavior to track kills and such in a non-simulated battle. (For my particular use case, I'm trying to keep track of when individual soldiers in the player's party die)

Current state


There's an existing interface, IBattleObserver which has a TroopNumberChanged method gives the basic information necessary:

C#:
public interface IBattleObserver
{
  void TroopNumberChanged(
    BattleSideEnum side,
    IBattleCombatant battleCombatant,
    BasicCharacterObject character,
    int number, int numberKilled, int numberWounded, int numberRouted, int killCount, int numberReadyToUpgrade);
 
    // other methods omitted
}

However, there can only be one IBattleObserver attached to the BattleSimulation at one time - (i.e. the one used to drive the Scoreboard VM, usually), so AFAIK there's no clean way for a mod to attach its own IBattleObserver. (For a not clean way... see below)

It'd be nice if BattleSimulation allowed multiple IBattleObserver's to be attached, or maybe there's some other way mods could be given access to this information.

---

Current workaround

The workaround I'm using right now is to override BattleSimulationGauntletView with a subclass to get access the to BattleSimulation and replace the IBattleObserver with a wrapped one. If there's a better way of doing this currently, that'd be great.

C#:
[OverrideView(typeof(BattleSimulationMapView))]
public class BattleSimulationOverride : BattleSimulationGauntletView {
    private readonly BattleSimulation _battleSimulation;

    public BattleSimulationOverride(BattleSimulation battleSimulation)
        : base(battleSimulation) {
        _battleSimulation = battleSimulation;
    }

    protected override void CreateLayout() {
        base.CreateLayout();
        // Wrap the BattleObserver here, after it's been set by SPScoreboardVM.Initialize
        _battleSimulation.BattleObserver =
            new BattleObserverWrapper(_battleSimulation.BattleObserver);
    }
}
public class BattleObserverWrapper : IBattleObserver {
    private readonly IBattleObserver _wrappedObserver;

    public BattleObserverWrapper(IBattleObserver wrappedObserver) {
        _wrappedObserver = wrappedObserver;
    }

    public void TroopNumberChanged(/* args */) {
        _wrappedObserver.TroopNumberChanged(/* args */);
        // Mod logic here
    }

    // other methods wrapped as well
}
 
Top Bottom