Skip to content

Ninth Manning Features

xpdota edited this page May 24, 2022 · 4 revisions

Triggevent provides two major pieces of functionality for 9th manning.

Observation/Log Analysis

Triggevent can connect to a remote ACT by way of OverlayPlugin websocket. Have at least one person of your raid group enable OverlayPlugin WSServer with settings like this:

image

Then, they need to configure their router to forward port 10501 to their computer, and give you their public IP.

Then, if their IP address is 1.2.3.4, set up your Triggevent like this, and restart it:

image

Now, you should see everything going on in real-time.

Let's go over a few features.

Events Tab

The Events tab gives you a view of everything that has happened. Rather than trying to read ACT log lines in real time, it actually parses and interprets them into higher-level events for you:

image

You can click on an event and look in the "details" section down below to get more information about that particular event.

If you do want to see the original log line, right click and select "Copy Net Line" or "Copy Emulated ACT Line".

You can hover over various elements in the table to get more information as to what was going on at the time of the event:

image

In addition, there are several boxes up at the top that can be used to filter down these events. For example, to see precisely when Chain Stratagem was applied and fell off, for pull #1, against Titan:

image

You can also use the freeform query entry (alone or in tandem with other filters). In this example, we are looking at all abilities that caused at least 1 point of damage to players, except autoattacks:

image

Lastly, some events support making an "easy trigger", where you can simply right click an event to make a quick trigger:

image

Results in:

image

ACT Log Tab

The original ACT log is also available:

image

Combatants Tab

This tab shows detailed information about the current state of all combatants (including fake actors):

image

Pulls Tab

This shows pulls. The most useful feature here is that you can right click one of them, and filter the events tab to just that pull.

Overlays

While overlays are more useful for the actual player, overlays can help a 9th man visualize cooldown usage and enemy casts. You can force them to show, even when the game is not open, by checking the "Force Visible Even When Game Inactive" box:

image

Map Tab

image

The map tab shows combatant HP, positions, and casts at the current point in time. This includes fake actors, so it makes it very easy to make triggers that use positions.

Importing/Replaying

ACT Logs

To import an existing log, run triggevent-import.exe. Then, you can import an ACT log.

Almost everything will work in this mode. However, you won't receive updates on combatant positions until they do something, or something happens to them (more or less the same restrictions as the FFLogs replay tab).

Triggevent Sessions

(TODO: bug with this)

Triggevent has a more complete storage format than raw log files, which includes periodic polling of combatant data.

To save in this format, go to the advanced tab, and select this option:

image

Then, as you use it, it will save sessions. Click "Open Session Dir" on the same tab to see them.

You can then import this with triggevent-import.exe.

FFLogs import

This is the most limited of the three, because FFLogs does not have certain data at all (such as headmarkers) and other data is in a slightly different format that is harder to convert back from. However, the basics will still work. You must create your own API key, and enter it in Advanced > FFLogs.

Trigger Creation

Easy Triggers

There are two options for creating triggers. The first, which we briefly mentioned already, is Easy Triggers. For example, here is a quick one for calling out if someone gets Frostbite:

image

You don't have to mess with log lines. You can just choose what type of event, pick IDs, and you're done. You can pick any extra conditions you want. Triggevent comes with the complete list of Abilities/Status Effects ripped from the game (same as you'd see on Xivapi), so unless there are multiple things with the same name, you don't even need a log to make a trigger.

But if you do have a log (or are watching live), if you right click something on the events tab, depending on the type of event, you may be able to have it automatically make a trigger for you. It will usually guess correctly, but you may need to tweak a few things.

Right now, these are very basic. However, you can extend them quite a bit by using Groovy if the currently supported conditions do not fit your needs (or just ask me, I can generally add them pretty quickly). Here's an example of a trigger that reminds you to use Soulsow when the countdown starts, but only if you are on Reaper:

image

Code Triggers

Like Cactbot, you can write triggers as code. This is how all the built-in triggers and other doodads work.

For example, here's a trigger to call out whether you are first/second/third/fourth group for P4S Curtain Call:

	private final ModifiableCallout<BuffApplied> curtainOrder = ModifiableCallout.durationBasedCall("Curtain Order", "{number} set");

	@HandleEvents
	public void curtainCallNumber(EventContext context, BuffApplied event) {
		if (currentAct == Act.CURTAIN && event.getBuff().getId() == 0xAF4 && event.getTarget().isThePlayer()) {
			long dur = event.getInitialDuration().toSeconds();
			final String number;
			if (dur < 15) {
				number = "First";
			}
			else if (dur < 25) {
				number = "Second";
			}
			else if (dur < 35) {
				number = "Third";
			}
			else {
				number = "Last";
			}
			context.accept(curtainOrder.getModified(event, Map.of("number", number)));
		}
	}

The use of "ModifiableCallout" rather than specifying the text directly gives you a place to customize it a la Cactbot on the Plugin Settings > Callouts tab:

image

Each {} in the callout supports Groovy scripting. In this example, ModifiableCallout.durationBasedCall automatically puts the remaining duration on the end of the on-screen text (the TTS is unmodified). For example, it might display "Third (15.0)" if you were in the third group and there are 15 seconds left on your debuff.

Sequential Triggers

Sequential Triggers are another type of code based trigger. They make it extremely easy to take long sequences of mechanics and make comprehensive triggers. Here's one of the simpler ones, which is for the double quad cleave in the first minute of DSU:

	@HandleEvents
	public void feedSeq(EventContext context, BaseEvent event) {
		p1_fourHeadMark.feed(context, event);
                // You can put all your SequentialTrigger feeds in one event handler
	}


	private final SequentialTrigger<BaseEvent> p1_fourHeadMark = new SequentialTrigger<>(30_000, BaseEvent.class,
			e -> e instanceof AbilityCastStart acs && acs.getAbility().getId() == 0x62DD,
			(e1, s) -> {
				if (s.waitEvents(4, HeadMarkerEvent.class, event -> getHeadmarkOffset(event) == 0)
						.stream().anyMatch(e -> e.getTarget().isThePlayer())) {
					s.accept(p1_firstCleaveMarker.getModified());
				}
				else {
					s.accept(p1_secondCleaveMarker.getModified());
				}
			});

This trigger is activated when it sees ability 62DD (Heavensblaze), and then simply collects four markers, with an offset ID of 0 (to deal with sequential headmarks). Then, if any of them were targeted on the player, it will tell you that you are in the first group. Otherwise, it will tell you that you are in the second group.

You can get very advanced with these. For example, take a look at the Wyrmhole trigger (in Dragonsong.java). Apart from some secondary triggers to handle intermediate gnash/lash calls and Geirskogul baits, the entirety of Wyrmhole, for every role, is written in a single trigger. It allows you to take a complex sequence of mechanics, and break it down into "wait for X, and call Y" while being able to use local variables and all that. It is also a good way to deal with re-used headmarkers or debuffs (for example, you could have it call out when you get a particular headmarker, but only if the boss cast ability XYZ in the last 20 seconds).

How to Actually Make Code Triggers

There are two ways you can do this:

  1. Fork the project and edit to your heart's content (quick and dirty)
  2. Fork the project, create a new module, add it to the dependencies in the Launcher module

Either way, install IntelliJ (the free version is more than fine for this), and open the project. Make sure it builds (try running launcher/src/main/java/gg/xp/xivsupport/gui/GuiLaunch).

How to Distribute Code Triggers to your Raid Team

The easiest way is to just copy the entire build system.

Edit the publish_notselfhosted.yml workflow (.github/workflows) - uncomment the "push:" near the top. Then, comment out the "push" line in publish.yml. This will cause your fork to be built every time you push to a branch. You may need to check your security settings to make sure the necessary actions are allowed.

Then, simply have your users point to your version instead of mine (Advanced > Updates):

image

Assuming you kept the name 'event-trigger', change the URL to https://github.com/your_user_name/event-trigger/raw/gh-pages/%s/v2/%s. (The actual release is set to use the github.io link, but this has a ~10 minute delay after pushing an update before it goes live - not recommended for 9th manning).