Exemplo n.º 1
0
        /// <summary>
        /// 周辺のキャラ情報を取得
        /// </summary>
        private unsafe List <Combatant> _getCombatantList()
        {
            int num = 344;
            List <Combatant> result = new List <Combatant>();

            int sz = 8;

            byte[] source = GetByteArray(charmapAddress, sz * num);
            if (source == null || source.Length == 0)
            {
                return(result);
            }

            for (int i = 0; i < num; i++)
            {
                IntPtr p;

                fixed(byte *bp = source) p = new IntPtr(*(Int64 *)&bp[i * sz]);

                if (!(p == IntPtr.Zero))
                {
                    byte[]    c         = GetByteArray(p, combatantDataSize);
                    Combatant combatant = GetCombatantFromByteArray(c);
                    if (combatant.type != ObjectType.PC && combatant.type != ObjectType.Monster)
                    {
                        continue;
                    }
                    if (combatant.ID != 0 && combatant.ID != 3758096384u && !result.Exists((Combatant x) => x.ID == combatant.ID))
                    {
                        combatant.Order = i;
                        result.Add(combatant);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 敵視リスト情報を取得
        /// </summary>
        public unsafe List <AggroEntry> GetAggroList()
        {
            int  num                        = 0;
            uint currentTargetID            = 0;
            List <AggroEntry> result        = new List <AggroEntry>();
            List <Combatant>  combatantList = Combatants;
            Combatant         mychar        = GetSelfCombatant();

            // 一度に全部読む
            byte[] buffer = GetByteArray(aggroAddress, 32 * 72 + 2);

            fixed(byte *p = buffer) num = (short)p[2296];

            if (num <= 0)
            {
                return(result);
            }
            if (num > 31)
            {
                num = 31;           // max changed??? 32->31
            }
            // current target
            //currentTargetID = GetUInt32(aggroAddress, -4);
            //if (currentTargetID == 3758096384u) currentTargetID = 0;
            var targetCombatant = GetTargetCombatant();

            if (targetCombatant != null)
            {
                currentTargetID = targetCombatant.ID;
            }
            else
            {
                currentTargetID = 0;
            }
            //
            for (int i = 0; i < num; i++)
            {
                int   p = i * 72;
                uint  _id;
                short _enmity;

                fixed(byte *bp = buffer)
                {
                    _id     = *(uint *)&bp[p + 56];
                    _enmity = (short)bp[p + 60];
                }

                var entry = new AggroEntry()
                {
                    ID       = _id,
                    HateRate = _enmity,
                    Name     = "Unknown",
                };
                if (entry.ID <= 0)
                {
                    continue;
                }
                Combatant c = combatantList.Find(x => x.ID == entry.ID);
                if (c != null)
                {
                    entry.ID              = c.ID;
                    entry.Order           = c.Order;
                    entry.isCurrentTarget = (c.ID == currentTargetID);
                    entry.Name            = c.Name;
                    entry.MaxHP           = c.MaxHP;
                    entry.CurrentHP       = c.CurrentHP;
                    entry.Statuses        = c.Statuses;
                    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,
                                Job      = t.Job,
                                OwnerID  = t.OwnerID,
                                isMe     = mychar.ID == t.ID ? true : false,
                                Enmity   = 0,
                                HateRate = 0
                            };
                        }
                    }
                }
                result.Add(entry);
            }
            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// カレントターゲットの敵視情報を取得
        /// </summary>
        public unsafe List <EnmityEntry> GetEnmityEntryList()
        {
            short num                        = 0;
            uint  topEnmity                  = 0;
            List <EnmityEntry> result        = new List <EnmityEntry>();
            List <Combatant>   combatantList = Combatants;
            Combatant          mychar        = GetSelfCombatant();

            /// 一度に全部読む
            byte[] buffer = GetByteArray(enmityAddress, 0x900 + 2);

            fixed(byte *p = buffer) num = (short)p[2296];

            if (num <= 0)
            {
                return(result);
            }
            if (num > 31)
            {
                num = 31;           // changed??? 32->31
            }
            for (short i = 0; i < num; i++)
            {
                int  p = i * 72;
                uint _id;
                uint _enmity;

                fixed(byte *bp = buffer)
                {
                    _id     = *(uint *)&bp[p + 56];
                    _enmity = *(uint *)&bp[p + 60];
                }

                var entry = new EnmityEntry()
                {
                    ID     = _id,
                    Enmity = _enmity,
                    isMe   = false,
                    Name   = "Unknown",
                    Job    = 0x00
                };
                if (entry.ID > 0)
                {
                    Combatant c = combatantList.Find(x => x.ID == entry.ID);
                    if (c != null)
                    {
                        entry.Name    = c.Name;
                        entry.Job     = c.Job;
                        entry.OwnerID = c.OwnerID;
                    }
                    if (entry.ID == mychar.ID)
                    {
                        entry.isMe = true;
                    }
                    if (topEnmity <= entry.Enmity)
                    {
                        topEnmity = entry.Enmity;
                    }
                    entry.HateRate = (int)(((double)entry.Enmity / (double)topEnmity) * 100);
                    result.Add(entry);
                }
            }
            return(result);
        }
Exemplo n.º 4
0
        /// <summary>
        /// メモリのバイト配列からキャラ情報に変換
        /// </summary>
        public unsafe Combatant GetCombatantFromByteArray(byte[] source)
        {
            int       offset    = 0;
            Combatant combatant = new Combatant();

            fixed(byte *p = source)
            {
                //combatant.BoA = BitConverter.ToString(source);

                combatant.Name    = GetStringFromBytes(source, 0x30);
                combatant.ID      = *(uint *)&p[0x74];
                combatant.OwnerID = *(uint *)&p[0x84];
                if (combatant.OwnerID == 3758096384u)
                {
                    combatant.OwnerID = 0u;
                }
                combatant.type = (ObjectType)p[0x8C];
                combatant.EffectiveDistance = p[0x92];

                offset         = 0xA0;
                combatant.PosX = *(Single *)&p[offset];
                combatant.PosZ = *(Single *)&p[offset + 4];
                combatant.PosY = *(Single *)&p[offset + 8];

                offset             = 5792 + 16;
                combatant.TargetID = *(uint *)&p[5680]; //5672? 5680? 5796? 6744? in 4.2

                if (combatant.type == ObjectType.PC || combatant.type == ObjectType.Monster)
                {
                    combatant.Job       = p[offset + 0x3E];
                    combatant.Level     = p[offset + 0x40];
                    combatant.CurrentHP = *(int *)&p[offset + 8];
                    combatant.MaxHP     = *(int *)&p[offset + 12];
                    combatant.CurrentMP = *(int *)&p[offset + 16];
                    combatant.MaxMP     = *(int *)&p[offset + 20];
                    combatant.CurrentTP = *(short *)&p[offset + 24];
                    combatant.MaxTP     = 1000;

                    // Status aka Buff,Debuff
                    combatant.Statuses = new List <Status>();
                    const int StatusEffectOffset = 5992;
                    const int statusSize         = 12;
                    int       statusCountLimit   = 60;
                    if (combatant.type == ObjectType.PC)
                    {
                        statusCountLimit = 30;
                    }
                    var statusesSource = new byte[statusCountLimit * statusSize];
                    Buffer.BlockCopy(source, StatusEffectOffset, statusesSource, 0, statusCountLimit * statusSize);
                    for (var i = 0; i < statusCountLimit; i++)
                    {
                        var statusBytes = new byte[statusSize];
                        Buffer.BlockCopy(statusesSource, i * statusSize, statusBytes, 0, statusSize);
                        var status = new Status
                        {
                            StatusID = BitConverter.ToInt16(statusBytes, 0),
                            Stacks   = statusBytes[2],
                            Duration = BitConverter.ToSingle(statusBytes, 4),
                            CasterID = BitConverter.ToUInt32(statusBytes, 8),
                            IsOwner  = false,
                        };

                        if (status.IsValid())
                        {
                            combatant.Statuses.Add(status);
                        }
                    }

                    // Cast
                    combatant.Casting = new Cast
                    {
                        ID       = BitConverter.ToInt16(source, 6372),
                        TargetID = BitConverter.ToUInt32(source, 6384),
                        Progress = BitConverter.ToSingle(source, 6420),
                        Time     = BitConverter.ToSingle(source, 6424),
                    };
                }
                else
                {
                    combatant.CurrentHP                     =
                        combatant.MaxHP                     =
                            combatant.CurrentMP             =
                                combatant.MaxMP             =
                                    combatant.MaxTP         =
                                        combatant.CurrentTP = 0;
                    combatant.Statuses = new List <Status>();
                    combatant.Casting  = new Cast();
                }
            }

            return(combatant);
        }
Exemplo n.º 5
0
        /// <summary>
        /// 各ポインタのアドレスを取得
        /// </summary>
        private bool getPointerAddress()
        {
            bool success = true;
            bool bRIP    = true;

            string        charmapSignature = charmapSignature64;
            string        targetSignature  = targetSignature64;
            string        enmitySignature  = enmitySignature64;
            int           targetOffset     = targetOffset64;
            int           charmapOffset    = charmapOffset64;
            int           enmityOffset     = enmityOffset64;
            List <string> fail             = new List <string>();

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

            if (list == null || list.Count == 0)
            {
                charmapAddress = IntPtr.Zero;
            }
            if (list.Count == 1)
            {
                charmapAddress = list[0] + charmapOffset;
            }
            if (charmapAddress == IntPtr.Zero)
            {
                fail.Add(nameof(charmapAddress));
                success = false;
            }

            // ENMITY
            //enmityAddress = IntPtr.Add(charmapAddress, enmityOffset);
            //aggroAddress = IntPtr.Add(enmityAddress, 0x900 + 8);

            list = SigScan(enmitySignature, 0, bRIP);
            if (list == null || list.Count == 0)
            {
                enmityAddress = IntPtr.Zero;
            }
            if (list.Count == 1)
            {
                enmityAddress = list[0] + enmityOffset;
                aggroAddress  = IntPtr.Add(enmityAddress, 0x900 + 8);
            }
            if (enmityAddress == IntPtr.Zero)
            {
                fail.Add(nameof(enmityAddress));
                success = false;
            }
            aggroAddress = IntPtr.Add(enmityAddress, 0x900 + 8);

            /// TARGET
            list = SigScan(targetSignature, 0, bRIP);
            if (list == null || list.Count == 0)
            {
                targetAddress = IntPtr.Zero;
            }
            if (list.Count == 1)
            {
                targetAddress = list[0] + targetOffset;
            }
            if (targetAddress == IntPtr.Zero)
            {
                fail.Add(nameof(targetAddress));
                success = false;
            }

            _overlay.LogDebug("charmapAddress: 0x{0:X}", charmapAddress.ToInt64());
            _overlay.LogDebug("enmityAddress: 0x{0:X}", enmityAddress.ToInt64());
            _overlay.LogDebug("targetAddress: 0x{0:X}", targetAddress.ToInt64());
            Combatant c = GetSelfCombatant();

            if (c != null)
            {
                _overlay.LogDebug("MyCharacter: '{0}' ({1})", c.Name, c.ID);
            }

            if (!success)
            {
                throw new MemoryScanException(String.Format(Messages.FailedToSigScan, String.Join(",", fail)));
            }

            return(success);
        }
Exemplo n.º 6
0
        /// <summary>
        /// メモリのバイト配列からキャラ情報に変換
        /// </summary>
        public unsafe Combatant GetCombatantFromByteArray(byte[] source)
        {
            Combatant combatant = new Combatant();

            fixed(byte *p = source)
            {
                // For Debug
                //combatant.BoA = BitConverter.ToString(source);

                combatant.Name    = GetStringFromBytes(source, combatantStructureOffset_Name);
                combatant.ID      = *(uint *)&p[combatantStructureOffset_ID];
                combatant.OwnerID = *(uint *)&p[combatantStructureOffset_OwnerID];
                if (combatant.OwnerID == 3758096384u)
                {
                    combatant.OwnerID = 0u;
                }
                combatant.type = (ObjectType)p[combatantStructureOffset_Type];
                combatant.EffectiveDistance = p[combatantStructureOffset_EffectiveDistance];

                combatant.PosX    = *(Single *)&p[combatantStructureOffset_PosX];
                combatant.PosZ    = *(Single *)&p[combatantStructureOffset_PosZ];
                combatant.PosY    = *(Single *)&p[combatantStructureOffset_PosY];
                combatant.Heading = *(Single *)&p[combatantStructureOffset_Heading];

                combatant.TargetID = *(uint *)&p[combatantStructureOffset_TargetID];

                if (combatant.type == ObjectType.PC || combatant.type == ObjectType.Monster)
                {
                    combatant.CurrentHP = *(int *)&p[combatantStructureOffset_CurrentHP];
                    combatant.MaxHP     = *(int *)&p[combatantStructureOffset_MaxHP];
                    combatant.CurrentMP = *(int *)&p[combatantStructureOffset_CurrentMP];
                    combatant.MaxMP     = *(int *)&p[combatantStructureOffset_MaxMP];
                    combatant.Job       = p[combatantStructureOffset_Job];
                    combatant.Level     = p[combatantStructureOffset_Level];
                    combatant.CurrentTP = 0;
                    combatant.MaxTP     = 0;

                    // Status aka Buff,Debuff
                    combatant.Statuses = new List <Status>();
                    int statusCountLimit = (combatant.type == ObjectType.PC) ? 30 : 60;

                    var statusesSource = new byte[statusCountLimit * combatantStructureOffset_StatusItemSize];
                    Buffer.BlockCopy(source, combatantStructureOffset_StatusOffset, statusesSource, 0, statusCountLimit * combatantStructureOffset_StatusItemSize);
                    for (var i = 0; i < statusCountLimit; i++)
                    {
                        var statusBytes = new byte[combatantStructureOffset_StatusItemSize];
                        Buffer.BlockCopy(statusesSource, i * combatantStructureOffset_StatusItemSize, statusBytes, 0, combatantStructureOffset_StatusItemSize);
                        var status = new Status
                        {
                            StatusID = BitConverter.ToUInt16(statusBytes, combatantStructureOffset_StatusItem_ID),
                            Stacks   = statusBytes[combatantStructureOffset_StatusItem_Stacks],
                            Duration = BitConverter.ToSingle(statusBytes, combatantStructureOffset_StatusItem_Duration),
                            CasterID = BitConverter.ToUInt32(statusBytes, combatantStructureOffset_StatusItem_CasterID),
                            IsOwner  = false,
                        };

                        if (status.IsValid())
                        {
                            combatant.Statuses.Add(status);
                        }
                    }

                    // Cast
                    combatant.Casting = new Cast
                    {
                        ID       = *(ushort *)&p[combatantStructureOffset_CastingID],
                        TargetID = *(uint *)&p[combatantStructureOffset_CastingTargetID],
                        Progress = *(Single *)&p[combatantStructureOffset_CastingProgress],
                        Time     = *(Single *)&p[combatantStructureOffset_CastingTime],
                    };
                }
                else
                {
                    combatant.CurrentHP                 =
                        combatant.MaxHP                 =
                            combatant.CurrentTP         =
                                combatant.MaxTP         =
                                    combatant.CurrentMP =
                                        combatant.MaxMP = 0;
                    combatant.Statuses = new List <Status>();
                    combatant.Casting  = new Cast();
                }
            }

            return(combatant);
        }
Exemplo n.º 7
0
 public float GetHorizontalDistanceTo(Combatant target)
 {
     var distanceX = (float)Math.Abs(PosX - target.PosX);
     var distanceY = (float)Math.Abs(PosY - target.PosY);
     return (float)Math.Sqrt((distanceX * distanceX) + (distanceY * distanceY));
 }
Exemplo n.º 8
0
 public float GetDistanceTo(Combatant target)
 {
     var distanceX = (float)Math.Abs(PosX - target.PosX);
     var distanceY = (float)Math.Abs(PosY - target.PosY);
     var distanceZ = (float)Math.Abs(PosZ - target.PosZ);
     return (float)Math.Sqrt((distanceX * distanceX) + (distanceY * distanceY) + (distanceZ * distanceZ));
 }
        public static List<Combatant> GetCombatantList()
        {
            List<Combatant> result = new List<Combatant>();
            try
            {
                var scanCombatants = GetScanCombatants();
                if (scanCombatants == null) return null;

                var item = scanCombatants.GetType().InvokeMember("GetCombatantList", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, scanCombatants, null);
                FieldInfo fi = item.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);

                Type[] nestedType = item.GetType().GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
                object tmp = fi.GetValue(item);
                if (tmp.GetType().IsArray)
                {
                    foreach (object temp in (Array)tmp)
                    {
                        if (temp == null) break;

                        Combatant combatant = new Combatant();

                        fi = temp.GetType().GetField("ID", BindingFlags.Public | BindingFlags.Instance);
                        combatant.ID = (uint)fi.GetValue(temp);
                        fi = temp.GetType().GetField("OwnerID", BindingFlags.Public | BindingFlags.Instance);
                        combatant.OwnerID = (uint)fi.GetValue(temp);
                        fi = temp.GetType().GetField("Job", BindingFlags.Public | BindingFlags.Instance);
                        combatant.Job = (int)fi.GetValue(temp);
                        fi = temp.GetType().GetField("Name", BindingFlags.Public | BindingFlags.Instance);
                        combatant.Name = (string)fi.GetValue(temp);
                        fi = temp.GetType().GetField("CurrentTP", BindingFlags.Public | BindingFlags.Instance);
                        combatant.CurrentTP = (int)fi.GetValue(temp);
                        fi = temp.GetType().GetField("CurrentHP", BindingFlags.Public | BindingFlags.Instance);
                        combatant.CurrentHP = (int)fi.GetValue(temp);
                        fi = temp.GetType().GetField("MaxHP", BindingFlags.Public | BindingFlags.Instance);
                        combatant.MaxHP = (int)fi.GetValue(temp);

                        result.Add(combatant);
                    }
                }
            }
            catch { }
            return result;
        }
Exemplo n.º 10
0
        /// <summary>
        /// メモリのバイト配列からキャラ情報に変換
        /// </summary>
        public unsafe Combatant GetCombatantFromByteArray(byte[] source)
        {
            int offset = 0;
            Combatant combatant = new Combatant();
            fixed (byte* p = source)
            {
                combatant.Name    = GetStringFromBytes(source, 48);
                combatant.ID      = *(uint*)&p[0x74];
                combatant.OwnerID = *(uint*)&p[0x84];
                if (combatant.OwnerID == 3758096384u)
                {
                    combatant.OwnerID = 0u;
                }
                combatant.type = (ObjectType)p[0x8A];
                combatant.EffectiveDistance = p[0x91];

                offset = (_mode == FFXIVClientMode.FFXIV_64) ? 176 : 160;
                combatant.PosX = *(Single*)&p[offset];
                combatant.PosZ = *(Single*)&p[offset + 4];
                combatant.PosY = *(Single*)&p[offset + 8];

                offset = (_mode == FFXIVClientMode.FFXIV_64) ? 448 : 392;
                combatant.TargetID = *(uint*)&p[offset];
                if (combatant.TargetID == 3758096384u)
                {
                    offset = (_mode == FFXIVClientMode.FFXIV_64) ? 2448 : 2520;
                    combatant.TargetID = *(uint*)&p[offset];
                }

                if (combatant.type == ObjectType.PC || combatant.type == ObjectType.Monster)
                {
                    offset = (_mode == FFXIVClientMode.FFXIV_64) ? 5872 : 5312;
                    combatant.Job       = p[offset];
                    combatant.Level     = p[offset + 1];
                    combatant.CurrentHP = *(int*)&p[offset + 8];
                    combatant.MaxHP     = *(int*)&p[offset + 12];
                    combatant.CurrentMP = *(int*)&p[offset + 16];
                    combatant.MaxMP     = *(int*)&p[offset + 20];
                    combatant.CurrentTP = *(short*)&p[offset + 24];
                    combatant.MaxTP     = 1000;
                }
                else
                {
                    combatant.CurrentHP =
                    combatant.MaxHP     =
                    combatant.CurrentMP =
                    combatant.MaxMP     =
                    combatant.MaxTP     =
                    combatant.CurrentTP = 0;
                }
            }
            return combatant;
        }