Sample of a UDF?

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
xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Sample of a UDF?

Post by xavram »

I'm looking at the wiki for define function and I must not be getting it. I don't see how, once you define it, you can then call it while passing in arguments...or getting results from it.

Does anyone have a sample of how to set this all up? Including how to "set" these at the "onCampaignLoad" call?

Also, what is the purpose of creating these? Do they improve code performance or is just a convenience thing?

Appreciate the info!

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

Re: Sample of a UDF?

Post by wolph42 »

well i guess you found this:
defineFunction(function, macro, ignoreOutput, newScope)

so

defineFunction("myMacro@lib:whatever", "myMacro", 1, 0)

which allows you to use
myMacro(1,"a")
instead of
macro("myMacro@lib:whatever"):json.append("",1,"A")

inside myMacro you simply call:
firstArg = arg(0)
secondArg = arg(1)
which will make firstArg==1 and secondArg=="a"

it will improve performance and it is convenient.
e.g. you can do
if(myMacro(1,2) == "someResult"):doThis() ; doThat()
which is not possible with the macro roll option.

clear?

note that the macro is defined AFTER onCampaignLoad has been run, which happens...on campaign load...go figure. You can also run it manually once.
also in case its not clear:
ignore output will ignore ANY output to chat in myMacro so
[r:"sho this"] inside myMacro will not show. The ONLY way to return a value is
[macro.return=result] which will return 'result' when you call the macro.
newScope means that the scope from within myMacro is called is NOT available so
[a=1]
[myMacro(1,"g")]
the value 'a' will NOT be available inside myMacro. set newScope to 0 and 'a' WILL be available inside!!

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

Re: Sample of a UDF?

Post by aliasmask »

I have a starter token you can use. It essentially makes all your macros UDF functions. All you have to do is set the prefix for the function in onCampaignLoad. Default is xx.lib., so if you make a macro named getStuff then you can call it from another macro as xx.lib.getStuff(). Or whatever you set the prefix to.

I also included some basic debug macros named label(string/number), pause(varName,...) and watch(varName,...) where label just outputs the string or number you pass it to know you made it that far. The varName is the variable you want to see, but in quotes. So, if you want to see your counter variable you would put [H: xx.lib.pause("counter")].

The onCampaignLoad UDF sets the default of all functions to no output, so I also included a generic output.basic() function. It looks like the normal MT output except the token image has alt text that shows the players name. Also, you can specify the targets of the output based on ownership of token using "owner" and "other" for non-owners. It can also subtract players from output list like -gm, -self. You can read the macro comments for more details in all the above macros.
Attachments
starter lib token.rptok
(83.63 KiB) Downloaded 82 times

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

Thanks guys, I'll dig into all this.

One last question on the UDF thing. Because of the "2 loop max" limitation in Maptool, I have a macro, that calls another, that calls another. Do ALL of them have to be UDFs? Or just the "top level" one?

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

Re: Sample of a UDF?

Post by aliasmask »

xavram wrote:Thanks guys, I'll dig into all this.

One last question on the UDF thing. Because of the "2 loop max" limitation in Maptool, I have a macro, that calls another, that calls another. Do ALL of them have to be UDFs? Or just the "top level" one?
There's a two {} nesting limit per macro. So, logically, you can go as deep as you want. It's the parser that limits the {}s. Also, the source of {} don't matter. Could be from any roll option or just {} in an html comment (where code is still executed). Personally, I almost never use [macro:] unless I'm forced to, like in a form submit or tweaking someone else's code.

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

Hmmm...so I put this in my "onCampaignLoad" macro...

[h : defineFunction("Orientation@lib:Math", "Orientation", 1, 0)]

...and then closed/restarted my campaign. Then I tried to call it, like so...

[h : intersectionResult = Orientation(pointP, pointQ, pointR, pointZ)]

...but in the chat window, I get back "Undefined function : Orientation".

This seems like it should be fairly straightforward, any ideas why this wouldn't be working? I know that the "onCampaignLoad" macro is being called because it creates an HTML form when the campaign is loaded.

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

Re: Sample of a UDF?

Post by aliasmask »

You example here looks right. Make sure the casing is correct in actual code for one. Also, turn off player editable on Orientation macro.

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

Ugh, what the heck...I changed the name of the macro to "ABC" (in all references), just to ensure I wasn't misnaming something but its still throwing the same "Undefined function".

Where is the "player editable" toggle for a macro? Only thing checked off on the "ABC" macro is "Auto Execute" checkbox.

Wouldn't you know that when i finally have time to implement the advice that everyone has been giving ("You should really change all these macros to UDFs"), I run into a problem on the very first one? :)

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

Re: Sample of a UDF?

Post by aliasmask »

Well, you could look at the Wiki: getInfo() and it will tell you all the defined udfs. This does sound familiar, like something I've done and I think it was an easy fix. The Allow Players to Edit is in the properties | options of the macro.

Code: Select all

[dialog("D"):{<pre>[R: json.indent(replace(getInfo("server"),"<","<"))]</pre>}]

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

So, doesn't look like any UDFs are being created...

{
"timeInMs": 1487012281830,
"restricted impersonation": 0,
"tooltips for default roll format": 1,
"movement locked": 0,
"initiative owner permissions": 0,
"gm": ["jramirez"],
"individual views": 0,
"movement metric": "ONE_TWO_ONE",
"players can reveal": 0,
"strict token management": 0,
"players receive campaign macros": 0,
"timeDate": "2017-02-13 11:58:01"
}

The only place I could find some kind of "Allow Players to Edit Macros" was in Preferences...but I don't think that's where you're talking about when you say "is in the properties | options of the macro". When I edit the macro, I see no flag/checkbox for this...am I missing something obvious?

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

Re: Sample of a UDF?

Post by aliasmask »

Sorry, brain fart. It should be "client" not "server" info.

Code: Select all

{
    "timeInMs": 1487022662329,
    "client id": "b1a1fc2e-5092-457e-82dd-f95047b1a39e",
    "library tokens":     {
        "Lib:CannedSpeech_v1": "unknown",
        "Lib:inventory": "unknown",
        "lib:player_Nicholas": "unknown",
        "Lib:Magic": "unknown",
        "lib:player_DM": "unknown",
        "Lib:Play": "unknown",
        "Lib:libDnD35Pathfinder": "unknown",
        "lib:player_Ray": "unknown",
        "lib:rpedit": "unknown",
        "Lib:spells": "unknown",
        "lib:healbot": "unknown",
        "Lib:Spell_database": "unknown",
        "Lib:debugger": "unknown",
        "Lib:msg_mngr": "unknown",
        "lib:players": "unknown",
        "lib:dialog": "unknown",
        "lib:DM": "unknown",
        "lib:player_Sage": "unknown",
        "Lib:UDFunctionsLGM": "unknown",
        "lib:token": "unknown",
        "lib:pathfinder": "unknown",
        "lib:skills": "unknown",
        "lib:player_Trey": "unknown",
        "lib:pf_Feats": "unknown",
        "lib:disguise": "unknown",
        "lib:pf_Skills": "unknown",
        "Lib:GlobalsSRDPF": "unknown",
        "lib:player_Chris": "unknown",
        "lib:player_Nick": "unknown",
        "Lib:cifTemplates": "unknown",
        "Lib:SpeakForMe": "unknown",
        "Lib:spells3": "unknown",
        "lib:player_Bryan": "unknown",
        "Lib:TokenManager_v2.0": "unknown"
    },
    "user defined functions":     [
        "math.isOdd",
        "am.dialog.oneClick",
        "am.play.ClearSoftFog",
        "am.play.updateGMs",
        "SpellLibrary",
        "am.play.imageHeader",
        "dbxLaunch",
        "Config_Library",
        "am.play.popup",
        "am.rpe.strComment",
        "am.play.getServerName",
        "json.pappend",
        "am.play.initServer",
        "json.psort",
        "am.play.onTokenMove",
        "am.rpe.getGroups",
        "json.sort",
        "am.play.isTokenId",
        "am.rpe.reformatMacroOutput",
        "am.hb.onCampaignLoad",
        "am.play.watch",
        "am.dialog.parseDialog",
        "glp",
        "getSpellIndex",
        "am.getModStamp",
        "am.play.updateTargets",
        "am.pf.onCampaignLoad",
        "am.defineTokenCoords.sub",
        "am.getMonsterXp",
        "framePopup",
        "am.rpe.onCampaignLoad",
        "distanceStatSheet",
        "json.fromMacros",
        "am.play.fixPath",
        "am.rpe.local.loadOptions",
        "am.play.output.icc",
        "json.type",
        "am.label",
        "am.play.getGMNames",
        "getSkillCheckLink",
        "InfoBank",
        "am.pf.editClass",
        "am.play.formatChatText",
        "oneClickLink",
        "mil",
        "json.reverse",
        "am.play.gotoMap",
        "am.play.multiSelectChange",
        "am.rpe.slp",
        "am.play.gotoMapLink",
        "am.play.getServerTime",
        "replaceStr",
        "rspk.displaySpeech",
        "am.hb.getStatusImage",
        "am.hb.tokenUpdate",
        "xx.lib.reload",
        "am.hb.saveSettings",
        "json.pRemove",
        "am.dialog.rawDialog",
        "reduceSpeedStep",
        "refresh",
        "cl",
        "am.rpe.configOptions",
        "am.play.runOnServer",
        "am.hb.cureSpell.tab",
        "am.play.getServerProperty",
        "am.play.onMultipleTokensMove",
        "displayDebug",
        "am.play.icc",
        "am.pfStatBlockImport",
        "xx.lib.label",
        "am.rpe.tool.editButtons.form",
        "am.hb.getHealTargets",
        "am.pf.initWeaponData",
        "am.pause",
        "am.rpe.closeOpenFrames",
        "xx.lib.getPlayerGroups",
        "list.difference",
        "am.rpe.setMinWidths",
        "rspk.speakForDialog",
        "json.insert",
        "getLibPlayerPref",
        "am.gotoSelect",
        "am.damageLink",
        "json.toTooltip",
        "am.rpe.openDebugger",
        "am.pf.initClasses",
        "am.play.label",
        "json.pAppend",
        "am.rpe.getStdMinWidth",
        "myEval",
        "am.rpe.formatAll",
        "am.play.varsToJson",
        "dbxOutputTo",
        "am.dialog.getSkillCheckLink",
        "tabSetup",
        "am.dialog.oneClickLink",
        "rspk.createSpeakDialog",
        "am.output.basic",
        "am.play.output",
        "am.rpe.debug",
        "get.targets",
        "am.rpe.verifyId",
        "am.dialog.uglySkillCheck",
        "am.sk.SkillCheck",
        "listDelete.trim",
        "am.rpe.addDebug",
        "am.rpe.processForm",
        "am.play.saveChatTranscripts",
        "css.main",
        "json.toVars",
        "skillRoll",
        "am.toggleMod",
        "am.play.configLibProperties",
        "math.mod",
        "r.currentToken",
        "am.hb.output.basic",
        "am.play.cleanVar",
        "am.pf.createItemId",
        "am.hb.lifelink.tab",
        "json.pGet",
        "am.hb.customCure.tab",
        "am.setModStamp",
        "am.play.output.room",
        "am.hb.settings.tab",
        "am.slopeRangeCheck",
        "editSpeech",
        "am.hb.lifelink.process",
        "am.play.findTokenMap",
        "roundPoint",
        "am.play.spanBlockHtml.sub",
        "am.hb.getPlayerGroups",
        "am.hb.getSettings",
        "getFeat",
        "am.play.INSPECT",
        "am.hb.healBot.defaults",
        "am.play.splashScreen",
        "am.play.PLAYERSWIP",
        "am.play.gotoLibMap",
        "am.play.clearSoftFOW",
        "am.play.jsonToVars",
        "am.play.multiDeselectChange",
        "am.sk.setSkills",
        "am.dialog.uniqueSaveCheck",
        "am.play.VBLMove",
        "json.fromMacros.withProps",
        "am.rpe.setStandardButtons",
        "am.play.isServer",
        "json.pget",
        "jaw.cspeech.displayPrefs",
        "am.play.Impersonate",
        "am.play.getPlayerProperty",
        "am.play.onCampaignLoad",
        "am.rpe.debugReport",
        "am.play.confusionMessage",
        "am.pf.cleanProp",
        "am.getFlankers",
        "canUseResetProperty",
        "getSpellName",
        "am.play.serverOnly",
        "am.play.setPlayerProperty",
        "am.dialog.onCampaignLoad",
        "am.play.deferFunction",
        "xx.lib.pause",
        "mod",
        "am.dialog.uglySaveCheck",
        "am.toggleItem",
        "uglySkillCheck",
        "am.rpe.refreshGroups",
        "am.lifelink",
        "am.play.setTokenXY",
        "am.hb.merciesTip",
        "redefined_1_debug",
        "am.rpe.parseMacros",
        "adjustHP",
        "am.watch",
        "am.changeElevation",
        "am.rpe.local.loadGroupsMenu",
        "am.rpe.editTokenMacros",
        "am.rpe.watch",
        "createMacro.u",
        "xx.lib.output.basic",
        "setPageCache",
        "am.pf.deleteClass",
        "slp",
        "am.hb.clericChannel.tab",
        "am.tabTable",
        "am.play.errorMessage",
        "am.hb.reload",
        "am.play.saveChat",
        "am.rpe.tool.editButtons.link",
        "am.play.tokenHeader",
        "am.play.PFConfusion",
        "am.rpe.tool.editButtons",
        "CannedSpeech.ui",
        "am.play.createToken",
        "getSeenTokens",
        "am.play.openSelectFrame",
        "am.play.onSelectToken",
        "am.rpe.selectMacroIndexes",
        "am.rpe.glp",
        "am.play.inspectToken",
        "am.play.inspectAll",
        "redefined_0_json.paths",
        "json.ifGet",
        "am.play.moveVBLToken",
        "am.isFlanking",
        "am.play.waitForServer",
        "am.hb.layOnHands.tab",
        "setLibPlayerPref",
        "getBody",
        "am.play.autoExecute",
        "am.rpe.openFrame",
        "saySpeech",
        "am.dm.disguiseMacro",
        "l.decode",
        "am.play.setAsServer",
        "outputTo",
        "am.play.deferVBLMove",
        "getShortDescription",
        "math.div",
        "libAttack.sub",
        "searchSpellLink",
        "math.dim",
        "am.play.setServerProperty",
        "am.play.getTokenInfo",
        "constructMacro",
        "rspk.getMyTokens",
        "am.play.hasServer",
        "list.unique",
        "msl",
        "am.hb.healBot",
        "json.layout.editable",
        "am.pf.addWeapon",
        "am.mirrorImage",
        "am.hasHighGround",
        "am.play.validateTokenInfo",
        "cif.t.removeTemplate",
        "am.play.serverTest",
        "manageSpeech",
        "am.play.doVBLMove",
        "am.play.execFunction",
        "am.hb.channel.process",
        "displaySpeech",
        "am.rpe.tool.editButtons.css",
        "am.dialog.description",
        "am.bullRushSpellPF",
        "json.layout",
        "cif.t.drawTemplate",
        "am.merciesTip",
        "am.tokenImageLink",
        "am.rpe.renameGroup",
        "am.hb.oracleChannel.tab",
        "pause",
        "am.rpe.updateMacros",
        "am.play.movementLock",
        "am.sk.skillRoll",
        "am.play.output.basic",
        "am.getRangedDistance",
        "am.dialog.skillCheck",
        "am.rpe.EditToken",
        "plo.specOutput",
        "am.rpe.local.loadMenu",
        "am.rpe.saveMacros",
        "am.rpe.removeDebug",
        "am.rpe.setOption",
        "displayWhisperFrame",
        "am.rpe.watchList",
        "rspk.configStates",
        "am.play.setupServer",
        "spellReport",
        "setSize",
        "r.eval",
        "am.rpe.setDefaultConfig",
        "am.play.deferCondition",
        "json.pSet",
        "getSpellData",
        "am.play.pause",
        "debug",
        "am.play.MoveLock",
        "json.paths",
        "am.pf.chooseClass",
        "am.rpe.loadMacros",
        "say",
        "am.getPlayerGroups",
        "am.play.addPlayer",
        "getPageCache",
        "am.dialog.uniqueSkillCheck",
        "gotoLocation",
        "am.hb.healbot.header",
        "am.sk.onCampaignLoad",
        "json.pset",
        "xx.lib.watch",
        "am.rpe.mtVarPixelCount",
        "am.play.drawFromDeck",
        "makeKeywordSpellList",
        "am.dialog.getSaveLink",
        "xx.lib.onCampaignLoad",
        "startsWith"
    ],
    "face edge": 1,
    "isFullScreen": 0,
    "portrait size": 100,
    "show stat sheet": true,
    "version": "1.4.1.7",
    "timeDate": "2017-02-13 13:51:02",
    "face vertex": 1
}

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

Gah, what the heck...there's the UDF!

Code: Select all

{
    "timeInMs": 1487040620196,
    "client id": "cc51caf7-41fd-4ebe-b7e2-ffddc262864a",
    "library tokens": {"lib:Math": "unknown"},
    "user defined functions":     [
        "LineIntersection@Lib:Math",
        "DistanceBetweenPoints@Lib:Math",
        "ABC@Lib:Math"
    ],
    "face edge": 1,
    "isFullScreen": 0,
    "portrait size": 175,
    "show stat sheet": true,
    "version": "1.4.0.5",
    "timeDate": "2017-02-13 19:50:20",
    "face vertex": 0
}
So if its showing up there, why does it throw the "Undefined Function" error when I try to call it? I'm calling it like so...

Code: Select all

[h : intersectionResult = ABC(pointP, pointQ, pointR, pointZ)]
That sure seems correct...right?

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Sample of a UDF?

Post by xavram »

GOT IT!

Had the function name and the actual macro/tobken swapped in the "defineFunction" call! Now its working!

Post Reply

Return to “Macros”