This should be more efficient, create less lag, and also fixes a few issues.
The existing code did most of the work in renderChatMessage, which is called on every chat message for every player. Even old chat messages.
This now tries to do less work there and more in hooks that happen less often.
When the chat message is first created (when someone rolls damage) the damage roller is checked to see if it's an EV target. This is a simple search of just the damage roller's effects. If it is, the thaumaturge(s) targetting it are known from the EV target effect origin, and then we can check if any of the roll's targets are allies in range.
Note that rather than checking for "party" alliance, we check if the damage targets have the same alliance as the thaumaturge, so this works for "opposition" targets too.
This is bundled up as an array of "abeyers" in the message flags. Each is an object with the actor and token UUID of a thaumaturge who can abey the damage.
Then in renderChatMessage, we just loop through the tokens in the abeyers array, if any, and add a button for the token if the current user is an owner. No need to look at the map and find anything within 15' of something else or any other sort of O(n²) loops.
When the button is clicked, then we can do most of the work. The callback no longer saves a reference to the amulet, as this could be stale by the time the button is clicked. Only the actor and the message.
We find the allies in range, based on targets or all allies for paragon vs non-paragon, the damage types, and make up the dialog.
The code to find the Amulet feat isn't needed, it's already there in this.baseFeat. And damage types don't need to be extracted from the html in dialog callback, we can use the data from when we made the dialog. The arrow functions' closures keep refernces to items used in enclosing scopes.
This should be more efficient, create less lag, and also fixes a few issues.
The existing code did most of the work in renderChatMessage, which is called on every chat message for every player. Even old chat messages.
This now tries to do less work there and more in hooks that happen less often.
When the chat message is first created (when someone rolls damage) the damage roller is checked to see if it's an EV target. This is a simple search of just the damage roller's effects. If it is, the thaumaturge(s) targetting it are known from the EV target effect origin, and then we can check if any of the roll's targets are allies in range.
Note that rather than checking for "party" alliance, we check if the damage targets have the same alliance as the thaumaturge, so this works for "opposition" targets too.
This is bundled up as an array of "abeyers" in the message flags. Each is an object with the actor and token UUID of a thaumaturge who can abey the damage.
Then in renderChatMessage, we just loop through the tokens in the abeyers array, if any, and add a button for the token if the current user is an owner. No need to look at the map and find anything within 15' of something else or any other sort of O(n²) loops.
When the button is clicked, then we can do most of the work. The callback no longer saves a reference to the amulet, as this could be stale by the time the button is clicked. Only the actor and the message.
We find the allies in range, based on targets or all allies for paragon vs non-paragon, the damage types, and make up the dialog.
The code to find the Amulet feat isn't needed, it's already there in this.baseFeat. And damage types don't need to be extracted from the html in dialog callback, we can use the data from when we made the dialog. The arrow functions' closures keep refernces to items used in enclosing scopes.