Beispiel #1
0
        // Will return any kind of combatant, even if not a mob.
        // This function always returns a combatant object, even if empty.
        public unsafe Combatant GetCombatantFromByteArray(byte[] source, uint mycharID, bool isPlayer, bool exceptEffects = false)
        {
            fixed(byte *p = source)
            {
                CombatantMemory mem = *(CombatantMemory *)&p[0];

                if (isPlayer)
                {
                    mycharID = mem.ID;
                }

                Combatant combatant = new Combatant()
                {
                    Name    = FFXIVMemory.GetStringFromBytes(mem.Name, CombatantMemory.nameBytes),
                    Job     = mem.Job,
                    ID      = mem.ID,
                    OwnerID = mem.OwnerID == emptyID ? 0 : mem.OwnerID,
                    Type    = (ObjectType)mem.Type,
                    RawEffectiveDistance = mem.EffectiveDistance,
                    PosX      = mem.PosX,
                    PosY      = mem.PosY,
                    PosZ      = mem.PosZ,
                    TargetID  = mem.TargetID,
                    CurrentHP = mem.CurrentHP,
                    MaxHP     = mem.MaxHP,
                    Effects   = exceptEffects ? new List <EffectEntry>() : GetEffectEntries(mem.Effects, (ObjectType)mem.Type, mycharID),
                };

                if (combatant.Type != ObjectType.PC && combatant.Type != ObjectType.Monster)
                {
                    // Other types have garbage memory for hp.
                    combatant.CurrentHP = 0;
                    combatant.MaxHP     = 0;
                }
                return(combatant);
            }
        }
        // Converts an EnmityList into a List<AggroEntry>.
        public override unsafe List <AggroEntry> GetAggroList(List <Combatant> combatantList)
        {
            Combatant mychar = GetSelfCombatant();

            uint currentTargetID = 0;
            var  targetCombatant = GetTargetCombatant();

            if (targetCombatant != null)
            {
                currentTargetID = targetCombatant.ID;
            }

            var result = new List <AggroEntry>();

            AggroList list = ReadAggroList(aggroAddress);

            for (int i = 0; i < list.numEntries; i++)
            {
                AggroListEntry e = list.GetEntry(i);
                if (e.ID <= 0)
                {
                    continue;
                }
                Combatant c = combatantList.Find(x => x.ID == e.ID);
                if (c == null)
                {
                    continue;
                }

                var entry = new AggroEntry()
                {
                    ID = e.ID,
                    // Rather than storing enmity, this is hate rate for the aggro list.
                    // This is likely because we're reading the memory for the aggro sidebar.
                    HateRate        = (int)e.Enmity,
                    isCurrentTarget = (e.ID == currentTargetID),
                    Name            = c.Name,
                    MaxHP           = c.MaxHP,
                    CurrentHP       = c.CurrentHP,
                    Effects         = c.Effects,
                };

                // TODO: it seems like when your chocobo has aggro, this entry
                // is you, and not your chocobo.  It's not clear if there's
                // anything that can be done about it.
                if (c.TargetID > 0)
                {
                    Combatant t = combatantList.Find(x => x.ID == c.TargetID);
                    if (t != null)
                    {
                        entry.Target = new EnmityEntry()
                        {
                            ID       = t.ID,
                            Name     = t.Name,
                            OwnerID  = t.OwnerID,
                            isMe     = mychar.ID == t.ID ? true : false,
                            Enmity   = 0,
                            HateRate = 0,
                            Job      = t.Job,
                        };
                    }
                }
                result.Add(entry);
            }
            return(result);
        }
        private bool GetPointerAddress()
        {
            if (!memory.IsValid())
            {
                return(false);
            }

            // Don't scan too often to avoid excessive CPU load
            if ((DateTime.Now - lastSigScan) < TimeSpan.FromSeconds(5))
            {
                return(false);
            }

            lastSigScan = DateTime.Now;
            bool success = true;
            bool bRIP    = true;

            List <string> fail = new List <string>();

            /// CHARMAP
            List <IntPtr> list = memory.SigScan(charmapSignature, 0, bRIP);

            if (list != null && list.Count > 0)
            {
                charmapAddress = list[0] + charmapSignatureOffset;
            }
            else
            {
                charmapAddress = IntPtr.Zero;
                fail.Add(nameof(charmapAddress));
                success = false;
            }

            // ENMITY
            list = memory.SigScan(enmitySignature, 0, bRIP);
            if (list != null && list.Count > 0)
            {
                enmityAddress = IntPtr.Add(list[0], enmitySignatureOffset);
                aggroAddress  = IntPtr.Add(list[0], aggroEnmityOffset);
            }
            else
            {
                enmityAddress = IntPtr.Zero;
                aggroAddress  = IntPtr.Zero;
                fail.Add(nameof(enmityAddress));
                fail.Add(nameof(aggroAddress));
                success = false;
            }

            /// TARGET
            list = memory.SigScan(targetSignature, 0, bRIP);

            if (list != null && list.Count > 0)
            {
                targetAddress = list[0] + targetSignatureOffset;
            }
            else
            {
                targetAddress = IntPtr.Zero;
                fail.Add(nameof(targetAddress));
                success = false;
            }

            /// IN COMBAT
            // The in combat address is set from a combination of two values, a base address and an offset.
            // They are found adjacent to the same signature, but at different offsets.
            var baseList = memory.SigScan(inCombatSignature, inCombatSignatureBaseOffset, bRIP);
            // SigScan returns pointers, but the offset is a 32-bit immediate value.  Do not use RIP.
            var offsetList = memory.SigScan(inCombatSignature, inCombatSignatureOffsetOffset, false);

            if (baseList != null && baseList.Count > 0 && offsetList != null && offsetList.Count > 0)
            {
                var baseAddress = baseList[0];
                var offset      = (int)(((UInt64)offsetList[0]) & 0xFFFFFFFF);
                inCombatAddress = IntPtr.Add(baseAddress, offset);
            }
            else
            {
                inCombatAddress = IntPtr.Zero;
                fail.Add(nameof(inCombatAddress));
                success = false;
            }

            // EnmityList
            list = memory.SigScan(enmityHudSignature, 0, bRIP);
            if (list != null && list.Count == 1)
            {
                enmityHudAddress = list[0] + enmityHudSignatureOffset;

                if (enmityHudAddress == IntPtr.Zero)
                {
                    fail.Add(nameof(enmityHudAddress));
                    success = false;
                }
            }
            else
            {
                enmityHudAddress = IntPtr.Zero;
                fail.Add(nameof(enmityHudAddress));
                success = false;
            }

            logger.Log(LogLevel.Debug, "charmapAddress: 0x{0:X}", charmapAddress.ToInt64());
            logger.Log(LogLevel.Debug, "enmityAddress: 0x{0:X}", enmityAddress.ToInt64());
            logger.Log(LogLevel.Debug, "aggroAddress: 0x{0:X}", aggroAddress.ToInt64());
            logger.Log(LogLevel.Debug, "targetAddress: 0x{0:X}", targetAddress.ToInt64());
            logger.Log(LogLevel.Debug, "inCombatAddress: 0x{0:X}", inCombatAddress.ToInt64());
            logger.Log(LogLevel.Debug, "enmityListAddress: 0x{0:X}", enmityHudAddress.ToInt64());

            Combatant c = GetSelfCombatant();

            if (c != null)
            {
                logger.Log(LogLevel.Debug, "MyCharacter: '{0}' (0x{1:X})", c.Name, c.ID);
            }

            if (!success)
            {
                if (loggedScanErrors < 10)
                {
                    logger.Log(LogLevel.Error, "Failed to find enmity memory for 5.4: {0}.", String.Join(",", fail));
                    loggedScanErrors++;

                    if (loggedScanErrors == 10)
                    {
                        logger.Log(LogLevel.Error, "Further enmity errors won't be logged.");
                    }
                }
            }
            else
            {
                logger.Log(LogLevel.Info, "Found enmity memory for 5.4.");
                loggedScanErrors = 0;
            }

            return(success);
        }
Beispiel #4
0
        private bool GetPointerAddress()
        {
            if (!memory.IsValid())
            {
                return(false);
            }

            // Don't scan too often to avoid excessive CPU load
            if ((DateTime.Now - lastSigScan) < TimeSpan.FromSeconds(5))
            {
                return(false);
            }

            lastSigScan = DateTime.Now;
            bool success = true;
            bool bRIP    = true;

            List <string> fail = new List <string>();

            /// CHARMAP
            List <IntPtr> list = memory.SigScan(charmapSignature, 0, bRIP);

            if (list != null && list.Count > 0)
            {
                charmapAddress = list[0] + charmapSignatureOffset;
            }
            else
            {
                charmapAddress = IntPtr.Zero;
                fail.Add(nameof(charmapAddress));
                success = false;
            }

            // ENMITY
            list = memory.SigScan(enmitySignature, 0, bRIP);
            if (list != null && list.Count > 0)
            {
                enmityAddress = IntPtr.Add(list[0], enmitySignatureOffset);
                aggroAddress  = IntPtr.Add(list[0], aggroEnmityOffset);
            }
            else
            {
                enmityAddress = IntPtr.Zero;
                aggroAddress  = IntPtr.Zero;
                fail.Add(nameof(enmityAddress));
                fail.Add(nameof(aggroAddress));
                success = false;
            }

            /// TARGET
            list = memory.SigScan(targetSignature, 0, bRIP);

            if (list != null && list.Count > 0)
            {
                targetAddress = list[0] + targetSignatureOffset;
            }
            else
            {
                targetAddress = IntPtr.Zero;
                fail.Add(nameof(targetAddress));
                success = false;
            }

            /// IN COMBAT
            list = memory.SigScan(inCombatSignature, inCombatSignatureOffset, bRIP, inCombatRIPOffset);

            if (list != null && list.Count > 0)
            {
                inCombatAddress = list[0];
            }
            else
            {
                inCombatAddress = IntPtr.Zero;
                fail.Add(nameof(inCombatAddress));
                success = false;
            }

            // EnmityList
            list = memory.SigScan(enmityHudSignature, 0, bRIP);
            if (list != null && list.Count == 1)
            {
                enmityHudAddress = list[0] + enmityHudSignatureOffset;

                if (enmityHudAddress == IntPtr.Zero)
                {
                    fail.Add(nameof(enmityHudAddress));
                    success = false;
                }
            }
            else
            {
                enmityHudAddress = IntPtr.Zero;
                fail.Add(nameof(enmityHudAddress));
                success = false;
            }

            logger.Log(LogLevel.Debug, "charmapAddress: 0x{0:X}", charmapAddress.ToInt64());
            logger.Log(LogLevel.Debug, "enmityAddress: 0x{0:X}", enmityAddress.ToInt64());
            logger.Log(LogLevel.Debug, "aggroAddress: 0x{0:X}", aggroAddress.ToInt64());
            logger.Log(LogLevel.Debug, "targetAddress: 0x{0:X}", targetAddress.ToInt64());
            logger.Log(LogLevel.Debug, "inCombatAddress: 0x{0:X}", inCombatAddress.ToInt64());
            logger.Log(LogLevel.Debug, "enmityListAddress: 0x{0:X}", enmityHudAddress.ToInt64());

            Combatant c = GetSelfCombatant();

            if (c != null)
            {
                logger.Log(LogLevel.Debug, "MyCharacter: '{0}' (0x{1:X})", c.Name, c.ID);
            }

            if (!success)
            {
                if (loggedScanErrors < 10)
                {
                    logger.Log(LogLevel.Error, "Failed to find enmity memory for 6.1: {0}.", String.Join(",", fail));
                    loggedScanErrors++;

                    if (loggedScanErrors == 10)
                    {
                        logger.Log(LogLevel.Error, "Further enmity errors won't be logged.");
                    }
                }
            }
            else
            {
                logger.Log(LogLevel.Info, "Found enmity memory for 6.1.");
                loggedScanErrors = 0;
            }

            return(success);
        }
 public string DistanceString(Combatant target)
 {
     return(GetDistance(target).ToString("0.00"));
 }