Ha! In spite of his efforts to confuse and confound me... I have managed to eke out a win of sorts...
var macroScroll = macroScroll || {};
on("chat:message", function(msg) {
if(msg.type == "api"){
if(msg.content.indexOf(' ') == -1){
var msgMessage = null;
var msgApiCommand = msg.content.substr(1, msg.content.length);
}else{
var msgMessage = msg.content.substr(msg.content.indexOf(' ') + 1);
var msgApiCommand = msg.content.substr(1, msg.content.indexOf(' ')-1);
};
macroScroll.Playerid = msg.playerid;
if(msgApiCommand == "macroids"){
macroScroll.utilityScroll = "API_Utility_Scrolling_Macro_Bar";
macroids();
};
if(msgApiCommand == "macroleftone"){
macroleft(1);
macroupdate();
};
if(msgApiCommand == "macrorightone"){
macroright(1);
macroupdate();
};
if(msgApiCommand == "macroleftmany"){
macroleft(3);
macroupdate();
};
if(msgApiCommand == "macrorightmany"){
macroright(3);
macroupdate();
};
};
});
macroids = function(msg) {
var findPlayers = findObjs({_type: "player",});
var findMacros = findObjs({_type: "macro",});
var playerCode = "<code>"
playerCode = playerCode + "Refresh using \"!macroids\""
playerCode = playerCode + "</code><br><br>"
_.each(findMacros, function(loopMacros) {
if(loopMacros.get("action").length == 0){
var createrid = loopMacros.get("_playerid")
var createrR20id = "Unknown";
var createrDname = "Unknown";
_.each(findPlayers, function(loopPlayer) {
if(loopPlayer.get("_id") == createrid){
createrDname = loopPlayer.get("_displayname");
createrR20id = loopPlayer.get("_id");
}
});
playerCode = playerCode + "<code>"
playerCode = playerCode + loopMacros.get("name") + " _id = " + loopMacros.get("_id") + "<br>";
playerCode = playerCode + createrDname + " _id = " + createrR20id + "<br>";
playerCode = playerCode + "</code></br><br>"
};
});
if(findObjs({ _type: "handout", name: macroScroll.utilityScroll }).length == 0){
createObj("handout", {
name: macroScroll.utilityScroll,
});
};
APIPlayerCode = findObjs({ _type: "handout", name: macroScroll.utilityScroll })
APIPlayerCode[0].set("notes", playerCode);
};
macroleft = function(repeat) {
var characterid = undefined;
var findCharacter = findObjs({_type: "character", name: macroScroll.Playerid});
var characterid = findCharacter[0].get("_id");
if(characterid !== undefined){
var findAbility = findObjs({_type: "ability", _characterid: characterid});
var nameArray = [];
var actnArray = [];
for (var abilityCount = 0;abilityCount<findAbility.length;abilityCount++){
nameArray[abilityCount] = findAbility[abilityCount].get("name");
actnArray[abilityCount] = findAbility[abilityCount].get("name");
};
var i = 0;
while (i < repeat) {
nameArray.push(nameArray.shift());
actnArray.push(actnArray.shift());
i++;
};
for (var abilityCount = 0;abilityCount<findAbility.length;abilityCount++){
findAbility[abilityCount].set({name: nameArray[abilityCount]});
findAbility[abilityCount].set({name: actnArray[abilityCount]});
};
};
};
macroright = function(repeat) {
var characterid = undefined;
var findCharacter = findObjs({_type: "character", name: macroScroll.Playerid});
var characterid = findCharacter[0].get("_id");
if(characterid !== undefined){
var findAbility = findObjs({_type: "ability", _characterid: characterid});
var nameArray = [];
var actnArray = [];
for (var abilityCount = 0;abilityCount<findAbility.length;abilityCount++){
nameArray[abilityCount] = findAbility[abilityCount].get("name");
actnArray[abilityCount] = findAbility[abilityCount].get("name");
};
nameArray.reverse()
actnArray.reverse()
var i = 0;
while (i < repeat) {
nameArray.push(nameArray.shift());
actnArray.push(actnArray.shift());
i++;
};
nameArray.reverse()
actnArray.reverse()
for (var abilityCount = 0;abilityCount<findAbility.length;abilityCount++){
findAbility[abilityCount].set({name: nameArray[abilityCount]});
findAbility[abilityCount].set({name: actnArray[abilityCount]});
};
};
};
macroupdate = function() {
var characterid = undefined;
var findCharacter = findObjs({_type: "character",name: macroScroll.Playerid});
var characterid = findCharacter[0].get("_id");
var findAbility = findObjs({_type: "ability", _characterid: characterid});
if(characterid !== undefined){
var findAttribute = findObjs({_type: "attribute", _characterid: characterid});
var buttonidArray = [];
for (var attributeCount = 0;attributeCount<findAttribute.length;attributeCount++){
buttonidArray[attributeCount] = findAttribute[attributeCount].get("current");
};
};
for (var buttonCount = 0;buttonCount<buttonidArray.length;buttonCount++){
findObjs({_type: "macro", _id: buttonidArray[buttonCount]})[0].set({name: findAbility[buttonCount].get("name")});
findObjs({_type: "macro", _id: buttonidArray[buttonCount]})[0].set({action: findAbility[buttonCount].get("action")});
};
};
Step1) Make these buttons usable by all (share these)
[<<] action is
!macroleftmany[<] action is
!macroleftone[>] action is
!macrorightone[>>] action
is
!macrorightmanyStep2) makes these buttons usable only
(do not share these and should be made by the player who will own them.)
THE ACTION FOR THESE MUST BE BLANKStep3) enter the API command !macroids and look for hand out called API_Utility_Scrolling_Macro_Bar

This gives you all the button ids and user id (this is why the action needs to be blank so they can be found from any others)
Step4) Make a character sheet where the name is the player ID

The attributes is the array of button ids.... once set you never have to change or edit the API!!! Easy to add other players.
The abilities are now the macro array.... just build whatever you want here.... add or remove...
The [<<] [<] [>] [>>] scrolls these up and down too!!!
Here is how it looks at the start and stepped through....

Very little hard coding and its really to add the character sheets with a utility aid....
Just repeats steps 2, 3 4 for each player (players should build the buttons in step 2.)
Character creations APIs could be used to makes dozens of macros to scroll through.... and you still have room and can have non-scolling buttons...