Tricky Initiative Help

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Tricky Initiative Help

Post by Xaelvaen »

I have a very elaborate initiative macro that is kind of an all-in one. It tracks ongoing damage and healing, rolls a new initiative at the beginning of every round, functions as the next initiative, and puts a 'current' state on the currently active token as well as selecting the token automatically. It's big.

The problem is, I've never had a need (until now) of grouping creatures together in initiative of a given type. In example, if you have 3 zombies and 3 mummies, having all the zombies going at the same time and all the mummies going together, but at a separate initiative count - I've no clue how I would go about doing that.

Any suggestions of what sort of code to use in my macro to separate out all tokens of Y naming convention and assure they receive the same initiative, would be appreciated.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Tricky Initiative Help

Post by aliasmask »

You can give your groups some kind of tag and have a macro to set the grouping. You can make it a state like 1,2,3... or just a hidden property. When rolling initiate for a token you check the tag and if it has one then you save the value. I would use a json object where the key is the tag and the value is the initiative. So, if there is a tag you check the json for a matching key and if there use that init, otherwise add the tag as a new key, roll init and add the value to the json.

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Tricky Initiative Help

Post by Xaelvaen »

Thanks for the idea, Alias - I guess I could predict how many different groups I need ahead of time and program a finite amount? I doubt I'd ever need more than 4 groups, in example.

EDIT: Found the coding error, removed to keep on topic.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Tricky Initiative Help

Post by aliasmask »

You could make the tag whatever you want so a near infinite number of groups. I imagine you have a macro called "Group Up". You then select all the members of that group and click the macro. You can get fancy if you want and prompt for a group name, state, add to existing group, remove from group... stuff like that.

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Tricky Initiative Help

Post by Xaelvaen »

The reason for the limitation would be based on my own coding limitations. I'd have no idea how to call for a specific property to alter the initiative, unless the code knows the property value ahead of time. Like, if the token has this property/state/value, then use rollX, otherwise use the generic roll macro. That'd keep them uniform. Am I missing an easier approach? Then to group the creatures together, though, I'd have to make sure it checks for multiple different properties, and groups them together appropriately.

I just don't really know how I'd do that without the specific types already programmed into the initiative macro.

To clarify, I don't need the coding done for me by any means, but just pointing me at the actual function is a big help - the updating documentation wiki has gone a long way in helping me figure out new methods, just gotta know where to look first.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Tricky Initiative Help

Post by aliasmask »

One of the most helpful coding basics is getData, processData and outputData. You may want to check out this POST I did awhile ago including related links. That's essentially the order of things for most programs. So, you get all the data you're going to need before you even start processing. You'll need to get all the info in the initiative list first which includes the tokenId. Then you can loop through the tokenIds to get the tags.

Specifically you'll need Wiki: getInitiativeList() which gets all the tokens in the initiative in order as a json object with an array of objects.
||| Example |||

Code: Select all

{
    "round": 3,
    "map": "Catacombs",
    "current": 2,
    "tokens":     [
                {
            "holding": false,
            "tokenId": "000000008EC5BE80F40A000000000000"
        },
                {
            "holding": false,
            "tokenId": "0000000092C5BE801C0B000000000000"
        },
                {
            "holding": false,
            "tokenId": "000000009BC5BE80400B000000000000"
        },
                {
            "holding": false,
            "tokenId": "00000000C1C5BE80140C000000000000"
        },
                {
            "holding": false,
            "tokenId": "00000000A0C5BE805C0B000000000000"
        },
                {
            "holding": false,
            "initiative": "6.02",
            "tokenId": "000000009DC5BE80420B000000000000"
        }
    ]
}
So, to get the tokenIds and resort your initiative would go something like this:

Code: Select all

<!-- initList is a json array -->
[H: initList = json.get(getInitiativeList(),"tokens")]

<!-- ## create new initiatives but check for group tags ## -->

<!-- groupInitData holds the tag and init of any tokens in a group -->
[H: groupInitData = "{}"]

<!-- hold the tokenIds and new inits in a json before processing -->
[H: newInitOrder = "[]"]

<!-- loop through current init list -->
[H, foreach(tokenData,initList), code: {
   [H: tokenId = json.get(tokenData,"tokenId")]
    [H: switchToken(tokenId)]
    
    <!-- check for group tag -->
    [H: groupTag = getProperty("groupTag")]
    
    <!-- decide to set a new initiative or use a group initiative -->
    [H, if(json.contains(groupInitData,groupTag)), code: {
        <!-- group tag found, so set init instead of rerolling -->
        [H: newInit = json.get(groupInitData,groupTag)]
    };{
        <!-- get new init. I assume you have a function for this already -->
        [H: newInit = am.xx.rollTokenInit(tokenId)]
        
        <!-- check for group and add to groupInitData if needed -->
        [H, if(! json.isEmpty(groupTag)): groupInitData = json.set(groupInitData,groupTag,newInit)]    
    }]
    
    <!-- set token init -->
    [H: newInitOrder = json.append(newInitOrder,json.set("{}","tokenId",tokenId,"init",newInit))]    
}]

<!-- sort new init order -->
[H: newInitOrder = json.sort(newInitOrder,"d","init")]

<!-- set new initiatives and resort -->
[H, foreach(tokenData,newInitOrder), code: {
    [H: switchToken(json.get(tokenData,"tokenId"))]
    [H: setInitiative(json.get(tokenData,"init"))]
}]

[H: sortInitiative()] 
You probably have to set the new round and current init as well, but this should get you started.

*edit* PS, I did this all without testing and it will have to be adapted to your existing code. I've already correct a couple of errors but should be good now.

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Tricky Initiative Help

Post by Xaelvaen »

Spoiler

Code: Select all

[h: card_list="C2,C3,C4,C5,C6,C7,C8,C9,C10,CJ,CQ,CK,CA,JK"]
[h: init=getInitiativeList()]
[h: initiativeList=json.get(init,"tokens")]

	[h, if(json.isEmpty(initiativeList)==1), CODE:{

		[h: token_List=getSelected()]
		[foreach(token,token_List,""), CODE:{
			[h, token(token) : addToInitiative()]
		}]
	[h: init=getInitiativeList()]
	[h: initiativeList=json.get(init,"tokens")]
	}]

[h: currentPhase=json.get(init,"current")]
[h: tokenList=""]
[foreach(init,initiativeList,""), CODE:{
	[h: tokenID=json.get(init,"tokenId")]
	[h: tokenList=json.append(tokenList,tokenID)]
}]
[h: tokenList=json.unique(tokenList)]

[r, if(currentPhase=="-1"), CODE:{
	[h: setInitiativeRound(1)]
	[foreach(tokenID,tokenList,""), CODE:{
		[h, token(tokenID) : type=getPropertyType()]
		[h: jokerRoll=1d52]
		[h: roll=1d13]
		[h: jokerCheck=if(jokerRoll>50,14,roll)]
		[h: rawk=input(
"junk|<html><b>Numbers Range 1 - 14</b></html>|-|LABEL|SPAN=TRUE",
"setROLL|" +jokerCheck +"|Manually Input Initiative for " +getName(tokenID) +"|TEXT|WIDTH=3")]
		[h: abort(rawk)]
		[h: total=setRoll]
		[h: chosen_card=listGet(card_list,total-1)]
		[h, token(tokenID) : setState(chosen_card,1)]
		[h, token(tokenID) : setInitiative(total)]
	}]

	[h: sortInitiative()]
	[h: setCurrentInitiative(0)]
	[h: curToken=getInitiativeToken()]
	[h, token(curToken) : type=getPropertyType()]
	[h, token(curToken) : setState("Current",1)]
	[h, if(type=="PC"), CODE:{
	[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" has received Initiative.")]
	};{
	[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" has received Initiative.","gm")]
	}]
	[h, MACRO("charCheck@Lib:Forms") : ""]

};{}]

[h: initSize=initiativeSize()]

[r, if(currentPhase==initSize-1),CODE:{

	[h: curToken=getInitiativeToken()]
	[h, token(curToken) : setState("Current",0)]
	[h, token(curToken) : initNumber=getInitiative()]
	[h: initCheck=initNumber-1]
	[h: chosen_card=listGet(card_list,initCheck)]
	[h, token(curToken) : setState(chosen_card,0)]
	[h: init=getInitiativeList()]
	[h: initiativeList=json.get(init,"tokens")]
	[h: tokenList=""]
	[h: initList=""]
	
	[foreach(init,initiativeList,""), CODE:{
		[h: tokenID=json.get(init,"tokenId")]
		[h: tokenList=listAppend(tokenList,tokenID)]
		[h: tokenInitiative=json.get(init,"initiative")]
		[h: initList=listAppend(initList,tokenInitiative)]
	}]

	[h: dis=getInitiativeRound()]
	[h: setInitiativeRound(sum(dis+1))]

	[h: removeAllFromInitiative()]
	[h: currentRound=dis]
	[h: setInitiativeRound(currentRound +1)]
	
	[foreach(tokenID,tokenList,""), CODE:{
		[h, token(tokenID) : addToInitiative()]
		[h: jokerRoll=1d52]
		[h: roll=1d13]
		[h: jokerCheck=if(jokerRoll>50,14,roll)]
		[h: rawk=input(
"junk|<html><b>Numbers Range 1 - 14</b></html>|-|LABEL|SPAN=TRUE",
"setROLL|" +jokerCheck +"|Manually Input Initiative for " +getName(tokenID) +"|TEXT|WIDTH=3")]
		[h: abort(rawk)]
		[h: total=setRoll]
		[h: chosen_card=listGet(card_list,total-1)]
		[h, token(tokenID) : setState(chosen_card,1)]
		[h, token(tokenID) : setInitiative(total)]
	}]
		
	[h: sortInitiative()]
	[h: setCurrentInitiative(0)]
	[h: curToken=getInitiativeToken()]
	[h, token(curToken) : type=getPropertyType()]
	[h, token(curToken) : setState("Current",1)]
	[h, if(type=="PC"), CODE:{
	[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" has received Initiative.")]
	};{
	[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" hase received Initiative.","gm")]
	}]
	};{}]

[r, if(currentPhase>-1 && currentPhase<initSize-1), CODE:{
	[h: curToken=getInitiativeToken()]
	[h, token(curToken) : setState("Current",0)]
	[h, token(curToken) : initNumber=getInitiative()]
	[h: initCheck=initNumber-1]
	[h: chosen_card=listGet(card_list,initCheck)]
	[h, token(curToken) : setState(chosen_card,0)]	
	[h: nextInitiative()]
	[h: curToken=getInitiativeToken()]
	[h, token(curToken) : type=getPropertyType()]
	[h, token(curToken) : setState("Current",1)]
		[h, if(type=="PC"), CODE:{
			[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" has received Initiative.")]
		};{
			[h: broadcast(macroLink(getName(curToken),"charCheck@Lib:Forms","","",curToken) +" has received Initiative.","gm")]
		}]
	[h, MACRO("charCheck@Lib:Forms") : ""]
	};{}]

[h: curToken=getInitiativeToken()]
[h: selectTokens(curToken)]
[h, MACRO("charCheck@Lib:Forms") : ""]
Yeah, I have all the initiative functions, removing and re-adding, so forth and so on (above is the code). I'm now focusing on the part where you're getting the group tags.

So if I were to create a property (your groupTag in example), and then give it a variable (1, 2, 3, 4, etc), is there a way to simply see if a property has a value on a token? Something like the json.isEmpty command? If so, I think I can use your example in my above initiative easily.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Tricky Initiative Help

Post by aliasmask »

Yes, the json.isEmpty is how I check for a blank value. Putting ==1 is just being redundant in the code and isn't needed. The function returns a 0 or a 1 which equates to a false or true respectively. If you want to take the reverse case, just put ! json.isEmpty.

You'll have to set the tags in a completely separate action. I assume before the first initiative is rolled, so it shouldn't be integrated with your existing code but rather be it's own macro.

The most basic would be take the selected tokens and apply a value to them randomly.

Code: Select all

[H: tokens = getSelected()]
[H: groupId = 1d10000000000]
[H, foreach(tokenId,tokens): setProperty("groupTag",groupId,tokenId)]

User avatar
Xaelvaen
Dragon
Posts: 498
Joined: Wed Aug 31, 2011 9:49 pm
Location: Somewhere between Heaven and Hell

Re: Tricky Initiative Help

Post by Xaelvaen »

I use a 'create monster' type of macro, so I can add a 'set group tag' function there. I suppose, since all monsters I use get cycled through this macro, I could assign a group tag value, with individual monsters having a tag of 0, and then assign all creatures of tag X with the roll. Okay, at least I have a grasp on the direction here - thanks once again, Aliasmask.

As for the redundant factor, just an old habit from less efficient codes from the late 90s - I'll remember to ignore that (or try to; habits die hard) for the future.
"An arrogant person considers himself perfect. This is the chief harm of arrogance. It interferes with a person's main task in life - becoming a better person." - Leo Tolstoy

Post Reply

Return to “Macros”