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

[HELP] [Demon Hunter] Learning to modify Trinity behavior

thebbandit

New Member
Joined
Jan 24, 2014
Messages
91
Reaction score
3
I have recently begun making some small modifications to trinity in an effort to making my specific build on my DemonHunter work correctly in its behavior. So far I am taking advantage of my 4 piece Natalya's by modifying the parameters for it firing off Rain of Vengence so that it is much more lenient and fires more often. The other modifications were more of a hackjob but I would like to somehow fix them with your help!

First I modified the triggers for firing the Demon Hunter ability "Companion" to remove all the rune checks because Marauder's gives you every pet type. Is there a way that I can return those rune checks but also have an OR statement that checks for Marauder's 4 piece bonus being active?

The other modification I made was to just remove the ! in front of the reapers wraps line so that if I don't have the legendary item Reapers Wraps on it will behave like I do. I want to return it to its default logic state, but also add in an OR statement so that having the Blood Vengeance talent will also use the slider in the config UI.

While also modifying the logic for health globes, it would be awesome to also see it picking up ALL health globes after combat IF we have the Nephalem Glory buff.

One more modification I made was to remove the Discipline check from Vault because I am rocking the Danetta's two piece. Would be cool to return the lines to normal but add in an OR statement to check for Danetta's.

Basically the only examples I have found inside the code are only using the full set bonus as the criteria, would be great if anyone had links to where I can look at syntax? I want to make some contributions to the Trinity by adding in behavior modifications when people have certain set bonuses. For example, I have to modify the avoidance behavior to disregard molten, desecrator, and plague because I have the Blackthorne's 4 piece. What would be much better is adding in a set bonus check for Blackthornes into Trinity so that it can just disregard them completely as long as you have the set bonus. This would help reduce some of the processing needed to keep track of those effects.

TLDR: can someone help me to put set bonus conditions into the trinity code. Also how to check if you have a talent or a buff? i.e. Blood Vengeance, Nephalem Glory)


So far this is what I have been able to piece together with stuff from the code.
Code:
//hope this sets up a new variable?
					bool hasBloodVengeance = HotbarSkills.PassiveSkills.Any(s => s == SNOPower.DemonHunter_Passive_Vengeance);

//this section for the weight
                                        if (Legendary.ReapersWraps.IsEquipped || hasBloodVengeance)
                                        {
                                            if (myHealth > 0d && myHealth < V.D("Weight.Globe.MinPlayerHealthPct") || Player.PrimaryResourcePct <= _playerHealthGlobeResource)
                                                cacheObject.Weight = .9 * MaxWeight;
                                        }
                                        else
                                        {
                                            if ((myHealth > 0d && myHealth < V.D("Weight.Globe.MinPlayerHealthPct")))
                                                cacheObject.Weight = .9 * MaxWeight;
                                        }


// and the extra bonus weight
                                    if (Me.IsInCombat && Player.PrimaryResourcePct < 0.3 && (Legendary.ReapersWraps.IsEquipped || hasBloodVengeance) && (TargetUtil.AnyMobsInRange(40, 5) || TargetUtil.AnyElitesInRange(40)))


//Editing the Set file for Ring of Royal Grandeur
    bool hasRORG = Legendary.RingofRoyalGrandeur.IsEquipped;

[COLOR="#FF0000"]//Using Notepad++ to do replace all using extended mode
            SecondBonusItemCount = 4,
            ThirdBonusItemCount = 6

//To this
            if (hasRORG)\n			{\n			SecondBonusItemCount = 3,\n            ThirdBonusItemCount = 5\n			}\n			else\n			{\n			SecondBonusItemCount = 4,\n            ThirdBonusItemCount = 6\n			}\n
//also these 
            FirstBonusItemCount = 2,
            SecondBonusItemCount = 3
//to this
            FirstBonusItemCount = 2,\n            if (hasRORG)\n			{\n			SecondBonusItemCount = 2\n			}\n			else\n			{\n			SecondBonusItemCount = 3\n			}\n
//then this 
            FirstBonusItemCount = 2,
            SecondBonusItemCount = 4
//to this 
            FirstBonusItemCount = 2,\n            if (hasRORG)\n			{\n			SecondBonusItemCount = 3\n			}\n			else\n			{\n			SecondBonusItemCount = 4\n			}\n
//and finally
            FirstBonusItemCount = 2,
            SecondBonusItemCount = 4,
            ThirdBonusItemCount = 5
//to 
            if (hasRORG)
			{
			SecondBonusItemCount = 3,
            ThirdBonusItemCount = 4
			}
			else
			{
			SecondBonusItemCount = 4,
            ThirdBonusItemCount = 5
			}[/COLOR]

OOPS have to take all that out now... lol cannot use IF in the reference file?

Now that I have figured out how to do the passive skill check for blood vengeance, I want to do something a little more difficult. I want to add in an option for the bot to always pick up health globes when out of combat and it has nephalem buff.
 
Last edited:
it looks like you are trying to change the set bonus reference to take RRoG into account, but the sets file already takes this into account.

see \Trinity\Object\Set.cs
Code:
        private bool IsBonusActive(int requiredItemCountForBonus)
        {
            var actualRequired = requiredItemCountForBonus - (Legendary.RingOfRoyalGrandeur.IsEquipped ? 1 : 0);
            if (actualRequired < 2) actualRequired = 2;
            return requiredItemCountForBonus > 0 && EquippedItems.Count >= actualRequired;
        }

If you look through Set.cs you can see what properties are available for you to use. ie.

Code:
            Sets.EmbodimentOfTheMarauder.IsFirstBonusActive
            Sets.EmbodimentOfTheMarauder.IsSecondBonusActive
            Sets.EmbodimentOfTheMarauder.IsThreeBonusSet

Skills, Runes and Passives and Legendary items all work in a similar way.

Code:
            Legendary.HellcatWaistguard.IsEquipped
            Legendary.MaraudersCarapace.Set.IsMaxBonusActive;
            Skills.DemonHunter.Sentry.IsActive;
            Skills.DemonHunter.Sentry.CurrentRune.Name;
            Runes.Barbarian.BatteringRam.IsActive;
            Passives.Monk.BeaconOfYtar.IsActive;


For example, I have to modify the avoidance behavior to disregard molten, desecrator, and plague because I have the Blackthorne's 4 piece.


avoidance should be taking blackthorns set into account already, see
Trinity\Cache\RefreshAvoidance.cs there is a section that checks for it.

Code:
// Set based immunity            
if (Sets.BlackthornesBattlegear.IsMaxBonusActive)
            {
                var blackthornsImmunity = new HashSet<AvoidanceType>
                {
                    AvoidanceType.Desecrator,
                    AvoidanceType.MoltenBall,
                    AvoidanceType.MoltenCore,
                    AvoidanceType.MoltenTrail,
                    AvoidanceType.PlagueHand
                };


                if (blackthornsImmunity.Contains(avoidanceType))
                {
                    Logger.Log(TrinityLogLevel.Debug, LogCategory.Avoidance, "Ignoring Avoidance {0} because BlackthornesBattlegear is equipped", avoidanceType);
                    minAvoidanceHealth = 0;
                }
            }

It is possible that the ItemIds for a particular legendary are incorrect, which would cause the set class to not realize you have it equipped. You can find out if this is the case pretty easily, either check the top of your log file which lists all your skills and equipped items. Or go to Trinity-> Debug -> Dump Build/Items. Check what it says, if things are not listed correctly - incorrect set bonuses - incorrect items equipped etc. then let us know so we can fix it.

If you really want to get into this stuff i strongly suggest you get yourself a copy of VisualStudio, and grab a copy of a plugin with Solution/Project files (like from Trinity source control). Then you can use 'Intellisense' to show you all the available properties/methods/fields on an object as you write code - so you dont have to remember everything or go jumping around to look for stuff.

temp.png
 
Last edited:
Thank you for the response, pointing out that these are already inside trinity makes me feel like a doofus for not looking harder for them. Recently I got through about 14 tutorial videos so the syntax and form of the C# language is making a lot more sense to me as far as its application. I have loaded in the source from the link you gave and its going to make working on this a lot easier! thank you!

So to answer your question, I am trying to find a way to check if you have The Nephalem Glory buff active. Because it is not a skill or rune I dont know which way I would go about doing that. With your bit of advice I hope that I can figure this out soon! :D

Using your advice I found the code inside CombatBase.cs that defines GetHasBuff(SNOPower power) but I do not understand how I should set up the SNOPower for the Nephalem glory buff... it is not assigned in any of the files.
 
Last edited:
Using your advice I found the code inside CombatBase.cs that defines GetHasBuff(SNOPower power) but I do not understand how I should set up the SNOPower for the Nephalem glory buff... it is not assigned in any of the files.

SNOPower is an enum, part of DB, that is dumped from Diablo directly so it contains all possible 'powers' - spells, buffs, effects etc. You can access the SNOPower for spells via the skill object eg. Skills.DemonHunter.RapidFire.SNOPower or you can browse the SNOPower enum with intellisense or Object browser to find the power u need. Most of the time the buff is the SNOPower of the skill that caused it. In this case u might have to do something like this to find it:

Code:
            ZetaDia.Me.GetAllBuffs().ForEach(b => Logger.Log("{0} {1}", b.InternalName, (SNOPower)b.SNOId));
 
Last edited:
The buff Nephalem Glory is given when you pick up the yellow orbs, it is not listed inside any of the files for trinity. If you search the files for the word Nephalem it returns a few results but nothing referencing the buff you get. So the code that you linked will create a SNOPower for the Nephalem Glory buff? I am still learning how to use the For syntax.

OK, so I looked more closely at the line of code that you gave me. I see that it takes all the buffs from the player, and then returns to the log information about ALL buffs active on the player. It gets the internal name and extracts its SNOId, but I dont understand why you put the parenthasis and SNOPower inside it. Also, not sure how I would execute this code so that I can see the results?
 
Last edited:
... you can browse the SNOPower enum with intellisense or Object browser to find the power u need.

I can browse SNOPower in trinity? I have been trying to get that working but it just gives me errors in all the files that SNOPower does not exist in the current context. Also, other keywords like Zeta have the same issue, not defined.

Ok now I see that I did not have the DemonBuddy executable in the folder when I launched the Visual Studio project, so the reference was broken and I had to fix it. Now I get to browse the SNOPower library, thank you very much.

I am fairly sure that SNOPower.Console_PowerGlobe is the one I have been looking for! Thank you very much for the help you have given this novice programmer!

This may seem like a noob question, but how do I export the plugin? Do I just take the files and paste them over?
 
Last edited:
OK I am kind of ADHD so I made a plugin real quickly trying to use examples from armory, trinity, lumberjack and greedsdomain. I wanted to insert this into the trinity namespace, and then use the helpers in trinity to evaluate conditions for the bot to fire off Furious Charge whenever there was an optimal pile of gold. (for now it will be gold, once I can get the game firing off a known ability and interfacing I can step up to figuring out how to check for the Nephalem Glory buff and actively seek out health globes) But for now I am obviously doing this incorrectly, as I am getting an error referencing something.
Code:
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(5,15) : error CS0234: The type or namespace name 'Cache' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(6,15) : error CS0234: The type or namespace name 'Combat' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(7,15) : error CS0234: The type or namespace name 'Combat' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(8,15) : error CS0234: The type or namespace name 'Configuration' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(9,15) : error CS0234: The type or namespace name 'DbProvider' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(10,15) : error CS0234: The type or namespace name 'Helpers' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(11,15) : error CS0234: The type or namespace name 'Items' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(12,15) : error CS0234: The type or namespace name 'Technicals' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(13,15) : error CS0234: The type or namespace name 'TrinityCacheObject' does not exist in the namespace 'Trinity' (are you missing an assembly reference?)
Compiler Error: c:\Users\Bandit\Desktop\DMN\Plugins\GoldFinger\GoldFinger.cs(95,28) : error CS0246: The type or namespace name 'TrinityCacheObject' could not be found (are you missing a using directive or an assembly reference?)

:) I appologize if I am asking for too much help, but could you look at what I have done so far?

Code:
using System;
using System.IO;
using System.Threading;
using System.Windows;
using Trinity;
using Trinity.Cache;
using Trinity.Combat;
using Trinity.Combat.Abilities;
using Trinity.Configuration;
using Trinity.DbProvider;
using Trinity.Helpers;
using Trinity.Items;
using Trinity.Technicals;
using Trinity.TrinityCacheObject;
using Zeta.Bot;
using Zeta.Bot.Navigation;
using Zeta.Common.Plugins;
using Zeta.Game;

namespace Trinity.XXXGoldFinger
{
       public class Plugin : IPlugin
       {
           public const string AUTHOR = "Bandit";
           public const string DESCRIPTION = "Provides better combat movement for looting.";
           public const string NAME = "GoldFinger";

           public static Version GFVersion = new Version(0, 0, 1);

           public Version Version
           {
               get
               {
                   return GFVersion;
               }
           }
           
           public void OnEnabled()
           {
               Logger.Log("v{0} Enabled", Version);     
           }

           public void OnDisabled()
           {
               Logger.Log("v{0} Disabled", Version);    
           }

           public void OnShutdown()
           {
               Logger.Log("v{0} Shutdown", Version);    
           }

           public void OnInitialize()
           {
               Logger.Log("v{0} Initialized", Version);  
           }
           
           public void OnPulse()
           {
               // Cast Furious Charge
               if (IsNull(power) && FuriousChargeReady)
                   power = PowerFuriousCharge;


           }
           public static bool FuriousChargeReady
           {
               get
               {
                   if (UseOOCBuff)
                       return false;

                   var bestTarget = GetBestGoldTarget(35f, 10f, 2);
                   int unitsInFrontOfBestTarget = 0;
                   int unitsAroundBestTarget = 0;
                   int unitsNearPlayer = 0;

                   if (bestTarget != null)
                   {
                       unitsInFrontOfBestTarget = bestTarget.CountUnitsInFront();
                       unitsAroundBestTarget = bestTarget.NearbyUnitsWithinDistance(10f);
                       unitsNearPlayer = ZetaDia.Me.Position.NearbyUnitsWithinDistance(10f);
                   }

                   return CanCast(SNOPower.Barbarian_FuriousCharge, CanCastFlags.NoTimer) && !IsCurrentlyAvoiding &&
                       (unitsInFrontOfBestTarget >= 3 || unitsAroundBestTarget >= 3 || unitsNearPlayer >= 3 );

               }
           }

           internal static TrinityCacheObject GetBestGoldTarget(float maxRange = 35f, float radius = 10f, int count = 2, bool ignoreUnitsInAoE = false)
           {
               var result =
                   (from u in ObjectCache
                    where u.Type == ObjectType.Gold &&
                    u.RadiusDistance <= maxRange &&
                    (u.NearbyUnitsWithinDistance(radius) >= count || u.CountUnitsInFront() >= count) 
                    ((ignoreUnitsInAoE && !u.IsStandingInAvoidance) || !ignoreUnitsInAoE)
                    orderby u.NearbyUnitsWithinDistance(radius) descending,
                    u.CountUnitsInFront() descending,
                    u.Distance,
                    u.IsEliteRareUnique descending
                    select u).FirstOrDefault();
               if (result != null)
                   return result;

               if (Trinity.CurrentTarget != null)
                   return Trinity.CurrentTarget;

               return default(TrinityCacheObject);
           }
       }
}
 

Attachments

Last edited:
Well, You cant just use trinity code from outside of trinity unless that code has been marked as Public. The Trinity.ObjectCache you are trying to use for GetBestGoldTarget() is marked as internal. You can still access these using reflection but that is a lot more complicated and cumbersome.

Generally plugins are self-contained and don't use other plugins. If you want to do it, you need to make sure that DB compiles your assembly after the one you are referencing - which you can do by prefixing your plugin folder with z or something so that it is ranked afterwards alphabetically.

Bare in mind that code from Trinity is designed to be run within Trinity. Ideally, nothing should be set to public unless its intended to be exposed and used publicly but this isn't a professional coding project so there is all sorts of shit exposed that probably shouldn't be. The point being you could really mess things up in Trinity if you poke around at the wrong things and aren't careful.

There is no way right now for example to Cast a DiaObject (what DB gives us by default) into a TrinityCacheObject, so you cant use any of the utility properties that TrinityCacheObject provides like .type or .NearbyUnitsWithinDistance(). Again, because it wasn't written with being used outside of trinity in mind. The Enemies.Alive collection could be used but it only contains monsters not gold and stuff.

All that said, i have modified your plugin to at least give you something working that you can play with, what it does is use furious charge over to gold whenever it finds it on the ground
 

Attachments

Last edited:
OK, now I am beginning to understand why there are no supplemental plugins for trinity. You are not able to interface with trinity because its using private internal methods and modules. :/ that's quite a bummer really, but now I know that if I want to modify trinity behavior I have to request it added into trinity itself.
 
Back
Top