What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

Trinity v1.6 - New Profile XML Tags

GilesSmith

New Member
Joined
Jun 2, 2012
Messages
1,564
Reaction score
34
Please scroll to the bottom of this post for an attached short example showing how to utilize useonce and deathhandling tags to merge multiple XML's into a single unified file that handles death handling fully.

See link below for a user-created profile template using Trinity tags for advanced profile creation with death-handling, randomized pathing etc. all in a single XML:
http://www.thebuddyforum.com/demonbuddy-forum/plugins/giles-plugins/75739-guide-writing-multipath-profiles-new-trinity-tags.html


New Profile (XML) Stuff:

Trinity v1.6 is here, and with it are a number of new features for profile makers to take advantage of. Below is the full list of custom XML tags that can be used in profiles for anyone running Trinity. First, the list of tags;
<TrinityTownRun />
<TrinityLog output="test" />
<TrinityMoveTo />
<TrinityMoveToSNO snoid="xxxx" />
<TrinityInteract snoid="xxxx" />
<TrinityIf> </TrinityIf>
<TrinityIfSNOInRange snoid="xxxxx" range="yy"> </TrinityIfSNOInRange>
<TrinityUseOnce id="12345"> </TrinityUseOnce>
<TrinityUseStop id="xxxx" />
<TrinityUseReset id="xxxx" />
<TrinityLoadProfile file="12345.xml" />
<TrinityRandomRoll id="1234" min="1" max="10" />
<TrinityIfRandom id="1234" result="1"> </TrinityIfRandom
<TrinityHandleDeaths max="5" />

And now for details on them all and some sample usage;

<TrinityTownRun />
Tells Trinity to town-run the moment it has finished dealing with any current targets.
Example:
Code:
<TrinityTownRun questId="1" />

<TrinityLog output="test" />
Sends a log output to the DemonBuddy window and continues the profile - useful for sending messages to the user or debugging complex profiles.
An optional parameter 'level="diagnostic"' allows you to only log at diagnostics level.
Examples:
Code:
<TrinityLog questId="1" output="Now in town, entering portal" />
<TrinityLog questId="1" level="diagnostic" output="Profile debug: We are inside the nested loop successfully!" />

<TrinityMoveTo />
Mimics the DemonBuddy MoveTo Tag in almost every way (supports all of it's parameters - pathprecision, x, y, z, name etc.) except WITH NO PATHFINDING OR NAV-SERVER HITS. It will just try to straightline between two points. Can help in problematic areas where you know your waypoints are correct. Use wisely, and don't abuse pathprecision with it!
TrinityMoveTo can skip ahead waypoints if you have already walked through/near those waypoints while fighting targets, to help speed runs up.
NOTE: The TrinityMoveTo "Skip Ahead" feature will NOT run if you have backtracking enabled - as the two features are complete opposites of eachother!
Examples:
Code:
<TrinityMoveTo questId="1" x="2248.932" y="1058.559" z="0.2" pathPrecision="1" />

NOTE: You can prevent a TrinityMoveTo from being allowed to be "skipped", by adding an optional parameter; noskip="true", for example;
Code:
<TrinityMoveTo questId="1" noskip="true" x="2248.932" y="1058.559" z="0.2" pathPrecision="1" />

<TrinityMoveToSNO snoid="xxxx" />
Similar to TrinityMoveTo, but supporting only three parameters: snoid (REQUIRED!), pathPrecision (optional), name (optional).
TrinityMoveToSNO will try to find the first instance of the SNOID you give in Diablo 3 memory, get it's location, and move towards it.
IT SUPPORTS MOVING OBJECTS.
Just like TrinityMoveTo, it has no path-finding - it tries to straight-line walk, with no nav-server hits.
Example:
Code:
<TrinityMoveToSNO questId="1" snoid="130400" pathPrecision="8" />

<TrinityInteract snoid="xxxx" />
This attempts to interact with the object as long as it is found in memory - REGARDLESS of range, position, or anything - will attempt no DB-side navigation.
This is just a pure, straight out interaction, and only attempts the interaction once, regardless of success or failure. (you can spam the tag multiple times to attempt multiple interacts in a row if you need/want).
Example:
Code:
<TrinityInteract questID="1" snoid="130400" />

If you want a really reliable way to enter orange portals/doorways, use TrinityInteract in a While loop that repeats until the world ID changes from whichever is the origin (leaving from) world ID, for example;
Code:
    <!-- Keep trying to enter the portal until successful -->
    <While questId="1" condition="Zeta.ZetaDia.CurrentWorldId==172909">
      <TrinityInteract questId="1" snoid="176001" />
      <WaitTimer questId="1" WaitTime="1000" />
    </While>

<TrinityIf> </TrinityIf>
This is identical in all ways to DemonBuddy's built in <If> tag. It supports all parameters and options. But people should find it more reliable, especially when nested. A sample use would be;
Code:
    <!-- If not in town, portal to town -->
    <TrinityIf questId="1" condition="not Zeta.ZetaDia.CurrentWorldId==172909" >
      <UseTownPortal questId="1" />
    </TrinityIf>
To check if you are already in town or not, at the start of a profile - and if you aren't, to teleport to town first.

<TrinityIfSNOInRange snoid="xxxxx" range="yy"> </TrinityIfSNOInRange>
This works like the default "If" tag and can have child nodes. It allows you to check if a particular SNO ID is within a specified range before carrying out actions.
Child-nodes can be any tag type - be they Trinity tags or any other tags (provided by DB or other plugins), and can be nested.
An optional parameter 'type="reverse"' allows you to only process the contents if an SNO is *NOT* within range (or not present at all).
Examples:
Code:
<TrinityIfSNOInRange snoid="130400" range="20">
    <TrinityLog questId="1" output="Player stash is within range, do stuff!" />
</TrinityIfSNOInRange>
<TrinityIfSNOInRange snoid="208620" range="20" type="reverse">
    <TrinityLog questId="1" output="The Priest NPC is not found within range... LETS PARTY!" />
</TrinityIfSNOInRange>

<TrinityUseOnce id="12345"> </TrinityUseOnce>
This is a container tag (and can have unlimited child nodes and nested child nodes). Child-nodes can be any tag type - be they Trinity tags or any other tags (provided by DB or other plugins), and can be nested.
Give it any ID you like (MUST be a number/integer!) - from 1 to 9999999. If Trinity encounters this element, it will remember the ID - and will NEVER process that ID again until the bot leaves the game and returns (unless you use the optional "max" parameter, see below).
You can use this to ensure certain parts of your profile do not get re-run after a death, or for more complicated uses where you want something to be done once only, but have multiple opportunities, eg;
Code:
<TrinityIfSNOInRange snoid="130400" range="15">
  <TrinityUseOnce id="666">
    <TrinityLog questId="1" output="Hey, we found the magic lever, going to interact with it!" />
    <TrinityInteract questID="1" snoid="52685" />
  </TrinityUseOnce>
</TrinityIfSNOInRange>
<move stuff>
<more profile stuff>
<etc.>
<TrinityIfSNOInRange snoid="130400" range="15">
  <TrinityUseOnce id="666">
    <TrinityLog questId="1" output="We definitely haven't used this yet this run, so using it now!" />
    <TrinityInteract questID="1" snoid="52685" />
  </TrinityUseOnce>
</TrinityIfSNOInRange>
^^ In the above example, once id 666 has been "processed", it won't get processed again for the rest of the run. So if the "magic lever" was found in the first if check, it will have been used there - if it ALSO appeared in the 2nd if check, it WON'T be used - since useonce has already been flagged as done for id 666. Also, if you die and a profile manager restarts the profile, it WON'T be used on your next run-through.

The optional parameter 'max="2"' - set how many times this ID can be re-used during this session. You can now allow an id to be re-used multiple times before being disabled.
A 2nd optional parameter is 'disableprevious="true"' - if this parameter is present when the useonce tag is reached *AND* if this useonce id hasn't been hit before, then *ALL* previously hit useonce id's will be instantly set to their max limits so they will never run again.
Example;
Code:
<TrinityMaxDeaths questId="1" max="3" />
<TrinityUseOnce questId="1" id="20" max="2">
  <TrinityLog questId="1" output="Now Running A3 Cursed Towers" />
  <!-- insert cursed towers profile stuff -->
</TrinityUseOnce>
<TrinityUseOnce questId="1" id="21" max="2" disableprevious="true">
  <TrinityLog questId="1" output="Now Running A3 Battlefields" />
  <!-- insert battlefields profile stuff -->
</TrinityUseOnce>
<LeaveGame reason="Run is done!" />

The above example would first tell Trinity that it is handling deaths, and that the max deaths allowed until exiting and restarting is 5.
Now for example, say the bot is running cursed towers, and dies - Trinity will restart the profile from the beginning. The "UseOnce" max of 2 tag will allow cursed towers to run a second time.
The bot dies again, Trinity restarts the current profile - but THIS time - the useonce for id 20 (the cursed towers area) has already been hit twice, so it is skipped - and the bot now moves onto the Battlefields area.
Now should the bot die again in the Battlefields - the max death count of 3, set by the very first tag, will trigger Trinity to exit the game, and start the whole process again.

This allows profiles to only ever be one single, self-contained XML file.

Don't forget to use the "LeaveGame" tag, to tell Db to leave the game at the end and restart the profile for you!

<TrinityUseStop id="12345" />
TrinityUseStop will prevent the specified "UseOnce" id being used again for the rest of the run - that ID is "completely disabled" until your game leaves and a new game started. You can use it within, but at the end of, a <UseOnce> tag as a way of disabling a UseOnce tag *ONLY* when that UseOnce tag has been completed, as one possible example usage.
Example line;
Code:
<TrinityUseStop questId="1" id="666" />

<TrinityUseReset id="12345" />
TrinityUseReset allows you to RESET a UseOnce ID (so Trinity will treat that UseOnce ID as if it has never been hit before).
It will re-enable any ID completely ready for use again (even one that use been "UseStopped").
You could combine a "UseStop" at the start of a section, with a "UseOnce" at the end of a section - so that a later UseOnce further down a profile is only run when the UseReset is reached (ie when a previous section has been FULLY completed).
Get creative with the tags, you can do a lot of clever things!

<TrinityLoadProfile file="12345.xml" />
This allows you to load a new profile up. Note that you can seperate multiple filenames with an exclamation mark, and a random profile will be selected.
NOTE: the .xml MUST be in the same folder as the currently loaded profile.
An optional parameter, 'exit="true"', can be given to tell Trinity to also exit the game after loading the profile, to allow a new game start.
Examples;
Code:
<TrinityLoadProfile file="12345.xml!56789.xml!abcdef.xml" />
Would cause one of those three XML's to be picked at random. You can of course just list a single .xml file for it to load.
Code:
<TrinityLoadProfile file="act4.xml" exit="true" />
Would cause act4.xml to be loaded, and the current game to be exited so that a new game can start.

An additional optional parameter, nodelay="true", removes the forced-3 second wait after loading the profile, to help speed runs up for when the new profile is continuing from the same map-zone, for example;
Code:
<TrinityLoadProfile file="12345.xml" nodelay="true" />

<TrinityRandomRoll id="1234" min="1" max="10" />
Generates a random value between the min and max (the given values are INCLUSIVE - so min 1 max 10 allows 1-10 to roll), and stores it in the given ID.
If giving the same ID, it will simply store a new random roll in the given ID.
The value is stored until the bot is stopped. (leaving/joining a game does not clear the value - but you can reset the value by running the command again on the same ID).
Example;
Code:
<TrinityRandomRoll questId="1" id="1" min="1" max="10" />

<TrinityIfRandom id="1234" result="1"> </TrinityIfRandom
This is a container tag - it can contain child-nodes of any tag type - be they Trinity tags or any other tags (provided by DB or other plugins), and can be nested.
The code inserted into the ifrandom will ONLY be run, if the random value of the specified id, matches the result.
Example usage;
Code:
<TrinityRandomRoll questId="1" id="69" min="1" max="2" />
<TrinityIfRandom questId="1" id="69" result="1">
    <TrinityLog questId="1" output="We rolled a 1! So we're going to take path A!" />
</TrinityIfRandom>
<TrinityIfRandom questId="1" id="69" result="2">
    <TrinityLog questId="1" output="We rolled a 2! So we're going to take path B!" />
</TrinityIfRandom>
The above will pick a random number between 1 and 2 - and output a different log entry depending on what value was rolled.
The id can be checked unlimited times anywhere in the profile or any other profiles loaded afterwards, and can be re-assigned/re-rolled. It is only reset to 0 when DemonBuddy is stopped..

<TrinityHandleDeaths max="5" />
Tells Trinity to handle total deaths during this run, and to restart the profile on death, and exit the game and restart the profile if the max death count is reached.
Max death count must be a minimum of 1 for Trinity to handle deaths.
An optional parameter 'reset="true"' will force Trinity to reset the current counted deaths this run to 0 (as if the player had never died yet).
Examples;
Code:
<TrinityMaxDeaths questId="1" max="5" />
<TrinityMaxDeaths questId="1" max="2" reset="true" />
NOTE: If using Trinity death handling, you should disable DB death handling (set to "Ignore" in settings tab of DB), and disable any plugins/profile managers that handle deaths/profiles.
DO NOT use "reset=true" for normal use. It will *RESET* your death counts back to 0 when run. For advanced/complex use only!

Random Tips/Code-Chunks:
A reliable way to portal *BACK* to town from any map is:
Code:
<!-- while our world ID is *NOT* the current act's town ID, keep trying to portal and wait -->
    <While questId="1" condition="Zeta.ZetaDia.CurrentWorldId != 161472">
     <UseTownPortal questId="1" />
     <WaitTimer questId="1" WaitTime="1000" />
    </While>
Where 161472 is the world ID of the town in your current act (sample above is the town world ID in act 2).

A reliable way to enter any orange portal/doorway is;
Code:
    <!-- Keep trying to enter the portal until successful -->
    <While questId="1" condition="Zeta.ZetaDia.CurrentWorldId==172909">
      <TrinityInteract questId="1" snoid="176001" />
      <WaitTimer questId="1" WaitTime="1000" />
    </While>
Where the world ID in the While check is the world ID you are trying to *LEAVE* (not the world ID you are trying to enter), and the snoid in the TrinityInteract tag is the SNOID of the orange portal/doorway (many of them are 176001).

The next chunk of code would check if the stash in Act 3 is within 50 foot. If so it will move to a location a little south-west of the stash, then try to move to the SNO ID itself, and then interact with the SNO.
REMEMBER: There is no path-finding in any TrinityMoveTo tags - you can mix in standard DemonBuddy moveto tags if you want to utilize demonbuddy path-finding and nav-server stuff!
Code:
  <TrinityIfSNOInRange questId="1" snoid="130400" range="50">
     <TrinityLog questId="1" output="Stash is nearby, now moving within range of stash..." />
     <TrinityMoveTo questId="1" x="412.8796" y="396.349" z="0.5461263" pathPrecision="8" />
     <TrinityMoveToSNO questId="1" snoid="130400" pathPrecision="8" />
     <TrinityIfSNOInRange questId="1" snoid="130400" range="8">
        <TrinityLog questId="1" output="We're next to the stash, now opening!" />
        <TrinityInteract questId="1" snoid="130400" />
     </TrinityIfSNOInRange>
  </TrinityIfSNOInRange>

The following gives an example of the TrinityUseOnce stuff. Only the first two log lines will be shown. The 2nd two will never be seen. The first two won't be seen again until DemonBuddy exits the game and starts a new run.
Code:
<TrinityUseOnce questId="1" id="54321">
    <TrinityLog questId="1" output="This is 54321 unique output!" />
</TrinityUseOnce>
<TrinityUseOnce questId="1" id="12345">
    <TrinityLog questId="1" output="And this is 12345 unique output!" />
</TrinityUseOnce>
<TrinityUseOnce questId="1" id="12345">
    <TrinityLog questId="1" output="Awww, I will never get to be seen!" />
</TrinityUseOnce>
<TrinityUseOnce questId="1" id="54321">
    <TrinityLog questId="1" output="Nor will I!" />
</TrinityUseOnce>
 

Attachments

Last edited:
Looks sick Giles! Should make profiles a lot more intelligent. I've been waiting for something like <TrinityUseOnce> for a while now...

Keep up the good work! Always blown away by what you come up with.
 
:cool:

Thanx for the awesome stuff

PS2: WTF dude, i just read the updates and went to look them => fukin awesome stuff right there => donating
 
Last edited:
Awesome i m leaving tnt to try your plugin and fix my profile with your stuff, hopefully #259 will help as well...
 
Several new XML commands added or modified, full details and a sample profile attached to first post.

<TrinityRandomRoll id="1234" min="1" max="10" />
<TrinityIfRandom id="1234" result="1"> </TrinityIfRandom
<TrinityHandleDeaths max="5" />
<TrinityUseOnce id="12345" max="2"> </TrinityUseOnce>
<TrinityLoadProfile file="zone1.xml!zone2.xml!zone3.xml" />

We are now capable of fully standalone, single unified .xml file profiles that have full death handling and randomization without the need of any profile managers or death handlers! :D
 
WOW amazing stuff. Gonna be a bit of effort to switch over from ciggarc to my own profiles, but probably worth it.

Anybody want to help me maintain a trinity branch of ciggarc's git tree?
 
No idea if it's easy to do but,
Could you have TrinityInteract to iterate through all the existing instance of a snoid until it find one in interact range.

I believe that would make it work in the cemetery of the forsaken :)
 
Last edited:
No idea if it's easy to do but,
Could you have TrinityInteract to iterate through all the existing instance of a snoid until it find one in interact range.
I believe that would make it work in the cemetery of the forsaken :)

Sure, I can make interact automatically pick the closest one where multiple ones are found, would that work?
 
I m not sure how it exactly works but i m sure that in the cemetery of the forsaken,
all the portal actor have the same snoid "176002" and I couldn't get TrinityInteract to work with those.

I just supposed that the problem was that it was not using the good one.

I guess using the closest one might make it work actually, yes.
 
Can you roll the random numbers before you actually create a game? I've been looking for a way for my bots to randomly run A1 and A2 every once in a while to break up the pattern of doing A3 a million times. I'm hoping this might be the solution; and with the MP levels in the next patch it won't actually hurt you to run these acts either. More humanization!
 
Can you roll the random numbers before you actually create a game? I've been looking for a way for my bots to randomly run A1 and A2 every once in a while to break up the pattern of doing A3 a million times. I'm hoping this might be the solution; and with the MP levels in the next patch it won't actually hurt you to run these acts either. More humanization!

I'm not sure if DB will let you do things before it enters a game (I think everything has to be within the <order> tags), but you could have it enter a random act/quest first, and the contents of your profile could just be;
Code:
<!-- Pick a random number from 1 to 3, and start a new game with a new unified act profile -->
<TrinityRandomRoll questId="1" id="69" min="1" max="3" />
<TrinityIfRandom questId="1" id="69" result="1">
    <TrinityLog questId="1" output="Now loading Act 1 profile..." />
    <TrinityLoadProfile file="Act1_Unified.xml" exit="true" />
</TrinityIfRandom>
<TrinityIfRandom questId="1" id="69" result="2">
    <TrinityLog questId="1" output="Now loading Act 2 profile..." />
    <TrinityLoadProfile file="Act2_Unified.xml" exit="true" />
</TrinityIfRandom>
<TrinityIfRandom questId="1" id="69" result="2">
    <TrinityLog questId="1" output="Now loading Act 3 profile..." />
    <TrinityLoadProfile file="Act3_Unified.xml" exit="true" />
</TrinityIfRandom>

But you could equally do this;
Code:
 <TrinityLoadProfile file="Act1_Unified.xml!Act2_Unified.xml!Act3_Unified.xml" exit="true" />
 
I'm not sure if DB will let you do things before it enters a game (I think everything has to be within the <order> tags), but you could have it enter a random act/quest first, and the contents of your profile could just be;
Code:
<!-- Pick a random number from 1 to 3, and start a new game with a new unified act profile -->
<TrinityRandomRoll questId="1" id="69" min="1" max="3" />
<TrinityIfRandom questId="1" id="69" result="1">
    <TrinityLog questId="1" output="Now loading Act 1 profile..." />
    <TrinityLoadProfile file="Act1_Unified.xml" exit="true" />
</TrinityIfRandom>
<TrinityIfRandom questId="1" id="69" result="2">
    <TrinityLog questId="1" output="Now loading Act 2 profile..." />
    <TrinityLoadProfile file="Act2_Unified.xml" exit="true" />
</TrinityIfRandom>
<TrinityIfRandom questId="1" id="69" result="2">
    <TrinityLog questId="1" output="Now loading Act 3 profile..." />
    <TrinityLoadProfile file="Act3_Unified.xml" exit="true" />
</TrinityIfRandom>

But you could equally do this;
Code:
 <TrinityLoadProfile file="Act1_Unified.xml!Act2_Unified.xml!Act3_Unified.xml" exit="true" />

Cool, I figured that would be the other solution. So if I start in A3 but it hits the A2 profile it will leave the game and start the A2 profile?

Also can you use a range for the results?

What I'd like to do is have it roll a random from 1 - 100. 1 - 5 would be the A1 profile. 6 - 15 would be the A2 profile. 16 - 100 would be the A3 profile. Is that possible?

Thanks for the reply.
 
Cool, I figured that would be the other solution. So if I start in A3 but it hits the A2 profile it will leave the game and start the A2 profile?
Also can you use a range for the results?
What I'd like to do is have it roll a random from 1 - 100. 1 - 5 would be the A1 profile. 6 - 15 would be the A2 profile. 16 - 100 would be the A3 profile. Is that possible?
Thanks for the reply.

No but that's something I can add support for.
 
No but that's something I can add support for.

It's not a big deal at all. I was more curious than anything. I can manually do it by just manually assigning results from 1 - 20. Don't worry about it. :)
 
Hey Giles,

Looks like when loading a profile using Trinity that the last trailing slash isn't being used for the lookup on the next profile.

Log:
Code:
[05:22:58.220 N] Failed to load profile: Path to profile element is not valid; file not found
[05:22:58.220 D] System.IO.FileNotFoundException: Path to profile element is not valid; file not found
File name: 'C:\Users\XXXX\Dropbox\Demonbuddy\Profiles\Random Act PickerA3_START_HERE.xml'

I tried taking a look at the Trinity .cs file to see if I could figure it out but no dice.

For the record I tried moving the profiles folder to a root directory and it didn't help.
 
Hey Giles,
Looks like when loading a profile using Trinity that the last trailing slash isn't being used for the lookup on the next profile.

For the record I tried moving the profiles folder to a root directory and it didn't help.

Thanks, I'll slip that in for a little mini-update next time I update things :)
 
Sounds good. Thanks for the quick replies. Sharp as always!

Edit: I think I might have found the solution. Maybe you could confirm.

All I did was a add '+ @"\";' to the end of this line:

Code:
string sCurrentProfilePath = Path.GetDirectoryName(Zeta.CommonBot.Settings.GlobalSettings.Instance.LastProfile)

I'd love to test it out but I'm having authentication issues right now :(

Edit 2: That worked!
 
Last edited:


<TrinityUseOnce id="12345"> </TrinityUseOnce>
This is a container tag (and can have unlimited child nodes and nested child nodes). Child-nodes can be any tag type - be they Trinity tags or any other tags (provided by DB or other plugins), and can be nested.
Give it any ID you like (MUST be a number/integer!) - from 1 to 9999999. If Trinity encounters this element, it will remember the ID - and will NEVER process that ID again until the bot leaves the game and returns.
You can use this to ensure certain parts of your profile do not get re-run after a death, or for more complicated uses where you want something to be done once only, but have multiple opportunities,

Is it possible to make it so that the id will only be discarded after all the elements inside that are processed? So if the bot die in the middle of a UseOnce, it will still run that again?
 
Back
Top