Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

If requesting help, make sure to mention what game you are attempting to use ACT with.
For the best FFXIV support, join Ravahn's Discord Server. Also check out OverlayPlugin's FFXIV FAQ and Setup Guide.

Death Report hanging

Getting my head back into making some plugins that may be useful...

One thing I'm trying to do is automatically open a death report when I die...

I've been able to successfully open an avoidance report using:
var characterName = ActGlobals.charName;
var encounter = ActGlobals.oFormActMain.ActiveZone.ActiveEncounter;
var combatant = encounter.GetCombatant(characterName);
new FormAvoidanceReport().ShowAvoidanceReport(combatant);

However, when I attempt to do similar to open a death report, I get a death report screen that is hung.

I've plugged into the "AfterCombatAction" event for now, and keep an eye on the deathcount of current player:

var encounter = ActGlobals.oFormActMain.ActiveZone.ActiveEncounter;

            //TODO: only need to do this once each new combat, but isn't always available on the OnCombatStart event
            currentCombatant = encounter.GetCombatant(ActGlobals.charName);
            if (currentCombatant != null)
            {
                infoLabel.Text = string.Format("{0}: {1}", currentCombatant.Name, currentCombatant.Damage);

                if (currentCombatant.Deaths != deathCount)
                {
                    if (currentCombatant.Deaths > deathCount)
                    {
                        // Player has died
                        new FormResistsDeathReport().ShowDeathReport(currentCombatant);
                    }
                    deathCount = currentCombatant.Deaths;
                }
            }




Any pointers appreciated.
Tagged:

Comments

  • AfterCombatAction should be running on a special thread that dequeues data from the log parsing thread to be added in a multi-core manner.  You should never spawn windows except on the UI thread nor modify them.  Technically Microsoft does not want you to even read anything about them either, but I think that is being too careful and I have disabled this check.  (See this...)

    I don't know why the avoidance report works for you at all, really.  Creating a new form outside of the UI thread would be lacking a window message pump to orchestrate user interactions.

    You can use this as quick and dirty one(?) liner:
    ActGlobals.oFormActMain.Invoke(new Action(() => 

        // This code will run on the UI thread
    }));
    Just be careful about you arrange things.  Thread invokes are somewhat costly due to context switching... so if you go in and out of this block as part of a loop... it will be noticeable.  But this is much more elegant than very early C# versions.

  • Thanks, that's worked a treat.

    The Avoidance Report was being done from "OnCombatStartEvent", I assume that operates somehow from within the UI thread? I'm not sure how to tell which events are operating on which threads.

    As for my specific use case, can you think of a better event for me to grab the current combatant from on combat starting? If a pet or someone else starts the combat, I assume that my own combatant won't exist yet. Looking at the documentation, I can't seem to see a better way.

    Regardless, cheers for the response, and appreciate the explanation!
  • Most parsing events would be from some non-UI thread or other...  though not always the same one, as with this.  I do not switch context to the UI thread to call event handlers because it would be expensive to do 2-3 times every log line if it was not necessary.  And if a handler does not return quickly, it will block UI responsiveness. 

    You can check this boolean on any working form: ActGlobals.oFormActMain.InvokeRequired
    If it's true, then you probably need to run the UI related code using Invoke().

    For EQ2, ActGlobals.charName usually has the name of the 1st person perspective.  But as you said, your combatant is not guaranteed to exist in any particular encounter.

    I feel like the following should work for what you are trying:
    void FormActMain_AfterCombatAction(bool isImport, CombatActionEventArgs actionInfo)
    {
        if(isImport == false && actionInfo.combatAction.victim == ActGlobals.charName && actionInfo.damage == Dnum.Death)
        {
            // Do something
        }
    }

  • Cheers, seems like a slicker way to do things!
Sign In or Register to comment.