Skip to content

Instantly share code, notes, and snippets.

@Cazra
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cazra/2378ab5a8a0ec3c208bf to your computer and use it in GitHub Desktop.
Save Cazra/2378ab5a8a0ec3c208bf to your computer and use it in GitHub Desktop.
roll20 follow v2
/**
* A script with a command for specifying tokens to follow other tokens.
* Simply select the tokens in the marching order and enter the "!follow"
* commandwith either a direction for the marching order of the selected tokens
* or the name of a token for the selected tokens to follow behind.
*
* E.G. "!follow west" will make the selected tokens follow each other in order
* from east to west, with the westmost token being the leader and the eastmost
* token being the caboose.
* Alternatively if we want the selected tokens to follow a character named
* "Drizt", enter the command "!follow Drizt".
*
* !follow [north|south|east|west|name of leader token]
*
* To make a token stop following the token in front of it, just manually move
* the token anywhere.
*/
/** Helper function: Makes one token follow another token. */
var _followCmd = function(leader, follower) {
if(!leader || !follower) {
return;
}
// unbind all of cur's following links.
_unfollowCmd(follower);
var prevFollower = leader.follower;
follower.leader = leader;
follower.follower = prevFollower;
leader.follower = follower;
if(prevFollower) {
prevFollower.leader = follower;
}
}
/**
* Helper method for making a character token stop following another token
* and stopped being followed by another token.
*/
var _unfollowCmd = function(token) {
if(token.leader) {
token.leader.follower = token.follower;
}
if(token.follower) {
token.follower.leader = token.leader;
}
token.leader = null;
token.follower = null;
}
/** Interpret the chat commands. */
on("chat:message", function(msg) {
var cmdName;
var msgTxt;
if(!msg.selected || msg.selected.length == 0) {
return;
}
cmdName = "!follow";
msgTxt = msg.content;
if(msg.type == "api" && msgTxt.indexOf(cmdName) !== -1) {
var curPageID = Campaign().get("playerpageid");
// A direction can be given for the marching order since
// the msg.selected array is in no particular order.
var direction;
if(msgTxt.indexOf("north") !== -1) {
direction = "north";
}
else if(msgTxt.indexOf("south") !== -1) {
direction = "south";
}
else if(msgTxt.indexOf("west") !== -1) {
direction = "west";
}
else if(msgTxt.indexOf("east") !== -1) {
direction = "east";
}
// Get the tokens for the selected objects.
var selected = msg.selected;
var marchingOrder = [];
for(var i=0; i<selected.length; i++) {
var token = findObjs({
_id: selected[i]._id,
_pageid: curPageID
})[0];
marchingOrder.push(token);
}
// Sort the marching order in the specified direction.
if(direction !== undefined) {
marchingOrder.sort(function(a,b) {
var aX = parseFloat(a.get("left"));
var bX = parseFloat(b.get("left"));
var aY = parseFloat(a.get("top"));
var bY = parseFloat(b.get("top"));
if(direction === "north") {
return (aY - bY);
}
else if(direction === "south") {
return (bY - aY);
}
else if(direction === "west") {
return (aX - bX);
}
else {
return (bX - aX);
}
});
}
// Alternatively, we can tell the tokens to follow a character given
// by name.
else {
var leader = findObjs({
name: msgTxt.substr(cmdName.length+1),
_pageid: curPageID
})[0];
if(leader === undefined) {
var playerName = msg.who;
if(playerName.indexOf(" ") !== -1) {
playerName = playerName.substring(0, playerName.indexOf(" "));
}
sendChat("A mysterious voice", "/w " + playerName + " Invalid " +
"command. After the command enter either north, south," +
" east, or west for the direction of the marching order, " +
"or the name of a character to follow.");
return;
}
else {
marchingOrder.unshift(leader);
}
}
// Set up the marching order from leader to caboose.
for(var i=0; i<marchingOrder.length - 1; i++) {
var leader = marchingOrder[i];
var follower = marchingOrder[i+1];
sendChat("", follower.get("name") + " is following " + leader.get("name"));
_followCmd(leader, follower);
}
}
});
/** Do the marching order effect when the leader tokens move! */
on("change:graphic", function(obj, prev) {
var leader = obj;
var follower = leader.follower;
leader.prevLeft = prev["left"];
leader.prevTop = prev["top"];
leader.prevRotation = prev["rotation"];
// Only move the followers if there was a change in either the leader's
// left or top attributes.
if(leader.get("left") == leader.prevLeft && leader.get("top") == leader.prevTop) {
return;
}
// We stepped out of line. Stop following the guy in front of us.
if(leader.leader) {
_unfollowCmd(leader);
}
// move everyone to the previous position of the token in front of them.
while(follower) {
follower.prevLeft = follower.get("left");
follower.prevTop = follower.get("top");
follower.prevRotation = follower.get("rotation")
follower.set("left",leader.prevLeft);
follower.set("top",leader.prevTop);
follower.set("rotation", leader.prevRotation);
leader = follower;
follower = follower.follower;
// avoid cycles.
if(follower == obj) {
return;
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment