edited April 2016 in ORK Support
Hi there,

I'm trying to update some UI elements based on who is active during a turn based battle. My main problem is I don't have a 'concrete' method to find who is the active team member.

The best I found was using ORK.Battle.GetMenuUser() which let me do the following:

Combatant temp = ORK.Battle.GetMenuUser();
_allCombatants.TryGetValue(temp, out tempDetails);
PointerEventData ped = new PointerEventData(EventSystem.current);
tempDetails.StatBar.OnPointerEnter(ped);


What would be ideal is if I could write an event (I have the ORK source) that would detect when the user changes, but I'm not sure where to have that event fire.

My event looks like this:
private CombatantChanged menuUserChanged;
public event CombatantChanged MenuUserChanged
{
add { this.menuUserChanged = value; }
remove { this.menuUserChanged -= value; }
}



And I'm currently putting it here (in Battle.cs):


public void ChangeMenuUserIndex(int change)
{
if (this.menuUser.Count > 1 && this.menuUser[this.menuIndex].BattleMenu.Controlable)
{
if(this.menuUser[this.menuIndex].BattleMenu.Box != null)
{
this.menuUser[this.menuIndex].BattleMenu.Box.Audio.PlayUserChange();
}
this.menuUser[this.menuIndex].BattleMenu.Reset(false);
this.menuIndex += change;
this.CheckMenuIndex();
this.menuUser[this.menuIndex].BattleMenu.Reset(true);

// My added event code!!!!!
menuUserChanged?.Invoke(GetMenuUser());
// End of my code!!!!!

if(ORK.BattleSettings.camera.blockEventCams && this.menuUser[this.menuIndex].GameObject != null)
{
ORK.BattleSettings.camera.SetMenuUser(this.menuUser[this.menuIndex].GameObject.transform);
}
}
}


But unfortunately (after looking at where ChangeMenuUserIndex is called), it only calls it in active or real time based battles, not classic turn based - and only if I am manually switching menu users:

if(ORK.GameControls.switchMenuUser && ORK.Battle.MenuCount > 1 &&
(ORK.GameControls.switchMenuActiveTime && ORK.Battle.IsActiveTime()) ||
(ORK.GameControls.switchMenuRealTime && ORK.Battle.IsRealTime()))


Any ideas on a better place to put this or a different way to handle this?

Thanks!!!
Post edited by deckrocket on
  • Maybe in the private method GetNextSelectingCombatant() in TurnBasedBattle.cs? Or perhaps in GetNextAction()?

    I'll likely need to do something similar at some point in the future.

    You could also try adding/removing handlers to the Combatant.Changed event for each combatant involved in the battle (it's also of type CombatantChanged).

    If that method works, then you might be able to put it in its own component that watches for a turn-based battle to start, adds the handlers to each combatant, and then cleans up when the battle is done. I always look for that sort of solution, as we get pretty regular updates to ORK and I don't really want to mess around with the source code and have to merge changes unless I really need to. :-)
  • Okay thanks for the advice Keldryn, I'll take a look at what you've mentioned!
  • edited April 2016
    No problem, @deckrocket. Once I started thinking about this problem, I just couldn't let it go... ;-)

    Adding handlers to the Combatant.Changed event does not work. This one seems to fire off when a combatant is selected as a target.

    What does work (mostly) is hooking into the Combatant.Actions.ChoosingStateChanged event. I say "mostly" because this event gets fired when the battle menu appears and again after a selection has been made. Depending on what you're doing with it, this may not matter.

    So I have a singleton component (called ORKMonitor) on a GameObject in my scene (just called ORK; it's what I parent the rest of the ORK objects under):


    void Update()
    {
    if (!_isInBattle && ORK.Battle.IsBattleRunning())
    {
    // a battle has started
    _isInBattle = true;
    Debug.Log("A battle has started");

    var combatants = ORK.Game.Combatants.GetAll();
    foreach (var c in combatants)
    {
    c.Actions.ChoosingStateChanged += Actions_ChoosingStateChanged;
    }
    }
    else if (_isInBattle && !ORK.Battle.IsBattleRunning())
    {
    // battle has ended
    _isInBattle = false;
    Debug.Log("The battle has ended.");

    var combatants = ORK.Game.Combatants.GetAll();
    foreach (var c in combatants)
    {
    c.Actions.ChoosingStateChanged -= Actions_ChoosingStateChanged;
    }
    }
    }

    private void Actions_ChoosingStateChanged(Combatant combatant)
    {
    Debug.Log(string.Format("{0} Choosing State Changed ({1})",
    combatant.GetName(), ORK.Game.GameTime));
    }

    private bool _isInBattle = false;


    Something else that I tried before Actions.ChoosingStateChanged was instead to hook into the UpdateHUD event (still inside the first condition above):


    if (ORK.Battle.IsTurnBased())
    {
    ORK.BattleSystem.turnBased.UpdateHUD += TurnBased_UpdateHUD;
    }



    private void TurnBased_UpdateHUD()
    {
    StartCoroutine(GetCurrentUser());
    }

    private IEnumerator GetCurrentUser()
    {
    while (ORK.Battle.GetMenuUser() == null)
    {
    yield return new WaitForSeconds(0.1f);
    }

    var name = ORK.Battle.GetMenuUser().GetName();
    Debug.Log(string.Format("New turn {0} ({1})", name, ORK.Game.GameTime));
    }


    This one tends to fire more often than once per combatant's turn, but it is what ORK uses internally to update HUDs during turn-based combat. I had to do it as a coroutine as I was often getting NullReferenceExceptions if I just called ORK.Battle.GetMenuUser().GetName() in the event handler.

    Hopefully that gets you on the right track. Of these two methods, I think I'd go with Actions.ChoosingStateChanged as it is the most predictable.

    EDIT: And in my Actions_ChoosingStateChanged handler, I would probably send a message to my custom UI using some sort of pub/sub messaging system, so that this component only serves as a bridge to ORK and doesn't call my own code directly (other than the messaging system).
    Post edited by Keldryn on
  • edited April 2016
    edit, can't delete post.
    Post edited by artainx on
    ORK user since 2014. Patron since 2018.
  • Thanks Keldryn. Combatant.Actions.ChoosingStateChanged is pretty close to what I need (ideally it would just trigger once, but I'll create a state so I know if its "starting" or "ending".

    Thanks for helping me with this!
  • No problem!
Sign In or Register to comment.