Dealing with Factions! menu

Shout-Out

User Tag List

Results 1 to 6 of 6
  1. #1
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Dealing with Factions!

    Well, this has been a pain in my ass for the last few days, but I finally got it all worked out.

    We're using a database to store vendors, mailboxes, and the items they have. We store the faction ID for each vendor (it *was* to make things easier, but it turned out to be the opposite, then turned out to be the best way to go in the end.)

    Basically we all know every unit has a FACTIONTEMPLATE descriptor, which points to the FactionTemplate.dbc record. The issue for me, was figuring out how to properly use it from C#. Long story short; I got it figured out, and the code is a bit ugly. It's an almost direct copy->paste from WoW's code, so it should work for all.

    Includes the ability to 'traverse' the faction tree, going up to each parent faction, etc.

    It also includes the faction comparison (best used at runtime) to decide whether another unit is friendly/hostile/neutral/etc.

    Firstly; don't give me the 'use UnitRelation!' crap. If all you have are the faction IDs, and not the actual unit objects, you're up shits creek without a paddle, unless you know how Blizz calculates the faction relations.

    Anyhow, here's the code, please let me know of anything I missed. (I intentionally left out friendly/hostile faction stuff, since the comparison funcs are there.)

    Code:
    using System.Runtime.InteropServices;
    
    namespace Onyx.WoW
    {
        public class WoWFaction
        {
            private readonly FactionTemplateDbcRecord _template;
            private FactionDbcRecord _record;
    
            public WoWFaction(int id) : this(id, true)
            {
            }
    
            internal WoWFaction(int id, bool isTemplate)
            {
                Id = id;
                if (IsValid)
                {
                    if (isTemplate)
                    {
                        _template = OnyxWoW.Db[ClientDb.FactionTemplate].GetRow(id).GetStruct<FactionTemplateDbcRecord>();
                        _record = OnyxWoW.Db[ClientDb.Faction].GetRow(_template.FactionId).GetStruct<FactionDbcRecord>();
                    }
                    else
                    {
                        _record = OnyxWoW.Db[ClientDb.Faction].GetRow(id).GetStruct<FactionDbcRecord>();
                    }
                }
            }
    
            public int Id { get; private set; }
            public string Name { get { return _record.Name; } }
            public string Description { get { return _record.Description; } }
            public WoWFaction ParentFaction { get { return new WoWFaction(_record.ParentFaction, false); } }
            public bool IsValid { get { return Id != 0; } }
    
            public WoWUnitRelation RelationTo(WoWFaction other)
            {
                return CompareFactions(this, other);
            }
    
            public static WoWUnitRelation CompareFactions(WoWFaction factionA, WoWFaction factionB)
            {
                FactionTemplateDbcRecord atmpl = factionA._template;
                FactionTemplateDbcRecord btmpl = factionB._template;
    
                if ((btmpl.FightSupport & atmpl.HostileMask) != 0)
                {
                    return (WoWUnitRelation) 1;
                }
    
                for (int i = 0; i < 4; i++)
                {
                    if (atmpl.EnemyFactions[i] == btmpl.Id)
                    {
                        return (WoWUnitRelation) 1;
                    }
                    if (atmpl.EnemyFactions[i] == 0)
                    {
                        break;
                    }
                }
    
                if ((btmpl.FightSupport & atmpl.FriendlyMask) != 0)
                {
                    return (WoWUnitRelation) 4;
                }
    
                for (int i = 0; i < 4; i++)
                {
                    if (atmpl.FriendlyFactions[i] == btmpl.Id)
                    {
                        return (WoWUnitRelation) 4;
                    }
                    if (atmpl.FriendlyFactions[i] == 0)
                    {
                        break;
                    }
                }
    
                if ((atmpl.FightSupport & btmpl.FriendlyMask) != 0)
                {
                    return (WoWUnitRelation) 4;
                }
    
                for (int i = 0; i < 4; i++)
                {
                    if (btmpl.FriendlyFactions[i] == atmpl.Id)
                    {
                        return (WoWUnitRelation) 4;
                    }
                    if (btmpl.FriendlyFactions[i] == 0)
                    {
                        break;
                    }
                }
    
                return (WoWUnitRelation) (~(byte) ((uint) atmpl.FactionFlags >> 12) & 2 | 1);
            }
    
            public override string ToString()
            {
                if (!IsValid)
                {
                    return "N/A";
                }
                return Name + ", Parent: " + ParentFaction;
            }
    
            #region Nested type: FactionDbcRecord
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            private struct FactionDbcRecord
            {
                public int Id;
                private int _unk0;
                public int Allied;
                public int AtWar;
                private int _unk1;
                private int _unk2;
                private int _unk3;
                private int _unk4;
                private int _unk5;
                private int _unk6;
                public int Reputation;
                public int Mod1;
                public int Mod2;
                public int Mod3;
                private int _unk7;
                private int _unk8;
                private int _unk9;
                private int _unk10;
                public int ParentFaction;
    
                // 4 unknowns added recently. Cba to figure out what they're for
                // since I have no use for them!
                private int _unk11;
                private int _unk12;
                private int _unk13;
                private int _unk14;
    
                [MarshalAs(UnmanagedType.LPStr)]
                public string Name;
    
                [MarshalAs(UnmanagedType.LPStr)]
                public string Description;
            }
    
            #endregion
    
            #region Nested type: FactionTemplateDbcRecord
    
            [StructLayout(LayoutKind.Sequential)]
            private struct FactionTemplateDbcRecord
            {
                public int Id;
                public int FactionId;
                public int FactionFlags;
                public int FightSupport;
                public int FriendlyMask;
                public int HostileMask;
    
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
                public int[] EnemyFactions;
    
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
                public int[] FriendlyFactions;
            }
    
            #endregion
        }
    }

    Dealing with Factions!
  2. #2
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    use UnitRelation!

    Well, rather... use Mangos

    Mangos has the full DBC structure as well as sample (C++) code that shows how to correctly sum up all of the faction templates, groups, and so on to produce a final unit reaction.

    I'm not sure it's 100% correct (I've been testing against a Mangos server, so the assumptions could be wrong), but so far after RE'ing their code and implementing it in C#, my bot's assumptions have been spot-on.

    I use Mangos for ALL kinds of stuff
    Don't believe everything you think.

  3. #3
    audible83's Avatar Member
    Reputation
    4
    Join Date
    Jun 2008
    Posts
    48
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    yeah, for templates of DBC mangos is spot on.

    Mangosdb struct - UDB

  4. #4
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The above code works just as well. It was ripped directly from WoW.

    For the most part, UnitRelation pretty much uses the 1 func to check the hostility. Most of the other code is checking pets, summoned minions, etc.

    I tend to not look at emu code. Mainly due to the fact that they cut so many corners, it can be *very* wrong on live servers.

  5. #5
    vulcanaoc's Avatar Member
    Reputation
    31
    Join Date
    Jul 2008
    Posts
    125
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by apoc View Post
    the above code works just as well. It was ripped directly from wow.

    zomg illegal!!!!!

  6. #6
    andy012345's Avatar Active Member
    Reputation
    59
    Join Date
    Oct 2007
    Posts
    124
    Thanks G/R
    0/7
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You might want to look at it for the neutral guards though (the ones that step in when people PVP). Simple faction checks will still show them as friendly, iirc their hostility is based on player bytes and some flags they have in their faction records.

    Basically if npc's faction flags & 0x1000 and player's PLAYER_FLAGS & 0x100 it's hostile to you.

Similar Threads

  1. Need help with faction
    By Kyiz in forum WoW EMU Guides & Tutorials
    Replies: 1
    Last Post: 02-25-2008, 10:29 PM
  2. Great addon for dealing with gold seller spams
    By cbass in forum World of Warcraft Guides
    Replies: 1
    Last Post: 12-04-2007, 08:38 AM
  3. Dealing with Exaustion with a Warlock
    By Calek in forum World of Warcraft Exploration
    Replies: 5
    Last Post: 08-06-2007, 03:55 PM
  4. Groups you've had to deal with...
    By Enfeebleness in forum World of Warcraft General
    Replies: 2
    Last Post: 01-29-2007, 01:58 AM
All times are GMT -5. The time now is 09:41 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search