[MACRO] debug tools - pause and watch (7-8-15)

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
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

[MACRO] debug tools - pause and watch (7-8-15)

Post by aliasmask »

There are some other debug tools out there, but I thought I'd share this simple one you can copy in to any lib token. Pause and Watch are essentially the same where pause will stop execution to show you the variables you want to watch. Hitting CANCEL will end execution and display the latest results in a dialog. Watch creates a dialog but you will only see the last result. This is good to use if you're getting an error somewhere and want to find out what the state of the variables are.

In order to use, copy the onCampaignLoad code to your onCampaignLoad macro and copy pause and watch to the lib token. You should manually run the onCampaignLoad the first time you want to use. You'll need to pass the "names" of the variables to the macros in quotes and not the actual variable. You'll get bad output, an error or prompts to enter variable data if you don't.

Example uses: wrote:[H: am.pause("var1","var2")]
[H: am.watch("var1","var2")]

Do not do this:
[H: am.pause(var1,var2)]
||| CODE |||

Code: Select all

@@ @onCampaignLoad
[H: this = getMacroLocation()]
[H: defineFunction("am.pause","pause@"+this,1,0)]
[H: defineFunction("am.watch","watch@"+this,1,0)]
[H: defineFunction("am.label","label@"+this,1)]

!!
@@ @pause
[H: sub_numVars = argCount()]
[H: sub_vars = "{}"]
[H, for(sub_i,0,sub_numVars): sub_vars = json.set(sub_vars,arg(sub_i),eval(arg(sub_i)))]
[H: sub_names = json.fields(sub_vars," ")]

[H: sub_output = "<pre>"+json.indent(replace(sub_vars,"<","<"))+"</pre>"]
[H: sub_output = replace(sub_output,decode("%0A"),"<br>")]
[H: sub_output = replace(sub_output,"     ","   ")]
[H: sub_output = replace(sub_output,"#","&#35")]
[H: sub_output = replace(sub_output,"\\|","&#124")]
[H: sub_output.proxy = replace(sub_output,"asset:","image:")]

[H: continue = input(strformat("Pause: %{sub_names}|<html><div width=800>%{sub_output.proxy}</div></html>||label|span=true"))]
[H, if(! continue), code: {
   [dialog("Pause: "+sub_names): {[r: strformat("<html><div width=800>%{sub_output}</div></html>")]}]
   [H: abort(0)]
};{}]

!!
@@ @watch
[H: sub_numVars = argCount()]
[H: sub_vars = "{}"]
[H, for(sub_i,0,sub_numVars): sub_vars = json.set(sub_vars,arg(sub_i),eval(arg(sub_i)))]
[H: sub_names = json.fields(sub_vars," ")]
[H: sub_output = replace(json.indent(replace(sub_vars,"<","<")),decode("%0A"),"<br>")]
[H: sub_output = replace(sub_output,"     ","   ")]
[dialog("Watch: "+sub_names): {[r: strformat("<html><div width=800>%{sub_output}</div></html>")]}]

!!
@@ @label
[H: label = arg(0)]
[dialog("Label"): {[r: label]}]

!!
edit: Updated pause function due to bug with special characters and changed function names to am.pause and am.watch so it doesn't conflict with other debug tools. BTW, the 3.5/pathfinder "pause" function had the same bug but mine works now.

edit: Added am.label() to functions. It's like watch but posts the value passed by label. I usually just put 1,2,3... to show how far I get in my code before trying to break down what's wrong. Also changed am.pause() because of the way image links are processed by input().

keywords: amsave tidbits debug
Attachments
lib-token.rptok
(83.64 KiB) Downloaded 192 times

User avatar
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by aliasmask »

Found a bug with special character. Original post updated with fix.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by wolph42 »

havent' checked but what the difference between your pause and the old one? I notice that you use a dialog vs input() but is there anything that makes yours *better* (e.g. more stable, robust, features, etc.)

User avatar
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by aliasmask »

Actually, pause does use input, but if you cancel it outputs a dialog of what you were just looking at.. the other doesn't. I also fixed a bug that the other one has.. use of ## or | in text blows stuff up. I actually like the other one's output a bit better, so I may update mine to something similar in the future rather than just using json.indent.

I also have a watch which is the dialog only. If something breaks, like in a loop, you can see exactly where in loop and what the values were when it breaks if you watch those variables.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by wolph42 »

aliasmask wrote:Actually, pause does use input, but if you cancel it outputs a dialog of what you were just looking at.. the other doesn't. I also fixed a bug that the other one has.. use of ## or | in text blows stuff up. I actually like the other one's output a bit better, so I may update mine to something similar in the future rather than just using json.indent.

I also have a watch which is the dialog only. If something breaks, like in a loop, you can see exactly where in loop and what the values were when it breaks if you watch those variables.
Ah ok. If you're interested I created something similar like this in the bot, called bot_debugInfo it has a buch of parameters to handle the output differently and it uses broadcast.

User avatar
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by aliasmask »

Dialog is a personal preference for me though and it gets the job done. I think just the format of output could be tweaked.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by wolph42 »

aliasmask wrote:Dialog is a personal preference for me though and it gets the job done. I think just the format of output could be tweaked.
ill have a look, curious what it looks like and there never can be enough debugging tools ;-)

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by wolph42 »

I don't know if it was intended to work as such, but I did a random test (just put the pause somewhere in the code and randomly picked two variables), this was the outcome:
Screenshot 2014-03-10 12.54.46.png
Screenshot 2014-03-10 12.54.46.png (30.73 KiB) Viewed 1554 times
(variables were 'activemaps' and 'txtOutput'). Especially with multiple variables with longer values it will be very hard to find the variable value combo in this. Even with this example it took me a while before I found 'txtOutput' ).

Is this supposed to happen?


edit: Next I tried 'watch' but that just gave me a blank dialog screen, that was filled after the code was done and only showed the last result (put it in a for loop). In this particular case my broadcast method has quite the advantage as it shows the result each step in the for loop (also AFTER the code is done). Maybe you can save the output to the dialog somewhere and show it in its entirety when done (so you create the same effect as I do with the broadcast).

User avatar
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MACRO] debug tools - pause and watch (3/9/14)

Post by aliasmask »

Yeah, my test only have 1 level before. I forget to put wrap json.indent in <pre> tag before. OP fixed. But this is typical output for json.indent for complex structures:
Spoiler

Code: Select all

{"PrivateJSON": {
"ActiveTempModSets": ["Flurry of Blows"],
"ActiveItems": [],
"CombatConfig":   {
    "fullRound": 1,
    "rangeIncrement": 0,
    "pointBlank": 0,
    "flurryRapid": 1,
    "favEnemy": 0,
    "sneak": "0d6",
    "fireIntoMelee": 0,
    "manyShot": 0,
    "critConfirm": 0,
    "modCritRange": 0
},
"CustomModSetValues":   {
    "Smite Evil":    {
       "mods":       {
          "MiscATK": {"v": 0},
          "MiscDMG": {"v": 1},
          "Deflection": {"v": 0}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> ShieldOfFaith</td></tr><tr><td align='left' valign='top'><b>MiscATK</b>: </td><td align='right'>  0</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>MiscDMG</b>: </td><td align='right'>  1</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>Deflection</b>: </td><td align='right'>  0</td><td align='left'><i>  Deflection</i></td></tr></table><table border='0' cellspacing='0' cellpadding='0' width='400px'><tr><td>DR bypassed, 2xDamage Bonus if evil outsider, evil dragon, or undead</td></tr></table>"
    },
    "Total Defense":    {
       "mods":       {
          "globalMod": {"v": 0},
          "Dodge": {"v": 4}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> TotalDefensive</td></tr><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  0</td></tr><tr><td align='left' valign='top'><b>MiscATK</b>: </td><td align='right'>-1000</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>Dodge</b>: </td><td align='right'>  4</td><td align='left'><i>  Dodge</i></td></tr></table>"
    },
    "Divine Grace":    {
       "mods":       {
          "globalMod": {"v": 5},
          "FortBonus": {"v": 5},
          "ReflexBonus": {"v": 5},
          "WillBonus": {"v": 5}
       },
       "f": 1,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  5</td></tr><tr><td align='left' valign='top'><b>FortBonus</b>: </td><td align='right'>  5</td><td align='left'><i>   Untyped</i></td></tr><tr><td align='left' valign='top'><b>ReflexBonus</b>: </td><td align='right'>  5</td><td align='left'><i>   Untyped</i></td></tr><tr><td align='left' valign='top'><b>WillBonus</b>: </td><td align='right'>  5</td><td align='left'><i>   Untyped</i></td></tr></table>"
    },
    "Strength Damage":    {
       "mods":       {
          "globalMod": {"v": -2},
          "StrMod": {"v": -2}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> StatDmg</td></tr><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  -2</td></tr><tr><td align='left' valign='top'><b>StrMod</b>: </td><td align='right'>  -2</td><td align='left'><i>  Untyped</i></td></tr></table>"
    },
    "Shawl Of Life-Keeping":    {
       "mods": {"globalMod": {"v": 10}},
       "f": 1,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'>  Protection from Negative Energy</td></tr><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  10</td></tr></table>"
    },
    "Haste":    {
       "mods":       {
          "Base": {"v": 30},
          "Burrow": {"v": 0},
          "Climb": {"v": 0},
          "Swim": {"v": 0},
          "Fly": {"v": 0}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'>  Haste</td></tr><tr><td align='left' valign='top'><b>ReflexBonus</b>: </td><td align='right'>1</td><td align='left'><i>   Untyped</i></td></tr><tr><td align='left' valign='top'><b>MiscATK</b>: </td><td align='right'>1</td><td align='left'><i>   Untyped</i></td></tr><tr><td align='left' valign='top'><b>Dodge</b>: </td><td align='right'>1</td><td align='left'><i>   Dodge</i></td></tr><tr><td align='left' valign='top'><b>Base</b>: </td><td align='right'>  30</td><td align='left'><i>   Enhancement</i></td></tr><tr><td align='left' valign='top'><b>Burrow</b>: </td><td align='right'>  0</td><td align='left'><i>   Enhancement</i></td></tr><tr><td align='left' valign='top'><b>Climb</b>: </td><td align='right'>  0</td><td align='left'><i>   Enhancement</i></td></tr><tr><td align='left' valign='top'><b>Swim</b>: </td><td align='right'>  0</td><td align='left'><i>   Enhancement</i></td></tr><tr><td align='left' valign='top'><b>Fly</b>: </td><td align='right'>  0</td><td align='left'><i>   Enhancement</i></td></tr></table><table border='0' cellspacing='0' cellpadding='0' width='400px'><tr><td>Multiple haste effects don’t stack. Haste dispels and counters slow.</td></tr></table>"
    },
    "Fear - Cowering":    {
       "mods": {"DexMod": {"v": -4}},
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> Fear</td></tr><tr><td align='left' valign='top'><b>DexMod</b>: </td><td align='right'>  -4</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>ACMod</b>: </td><td align='right'>-2</td><td align='left'><i>  Untyped</i></td></tr></table>"
    },
    "Fight Defensively":    {
       "mods":       {
          "globalMod": {"v": 1},
          "Dodge": {"v": 3}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> FightDefensively</td></tr><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  1</td></tr><tr><td align='left' valign='top'><b>MiscATK</b>: </td><td align='right'>-4</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>Dodge</b>: </td><td align='right'>  3</td><td align='left'><i>  Dodge</i></td></tr></table>"
    },
    "Paralyzed":    {
       "mods":       {
          "StrMod": {"v": -16},
          "DexMod": {"v": -14}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> Paralyzed</td></tr><tr><td align='left' valign='top'><b>StrMod</b>: </td><td align='right'>  -16</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>DexMod</b>: </td><td align='right'>  -14</td><td align='left'><i>  Untyped</i></td></tr><tr><td align='left' valign='top'><b>ReflexBonus</b>: </td><td align='right'>-100</td><td align='left'><i>  Untyped</i></td></tr></table><table border='0' cellspacing='0' cellpadding='0' width='400px'><tr><td>Str and Dex Score of 0. Helpless.</td></tr></table>"
    },
    "Divine Favor":    {
       "mods":       {
          "globalMod": {"v": 3},
          "MiscATK": {"v": 3},
          "MiscDMG": {"v": 3}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  3</td></tr><tr><td align='left' valign='top'><b>MiscATK</b>: </td><td align='right'>  3</td><td align='left'><i>   Luck</i></td></tr><tr><td align='left' valign='top'><b>MiscDMG</b>: </td><td align='right'>  3</td><td align='left'><i>   Luck</i></td></tr></table>"
    },
    "Wisdom Damage":    {
       "mods":       {
          "globalMod": {"v": -3},
          "WisMod": {"v": -3}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>State Icon</b>: </td><td align='left' colspan='2'> StatDmg</td></tr><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  -3</td></tr><tr><td align='left' valign='top'><b>WisMod</b>: </td><td align='right'>  -3</td><td align='left'><i>  Untyped</i></td></tr></table>"
    },
    "Bastion of Good":    {
       "mods":       {
          "globalMod": {"v": 6},
          "Deflection": {"v": 6}
       },
       "f": 0,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  6</td></tr><tr><td align='left' valign='top'><b>Deflection</b>: </td><td align='right'>  6</td><td align='left'><i>   Deflection</i></td></tr></table>"
    },
    "Flurry of Blows":    {
       "mods": {"globalMod": {"v":       {
          "mLVL": 9,
          "newBAB": 9,
          "baseBAB": 9,
          "baseTWF": 1,
          "baseITWF": 1,
          "baseGTWF": 0
       }}},
       "f": 1,
       "tip": "<table border='0' cellspacing='0' cellpadding='0'><tr><td align='left' valign='top'><b>globalMod</b>: </td><td colspan='2'>  {`mLVL`:9,`newBAB`:9,`baseBAB`:8,`baseTWF`:0,`baseITWF`:0,`baseGTWF`:0}</td></tr></table><table border='0' cellspacing='0' cellpadding='0' width='400px'><tr><td>Use Primary+Secondary weapons</td></tr></table>"
    }
}
}} 

I wrap the input in <div width=800> so it doesn't go off the screen with long strings.

Storing the variables, IMO is not really an option. It slows down the code and seeing the variables that do work doesn't usually help in debugging. But, in that case dumping to chat with broadcast is a better idea, but I think depending on the data that stack issues could arise.

For purdy output, I was thinking of putting data in to a table and coloring fields based on the data type and structure. That way, arrays will be in blue shades, objects in green (or whatever). json.indent doesn't linefeed arrays like it does object keys and it would be a pain to loop through arrays just to format that data, so I would leave it like that. Oh, I would also increase the indent like json.indent shows. Basically, I'll use json.indent as a template and then use strfind/replace and some clever regex to change the formatting elements.

User avatar
aliasmask
RPTools Team
Posts: 9149
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MACRO] debug tools - pause and watch (7-8-15)

Post by aliasmask »

Updated debug tools, but still keep'n it simple.

Post Reply

Return to “Macros”