Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

TurnMarker & Face2Face Compatibility

Hey All, As I'm sure some of you are aware, there is some compatibility issues with using TurnMarker with Face2Face, or other scripts that listen to turn tracker events.  Specifically with Face2Face, when TurnMarker auto-skips the marker's turn, Face2Face doesn't switch to the sight of the next token. I was able to fix this issue by commenting out line 504 in the TurnMarker script.  Here is the relevant section, starting at line 492: handleMarkerTurn = function(){ var marker = getMarker(), turnOrder = TurnOrder.Get(), round; if(turnOrder[0].id === marker.id) { round=parseInt(marker.get('bar2_value'))+1; marker.set({ name: state.TurnMarker.tokenName+' '+round, bar2_value: round }); announceRound(round); // TurnOrder.Next(); } This is the function that handles the Marker's turn, and I've commented out the line that advances to the next turn.  I now have to manually click through the TurnMarker's turn in initiative, but it still advances the round correctly.  And Face2Face works as expected.
1507574901
The Aaron
Pro
API Scripter
This should let it operate with TurnMarker's autoadvance correctly: on('ready',()=>{     const handleTurnOrderChange = _.debounce((c,prev) => ((current,previous) => {         var CharacterIDs = [];         var CurrentTO = JSON.parse(current.get("turnorder"));         var PreviousTO = JSON.parse(previous["turnorder"]);         var Token;         var Character;                  // Save F2F data...         if (!state.f2f) state.f2f = {};         if (_.isEmpty(state.f2f)) {             _.each(CharacterIDs, function(charid) {                 Character = getObj("character", charid);                 state.f2f[charid] = {                     CharacterID: charid,                     ControlledBy: Character.get("controlledby")                 };             });         }                  // Process the turn order...         if (CurrentTO.length > 0) {             _.each(state.f2f, function(a) {                 getObj("character", a["CharacterID"]).set("controlledby", "");             });             if (CurrentTO[0].id != -1) Token = getObj("graphic", CurrentTO[0].id);             if (CurrentTO[0].id != -1 && Token.get("represents") !== "") Character = getObj("character", Token.get("represents"));             if (CurrentTO[0].id != -1 && Token.get("represents") !== "" && Character.id in state.f2f) {                 Character.set("controlledby", state.f2f[Character.id]["ControlledBy"]);             } else {                 // Return control to all players during npc and custom item turns...                 _.each(state.f2f, function(b) {                     getObj("character", b["CharacterID"]).set("controlledby", b["ControlledBy"]);                 });             }         } else {             // Turn order tracker is empty. Return control to all players...             _.each(state.f2f, function(z) {                 getObj("character", z["CharacterID"]).set("controlledby", z["ControlledBy"]);             });             state.f2f = {};         }                  // Simple Initiative Tracker (Green Dot)...         if (CurrentTO.length === 0 && PreviousTO[0].id != -1) getObj("graphic", PreviousTO[0].id).set("status_green", false);         if (CurrentTO.length > 0 && CurrentTO[0].id != -1) getObj("graphic", CurrentTO[0].id).set("status_green", true);         if (PreviousTO.length > 0 && PreviousTO[0].id != -1) getObj("graphic", PreviousTO[0].id).set("status_green", false);     })(Campaign(),prev));     on("change:campaign:turnorder", handleTurnOrderChange); }); Still won't let you use !eot, but that could be added as well.
Thanks, I'll try that out.
1507576759
The Aaron
Pro
API Scripter
I've not tested it out, but this should let you use !eot and also adds a command !f2f-restore that puts all the controlled by entries back in the event that things get out of sync... on('ready',()=>{     const CharacterIDs = [];     // Save F2F data...     if (!state.f2f) state.f2f = {};     if (_.isEmpty(state.f2f)) {         _.each(CharacterIDs, function(charid) {             let Character = getObj("character", charid);             state.f2f[charid] = {                 CharacterID: charid,                 ControlledBy: Character.get("controlledby")             };         });         state.f2f.prev='';     }     const restoreCharacterControlledby = ()=>{         _.each(state.f2f, function(b) {             getObj("character", b["CharacterID"]).set("controlledby", b["ControlledBy"]);         });     };     const handleTurnOrderChange = _.debounce(() => {         var CurrentTO = JSON.parse(Campaign().get("turnorder"));         var Token = getObj('graphic',CurrentTO[0].id);         var prevToken = getObj('graphic',state.f2f.prev);         var Character;              // Process the turn order...         if (CurrentTO.length > 0) {             _.each(state.f2f, function(a) {                 getObj("character", a["CharacterID"]).set("controlledby", "");             });             if(Token){                 if(prevToken){                     prevToken.set('status_green',false);                 }                 Token.set('status_green',true);                 state.f2f.prev=Token.id;             }             if (Token && Token.get("represents") !== "") {                 Character = getObj("character", Token.get("represents"));             }             if (Character && Character.id in state.f2f) {                 Character.set("controlledby", state.f2f[Character.id]["ControlledBy"]);             } else {                 // Return control to all players during npc and custom item turns...                 restoreCharacterControlledby();             }         } else {             // Turn order tracker is empty. Return control to all players...             restoreCharacterControlledby();             if(prevToken){                 prevToken.set('status_green',false);             }             state.f2f = {};         }     });     on('chat:message',(msg)=>{         if('api'===msg.type){             if(/^!eot/.test(msg.content)){                 handleTurnOrderChange();             } else if(/^!f2f-restore/.test(msg.content) && playerIsGM(msg.playerid)){                 restoreCharacterControlledby();             }         }     });     on("change:campaign:turnorder", handleTurnOrderChange); });
Nice!  I don't typically use the !eot command at the table, but having the restore command should be useful.  Using groupinit to clear the initiative order doesn't always reset the controlled bys, so I'll try adding that to our ClearCombat macro as a backup.
1507650112
The Aaron
Pro
API Scripter
You know, you might try hitting !eot after clearing, that might actually clean things up correctly.
1507650170
The Aaron
Pro
API Scripter
If you have any problems, let me know.  If necessary, you can shoot me an invite and GM me.
I have been trying to help Andrew debug a couple of problems, but there is a problem that I am not sure there is a good solution for. Scripts in use:  GroupInitiative, TurnMarker1, Face2Face. Problem - When starting combat via GroupInitiative, Face2Face isn't setting vision (controlledby property) until the turn order is changed.  I thought to use the "change:campaign:initiativepage" event to detect when the turn order is opened, however it doesn't seem like this event fires when you run !group-init (and Auto Open Init is enabled). What I can't seem to wrap my head around is that there is a similar event in TurnMarker1 that seems to work properly when this is started from !group-init. The only other way I can think to address this is to make an !api command that simply calls Face2Face's handleTurnOrderChange() function and include that in a macro after !group-init is executed, but if feels like I am missing something. Here is what I tried to do: on('ready',()=>{ const CharacterIDs = ["-Kh-HGX4C5QAdR_IeraB", "-Kh-HKDRKZwH04QnavTT", "-Knjvt1i1JLQWTcKjWHg", "-Kh-HRm_1KNDjbK-rS1j", "-KnjvtQp13JnpfNnq4q8"]; // Save F2F data... if (!state.f2f) state.f2f = {}; if (_.isEmpty(state.f2f)) { _.each(CharacterIDs, function(charid) { let Character = getObj("character", charid); state.f2f[charid] = { CharacterID: charid, ControlledBy: Character.get("controlledby") }; }); state.f2f.prev=''; } const restoreCharacterControlledby = ()=>{ _.each(state.f2f, function(b) { if (b.CharacterID) { getObj("character", b["CharacterID"]).set("controlledby", b["ControlledBy"]); } }); }; const handleTurnOrderChange = _.debounce(() => { var CurrentTO = JSON.parse(Campaign().get("turnorder")); var Token = getObj('graphic',CurrentTO[0].id); var prevToken = getObj('graphic',state.f2f.prev); var Character; log(CurrentTO); //temporarily to confirm handleTurnOrderChange fires // Process the turn order... if (CurrentTO.length > 0) { _.each(state.f2f, function(a) { if (a.CharacterID) { getObj("character", a["CharacterID"]).set("controlledby", ""); } }); if(Token){ if(prevToken){ prevToken.set('status_green',false); } Token.set('status_green',false); state.f2f.prev=Token.id; } if (Token && Token.get("represents") !== "") { Character = getObj("character", Token.get("represents")); } if (Character && Character.id in state.f2f) { Character.set("controlledby", state.f2f[Character.id]["ControlledBy"]); } else { // Return control to all players during npc and custom item turns... restoreCharacterControlledby(); } } else { // Turn order tracker is empty. Return control to all players... restoreCharacterControlledby(); if(prevToken){ prevToken.set('status_green',false); } state.f2f = {}; } }); on('chat:message',(msg)=>{ if('api'===msg.type){ if(/^!eot/.test(msg.content)){ handleTurnOrderChange(); } else if(/^!f2f-restore/.test(msg.content) && playerIsGM(msg.playerid)){ restoreCharacterControlledby(); } } }); on("change:campaign:turnorder", handleTurnOrderChange ); on("change:campaign:initiativepage", ()=>{ if (Campaign().get('initiativepage')) { handleTurnOrderChange(); }; }); });
1507813664
The Aaron
Pro
API Scripter
You're missing that I'm a dirty rotten cheater.  =D If you search for GroupInitiative in TurnMarker1, you'll find these lines:         if('undefined' !== typeof GroupInitiative && GroupInitiative.ObserveTurnOrderChange){             GroupInitiative.ObserveTurnOrderChange(handleExternalTurnOrderChange);         } GroupInitiative implements the  Observer Pattern by exposing the function ObserveTurnOrderChange().  The above lines check to see if GroupInitiative is installed (by finding the global variable it lives in) and that it has the ObserverTurnOrderChange() function (to make sure it's new enough or the write script), then passes a function to it to be called when GroupInitiative changes the turn order. This should do the same in Face2Face: on('ready',()=>{     const CharacterIDs = ["-Kh-HGX4C5QAdR_IeraB", "-Kh-HKDRKZwH04QnavTT", "-Knjvt1i1JLQWTcKjWHg", "-Kh-HRm_1KNDjbK-rS1j", "-KnjvtQp13JnpfNnq4q8"];     // Save F2F data...     if (!state.f2f) state.f2f = {};     if (_.isEmpty(state.f2f)) {         _.each(CharacterIDs, function(charid) {             let Character = getObj("character", charid);             state.f2f[charid] = {                 CharacterID: charid,                 ControlledBy: Character.get("controlledby")             };         });         state.f2f.prev='';     }     const restoreCharacterControlledby = ()=>{         _.each(state.f2f, function(b) {             if (b.CharacterID) {                 getObj("character", b["CharacterID"]).set("controlledby", b["ControlledBy"]);             }         });     };     const handleTurnOrderChange = _.debounce(() => {         var CurrentTO = JSON.parse(Campaign().get("turnorder"));         var Token = getObj('graphic',CurrentTO[0].id);         var prevToken = getObj('graphic',state.f2f.prev);         var Character;         log(CurrentTO); //temporarily to confirm handleTurnOrderChange fires         // Process the turn order...         if (CurrentTO.length > 0) {             _.each(state.f2f, function(a) {                 if (a.CharacterID) {                     getObj("character", a["CharacterID"]).set("controlledby", "");                 }             });             if(Token){                 if(prevToken){                     prevToken.set('status_green',false);                 }                 Token.set('status_green',false);                 state.f2f.prev=Token.id;             }             if (Token && Token.get("represents") !== "") {                 Character = getObj("character", Token.get("represents"));             }             if (Character && Character.id in state.f2f) {                 Character.set("controlledby", state.f2f[Character.id]["ControlledBy"]);             } else {                 // Return control to all players during npc and custom item turns...                 restoreCharacterControlledby();             }         } else {             // Turn order tracker is empty. Return control to all players...             restoreCharacterControlledby();             if(prevToken){                 prevToken.set('status_green',false);             }             state.f2f = {};         }     });     on('chat:message',(msg)=>{         if('api'===msg.type){             if(/^!eot/.test(msg.content)){                 handleTurnOrderChange();             } else if(/^!f2f-restore/.test(msg.content) && playerIsGM(msg.playerid)){                 restoreCharacterControlledby();             }         }     });     on("change:campaign:turnorder", handleTurnOrderChange );     if('undefined' !== typeof GroupInitiative && GroupInitiative.ObserveTurnOrderChange){         GroupInitiative.ObserveTurnOrderChange(handleTurnOrderChange);     } });
1507813713
The Aaron
Pro
API Scripter
If you're still having problems, PM me an invite and I'll come take a look.
This worked great.  Glad at least I wasn't completely off the mark :)
1507816458

Edited 1507817211
The Aaron
Pro
API Scripter
=D  Several of my scripts have that Observer pattern in them.  TokenMod is another one that can be handy to observe, depending on what you're doing.